Skip to content

Commit 7c6e1f5

Browse files
committed
Fix long filename support.
- use kamranzafar star instead of xeustechnologies. - force the tar creation to use USTAR format (default is GNU, and unsupported by kamranzafar).
1 parent 2442091 commit 7c6e1f5

13 files changed

+931
-767
lines changed

src/build.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,7 @@ def select(fn):
180180
if select(x)]
181181

182182
# create tar.gz of thoses files
183-
tf = tarfile.open(tfn, 'w:gz')
183+
tf = tarfile.open(tfn, 'w:gz', format=tarfile.USTAR_FORMAT)
184184
dirs = []
185185
for fn, afn in files:
186186
print '%s: %s' % (tfn, fn)

src/src/org/xeustechnologies/jtar/Octal.java renamed to src/src/org/kamranzafar/jtar/Octal.java

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/**
2-
* Copyright 2010 Xeus Technologies
2+
* Copyright 2012 Kamran Zafar
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -15,7 +15,7 @@
1515
*
1616
*/
1717

18-
package org.xeustechnologies.jtar;
18+
package org.kamranzafar.jtar;
1919

2020
/**
2121
* @author Kamran Zafar
@@ -41,15 +41,15 @@ public static long parseOctal(byte[] header, int offset, int length) {
4141
boolean stillPadding = true;
4242

4343
int end = offset + length;
44-
for( int i = offset; i < end; ++i ) {
45-
if( header[i] == 0 )
44+
for (int i = offset; i < end; ++i) {
45+
if (header[i] == 0)
4646
break;
4747

48-
if( header[i] == (byte) ' ' || header[i] == '0' ) {
49-
if( stillPadding )
48+
if (header[i] == (byte) ' ' || header[i] == '0') {
49+
if (stillPadding)
5050
continue;
5151

52-
if( header[i] == (byte) ' ' )
52+
if (header[i] == (byte) ' ')
5353
break;
5454
}
5555

@@ -82,17 +82,17 @@ public static int getOctalBytes(long value, byte[] buf, int offset, int length)
8282
buf[offset + idx] = (byte) ' ';
8383
--idx;
8484

85-
if( value == 0 ) {
85+
if (value == 0) {
8686
buf[offset + idx] = (byte) '0';
8787
--idx;
8888
} else {
89-
for( long val = value; idx >= 0 && val > 0; --idx ) {
89+
for (long val = value; idx >= 0 && val > 0; --idx) {
9090
buf[offset + idx] = (byte) ( (byte) '0' + (byte) ( val & 7 ) );
9191
val = val >> 3;
9292
}
9393
}
9494

95-
for( ; idx >= 0; --idx ) {
95+
for (; idx >= 0; --idx) {
9696
buf[offset + idx] = (byte) ' ';
9797
}
9898

src/src/org/xeustechnologies/jtar/TarConstants.java renamed to src/src/org/kamranzafar/jtar/TarConstants.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/**
2-
* Copyright 2010 Xeus Technologies
2+
* Copyright 2012 Kamran Zafar
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -15,7 +15,7 @@
1515
*
1616
*/
1717

18-
package org.xeustechnologies.jtar;
18+
package org.kamranzafar.jtar;
1919

2020
/**
2121
* @author Kamran Zafar
Lines changed: 284 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,284 @@
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

Comments
 (0)