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 junit.framework.TestCase;
22  
23  import org.apache.commons.compress.archivers.zip.ZipEncoding;
24  import org.apache.commons.compress.archivers.zip.ZipEncodingHelper;
25  import org.apache.commons.compress.utils.CharsetNames;
26  
27  public class TarUtilsTest extends TestCase {
28  
29  
30      public void testName(){
31          byte [] buff = new byte[20];
32          String sb1 = "abcdefghijklmnopqrstuvwxyz";
33          int off = TarUtils.formatNameBytes(sb1, buff, 1, buff.length-1);
34          assertEquals(off, 20);
35          String sb2 = TarUtils.parseName(buff, 1, 10);
36          assertEquals(sb2,sb1.substring(0,10));
37          sb2 = TarUtils.parseName(buff, 1, 19);
38          assertEquals(sb2,sb1.substring(0,19));
39          buff = new byte[30];
40          off = TarUtils.formatNameBytes(sb1, buff, 1, buff.length-1);
41          assertEquals(off, 30);
42          sb2 = TarUtils.parseName(buff, 1, buff.length-1);
43          assertEquals(sb1, sb2);
44      }
45  
46      public void testParseOctal() throws Exception{
47          long value; 
48          byte [] buffer;
49          final long MAX_OCTAL  = 077777777777L; // Allowed 11 digits
50          final String maxOctal = "77777777777 "; // Maximum valid octal
51          buffer = maxOctal.getBytes(CharsetNames.UTF_8);
52          value = TarUtils.parseOctal(buffer,0, buffer.length);
53          assertEquals(MAX_OCTAL, value);
54          buffer[buffer.length-1]=0;
55          value = TarUtils.parseOctal(buffer,0, buffer.length);
56          assertEquals(MAX_OCTAL, value);
57          buffer=new byte[]{0,0};
58          value = TarUtils.parseOctal(buffer,0, buffer.length);
59          assertEquals(0, value);
60          buffer=new byte[]{0,' '};
61          value = TarUtils.parseOctal(buffer,0, buffer.length);
62          assertEquals(0, value);
63      }
64  
65      public void testParseOctalInvalid() throws Exception{
66          byte [] buffer;
67          buffer=new byte[0]; // empty byte array
68          try {
69              TarUtils.parseOctal(buffer,0, buffer.length);
70              fail("Expected IllegalArgumentException - should be at least 2 bytes long");
71          } catch (IllegalArgumentException expected) {
72          }
73          buffer=new byte[]{0}; // 1-byte array
74          try {
75              TarUtils.parseOctal(buffer,0, buffer.length);
76              fail("Expected IllegalArgumentException - should be at least 2 bytes long");
77          } catch (IllegalArgumentException expected) {
78          }
79          buffer=new byte[]{' ',0,0,0}; // not all NULs
80          try {
81              TarUtils.parseOctal(buffer,0, buffer.length);
82              fail("Expected IllegalArgumentException - not all NULs");
83          } catch (IllegalArgumentException expected) {
84          }
85          buffer = "abcdef ".getBytes(CharsetNames.UTF_8); // Invalid input
86          try {
87              TarUtils.parseOctal(buffer,0, buffer.length);
88              fail("Expected IllegalArgumentException");
89          } catch (IllegalArgumentException expected) {
90          }
91          buffer = "77777777777".getBytes(CharsetNames.UTF_8); // Invalid input - no trailer
92          try {
93              TarUtils.parseOctal(buffer,0, buffer.length);
94              fail("Expected IllegalArgumentException - no trailer");
95          } catch (IllegalArgumentException expected) {
96          }
97          buffer = " 0 07 ".getBytes(CharsetNames.UTF_8); // Invalid - embedded space
98          try {
99              TarUtils.parseOctal(buffer,0, buffer.length);
100             fail("Expected IllegalArgumentException - embedded space");
101         } catch (IllegalArgumentException expected) {
102         }
103         buffer = " 0\00007 ".getBytes(CharsetNames.UTF_8); // Invalid - embedded NUL
104         try {
105             TarUtils.parseOctal(buffer,0, buffer.length);
106             fail("Expected IllegalArgumentException - embedded NUL");
107         } catch (IllegalArgumentException expected) {
108         }
109     }
110 
111     private void checkRoundTripOctal(final long value, final int bufsize) {
112         byte [] buffer = new byte[bufsize];
113         long parseValue;
114         TarUtils.formatLongOctalBytes(value, buffer, 0, buffer.length);
115         parseValue = TarUtils.parseOctal(buffer,0, buffer.length);
116         assertEquals(value,parseValue);
117     }
118 
119     private void checkRoundTripOctal(final long value) {
120         checkRoundTripOctal(value, TarConstants.SIZELEN);
121     }
122 
123     public void testRoundTripOctal() {
124         checkRoundTripOctal(0);
125         checkRoundTripOctal(1);
126 //        checkRoundTripOctal(-1); // TODO What should this do?
127         checkRoundTripOctal(TarConstants.MAXSIZE);
128 //        checkRoundTripOctal(0100000000000L); // TODO What should this do?
129 
130         checkRoundTripOctal(0, TarConstants.UIDLEN);
131         checkRoundTripOctal(1, TarConstants.UIDLEN);
132         checkRoundTripOctal(TarConstants.MAXID, 8);
133     }
134 
135     private void checkRoundTripOctalOrBinary(final long value, final int bufsize) {
136         byte [] buffer = new byte[bufsize];
137         long parseValue;
138         TarUtils.formatLongOctalOrBinaryBytes(value, buffer, 0, buffer.length);
139         parseValue = TarUtils.parseOctalOrBinary(buffer,0, buffer.length);
140         assertEquals(value,parseValue);
141     }
142 
143     public void testRoundTripOctalOrBinary8() {
144         testRoundTripOctalOrBinary(8);
145     }
146 
147     public void testRoundTripOctalOrBinary12() {
148         testRoundTripOctalOrBinary(12);
149         checkRoundTripOctalOrBinary(Long.MAX_VALUE, 12);
150         checkRoundTripOctalOrBinary(Long.MIN_VALUE + 1, 12);
151     }
152 
153     private void testRoundTripOctalOrBinary(int length) {
154         checkRoundTripOctalOrBinary(0, length);
155         checkRoundTripOctalOrBinary(1, length);
156         checkRoundTripOctalOrBinary(TarConstants.MAXSIZE, length); // will need binary format
157         checkRoundTripOctalOrBinary(-1, length); // will need binary format
158         checkRoundTripOctalOrBinary(0xff00000000000001l, length);
159     }
160 
161     // Check correct trailing bytes are generated
162     public void testTrailers() {
163         byte [] buffer = new byte[12];
164         TarUtils.formatLongOctalBytes(123, buffer, 0, buffer.length);
165         assertEquals(' ', buffer[buffer.length-1]);
166         assertEquals('3', buffer[buffer.length-2]); // end of number
167         TarUtils.formatOctalBytes(123, buffer, 0, buffer.length);
168         assertEquals(0  , buffer[buffer.length-1]);
169         assertEquals(' ', buffer[buffer.length-2]);
170         assertEquals('3', buffer[buffer.length-3]); // end of number
171         TarUtils.formatCheckSumOctalBytes(123, buffer, 0, buffer.length);
172         assertEquals(' ', buffer[buffer.length-1]);
173         assertEquals(0  , buffer[buffer.length-2]);
174         assertEquals('3', buffer[buffer.length-3]); // end of number
175     }
176 
177     public void testNegative() throws Exception {
178         byte [] buffer = new byte[22];
179         TarUtils.formatUnsignedOctalString(-1, buffer, 0, buffer.length);
180         assertEquals("1777777777777777777777", new String(buffer, CharsetNames.UTF_8));
181     }
182 
183     public void testOverflow() throws Exception {
184         byte [] buffer = new byte[8-1]; // a lot of the numbers have 8-byte buffers (nul term)
185         TarUtils.formatUnsignedOctalString(07777777L, buffer, 0, buffer.length);
186         assertEquals("7777777", new String(buffer, CharsetNames.UTF_8));
187         try {
188             TarUtils.formatUnsignedOctalString(017777777L, buffer, 0, buffer.length);
189             fail("Should have cause IllegalArgumentException");
190         } catch (IllegalArgumentException expected) {
191         }
192     }
193 
194     public void testRoundTripNames(){
195         checkName("");
196         checkName("The quick brown fox\n");
197         checkName("\177");
198         // checkName("\0"); // does not work, because NUL is ignored
199     }
200 
201     public void testRoundEncoding() throws Exception {
202         // COMPRESS-114
203         ZipEncoding enc = ZipEncodingHelper.getZipEncoding(CharsetNames.ISO_8859_1);
204         String s = "0302-0601-3\u00b1\u00b1\u00b1F06\u00b1W220\u00b1ZB\u00b1LALALA\u00b1\u00b1\u00b1\u00b1\u00b1\u00b1\u00b1\u00b1\u00b1\u00b1CAN\u00b1\u00b1DC\u00b1\u00b1\u00b104\u00b1060302\u00b1MOE.model";
205         byte buff[] = new byte[100];
206         int len = TarUtils.formatNameBytes(s, buff, 0, buff.length, enc);
207         assertEquals(s, TarUtils.parseName(buff, 0, len, enc));
208     }
209 
210     private void checkName(String string) {
211         byte buff[] = new byte[100];
212         int len = TarUtils.formatNameBytes(string, buff, 0, buff.length);
213         assertEquals(string, TarUtils.parseName(buff, 0, len));
214     }
215 
216     public void testReadNegativeBinary8Byte() {
217         byte[] b = new byte[] {
218             (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
219             (byte) 0xff, (byte) 0xff, (byte) 0xf1, (byte) 0xef,
220         };
221         assertEquals(-3601l, TarUtils.parseOctalOrBinary(b, 0, 8));
222     }
223 
224     public void testReadNegativeBinary12Byte() {
225         byte[] b = new byte[] {
226             (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
227             (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
228             (byte) 0xff, (byte) 0xff, (byte) 0xf1, (byte) 0xef,
229         };
230         assertEquals(-3601l, TarUtils.parseOctalOrBinary(b, 0, 12));
231     }
232 
233 
234     public void testWriteNegativeBinary8Byte() {
235         byte[] b = new byte[] {
236             (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
237             (byte) 0xff, (byte) 0xff, (byte) 0xf1, (byte) 0xef,
238         };
239         assertEquals(-3601l, TarUtils.parseOctalOrBinary(b, 0, 8));
240     }
241 
242     // https://issues.apache.org/jira/browse/COMPRESS-191
243     public void testVerifyHeaderCheckSum() {
244         byte[] valid = { // from bla.tar
245                 116, 101, 115, 116, 49, 46, 120, 109, 108, 0, 0, 0, 0, 0, 0,
246                 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
247                 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
248                 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
249                 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
250                 0, 48, 48, 48, 48, 54, 52, 52, 0, 48, 48, 48, 48, 55, 54, 53,
251                 0, 48, 48, 48, 48, 55, 54, 53, 0, 48, 48, 48, 48, 48, 48, 48,
252                 49, 49, 52, 50, 0, 49, 48, 55, 49, 54, 53, 52, 53, 54, 50, 54,
253                 0, 48, 49, 50, 50, 54, 48, 0, 32, 48, 0, 0, 0, 0, 0, 0, 0, 0,
254                 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
255                 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
256                 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
257                 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
258                 0, 0, 0, 0, 0, 0, 0, 0, 117, 115, 116, 97, 114, 32, 32, 0,
259                 116, 99, 117, 114, 100, 116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
260                 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 116, 99, 117,
261                 114, 100, 116, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
262                 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
263                 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
264                 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
265                 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
266                 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
267                 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
268                 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
269                 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
270                 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
271                 0, 0, 0, 0 };
272         assertTrue(TarUtils.verifyCheckSum(valid));
273 
274         byte[] compress117 = { // from COMPRESS-117
275                 116, 101, 115, 116, 49, 46, 120, 109, 108, 0, 0, 0, 0, 0, 0,
276                 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
277                 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
278                 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
279                 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
280                 0, 48, 48, 48, 48, 54, 52, 52, 0, 48, 48, 48, 48, 55, 54, 53,
281                 0, 48, 48, 48, 48, 55, 54, 53, 0, 48, 48, 48, 48, 48, 48, 48,
282                 49, 49, 52, 50, 0, 49, 48, 55, 49, 54, 53, 52, 53, 54, 50, 54,
283                 0, 48, 49, 50, 50, 54, 48, 0, 32, 48, 0, 0, 0, 0, 0, 0, 0, 0,
284                 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
285                 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
286                 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
287                 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
288                 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
289                 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
290                 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
291                 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
292                 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
293                 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
294                 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
295                 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
296                 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
297                 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
298                 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
299                 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
300                 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
301         assertTrue(TarUtils.verifyCheckSum(compress117));
302 
303         byte[] invalid = { // from the testAIFF.aif file in Tika
304                 70, 79, 82, 77, 0, 0, 15, 46, 65, 73, 70, 70, 67, 79, 77, 77,
305                 0, 0, 0, 18, 0, 2, 0, 0, 3, -64, 0, 16, 64, 14, -84, 68, 0, 0,
306                 0, 0, 0, 0, 83, 83, 78, 68, 0, 0, 15, 8, 0, 0, 0, 0, 0, 0, 0,
307                 0, 0, 1, -1, -1, 0, 1, -1, -1, 0, 0, 0, 0, 0, 0, 0, 1, -1, -1,
308                 0, 0, 0, 0, 0, 0, -1, -1, 0, 2, -1, -2, 0, 2, -1, -1, 0, 0, 0,
309                 0, 0, 0, 0, 0, 0, 1, -1, -1, 0, 0, -1, -1, 0, 1, 0, 0, 0, 0,
310                 0, 0, 0, 1, -1, -1, 0, 1, -1, -2, 0, 1, -1, -1, 0, 1, 0, 0, 0,
311                 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, 0,
312                 2, -1, -2, 0, 2, -1, -1, 0, 0, 0, 1, -1, -1, 0, 1, -1, -1, 0,
313                 0, 0, 0, 0, 0, 0, 0, 0, 1, -1, -2, 0, 2, -1, -2, 0, 1, 0, 0,
314                 0, 1, -1, -1, 0, 0, 0, 1, -1, -1, 0, 0, 0, 1, -1, -2, 0, 2,
315                 -1, -1, 0, 0, 0, 0, 0, 0, -1, -1, 0, 1, 0, 0, 0, 0, 0, 0, 0,
316                 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, 0, 1, -1, -1, 0, 2, -1, -2,
317                 0, 2, -1, -2, 0, 2, -1, -2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, -1,
318                 -2, 0, 2, -1, -2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
319                 -1, -1, 0, 1, 0, 0, -1, -1, 0, 2, -1, -2, 0, 2, -1, -1, 0, 0,
320                 0, 0, 0, 0, -1, -1, 0, 1, -1, -1, 0, 1, -1, -1, 0, 2, -1, -2,
321                 0, 1, 0, 0, -1, -1, 0, 2, -1, -2, 0, 2, -1, -2, 0, 1, 0, 0, 0,
322                 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, -1, -1, 0, 0, 0,
323                 0, -1, -1, 0, 1, 0, 0, 0, 0, 0, 1, -1, -1, 0, 0, 0, 0, 0, 0,
324                 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, -1, -2, 0, 2, -1, -1, 0,
325                 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, -1, -2, 0, 1, 0, 0, 0, 0, 0,
326                 0, 0, 0, 0, 0, 0, 1, -1, -1, 0, 0, 0, 0, -1, -1, 0, 2, -1, -2,
327                 0, 2, -1, -2, 0, 2, -1, -1, 0, 0, 0, 0, -1, -1, 0, 1, -1, -1,
328                 0, 1, -1, -1, 0, 1, -1, -1, 0, 1, -1, -1, 0, 1, 0, 0, 0, 0,
329                 -1, -1, 0, 2, -1, -2, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
330                 1, -1, -1, 0, 0, 0, 0, -1, -1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,
331                 0, 0, 0, 0, 0, 1 };
332         assertFalse(TarUtils.verifyCheckSum(invalid));
333     }
334 
335 }