1+ /**
2+ * Copyright 2012 Kamran Zafar
3+ *
4+ * Licensed under the Apache License, Version 2.0 (the "License");
5+ * you may not use this file except in compliance with the License.
6+ * You may obtain a copy of the License at
7+ *
8+ * http://www.apache.org/licenses/LICENSE-2.0
9+ *
10+ * Unless required by applicable law or agreed to in writing, software
11+ * distributed under the License is distributed on an "AS IS" BASIS,
12+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+ * See the License for the specific language governing permissions and
14+ * limitations under the License.
15+ *
16+ */
17+
18+ package org .kamranzafar .jtar ;
19+
20+ import java .io .File ;
21+ import java .util .Date ;
22+
23+ /**
24+ * @author Kamran Zafar
25+ *
26+ */
27+ public class TarEntry {
28+ protected File file ;
29+ protected TarHeader header ;
30+
31+ private TarEntry () {
32+ this .file = null ;
33+ header = new TarHeader ();
34+ }
35+
36+ public TarEntry (File file , String entryName ) {
37+ this ();
38+ this .file = file ;
39+ this .extractTarHeader (entryName );
40+ }
41+
42+ public TarEntry (byte [] headerBuf ) {
43+ this ();
44+ this .parseTarHeader (headerBuf );
45+ }
46+
47+ /**
48+ * Constructor to create an entry from an existing TarHeader object.
49+ *
50+ * This method is useful to add new entries programmatically (e.g. for
51+ * adding files or directories that do not exist in the file system).
52+ *
53+ * @param header
54+ *
55+ */
56+ public TarEntry (TarHeader header ) {
57+ this .file = null ;
58+ this .header = header ;
59+ }
60+
61+ public boolean equals (TarEntry it ) {
62+ return header .name .toString ().equals (it .header .name .toString ());
63+ }
64+
65+ public boolean isDescendent (TarEntry desc ) {
66+ return desc .header .name .toString ().startsWith (header .name .toString ());
67+ }
68+
69+ public TarHeader getHeader () {
70+ return header ;
71+ }
72+
73+ public String getName () {
74+ String name = header .name .toString ();
75+ if (header .namePrefix != null && !header .namePrefix .toString ().equals ("" )) {
76+ name = header .namePrefix .toString () + "/" + name ;
77+ }
78+
79+ return name ;
80+ }
81+
82+ public void setName (String name ) {
83+ header .name = new StringBuffer (name );
84+ }
85+
86+ public int getUserId () {
87+ return header .userId ;
88+ }
89+
90+ public void setUserId (int userId ) {
91+ header .userId = userId ;
92+ }
93+
94+ public int getGroupId () {
95+ return header .groupId ;
96+ }
97+
98+ public void setGroupId (int groupId ) {
99+ header .groupId = groupId ;
100+ }
101+
102+ public String getUserName () {
103+ return header .userName .toString ();
104+ }
105+
106+ public void setUserName (String userName ) {
107+ header .userName = new StringBuffer (userName );
108+ }
109+
110+ public String getGroupName () {
111+ return header .groupName .toString ();
112+ }
113+
114+ public void setGroupName (String groupName ) {
115+ header .groupName = new StringBuffer (groupName );
116+ }
117+
118+ public void setIds (int userId , int groupId ) {
119+ this .setUserId (userId );
120+ this .setGroupId (groupId );
121+ }
122+
123+ public void setModTime (long time ) {
124+ header .modTime = time / 1000 ;
125+ }
126+
127+ public void setModTime (Date time ) {
128+ header .modTime = time .getTime () / 1000 ;
129+ }
130+
131+ public Date getModTime () {
132+ return new Date (header .modTime * 1000 );
133+ }
134+
135+ public File getFile () {
136+ return this .file ;
137+ }
138+
139+ public long getSize () {
140+ return header .size ;
141+ }
142+
143+ public void setSize (long size ) {
144+ header .size = size ;
145+ }
146+
147+ /**
148+ * Checks if the org.kamrazafar.jtar entry is a directory
149+ *
150+ * @return
151+ */
152+ public boolean isDirectory () {
153+ if (this .file != null )
154+ return this .file .isDirectory ();
155+
156+ if (header != null ) {
157+ if (header .linkFlag == TarHeader .LF_DIR )
158+ return true ;
159+
160+ if (header .name .toString ().endsWith ("/" ))
161+ return true ;
162+ }
163+
164+ return false ;
165+ }
166+
167+ /**
168+ * Extract header from File
169+ *
170+ * @param entryName
171+ */
172+ public void extractTarHeader (String entryName ) {
173+ header = TarHeader .createHeader (entryName , file .length (), file .lastModified () / 1000 , file .isDirectory ());
174+ }
175+
176+ /**
177+ * Calculate checksum
178+ *
179+ * @param buf
180+ * @return
181+ */
182+ public long computeCheckSum (byte [] buf ) {
183+ long sum = 0 ;
184+
185+ for (int i = 0 ; i < buf .length ; ++i ) {
186+ sum += 255 & buf [i ];
187+ }
188+
189+ return sum ;
190+ }
191+
192+ /**
193+ * Writes the header to the byte buffer
194+ *
195+ * @param outbuf
196+ */
197+ public void writeEntryHeader (byte [] outbuf ) {
198+ int offset = 0 ;
199+
200+ offset = TarHeader .getNameBytes (header .name , outbuf , offset , TarHeader .NAMELEN );
201+ offset = Octal .getOctalBytes (header .mode , outbuf , offset , TarHeader .MODELEN );
202+ offset = Octal .getOctalBytes (header .userId , outbuf , offset , TarHeader .UIDLEN );
203+ offset = Octal .getOctalBytes (header .groupId , outbuf , offset , TarHeader .GIDLEN );
204+
205+ long size = header .size ;
206+
207+ offset = Octal .getLongOctalBytes (size , outbuf , offset , TarHeader .SIZELEN );
208+ offset = Octal .getLongOctalBytes (header .modTime , outbuf , offset , TarHeader .MODTIMELEN );
209+
210+ int csOffset = offset ;
211+ for (int c = 0 ; c < TarHeader .CHKSUMLEN ; ++c )
212+ outbuf [offset ++] = (byte ) ' ' ;
213+
214+ outbuf [offset ++] = header .linkFlag ;
215+
216+ offset = TarHeader .getNameBytes (header .linkName , outbuf , offset , TarHeader .NAMELEN );
217+ offset = TarHeader .getNameBytes (header .magic , outbuf , offset , TarHeader .USTAR_MAGICLEN );
218+ offset = TarHeader .getNameBytes (header .userName , outbuf , offset , TarHeader .USTAR_USER_NAMELEN );
219+ offset = TarHeader .getNameBytes (header .groupName , outbuf , offset , TarHeader .USTAR_GROUP_NAMELEN );
220+ offset = Octal .getOctalBytes (header .devMajor , outbuf , offset , TarHeader .USTAR_DEVLEN );
221+ offset = Octal .getOctalBytes (header .devMinor , outbuf , offset , TarHeader .USTAR_DEVLEN );
222+ offset = TarHeader .getNameBytes (header .namePrefix , outbuf , offset , TarHeader .USTAR_FILENAME_PREFIX );
223+
224+ for (; offset < outbuf .length ;)
225+ outbuf [offset ++] = 0 ;
226+
227+ long checkSum = this .computeCheckSum (outbuf );
228+
229+ Octal .getCheckSumOctalBytes (checkSum , outbuf , csOffset , TarHeader .CHKSUMLEN );
230+ }
231+
232+ /**
233+ * Parses the tar header to the byte buffer
234+ *
235+ * @param header
236+ * @param bh
237+ */
238+ public void parseTarHeader (byte [] bh ) {
239+ int offset = 0 ;
240+
241+ header .name = TarHeader .parseName (bh , offset , TarHeader .NAMELEN );
242+ offset += TarHeader .NAMELEN ;
243+
244+ header .mode = (int ) Octal .parseOctal (bh , offset , TarHeader .MODELEN );
245+ offset += TarHeader .MODELEN ;
246+
247+ header .userId = (int ) Octal .parseOctal (bh , offset , TarHeader .UIDLEN );
248+ offset += TarHeader .UIDLEN ;
249+
250+ header .groupId = (int ) Octal .parseOctal (bh , offset , TarHeader .GIDLEN );
251+ offset += TarHeader .GIDLEN ;
252+
253+ header .size = Octal .parseOctal (bh , offset , TarHeader .SIZELEN );
254+ offset += TarHeader .SIZELEN ;
255+
256+ header .modTime = Octal .parseOctal (bh , offset , TarHeader .MODTIMELEN );
257+ offset += TarHeader .MODTIMELEN ;
258+
259+ header .checkSum = (int ) Octal .parseOctal (bh , offset , TarHeader .CHKSUMLEN );
260+ offset += TarHeader .CHKSUMLEN ;
261+
262+ header .linkFlag = bh [offset ++];
263+
264+ header .linkName = TarHeader .parseName (bh , offset , TarHeader .NAMELEN );
265+ offset += TarHeader .NAMELEN ;
266+
267+ header .magic = TarHeader .parseName (bh , offset , TarHeader .USTAR_MAGICLEN );
268+ offset += TarHeader .USTAR_MAGICLEN ;
269+
270+ header .userName = TarHeader .parseName (bh , offset , TarHeader .USTAR_USER_NAMELEN );
271+ offset += TarHeader .USTAR_USER_NAMELEN ;
272+
273+ header .groupName = TarHeader .parseName (bh , offset , TarHeader .USTAR_GROUP_NAMELEN );
274+ offset += TarHeader .USTAR_GROUP_NAMELEN ;
275+
276+ header .devMajor = (int ) Octal .parseOctal (bh , offset , TarHeader .USTAR_DEVLEN );
277+ offset += TarHeader .USTAR_DEVLEN ;
278+
279+ header .devMinor = (int ) Octal .parseOctal (bh , offset , TarHeader .USTAR_DEVLEN );
280+ offset += TarHeader .USTAR_DEVLEN ;
281+
282+ header .namePrefix = TarHeader .parseName (bh , offset , TarHeader .USTAR_FILENAME_PREFIX );
283+ }
284+ }
0 commit comments