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  package org.apache.commons.compress.archivers;
20  
21  import static org.junit.jupiter.api.Assertions.assertEquals;
22  import static org.junit.jupiter.api.Assertions.assertFalse;
23  import static org.junit.jupiter.api.Assertions.assertNotNull;
24  import static org.junit.jupiter.api.Assertions.assertTrue;
25  
26  import java.io.File;
27  import java.io.InputStream;
28  import java.io.OutputStream;
29  import java.nio.charset.Charset;
30  import java.nio.charset.StandardCharsets;
31  import java.nio.file.Files;
32  import java.util.HashMap;
33  import java.util.Map;
34  
35  import org.apache.commons.compress.AbstractTest;
36  import org.apache.commons.compress.archivers.cpio.CpioArchiveEntry;
37  import org.apache.commons.compress.archivers.cpio.CpioArchiveInputStream;
38  import org.apache.commons.compress.archivers.cpio.CpioArchiveOutputStream;
39  import org.apache.commons.compress.archivers.cpio.CpioConstants;
40  import org.apache.commons.io.IOUtils;
41  import org.junit.jupiter.api.Test;
42  
43  public final class CpioTest extends AbstractTest {
44  
45      @Test
46      void testCpioArchiveCreation() throws Exception {
47          final File output = newTempFile("bla.cpio");
48  
49          final File file1 = getFile("test1.xml");
50          final File file2 = getFile("test2.xml");
51  
52          try (OutputStream outputStream = Files.newOutputStream(output.toPath());
53                  ArchiveOutputStream<CpioArchiveEntry> archiveOutputStream = ArchiveStreamFactory.DEFAULT.createArchiveOutputStream("cpio", outputStream)) {
54              // file 1
55              archiveOutputStream.putArchiveEntry(new CpioArchiveEntry("test1.xml", file1.length()));
56              archiveOutputStream.write(file1);
57              archiveOutputStream.closeArchiveEntry();
58              // file 2
59              archiveOutputStream.putArchiveEntry(new CpioArchiveEntry("test2.xml", file2.length()));
60              archiveOutputStream.write(file2);
61              archiveOutputStream.closeArchiveEntry();
62          }
63      }
64  
65      @Test
66      void testCpioUnarchive() throws Exception {
67          final File output = newTempFile("bla.cpio");
68          final File file1 = getFile("test1.xml");
69          final File file2 = getFile("test2.xml");
70          final long file1Length = file1.length();
71          final long file2Length = file2.length();
72  
73          try (OutputStream outputStream = Files.newOutputStream(output.toPath());
74                  ArchiveOutputStream<CpioArchiveEntry> archiveOutputStream = ArchiveStreamFactory.DEFAULT.createArchiveOutputStream("cpio", outputStream)) {
75              // file 1
76              CpioArchiveEntry entry = new CpioArchiveEntry("test1.xml", file1Length);
77              entry.setMode(CpioConstants.C_ISREG);
78              archiveOutputStream.putArchiveEntry(entry);
79              archiveOutputStream.write(file1);
80              archiveOutputStream.closeArchiveEntry();
81              // file 2
82              entry = new CpioArchiveEntry("test2.xml", file2Length);
83              entry.setMode(CpioConstants.C_ISREG);
84              archiveOutputStream.putArchiveEntry(entry);
85              archiveOutputStream.write(file2);
86              archiveOutputStream.closeArchiveEntry();
87              archiveOutputStream.finish();
88              archiveOutputStream.close();
89              outputStream.close();
90          }
91  
92          // Unarchive Operation
93          final Map<String, File> result = new HashMap<>();
94          try (InputStream inputStream = Files.newInputStream(output.toPath());
95                  ArchiveInputStream<?> archiveInputStream = ArchiveStreamFactory.DEFAULT.createArchiveInputStream("cpio", inputStream)) {
96              archiveInputStream.forEach(entry -> {
97                  final File cpioget = newTempFile(entry.getName());
98                  Files.copy(archiveInputStream, cpioget.toPath());
99                  result.put(entry.getName(), cpioget);
100             });
101         }
102 
103         File testFile = result.get("test1.xml");
104         assertTrue(testFile.exists(), "Expected " + testFile.getAbsolutePath() + " to exist");
105         assertEquals(file1Length, testFile.length(), "length of " + testFile.getAbsolutePath());
106 
107         testFile = result.get("test2.xml");
108         assertTrue(testFile.exists(), "Expected " + testFile.getAbsolutePath() + " to exist");
109         assertEquals(file2Length, testFile.length(), "length of " + testFile.getAbsolutePath());
110     }
111 
112     @Test
113     void testDirectoryEntryFromFile() throws Exception {
114         final File archive = createTempFile("test.", ".cpio");
115         final File dir = getTempDirFile();
116         final long beforeArchiveWrite = dir.lastModified();
117         final CpioArchiveEntry entryIn = new CpioArchiveEntry(dir, "foo");
118         try (CpioArchiveOutputStream tos = new CpioArchiveOutputStream(Files.newOutputStream(archive.toPath()))) {
119             tos.putArchiveEntry(entryIn);
120             tos.closeArchiveEntry();
121         }
122         final CpioArchiveEntry entryOut;
123         try (CpioArchiveInputStream tis = new CpioArchiveInputStream(Files.newInputStream(archive.toPath()))) {
124             entryOut = tis.getNextCPIOEntry();
125         }
126         assertNotNull(entryOut);
127         assertEquals("foo", entryOut.getName());
128         assertEquals(0, entryOut.getSize());
129         // CPIO stores time with a granularity of 1 second
130         assertEquals(beforeArchiveWrite / 1000, entryOut.getLastModifiedDate().getTime() / 1000);
131         assertTrue(entryOut.isDirectory());
132     }
133 
134     @Test
135     void testExplicitDirectoryEntry() throws Exception {
136         final File archive = createTempFile("test.", ".cpio");
137         final long beforeArchiveWrite;
138         try (CpioArchiveOutputStream tos = new CpioArchiveOutputStream(Files.newOutputStream(archive.toPath()))) {
139             beforeArchiveWrite = getTempDirFile().lastModified();
140             final CpioArchiveEntry in = new CpioArchiveEntry("foo/");
141             in.setTime(beforeArchiveWrite / 1000);
142             in.setMode(CpioConstants.C_ISDIR);
143             tos.putArchiveEntry(in);
144             tos.closeArchiveEntry();
145         }
146         final CpioArchiveEntry out;
147         try (CpioArchiveInputStream tis = new CpioArchiveInputStream(Files.newInputStream(archive.toPath()))) {
148             out = tis.getNextCPIOEntry();
149         }
150         assertNotNull(out);
151         assertEquals("foo/", out.getName());
152         assertEquals(0, out.getSize());
153         assertEquals(beforeArchiveWrite / 1000, out.getLastModifiedDate().getTime() / 1000);
154         assertTrue(out.isDirectory());
155     }
156 
157     @Test
158     void testExplicitFileEntry() throws Exception {
159         final File tmp = createTempFile();
160         final File archive = createTempFile("test.", ".cpio");
161         try (CpioArchiveOutputStream tos = new CpioArchiveOutputStream(Files.newOutputStream(archive.toPath()))) {
162             final CpioArchiveEntry in = new CpioArchiveEntry("foo");
163             in.setTime(tmp.lastModified() / 1000);
164             in.setSize(tmp.length());
165             in.setMode(CpioConstants.C_ISREG);
166             tos.putArchiveEntry(in);
167             tos.write(tmp);
168             tos.closeArchiveEntry();
169         }
170         final CpioArchiveEntry out;
171         try (CpioArchiveInputStream tis = new CpioArchiveInputStream(Files.newInputStream(archive.toPath()))) {
172             out = tis.getNextCPIOEntry();
173         }
174         assertNotNull(out);
175         assertEquals("foo", out.getName());
176         assertEquals(tmp.length(), out.getSize());
177         assertEquals(tmp.lastModified() / 1000, out.getLastModifiedDate().getTime() / 1000);
178         assertFalse(out.isDirectory());
179     }
180 
181     @Test
182     void testFileEntryFromFile() throws Exception {
183         final File tmp = createTempFile();
184         final File archive = createTempFile("test.", ".cpio");
185         try (CpioArchiveOutputStream tos = new CpioArchiveOutputStream(Files.newOutputStream(archive.toPath()))) {
186             final CpioArchiveEntry in = new CpioArchiveEntry(tmp, "foo");
187             tos.putArchiveEntry(in);
188             tos.write(tmp);
189             tos.closeArchiveEntry();
190         }
191         final CpioArchiveEntry out;
192         try (CpioArchiveInputStream tis = new CpioArchiveInputStream(Files.newInputStream(archive.toPath()))) {
193             out = tis.getNextCPIOEntry();
194         }
195         assertNotNull(out);
196         assertEquals("foo", out.getName());
197         assertEquals(tmp.length(), out.getSize());
198         assertEquals(tmp.lastModified() / 1000, out.getLastModifiedDate().getTime() / 1000);
199         assertFalse(out.isDirectory());
200     }
201 
202     /**
203      * Tests COMPRESS-690.
204      */
205     @Test
206     void testSymbolicLinkFileEntry() throws Exception {
207         final File tmp = createTempFile();
208         final File archive = createTempFile("test.", ".cpio");
209         final String name = "EntryName";
210         final String nameLink = "LinkName";
211         final Charset charset = StandardCharsets.UTF_8;
212         try (CpioArchiveOutputStream tos = new CpioArchiveOutputStream(Files.newOutputStream(archive.toPath()))) {
213             final CpioArchiveEntry entry = new CpioArchiveEntry(name);
214             entry.setTime(tmp.lastModified() / 1000);
215             entry.setSize(nameLink.length());
216             entry.setMode(CpioConstants.C_ISLNK);
217             assertTrue(entry.isSymbolicLink());
218             tos.putArchiveEntry(entry);
219             tos.write(nameLink.getBytes(charset));
220             tos.closeArchiveEntry();
221         }
222         final CpioArchiveEntry entry;
223         try (CpioArchiveInputStream tis = new CpioArchiveInputStream(Files.newInputStream(archive.toPath()))) {
224             entry = tis.getNextEntry();
225             assertEquals(nameLink, IOUtils.toString(tis, charset));
226         }
227         assertNotNull(entry);
228         assertEquals(name, entry.getName());
229         assertTrue(entry.isSymbolicLink());
230         assertEquals(nameLink.length(), entry.getSize());
231         assertEquals(tmp.lastModified() / 1000, entry.getLastModifiedDate().getTime() / 1000);
232         assertFalse(entry.isDirectory());
233     }
234 
235 }