View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   https://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  
20  package org.apache.commons.compress.archivers.ar;
21  
22  import static org.junit.jupiter.api.Assertions.assertEquals;
23  import static org.junit.jupiter.api.Assertions.assertNotNull;
24  import static org.junit.jupiter.api.Assertions.assertThrows;
25  
26  import java.io.File;
27  import java.io.FileInputStream;
28  import java.io.FileNotFoundException;
29  import java.io.FileOutputStream;
30  import java.io.IOException;
31  import java.nio.file.Files;
32  
33  import org.apache.commons.lang3.StringUtils;
34  import org.junit.jupiter.api.Test;
35  import org.junit.jupiter.params.ParameterizedTest;
36  import org.junit.jupiter.params.provider.ValueSource;
37  
38  /**
39   * Tests COMPRESS-678.
40   */
41  class Compress678Test {
42  
43      @ParameterizedTest
44      @ValueSource(ints = { 15, 16, 17, 18, 32, 64, 128 })
45      void test_LONGFILE_BSD(final int fileNameLen) throws IOException {
46          test_LONGFILE_BSD(StringUtils.repeat('x', fileNameLen));
47      }
48  
49      /**
50       * @param fileName
51       * @throws IOException if an I/O error occurs.
52       * @throws FileNotFoundException
53       */
54      private void test_LONGFILE_BSD(final String fileName) throws IOException, FileNotFoundException {
55          final File file = new File("target/Compress678Test-b.ar");
56          Files.deleteIfExists(file.toPath());
57          // First entry's name length is longer than 16 bytes and odd
58          // data length is odd.
59          final byte[] data = { 1 };
60          try (ArArchiveOutputStream arOut = new ArArchiveOutputStream(new FileOutputStream(file))) {
61              arOut.setLongFileMode(ArArchiveOutputStream.LONGFILE_BSD);
62              // entry 1
63              arOut.putArchiveEntry(new ArArchiveEntry(fileName, data.length));
64              arOut.write(data);
65              arOut.closeArchiveEntry();
66              // entry 2
67              arOut.putArchiveEntry(new ArArchiveEntry("a", data.length));
68              arOut.write(data);
69              arOut.closeArchiveEntry();
70          }
71          try (ArArchiveInputStream arIn = new ArArchiveInputStream(new FileInputStream(file))) {
72              final ArArchiveEntry entry = arIn.getNextEntry();
73              assertEquals(fileName, entry.getName());
74              // Fix
75              // ar -tv Compress678Test-b.ar
76              // rw-r--r-- 0/0 1 Apr 27 16:10 2024 01234567891234567
77              // ar: Compress678Test-b.ar: Inappropriate file type or format
78              assertNotNull(arIn.getNextEntry());
79          }
80      }
81  
82      @ParameterizedTest
83      @ValueSource(ints = { 15, 16, 17, 18, 32, 64, 128 })
84      void test_LONGFILE_BSD_with_spaces(final int fileNameLen) throws IOException {
85          test_LONGFILE_BSD(StringUtils.repeat("x y", fileNameLen / 3));
86      }
87  
88      @Test
89      void test_LONGFILE_ERROR() throws IOException {
90          final File file = new File("target/Compress678Test-a.ar");
91          Files.deleteIfExists(file.toPath());
92          // First entry's name length is longer than 16 bytes and odd
93          final String name1 = "01234567891234567";
94          // data length is odd.
95          final byte[] data = { 1 };
96          try (ArArchiveOutputStream arOut = new ArArchiveOutputStream(new FileOutputStream(file))) {
97              arOut.setLongFileMode(ArArchiveOutputStream.LONGFILE_ERROR);
98              // java.io.IOException: File name too long, > 16 chars: 01234567891234567
99              assertThrows(IOException.class, () -> arOut.putArchiveEntry(new ArArchiveEntry(name1, data.length)));
100         }
101     }
102 
103     @Test
104     void testShortName() throws IOException {
105         final File file = new File("target/Compress678Test-c.ar");
106         Files.deleteIfExists(file.toPath());
107         // First entry's name length is <= than 16 bytes and odd
108         final String name1 = "0123456789123456";
109         // data length is odd.
110         final byte[] data = { 1 };
111         try (ArArchiveOutputStream arOut = new ArArchiveOutputStream(new FileOutputStream(file))) {
112             arOut.setLongFileMode(ArArchiveOutputStream.LONGFILE_BSD);
113             // entry 1
114             arOut.putArchiveEntry(new ArArchiveEntry(name1, data.length));
115             arOut.write(data);
116             arOut.closeArchiveEntry();
117             // entry 2
118             arOut.putArchiveEntry(new ArArchiveEntry("a", data.length));
119             arOut.write(data);
120             arOut.closeArchiveEntry();
121         }
122         try (ArArchiveInputStream arIn = new ArArchiveInputStream(new FileInputStream(file))) {
123             final ArArchiveEntry entry = arIn.getNextEntry();
124             assertEquals(name1, entry.getName());
125             assertNotNull(arIn.getNextEntry());
126         }
127     }
128 }