1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.commons.compress.archivers.tar;
20
21 import java.io.ByteArrayInputStream;
22 import java.io.ByteArrayOutputStream;
23 import java.io.File;
24 import java.io.FileInputStream;
25 import java.io.FileOutputStream;
26 import java.util.Calendar;
27 import java.util.HashMap;
28 import java.util.Map;
29 import java.util.TimeZone;
30
31 import org.apache.commons.compress.AbstractTestCase;
32 import org.apache.commons.compress.archivers.ArchiveOutputStream;
33 import org.apache.commons.compress.archivers.ArchiveStreamFactory;
34 import org.apache.commons.compress.utils.CharsetNames;
35
36 public class TarArchiveOutputStreamTest extends AbstractTestCase {
37
38 public void testCount() throws Exception {
39 File f = File.createTempFile("commons-compress-tarcount", ".tar");
40 f.deleteOnExit();
41 FileOutputStream fos = new FileOutputStream(f);
42
43 ArchiveOutputStream tarOut = new ArchiveStreamFactory()
44 .createArchiveOutputStream(ArchiveStreamFactory.TAR, fos);
45
46 File file1 = getFile("test1.xml");
47 TarArchiveEntry sEntry = new TarArchiveEntry(file1);
48 tarOut.putArchiveEntry(sEntry);
49
50 FileInputStream in = new FileInputStream(file1);
51 byte[] buf = new byte[8192];
52
53 int read = 0;
54 while ((read = in.read(buf)) > 0) {
55 tarOut.write(buf, 0, read);
56 }
57
58 in.close();
59 tarOut.closeArchiveEntry();
60 tarOut.close();
61
62 assertEquals(f.length(), tarOut.getBytesWritten());
63 }
64
65 public void testMaxFileSizeError() throws Exception {
66 TarArchiveEntry t = new TarArchiveEntry("foo");
67 t.setSize(077777777777L);
68 TarArchiveOutputStream tos =
69 new TarArchiveOutputStream(new ByteArrayOutputStream());
70 tos.putArchiveEntry(t);
71 t.setSize(0100000000000L);
72 tos = new TarArchiveOutputStream(new ByteArrayOutputStream());
73 try {
74 tos.putArchiveEntry(t);
75 fail("Should have generated RuntimeException");
76 } catch (RuntimeException expected) {
77 }
78 }
79
80 public void testBigNumberStarMode() throws Exception {
81 TarArchiveEntry t = new TarArchiveEntry("foo");
82 t.setSize(0100000000000L);
83 ByteArrayOutputStream bos = new ByteArrayOutputStream();
84 TarArchiveOutputStream tos = new TarArchiveOutputStream(bos);
85 tos.setBigNumberMode(TarArchiveOutputStream.BIGNUMBER_STAR);
86 tos.putArchiveEntry(t);
87
88 tos.write(new byte[10 * 1024]);
89 byte[] data = bos.toByteArray();
90 assertEquals(0x80,
91 data[TarConstants.NAMELEN
92 + TarConstants.MODELEN
93 + TarConstants.UIDLEN
94 + TarConstants.GIDLEN] & 0x80);
95 TarArchiveInputStream tin =
96 new TarArchiveInputStream(new ByteArrayInputStream(data));
97 TarArchiveEntry e = tin.getNextTarEntry();
98 assertEquals(0100000000000L, e.getSize());
99 tin.close();
100
101
102 closeQuietly(tos);
103 }
104
105 public void testBigNumberPosixMode() throws Exception {
106 TarArchiveEntry t = new TarArchiveEntry("foo");
107 t.setSize(0100000000000L);
108 ByteArrayOutputStream bos = new ByteArrayOutputStream();
109 TarArchiveOutputStream tos = new TarArchiveOutputStream(bos);
110 tos.setBigNumberMode(TarArchiveOutputStream.BIGNUMBER_POSIX);
111 tos.putArchiveEntry(t);
112
113 tos.write(new byte[10 * 1024]);
114 byte[] data = bos.toByteArray();
115 assertEquals("00000000000 ",
116 new String(data,
117 1024 + TarConstants.NAMELEN
118 + TarConstants.MODELEN
119 + TarConstants.UIDLEN
120 + TarConstants.GIDLEN, 12,
121 CharsetNames.UTF_8));
122 TarArchiveInputStream tin =
123 new TarArchiveInputStream(new ByteArrayInputStream(data));
124 TarArchiveEntry e = tin.getNextTarEntry();
125 assertEquals(0100000000000L, e.getSize());
126 tin.close();
127
128
129 closeQuietly(tos);
130 }
131
132 public void testWriteSimplePaxHeaders() throws Exception {
133 Map<String, String> m = new HashMap<String, String>();
134 m.put("a", "b");
135 byte[] data = writePaxHeader(m);
136 assertEquals("00000000006 ",
137 new String(data, TarConstants.NAMELEN
138 + TarConstants.MODELEN
139 + TarConstants.UIDLEN
140 + TarConstants.GIDLEN, 12,
141 CharsetNames.UTF_8));
142 assertEquals("6 a=b\n", new String(data, 512, 6, CharsetNames.UTF_8));
143 }
144
145 public void testPaxHeadersWithLength99() throws Exception {
146 Map<String, String> m = new HashMap<String, String>();
147 m.put("a",
148 "0123456789012345678901234567890123456789"
149 + "01234567890123456789012345678901234567890123456789"
150 + "012");
151 byte[] data = writePaxHeader(m);
152 assertEquals("00000000143 ",
153 new String(data, TarConstants.NAMELEN
154 + TarConstants.MODELEN
155 + TarConstants.UIDLEN
156 + TarConstants.GIDLEN, 12,
157 CharsetNames.UTF_8));
158 assertEquals("99 a=0123456789012345678901234567890123456789"
159 + "01234567890123456789012345678901234567890123456789"
160 + "012\n", new String(data, 512, 99, CharsetNames.UTF_8));
161 }
162
163 public void testPaxHeadersWithLength101() throws Exception {
164 Map<String, String> m = new HashMap<String, String>();
165 m.put("a",
166 "0123456789012345678901234567890123456789"
167 + "01234567890123456789012345678901234567890123456789"
168 + "0123");
169 byte[] data = writePaxHeader(m);
170 assertEquals("00000000145 ",
171 new String(data, TarConstants.NAMELEN
172 + TarConstants.MODELEN
173 + TarConstants.UIDLEN
174 + TarConstants.GIDLEN, 12,
175 CharsetNames.UTF_8));
176 assertEquals("101 a=0123456789012345678901234567890123456789"
177 + "01234567890123456789012345678901234567890123456789"
178 + "0123\n", new String(data, 512, 101, CharsetNames.UTF_8));
179 }
180
181 private byte[] writePaxHeader(Map<String, String> m) throws Exception {
182 ByteArrayOutputStream bos = new ByteArrayOutputStream();
183 TarArchiveOutputStream tos = new TarArchiveOutputStream(bos, "ASCII");
184 tos.writePaxHeaders("foo", m);
185
186
187 TarArchiveEntry t = new TarArchiveEntry("foo");
188 t.setSize(10 * 1024);
189 tos.putArchiveEntry(t);
190 tos.write(new byte[10 * 1024]);
191 tos.closeArchiveEntry();
192 tos.close();
193
194 return bos.toByteArray();
195 }
196
197 public void testWriteLongFileNamePosixMode() throws Exception {
198 String n = "01234567890123456789012345678901234567890123456789"
199 + "01234567890123456789012345678901234567890123456789"
200 + "01234567890123456789012345678901234567890123456789";
201 TarArchiveEntry t =
202 new TarArchiveEntry(n);
203 t.setSize(10 * 1024);
204 ByteArrayOutputStream bos = new ByteArrayOutputStream();
205 TarArchiveOutputStream tos = new TarArchiveOutputStream(bos, "ASCII");
206 tos.setLongFileMode(TarArchiveOutputStream.LONGFILE_POSIX);
207 tos.putArchiveEntry(t);
208 tos.write(new byte[10 * 1024]);
209 tos.closeArchiveEntry();
210 byte[] data = bos.toByteArray();
211 assertEquals("160 path=" + n + "\n",
212 new String(data, 512, 160, CharsetNames.UTF_8));
213 TarArchiveInputStream tin =
214 new TarArchiveInputStream(new ByteArrayInputStream(data));
215 TarArchiveEntry e = tin.getNextTarEntry();
216 assertEquals(n, e.getName());
217 tin.close();
218 tos.close();
219 }
220
221 public void testOldEntryStarMode() throws Exception {
222 TarArchiveEntry t = new TarArchiveEntry("foo");
223 t.setSize(Integer.MAX_VALUE);
224 t.setModTime(-1000);
225 ByteArrayOutputStream bos = new ByteArrayOutputStream();
226 TarArchiveOutputStream tos = new TarArchiveOutputStream(bos);
227 tos.setBigNumberMode(TarArchiveOutputStream.BIGNUMBER_STAR);
228 tos.putArchiveEntry(t);
229
230 tos.write(new byte[10 * 1024]);
231 byte[] data = bos.toByteArray();
232 assertEquals((byte) 0xff,
233 data[TarConstants.NAMELEN
234 + TarConstants.MODELEN
235 + TarConstants.UIDLEN
236 + TarConstants.GIDLEN
237 + TarConstants.SIZELEN]);
238 TarArchiveInputStream tin =
239 new TarArchiveInputStream(new ByteArrayInputStream(data));
240 TarArchiveEntry e = tin.getNextTarEntry();
241 Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
242 cal.set(1969, 11, 31, 23, 59, 59);
243 cal.set(Calendar.MILLISECOND, 0);
244 assertEquals(cal.getTime(), e.getLastModifiedDate());
245 tin.close();
246
247
248 closeQuietly(tos);
249 }
250
251 public void testOldEntryPosixMode() throws Exception {
252 TarArchiveEntry t = new TarArchiveEntry("foo");
253 t.setSize(Integer.MAX_VALUE);
254 t.setModTime(-1000);
255 ByteArrayOutputStream bos = new ByteArrayOutputStream();
256 TarArchiveOutputStream tos = new TarArchiveOutputStream(bos);
257 tos.setBigNumberMode(TarArchiveOutputStream.BIGNUMBER_POSIX);
258 tos.putArchiveEntry(t);
259
260 tos.write(new byte[10 * 1024]);
261 byte[] data = bos.toByteArray();
262 assertEquals("00000000000 ",
263 new String(data,
264 1024 + TarConstants.NAMELEN
265 + TarConstants.MODELEN
266 + TarConstants.UIDLEN
267 + TarConstants.GIDLEN
268 + TarConstants.SIZELEN, 12,
269 CharsetNames.UTF_8));
270 TarArchiveInputStream tin =
271 new TarArchiveInputStream(new ByteArrayInputStream(data));
272 TarArchiveEntry e = tin.getNextTarEntry();
273 Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
274 cal.set(1969, 11, 31, 23, 59, 59);
275 cal.set(Calendar.MILLISECOND, 0);
276 assertEquals(cal.getTime(), e.getLastModifiedDate());
277 tin.close();
278
279
280 closeQuietly(tos);
281 }
282
283 public void testOldEntryError() throws Exception {
284 TarArchiveEntry t = new TarArchiveEntry("foo");
285 t.setSize(Integer.MAX_VALUE);
286 t.setModTime(-1000);
287 TarArchiveOutputStream tos =
288 new TarArchiveOutputStream(new ByteArrayOutputStream());
289 try {
290 tos.putArchiveEntry(t);
291 fail("Should have generated RuntimeException");
292 } catch (RuntimeException expected) {
293 }
294 tos.close();
295 }
296
297 public void testWriteNonAsciiPathNamePaxHeader() throws Exception {
298 String n = "\u00e4";
299 TarArchiveEntry t = new TarArchiveEntry(n);
300 t.setSize(10 * 1024);
301 ByteArrayOutputStream bos = new ByteArrayOutputStream();
302 TarArchiveOutputStream tos = new TarArchiveOutputStream(bos);
303 tos.setAddPaxHeadersForNonAsciiNames(true);
304 tos.putArchiveEntry(t);
305 tos.write(new byte[10 * 1024]);
306 tos.closeArchiveEntry();
307 tos.close();
308 byte[] data = bos.toByteArray();
309 assertEquals("11 path=" + n + "\n",
310 new String(data, 512, 11, CharsetNames.UTF_8));
311 TarArchiveInputStream tin =
312 new TarArchiveInputStream(new ByteArrayInputStream(data));
313 TarArchiveEntry e = tin.getNextTarEntry();
314 assertEquals(n, e.getName());
315 tin.close();
316 }
317
318 public void testWriteNonAsciiLinkPathNamePaxHeader() throws Exception {
319 String n = "\u00e4";
320 TarArchiveEntry t = new TarArchiveEntry("a", TarConstants.LF_LINK);
321 t.setSize(10 * 1024);
322 t.setLinkName(n);
323 ByteArrayOutputStream bos = new ByteArrayOutputStream();
324 TarArchiveOutputStream tos = new TarArchiveOutputStream(bos);
325 tos.setAddPaxHeadersForNonAsciiNames(true);
326 tos.putArchiveEntry(t);
327 tos.write(new byte[10 * 1024]);
328 tos.closeArchiveEntry();
329 tos.close();
330 byte[] data = bos.toByteArray();
331 assertEquals("15 linkpath=" + n + "\n",
332 new String(data, 512, 15, CharsetNames.UTF_8));
333 TarArchiveInputStream tin =
334 new TarArchiveInputStream(new ByteArrayInputStream(data));
335 TarArchiveEntry e = tin.getNextTarEntry();
336 assertEquals(n, e.getLinkName());
337 tin.close();
338 }
339
340
341
342
343 public void testRoundtripWith67CharFileNameGnu() throws Exception {
344 testRoundtripWith67CharFileName(TarArchiveOutputStream.LONGFILE_GNU);
345 }
346
347
348
349
350 public void testRoundtripWith67CharFileNamePosix() throws Exception {
351 testRoundtripWith67CharFileName(TarArchiveOutputStream.LONGFILE_POSIX);
352 }
353
354 private void testRoundtripWith67CharFileName(int mode) throws Exception {
355 String n = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
356 + "AAAAAAA";
357 assertEquals(67, n.length());
358 TarArchiveEntry t = new TarArchiveEntry(n);
359 t.setSize(10 * 1024);
360 ByteArrayOutputStream bos = new ByteArrayOutputStream();
361 TarArchiveOutputStream tos = new TarArchiveOutputStream(bos, "ASCII");
362 tos.setLongFileMode(mode);
363 tos.putArchiveEntry(t);
364 tos.write(new byte[10 * 1024]);
365 tos.closeArchiveEntry();
366 tos.close();
367 byte[] data = bos.toByteArray();
368 TarArchiveInputStream tin =
369 new TarArchiveInputStream(new ByteArrayInputStream(data));
370 TarArchiveEntry e = tin.getNextTarEntry();
371 assertEquals(n, e.getName());
372 tin.close();
373 }
374
375
376
377
378 public void testWriteLongDirectoryNameGnuMode() throws Exception {
379 testWriteLongDirectoryName(TarArchiveOutputStream.LONGFILE_GNU);
380 }
381
382
383
384
385 public void testWriteLongDirectoryNamePosixMode() throws Exception {
386 testWriteLongDirectoryName(TarArchiveOutputStream.LONGFILE_POSIX);
387 }
388
389 private void testWriteLongDirectoryName(int mode) throws Exception {
390 String n = "01234567890123456789012345678901234567890123456789"
391 + "01234567890123456789012345678901234567890123456789"
392 + "01234567890123456789012345678901234567890123456789/";
393 TarArchiveEntry t = new TarArchiveEntry(n);
394 ByteArrayOutputStream bos = new ByteArrayOutputStream();
395 TarArchiveOutputStream tos = new TarArchiveOutputStream(bos, "ASCII");
396 tos.setLongFileMode(mode);
397 tos.putArchiveEntry(t);
398 tos.closeArchiveEntry();
399 tos.close();
400 byte[] data = bos.toByteArray();
401 TarArchiveInputStream tin =
402 new TarArchiveInputStream(new ByteArrayInputStream(data));
403 TarArchiveEntry e = tin.getNextTarEntry();
404 assertEquals(n, e.getName());
405 assertTrue(e.isDirectory());
406 tin.close();
407 }
408
409
410
411
412 public void testWriteNonAsciiDirectoryNamePosixMode() throws Exception {
413 String n = "f\u00f6\u00f6/";
414 TarArchiveEntry t = new TarArchiveEntry(n);
415 ByteArrayOutputStream bos = new ByteArrayOutputStream();
416 TarArchiveOutputStream tos = new TarArchiveOutputStream(bos);
417 tos.setAddPaxHeadersForNonAsciiNames(true);
418 tos.putArchiveEntry(t);
419 tos.closeArchiveEntry();
420 tos.close();
421 byte[] data = bos.toByteArray();
422 TarArchiveInputStream tin =
423 new TarArchiveInputStream(new ByteArrayInputStream(data));
424 TarArchiveEntry e = tin.getNextTarEntry();
425 assertEquals(n, e.getName());
426 assertTrue(e.isDirectory());
427 tin.close();
428 }
429
430 }