View Javadoc
1   /*
2    *  Licensed to the Apache Software Foundation (ASF) under one or more
3    *  contributor license agreements.  See the NOTICE file distributed with
4    *  this work for additional information regarding copyright ownership.
5    *  The ASF licenses this file to You under the Apache License, Version 2.0
6    *  (the "License"); you may not use this file except in compliance with
7    *  the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   *  Unless required by applicable law or agreed to in writing, software
12   *  distributed under the License is distributed on an "AS IS" BASIS,
13   *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   *  See the License for the specific language governing permissions and
15   *  limitations under the License.
16   *
17   */
18  
19  package org.apache.commons.compress.archivers.tar;
20  
21  import static org.apache.commons.compress.AbstractTestCase.getFile;
22  import static org.junit.Assert.assertArrayEquals;
23  import static org.junit.Assert.assertEquals;
24  import static org.junit.Assert.assertTrue;
25  import static org.junit.Assert.fail;
26  
27  import java.io.ByteArrayInputStream;
28  import java.io.ByteArrayOutputStream;
29  import java.io.FileInputStream;
30  import java.io.IOException;
31  import java.io.InputStream;
32  import java.util.Calendar;
33  import java.util.Date;
34  import java.util.Map;
35  import java.util.TimeZone;
36  import java.util.zip.GZIPInputStream;
37  
38  import org.apache.commons.compress.utils.CharsetNames;
39  import org.junit.Test;
40  
41  public class TarArchiveInputStreamTest {
42  
43      @Test
44      public void readSimplePaxHeader() throws Exception {
45          final InputStream is = new ByteArrayInputStream(new byte[1]);
46          final TarArchiveInputStream tais = new TarArchiveInputStream(is);
47          Map<String, String> headers = tais
48              .parsePaxHeaders(new ByteArrayInputStream("30 atime=1321711775.972059463\n"
49                                                        .getBytes(CharsetNames.UTF_8)));
50          assertEquals(1, headers.size());
51          assertEquals("1321711775.972059463", headers.get("atime"));
52          tais.close();
53      }
54  
55      @Test
56      public void readPaxHeaderWithEmbeddedNewline() throws Exception {
57          final InputStream is = new ByteArrayInputStream(new byte[1]);
58          final TarArchiveInputStream tais = new TarArchiveInputStream(is);
59          Map<String, String> headers = tais
60              .parsePaxHeaders(new ByteArrayInputStream("28 comment=line1\nline2\nand3\n"
61                                                        .getBytes(CharsetNames.UTF_8)));
62          assertEquals(1, headers.size());
63          assertEquals("line1\nline2\nand3", headers.get("comment"));
64          tais.close();
65      }
66  
67      @Test
68      public void readNonAsciiPaxHeader() throws Exception {
69          String ae = "\u00e4";
70          String line = "11 path="+ ae + "\n";
71          assertEquals(11, line.getBytes(CharsetNames.UTF_8).length);
72          final InputStream is = new ByteArrayInputStream(new byte[1]);
73          final TarArchiveInputStream tais = new TarArchiveInputStream(is);
74          Map<String, String> headers = tais
75              .parsePaxHeaders(new ByteArrayInputStream(line.getBytes(CharsetNames.UTF_8)));
76          assertEquals(1, headers.size());
77          assertEquals(ae, headers.get("path"));
78          tais.close();
79      }
80  
81      @Test
82      public void workaroundForBrokenTimeHeader() throws Exception {
83          TarArchiveInputStream in = null;
84          try {
85              in = new TarArchiveInputStream(new FileInputStream(getFile("simple-aix-native-tar.tar")));
86              TarArchiveEntry tae = in.getNextTarEntry();
87              tae = in.getNextTarEntry();
88              assertEquals("sample/link-to-txt-file.lnk", tae.getName());
89              assertEquals(new Date(0), tae.getLastModifiedDate());
90              assertTrue(tae.isSymbolicLink());
91              assertTrue(tae.isCheckSumOK());
92          } finally {
93              if (in != null) {
94                  in.close();
95              }
96          }
97      }
98  
99      @Test
100     public void datePriorToEpochInGNUFormat() throws Exception {
101         datePriorToEpoch("preepoch-star.tar");
102     }
103 
104 
105     @Test
106     public void datePriorToEpochInPAXFormat() throws Exception {
107         datePriorToEpoch("preepoch-posix.tar");
108     }
109 
110     private void datePriorToEpoch(String archive) throws Exception {
111         TarArchiveInputStream in = null;
112         try {
113             in = new TarArchiveInputStream(new FileInputStream(getFile(archive)));
114             TarArchiveEntry tae = in.getNextTarEntry();
115             assertEquals("foo", tae.getName());
116             Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
117             cal.set(1969, 11, 31, 23, 59, 59);
118             cal.set(Calendar.MILLISECOND, 0);
119             assertEquals(cal.getTime(), tae.getLastModifiedDate());
120             assertTrue(tae.isCheckSumOK());
121         } finally {
122             if (in != null) {
123                 in.close();
124             }
125         }
126     }
127 
128     @Test
129     public void testCompress197() throws Exception {
130         TarArchiveInputStream tar = getTestStream("/COMPRESS-197.tar");
131         try {
132             TarArchiveEntry entry = tar.getNextTarEntry();
133             while (entry != null) {
134                 entry = tar.getNextTarEntry();
135             }
136         } catch (IOException e) {
137             fail("COMPRESS-197: " + e.getMessage());
138         } finally {
139             tar.close();
140         }
141     }
142 
143     @Test
144     public void shouldUseSpecifiedEncodingWhenReadingGNULongNames()
145         throws Exception {
146         ByteArrayOutputStream bos = new ByteArrayOutputStream();
147         String encoding = CharsetNames.UTF_16;
148         String name = "1234567890123456789012345678901234567890123456789"
149             + "01234567890123456789012345678901234567890123456789"
150             + "01234567890\u00e4";
151         TarArchiveOutputStream tos =
152             new TarArchiveOutputStream(bos, encoding);
153         tos.setLongFileMode(TarArchiveOutputStream.LONGFILE_GNU);
154         TarArchiveEntry t = new TarArchiveEntry(name);
155         t.setSize(1);
156         tos.putArchiveEntry(t);
157         tos.write(30);
158         tos.closeArchiveEntry();
159         tos.close();
160         byte[] data = bos.toByteArray();
161         ByteArrayInputStream bis = new ByteArrayInputStream(data);
162         TarArchiveInputStream tis =
163             new TarArchiveInputStream(bis, encoding);
164         t = tis.getNextTarEntry();
165         assertEquals(name, t.getName());
166         tis.close();
167     }
168 
169     @Test
170     public void shouldConsumeArchiveCompletely() throws Exception {
171         InputStream is = TarArchiveInputStreamTest.class
172             .getResourceAsStream("/archive_with_trailer.tar");
173         TarArchiveInputStream tar = new TarArchiveInputStream(is);
174         while (tar.getNextTarEntry() != null) {
175             // just consume the archive
176         }
177         byte[] expected = new byte[] {
178             'H', 'e', 'l', 'l', 'o', ',', ' ', 'w', 'o', 'r', 'l', 'd', '!', '\n'
179         };
180         byte[] actual = new byte[expected.length];
181         is.read(actual);
182         assertArrayEquals(expected, actual);
183         tar.close();
184     }
185 
186     @Test
187     public void readsArchiveCompletely_COMPRESS245() throws Exception {
188         InputStream is = TarArchiveInputStreamTest.class
189             .getResourceAsStream("/COMPRESS-245.tar.gz");
190         try {
191             InputStream gin = new GZIPInputStream(is);
192             TarArchiveInputStream tar = new TarArchiveInputStream(gin);
193             int count = 0;
194             TarArchiveEntry entry = tar.getNextTarEntry();
195             while (entry != null) {
196                 count++;
197                 entry = tar.getNextTarEntry();
198             }
199             assertEquals(31, count);
200         } catch (IOException e) {
201             fail("COMPRESS-245: " + e.getMessage());
202         } finally {
203             is.close();
204         }
205     }
206 
207 
208     private TarArchiveInputStream getTestStream(String name) {
209         return new TarArchiveInputStream(
210                 TarArchiveInputStreamTest.class.getResourceAsStream(name));
211     }
212 
213 }