xref: /freebsd/contrib/libarchive/libarchive/test/test_read_format_cab.c (revision b9128a37faafede823eb456aa65a11ac69997284)
1 /*-
2  * Copyright (c) 2010 Michihiro NAKAJIMA
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
15  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
16  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
17  * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
18  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
19  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
21  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  */
25 #include "test.h"
26 
27 /*
28 Execute the following command to rebuild the data for this program:
29    tail -n +44 test_read_format_cab.c | /bin/sh
30 And following works are:
31 1. Move /tmp/cab/cab.zip to Windows PC
32 2. Extract cab.zip
33 3. Open command prompt and change current directory where you extracted cab.zip
34 4. Execute cab.bat
35 5. Then you will see that there is a cabinet file, test.cab
36 6. Move test.cab to posix platform
37 7. Extract test.cab with this version of bsdtar
38 8. Execute the following command to make uuencoded files.
39  uuencode test_read_format_cab_1.cab test_read_format_cab_1.cab > test_read_format_cab_1.cab.uu
40  uuencode test_read_format_cab_2.cab test_read_format_cab_2.cab > test_read_format_cab_2.cab.uu
41  uuencode test_read_format_cab_3.cab test_read_format_cab_3.cab > test_read_format_cab_3.cab.uu
42 
43 #!/bin/sh
44 #
45 # How to make test data.
46 #
47 # Temporary directory.
48 base=/tmp/cab
49 # Owner id
50 owner=1001
51 # Group id
52 group=1001
53 #
54 # Make contents of a cabinet file.
55 #
56 rm -rf ${base}
57 mkdir ${base}
58 mkdir ${base}/dir1
59 mkdir ${base}/dir2
60 #
61 touch ${base}/empty
62 cat > ${base}/dir1/file1 << END
63                           file 1 contents
64 hello
65 hello
66 hello
67 END
68 #
69 cat > ${base}/dir2/file2 << END
70                           file 2 contents
71 hello
72 hello
73 hello
74 hello
75 hello
76 hello
77 END
78 #
79 dd if=/dev/zero of=${base}/zero bs=1 count=33000 > /dev/null 2>&1
80 #
81 cab1=test_read_format_cab_1.cab
82 cab2=test_read_format_cab_2.cab
83 cab3=test_read_format_cab_3.cab
84 #
85 #
86 cat > ${base}/mkcab1 << END
87 .Set Compress=OFF
88 .Set DiskDirectory1=.
89 .Set InfDate=1980-01-02
90 .Set InfTime=00:00:00
91 .Set CabinetName1=${cab1}
92 empty
93 .Set DestinationDir=dir1
94 dir1/file1
95 .Set DestinationDir=dir2
96 dir2/file2
97 END
98 #
99 cat > ${base}/mkcab2 << END
100 .Set CompressionType=MSZIP
101 .Set DiskDirectory1=.
102 .Set InfDate=1980-01-02
103 .Set InfTime=00:00:00
104 .Set CabinetName1=${cab2}
105 empty
106 zero
107 .Set DestinationDir=dir1
108 dir1/file1
109 .Set DestinationDir=dir2
110 dir2/file2
111 END
112 #
113 cat > ${base}/mkcab3 << END
114 .Set CompressionType=LZX
115 .Set DiskDirectory1=.
116 .Set InfDate=1980-01-02
117 .Set InfTime=00:00:00
118 .Set CabinetName1=${cab3}
119 empty
120 zero
121 .Set DestinationDir=dir1
122 dir1/file1
123 .Set DestinationDir=dir2
124 dir2/file2
125 END
126 #
127 cat > ${base}/mkcab4 << END
128 .Set CompressionType=MSZIP
129 .Set DiskDirectory1=.
130 .Set CabinetName1=test.cab
131 ${cab1}
132 ${cab2}
133 ${cab3}
134 END
135 #
136 cat > ${base}/cab.bat << END
137 makecab.exe /F mkcab1
138 makecab.exe /F mkcab2
139 makecab.exe /F mkcab3
140 makecab.exe /F mkcab4
141 del setup.inf setup.rpt
142 del empty zero dir1\file1 dir2\file2 mkcab1 mkcab2 mkcab3 mkcab4
143 del ${cab1} ${cab2} ${cab3}
144 rmdir dir1 dir2
145 END
146 #
147 f=cab.zip
148 (cd ${base}; zip -q -c $f empty zero dir1/file1 dir2/file2 mkcab1 mkcab2 mkcab3 mkcab4 cab.bat)
149 #
150 exit 1
151 */
152 
153 static const char file1[] = {
154 "                          file 1 contents\n"
155 "hello\n"
156 "hello\n"
157 "hello\n"
158 };
159 #define file1_size (sizeof(file1)-1)
160 static const char file2[] = {
161 "                          file 2 contents\n"
162 "hello\n"
163 "hello\n"
164 "hello\n"
165 "hello\n"
166 "hello\n"
167 "hello\n"
168 };
169 #define file2_size (sizeof(file2)-1)
170 
171 enum comp_type {
172 	STORE = 0,
173 	MSZIP,
174 	LZX
175 };
176 static void
177 verify(const char *refname, enum comp_type comp)
178 {
179 	struct archive_entry *ae;
180 	struct archive *a;
181 	char buff[128];
182 	char zero[128];
183 	size_t s;
184 
185 	memset(zero, 0, sizeof(zero));
186 	extract_reference_file(refname);
187 	assert((a = archive_read_new()) != NULL);
188 	assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a));
189 	assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a));
190 	assertEqualIntA(a, ARCHIVE_OK,
191 	    archive_read_open_filename(a, refname, 10240));
192 
193 	/* Verify regular empty. */
194 	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
195 	assertEqualInt((AE_IFREG | 0666), archive_entry_mode(ae));
196 	assertEqualString("empty", archive_entry_pathname(ae));
197 	assertEqualInt(0, archive_entry_uid(ae));
198 	assertEqualInt(0, archive_entry_gid(ae));
199 	assertEqualInt(0, archive_entry_size(ae));
200 	assertEqualInt(archive_entry_is_encrypted(ae), 0);
201 	assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED);
202 
203 	if (comp != STORE) {
204 		/* Verify regular zero.
205 		 * Maximum CFDATA size is 32768, so we need over 32768 bytes
206 		 * file to check if we properly handle multiple CFDATA.
207 		 */
208 		assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
209 		assertEqualInt((AE_IFREG | 0666), archive_entry_mode(ae));
210 		assertEqualString("zero", archive_entry_pathname(ae));
211 		assertEqualInt(0, archive_entry_uid(ae));
212 		assertEqualInt(0, archive_entry_gid(ae));
213 		assertEqualInt(archive_entry_is_encrypted(ae), 0);
214 		assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED);
215 		assertEqualInt(33000, archive_entry_size(ae));
216 		for (s = 0; s + sizeof(buff) < 33000; s+= sizeof(buff)) {
217 			ssize_t rsize = archive_read_data(a, buff, sizeof(buff));
218 			if (comp == MSZIP && rsize == ARCHIVE_FATAL && archive_zlib_version() == NULL) {
219 				skipping("Skipping CAB format(MSZIP) check: %s",
220 				    archive_error_string(a));
221 				goto finish;
222 			}
223 			assertEqualInt(sizeof(buff), rsize);
224 			assertEqualMem(buff, zero, sizeof(buff));
225 		}
226 		assertEqualInt(33000 - s, archive_read_data(a, buff, 33000 - s));
227 		assertEqualMem(buff, zero, 33000 - s);
228 	}
229 
230 	/* Verify regular file1. */
231 	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
232 	assertEqualInt((AE_IFREG | 0666), archive_entry_mode(ae));
233 	assertEqualString("dir1/file1", archive_entry_pathname(ae));
234 	assertEqualInt(0, archive_entry_uid(ae));
235 	assertEqualInt(0, archive_entry_gid(ae));
236 	assertEqualInt(archive_entry_is_encrypted(ae), 0);
237 	assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED);
238 	assertEqualInt(file1_size, archive_entry_size(ae));
239 	assertEqualInt(file1_size, archive_read_data(a, buff, file1_size));
240 	assertEqualMem(buff, file1, file1_size);
241 
242 	/* Verify regular file2. */
243 	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
244 	assertEqualInt((AE_IFREG | 0666), archive_entry_mode(ae));
245 	assertEqualString("dir2/file2", archive_entry_pathname(ae));
246 	assertEqualInt(0, archive_entry_uid(ae));
247 	assertEqualInt(0, archive_entry_gid(ae));
248 	assertEqualInt(archive_entry_is_encrypted(ae), 0);
249 	assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED);
250 	assertEqualInt(file2_size, archive_entry_size(ae));
251 	assertEqualInt(file2_size, archive_read_data(a, buff, file2_size));
252 	assertEqualMem(buff, file2, file2_size);
253 
254 	/* End of archive. */
255 	assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae));
256 
257 	if (comp != STORE) {
258 		assertEqualInt(4, archive_file_count(a));
259 	} else {
260 		assertEqualInt(3, archive_file_count(a));
261 	}
262 
263 	/* Verify archive format. */
264 	assertEqualIntA(a, ARCHIVE_FILTER_NONE, archive_filter_code(a, 0));
265 	assertEqualIntA(a, ARCHIVE_FORMAT_CAB, archive_format(a));
266 
267 	/* Close the archive. */
268 finish:
269 	assertEqualInt(ARCHIVE_OK, archive_read_close(a));
270 	assertEqualInt(ARCHIVE_OK, archive_read_free(a));
271 }
272 
273 /*
274  * Skip beginning files and Read the last file.
275  */
276 static void
277 verify2(const char *refname, enum comp_type comp)
278 {
279 	struct archive_entry *ae;
280 	struct archive *a;
281 	char buff[128];
282 	char zero[128];
283 
284 	if (comp == MSZIP && archive_zlib_version() == NULL) {
285 		skipping("Skipping CAB format(MSZIP) check for %s",
286 		  refname);
287 		return;
288 	}
289 	memset(zero, 0, sizeof(zero));
290 	extract_reference_file(refname);
291 	assert((a = archive_read_new()) != NULL);
292 	assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a));
293 	assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a));
294 	assertEqualIntA(a, ARCHIVE_OK,
295 	    archive_read_open_filename(a, refname, 10240));
296 
297 	/* Verify regular empty. */
298 	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
299 	assertEqualInt(archive_entry_is_encrypted(ae), 0);
300 	assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED);
301 	if (comp != STORE) {
302 		assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
303 		assertEqualInt(archive_entry_is_encrypted(ae), 0);
304 		assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED);
305 	}
306 	/* Verify regular file1. */
307 	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
308 	assertEqualInt(archive_entry_is_encrypted(ae), 0);
309 	assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED);
310 
311 	/* Verify regular file2. */
312 	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
313 	assertEqualInt((AE_IFREG | 0666), archive_entry_mode(ae));
314 	assertEqualString("dir2/file2", archive_entry_pathname(ae));
315 	assertEqualInt(0, archive_entry_uid(ae));
316 	assertEqualInt(0, archive_entry_gid(ae));
317 	assertEqualInt(file2_size, archive_entry_size(ae));
318 	assertEqualInt(file2_size, archive_read_data(a, buff, file2_size));
319 	assertEqualMem(buff, file2, file2_size);
320 
321 	/* End of archive. */
322 	assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae));
323 
324 	if (comp != STORE) {
325 		assertEqualInt(4, archive_file_count(a));
326 	} else {
327 		assertEqualInt(3, archive_file_count(a));
328 	}
329 
330 	/* Verify archive format. */
331 	assertEqualIntA(a, ARCHIVE_FILTER_NONE, archive_filter_code(a, 0));
332 	assertEqualIntA(a, ARCHIVE_FORMAT_CAB, archive_format(a));
333 
334 	/* Close the archive. */
335 	assertEqualInt(ARCHIVE_OK, archive_read_close(a));
336 	assertEqualInt(ARCHIVE_OK, archive_read_free(a));
337 }
338 
339 /*
340  * Skip all file like 'bsdtar tvf foo.cab'.
341  */
342 static void
343 verify3(const char *refname, enum comp_type comp)
344 {
345 	struct archive_entry *ae;
346 	struct archive *a;
347 	char zero[128];
348 
349 	memset(zero, 0, sizeof(zero));
350 	extract_reference_file(refname);
351 	assert((a = archive_read_new()) != NULL);
352 	assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a));
353 	assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a));
354 	assertEqualIntA(a, ARCHIVE_OK,
355 	    archive_read_open_filename(a, refname, 10240));
356 
357 	/* Verify regular empty. */
358 	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
359 	assertEqualInt(archive_entry_is_encrypted(ae), 0);
360 	assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED);
361 	if (comp != STORE) {
362 		assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
363 		assertEqualInt(archive_entry_is_encrypted(ae), 0);
364 		assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED);
365 	}
366 	/* Verify regular file1. */
367 	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
368 	assertEqualInt(archive_entry_is_encrypted(ae), 0);
369 	assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED);
370 
371 	/* Verify regular file2. */
372 	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
373 	assertEqualInt(archive_entry_is_encrypted(ae), 0);
374 	assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED);
375 
376 	/* End of archive. */
377 	assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae));
378 
379 	if (comp != STORE) {
380 		assertEqualInt(4, archive_file_count(a));
381 	} else {
382 		assertEqualInt(3, archive_file_count(a));
383 	}
384 
385 	/* Verify archive format. */
386 	assertEqualIntA(a, ARCHIVE_FILTER_NONE, archive_filter_code(a, 0));
387 	assertEqualIntA(a, ARCHIVE_FORMAT_CAB, archive_format(a));
388 
389 	/* Close the archive. */
390 	assertEqualInt(ARCHIVE_OK, archive_read_close(a));
391 	assertEqualInt(ARCHIVE_OK, archive_read_free(a));
392 }
393 
394 DEFINE_TEST(test_read_format_cab)
395 {
396 	/* Verify Cabinet file in no compression. */
397 	verify("test_read_format_cab_1.cab", STORE);
398 	verify2("test_read_format_cab_1.cab", STORE);
399 	verify3("test_read_format_cab_1.cab", STORE);
400 	/* Verify Cabinet file in MSZIP. */
401 	verify("test_read_format_cab_2.cab", MSZIP);
402 	verify2("test_read_format_cab_2.cab", MSZIP);
403 	verify3("test_read_format_cab_2.cab", MSZIP);
404 	/* Verify Cabinet file in LZX. */
405 	verify("test_read_format_cab_3.cab", LZX);
406 	verify2("test_read_format_cab_3.cab", LZX);
407 	verify3("test_read_format_cab_3.cab", LZX);
408 }
409 
410