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.InputStream;
31  import java.io.IOException;
32  import java.util.Calendar;
33  import java.util.Date;
34  import java.util.Map;
35  import java.util.TimeZone;
36  
37  import org.apache.commons.compress.utils.CharsetNames;
38  import org.junit.Test;
39  
40  public class TarArchiveInputStreamTest {
41  
42      @Test
43      public void readSimplePaxHeader() throws Exception {
44          final TarArchiveInputStream tais = new TarArchiveInputStream(null);
45          Map<String, String> headers = tais
46              .parsePaxHeaders(new ByteArrayInputStream("30 atime=1321711775.972059463\n"
47                                                        .getBytes(CharsetNames.UTF_8)));
48          assertEquals(1, headers.size());
49          assertEquals("1321711775.972059463", headers.get("atime"));
50          tais.close();
51      }
52  
53      @Test
54      public void readPaxHeaderWithEmbeddedNewline() throws Exception {
55          final TarArchiveInputStream tais = new TarArchiveInputStream(null);
56          Map<String, String> headers = tais
57              .parsePaxHeaders(new ByteArrayInputStream("28 comment=line1\nline2\nand3\n"
58                                                        .getBytes(CharsetNames.UTF_8)));
59          assertEquals(1, headers.size());
60          assertEquals("line1\nline2\nand3", headers.get("comment"));
61          tais.close();
62      }
63  
64      @Test
65      public void readNonAsciiPaxHeader() throws Exception {
66          String ae = "\u00e4";
67          String line = "11 path="+ ae + "\n";
68          assertEquals(11, line.getBytes(CharsetNames.UTF_8).length);
69          final TarArchiveInputStream tais = new TarArchiveInputStream(null);
70          Map<String, String> headers = tais
71              .parsePaxHeaders(new ByteArrayInputStream(line.getBytes(CharsetNames.UTF_8)));
72          assertEquals(1, headers.size());
73          assertEquals(ae, headers.get("path"));
74          tais.close();
75      }
76  
77      @Test
78      public void workaroundForBrokenTimeHeader() throws Exception {
79          TarArchiveInputStream in = null;
80          try {
81              in = new TarArchiveInputStream(new FileInputStream(getFile("simple-aix-native-tar.tar")));
82              TarArchiveEntry tae = in.getNextTarEntry();
83              tae = in.getNextTarEntry();
84              assertEquals("sample/link-to-txt-file.lnk", tae.getName());
85              assertEquals(new Date(0), tae.getLastModifiedDate());
86              assertTrue(tae.isSymbolicLink());
87              assertTrue(tae.isCheckSumOK());
88          } finally {
89              if (in != null) {
90                  in.close();
91              }
92          }
93      }
94  
95      @Test
96      public void datePriorToEpochInGNUFormat() throws Exception {
97          datePriorToEpoch("preepoch-star.tar");
98      }
99  
100 
101     @Test
102     public void datePriorToEpochInPAXFormat() throws Exception {
103         datePriorToEpoch("preepoch-posix.tar");
104     }
105 
106     private void datePriorToEpoch(String archive) throws Exception {
107         TarArchiveInputStream in = null;
108         try {
109             in = new TarArchiveInputStream(new FileInputStream(getFile(archive)));
110             TarArchiveEntry tae = in.getNextTarEntry();
111             assertEquals("foo", tae.getName());
112             Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
113             cal.set(1969, 11, 31, 23, 59, 59);
114             cal.set(Calendar.MILLISECOND, 0);
115             assertEquals(cal.getTime(), tae.getLastModifiedDate());
116             assertTrue(tae.isCheckSumOK());
117         } finally {
118             if (in != null) {
119                 in.close();
120             }
121         }
122     }
123 
124     @Test
125     public void testCompress197() throws Exception {
126         TarArchiveInputStream tar = getTestStream("/COMPRESS-197.tar");
127         try {
128             TarArchiveEntry entry = tar.getNextTarEntry();
129             while (entry != null) {
130                 entry = tar.getNextTarEntry();
131             }
132         } catch (IOException e) {
133             fail("COMPRESS-197: " + e.getMessage());
134         } finally {
135             tar.close();
136         }
137     }
138 
139     @Test
140     public void shouldUseSpecifiedEncodingWhenReadingGNULongNames()
141         throws Exception {
142         ByteArrayOutputStream bos = new ByteArrayOutputStream();
143         String encoding = CharsetNames.UTF_16;
144         String name = "1234567890123456789012345678901234567890123456789"
145             + "01234567890123456789012345678901234567890123456789"
146             + "01234567890\u00e4";
147         TarArchiveOutputStream tos =
148             new TarArchiveOutputStream(bos, encoding);
149         tos.setLongFileMode(TarArchiveOutputStream.LONGFILE_GNU);
150         TarArchiveEntry t = new TarArchiveEntry(name);
151         t.setSize(1);
152         tos.putArchiveEntry(t);
153         tos.write(30);
154         tos.closeArchiveEntry();
155         tos.close();
156         byte[] data = bos.toByteArray();
157         ByteArrayInputStream bis = new ByteArrayInputStream(data);
158         TarArchiveInputStream tis =
159             new TarArchiveInputStream(bis, encoding);
160         t = tis.getNextTarEntry();
161         assertEquals(name, t.getName());
162         tis.close();
163     }
164 
165     @Test
166     public void shouldConsumeArchiveCompletely() throws Exception {
167         InputStream is = TarArchiveInputStreamTest.class
168             .getResourceAsStream("/archive_with_trailer.tar");
169         TarArchiveInputStream tar = new TarArchiveInputStream(is);
170         while (tar.getNextTarEntry() != null) {
171             // just consume the archive
172         }
173         byte[] expected = new byte[] {
174             'H', 'e', 'l', 'l', 'o', ',', ' ', 'w', 'o', 'r', 'l', 'd', '!', '\n'
175         };
176         byte[] actual = new byte[expected.length];
177         is.read(actual);
178         assertArrayEquals(expected, actual);
179         tar.close();
180     }
181 
182     private TarArchiveInputStream getTestStream(String name) {
183         return new TarArchiveInputStream(
184                 TarArchiveInputStreamTest.class.getResourceAsStream(name));
185     }
186 
187 }