1231200Smm/*-
2231200Smm * Copyright (c) 2010 Michihiro NAKAJIMA
3231200Smm * All rights reserved.
4231200Smm *
5231200Smm * Redistribution and use in source and binary forms, with or without
6231200Smm * modification, are permitted provided that the following conditions
7231200Smm * are met:
8231200Smm * 1. Redistributions of source code must retain the above copyright
9231200Smm *    notice, this list of conditions and the following disclaimer.
10231200Smm * 2. Redistributions in binary form must reproduce the above copyright
11231200Smm *    notice, this list of conditions and the following disclaimer in the
12231200Smm *    documentation and/or other materials provided with the distribution.
13231200Smm *
14231200Smm * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
15231200Smm * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
16231200Smm * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
17231200Smm * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
18231200Smm * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
19231200Smm * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20231200Smm * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
21231200Smm * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22231200Smm * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23231200Smm * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24231200Smm */
25231200Smm#include "test.h"
26231200Smm__FBSDID("$FreeBSD");
27231200Smm
28231200Smm/*
29231200SmmExecute the following command to rebuild the data for this program:
30231200Smm   tail -n +44 test_read_format_cab.c | /bin/sh
31231200SmmAnd following works are:
32231200Smm1. Move /tmp/cab/cab.zip to Windows PC
33231200Smm2. Extract cab.zip
34231200Smm3. Open command prompt and change current directory where you extracted cab.zip
35231200Smm4. Execute cab.bat
36231200Smm5. Then you will see that there is a cabinet file, test.cab
37231200Smm6. Move test.cab to posix platform
38231200Smm7. Extract test.cab with this version of bsdtar
39231200Smm8. Execute the following command to make uuencoded files.
40231200Smm uuencode test_read_format_cab_1.cab test_read_format_cab_1.cab > test_read_format_cab_1.cab.uu
41231200Smm uuencode test_read_format_cab_2.cab test_read_format_cab_2.cab > test_read_format_cab_2.cab.uu
42231200Smm uuencode test_read_format_cab_3.cab test_read_format_cab_3.cab > test_read_format_cab_3.cab.uu
43231200Smm
44231200Smm#!/bin/sh
45231200Smm#
46231200Smm# How to make test data.
47231200Smm#
48231200Smm# Temporary directory.
49231200Smmbase=/tmp/cab
50231200Smm# Owner id
51231200Smmowner=1001
52231200Smm# Group id
53231200Smmgroup=1001
54231200Smm#
55231200Smm# Make contents of a cabinet file.
56231200Smm#
57231200Smmrm -rf ${base}
58231200Smmmkdir ${base}
59231200Smmmkdir ${base}/dir1
60231200Smmmkdir ${base}/dir2
61231200Smm#
62231200Smmtouch ${base}/empty
63231200Smmcat > ${base}/dir1/file1 << END
64231200Smm                          file 1 contents
65231200Smmhello
66231200Smmhello
67231200Smmhello
68231200SmmEND
69231200Smm#
70231200Smmcat > ${base}/dir2/file2 << END
71231200Smm                          file 2 contents
72231200Smmhello
73231200Smmhello
74231200Smmhello
75231200Smmhello
76231200Smmhello
77231200Smmhello
78231200SmmEND
79231200Smm#
80231200Smmdd if=/dev/zero of=${base}/zero bs=1 count=33000 > /dev/null 2>&1
81231200Smm#
82231200Smmcab1=test_read_format_cab_1.cab
83231200Smmcab2=test_read_format_cab_2.cab
84231200Smmcab3=test_read_format_cab_3.cab
85231200Smm#
86231200Smm#
87231200Smmcat > ${base}/mkcab1 << END
88231200Smm.Set Compress=OFF
89231200Smm.Set DiskDirectory1=.
90231200Smm.Set InfDate=1980-01-02
91231200Smm.Set InfTime=00:00:00
92231200Smm.Set CabinetName1=${cab1}
93231200Smmempty
94231200Smm.Set DestinationDir=dir1
95231200Smmdir1/file1
96231200Smm.Set DestinationDir=dir2
97231200Smmdir2/file2
98231200SmmEND
99231200Smm#
100231200Smmcat > ${base}/mkcab2 << END
101231200Smm.Set CompressionType=MSZIP
102231200Smm.Set DiskDirectory1=.
103231200Smm.Set InfDate=1980-01-02
104231200Smm.Set InfTime=00:00:00
105231200Smm.Set CabinetName1=${cab2}
106231200Smmempty
107231200Smmzero
108231200Smm.Set DestinationDir=dir1
109231200Smmdir1/file1
110231200Smm.Set DestinationDir=dir2
111231200Smmdir2/file2
112231200SmmEND
113231200Smm#
114231200Smmcat > ${base}/mkcab3 << END
115231200Smm.Set CompressionType=LZX
116231200Smm.Set DiskDirectory1=.
117231200Smm.Set InfDate=1980-01-02
118231200Smm.Set InfTime=00:00:00
119231200Smm.Set CabinetName1=${cab3}
120231200Smmempty
121231200Smmzero
122231200Smm.Set DestinationDir=dir1
123231200Smmdir1/file1
124231200Smm.Set DestinationDir=dir2
125231200Smmdir2/file2
126231200SmmEND
127231200Smm#
128231200Smmcat > ${base}/mkcab4 << END
129231200Smm.Set CompressionType=MSZIP
130231200Smm.Set DiskDirectory1=.
131231200Smm.Set CabinetName1=test.cab
132231200Smm${cab1}
133231200Smm${cab2}
134231200Smm${cab3}
135231200SmmEND
136231200Smm#
137231200Smmcat > ${base}/cab.bat << END
138231200Smmmakecab.exe /F mkcab1
139231200Smmmakecab.exe /F mkcab2
140231200Smmmakecab.exe /F mkcab3
141231200Smmmakecab.exe /F mkcab4
142231200Smmdel setup.inf setup.rpt
143231200Smmdel empty zero dir1\file1 dir2\file2 mkcab1 mkcab2 mkcab3 mkcab4
144231200Smmdel ${cab1} ${cab2} ${cab3}
145231200Smmrmdir dir1 dir2
146231200SmmEND
147231200Smm#
148231200Smmf=cab.zip
149231200Smm(cd ${base}; zip -q -c $f empty zero dir1/file1 dir2/file2 mkcab1 mkcab2 mkcab3 mkcab4 cab.bat)
150231200Smm#
151231200Smmexit 1
152231200Smm*/
153231200Smm
154231200Smmstatic const char file1[] = {
155231200Smm"                          file 1 contents\n"
156231200Smm"hello\n"
157231200Smm"hello\n"
158231200Smm"hello\n"
159231200Smm};
160231200Smm#define file1_size (sizeof(file1)-1)
161231200Smmstatic const char file2[] = {
162231200Smm"                          file 2 contents\n"
163231200Smm"hello\n"
164231200Smm"hello\n"
165231200Smm"hello\n"
166231200Smm"hello\n"
167231200Smm"hello\n"
168231200Smm"hello\n"
169231200Smm};
170231200Smm#define file2_size (sizeof(file2)-1)
171231200Smm
172231200Smmenum comp_type {
173231200Smm	STORE = 0,
174231200Smm	MSZIP,
175231200Smm	LZX
176231200Smm};
177231200Smmstatic void
178231200Smmverify(const char *refname, enum comp_type comp)
179231200Smm{
180231200Smm	struct archive_entry *ae;
181231200Smm	struct archive *a;
182231200Smm	char buff[128];
183231200Smm	char zero[128];
184231200Smm	size_t s;
185231200Smm
186231200Smm	memset(zero, 0, sizeof(zero));
187231200Smm	extract_reference_file(refname);
188231200Smm	assert((a = archive_read_new()) != NULL);
189231200Smm	assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a));
190231200Smm	assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a));
191231200Smm	assertEqualIntA(a, ARCHIVE_OK,
192231200Smm	    archive_read_open_filename(a, refname, 10240));
193231200Smm
194231200Smm	/* Verify regular empty. */
195231200Smm	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
196238856Smm	assertEqualInt((AE_IFREG | 0666), archive_entry_mode(ae));
197231200Smm	assertEqualString("empty", archive_entry_pathname(ae));
198231200Smm	assertEqualInt(0, archive_entry_uid(ae));
199231200Smm	assertEqualInt(0, archive_entry_gid(ae));
200231200Smm	assertEqualInt(0, archive_entry_size(ae));
201299529Smm	assertEqualInt(archive_entry_is_encrypted(ae), 0);
202299529Smm	assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED);
203231200Smm
204231200Smm	if (comp != STORE) {
205231200Smm		/* Verify regular zero.
206231200Smm		 * Maximum CFDATA size is 32768, so we need over 32768 bytes
207231200Smm		 * file to check if we properly handle multiple CFDATA.
208231200Smm		 */
209231200Smm		assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
210238856Smm		assertEqualInt((AE_IFREG | 0666), archive_entry_mode(ae));
211231200Smm		assertEqualString("zero", archive_entry_pathname(ae));
212231200Smm		assertEqualInt(0, archive_entry_uid(ae));
213231200Smm		assertEqualInt(0, archive_entry_gid(ae));
214299529Smm		assertEqualInt(archive_entry_is_encrypted(ae), 0);
215299529Smm		assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED);
216231200Smm		assertEqualInt(33000, archive_entry_size(ae));
217231200Smm		for (s = 0; s + sizeof(buff) < 33000; s+= sizeof(buff)) {
218231200Smm			ssize_t rsize = archive_read_data(a, buff, sizeof(buff));
219299529Smm			if (comp == MSZIP && rsize == ARCHIVE_FATAL && archive_zlib_version() == NULL) {
220231200Smm				skipping("Skipping CAB format(MSZIP) check: %s",
221231200Smm				    archive_error_string(a));
222231200Smm				goto finish;
223231200Smm			}
224231200Smm			assertEqualInt(sizeof(buff), rsize);
225231200Smm			assertEqualMem(buff, zero, sizeof(buff));
226231200Smm		}
227231200Smm		assertEqualInt(33000 - s, archive_read_data(a, buff, 33000 - s));
228231200Smm		assertEqualMem(buff, zero, 33000 - s);
229231200Smm	}
230231200Smm
231231200Smm	/* Verify regular file1. */
232231200Smm	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
233238856Smm	assertEqualInt((AE_IFREG | 0666), archive_entry_mode(ae));
234231200Smm	assertEqualString("dir1/file1", archive_entry_pathname(ae));
235231200Smm	assertEqualInt(0, archive_entry_uid(ae));
236231200Smm	assertEqualInt(0, archive_entry_gid(ae));
237299529Smm	assertEqualInt(archive_entry_is_encrypted(ae), 0);
238299529Smm	assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED);
239231200Smm	assertEqualInt(file1_size, archive_entry_size(ae));
240231200Smm	assertEqualInt(file1_size, archive_read_data(a, buff, file1_size));
241231200Smm	assertEqualMem(buff, file1, file1_size);
242231200Smm
243231200Smm	/* Verify regular file2. */
244231200Smm	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
245238856Smm	assertEqualInt((AE_IFREG | 0666), archive_entry_mode(ae));
246231200Smm	assertEqualString("dir2/file2", archive_entry_pathname(ae));
247231200Smm	assertEqualInt(0, archive_entry_uid(ae));
248231200Smm	assertEqualInt(0, archive_entry_gid(ae));
249299529Smm	assertEqualInt(archive_entry_is_encrypted(ae), 0);
250299529Smm	assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED);
251231200Smm	assertEqualInt(file2_size, archive_entry_size(ae));
252231200Smm	assertEqualInt(file2_size, archive_read_data(a, buff, file2_size));
253231200Smm	assertEqualMem(buff, file2, file2_size);
254231200Smm
255231200Smm	/* End of archive. */
256231200Smm	assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae));
257231200Smm
258231200Smm	if (comp != STORE) {
259231200Smm		assertEqualInt(4, archive_file_count(a));
260231200Smm	} else {
261231200Smm		assertEqualInt(3, archive_file_count(a));
262231200Smm	}
263231200Smm
264231200Smm	/* Verify archive format. */
265248616Smm	assertEqualIntA(a, ARCHIVE_FILTER_NONE, archive_filter_code(a, 0));
266231200Smm	assertEqualIntA(a, ARCHIVE_FORMAT_CAB, archive_format(a));
267231200Smm
268231200Smm	/* Close the archive. */
269231200Smmfinish:
270231200Smm	assertEqualInt(ARCHIVE_OK, archive_read_close(a));
271231200Smm	assertEqualInt(ARCHIVE_OK, archive_read_free(a));
272231200Smm}
273231200Smm
274238856Smm/*
275238856Smm * Skip beginning files and Read the last file.
276238856Smm */
277238856Smmstatic void
278238856Smmverify2(const char *refname, enum comp_type comp)
279238856Smm{
280238856Smm	struct archive_entry *ae;
281238856Smm	struct archive *a;
282238856Smm	char buff[128];
283238856Smm	char zero[128];
284238856Smm
285299529Smm	if (comp == MSZIP && archive_zlib_version() == NULL) {
286248616Smm		skipping("Skipping CAB format(MSZIP) check for %s",
287248616Smm		  refname);
288248616Smm		return;
289248616Smm	}
290238856Smm	memset(zero, 0, sizeof(zero));
291238856Smm	extract_reference_file(refname);
292238856Smm	assert((a = archive_read_new()) != NULL);
293238856Smm	assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a));
294238856Smm	assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a));
295238856Smm	assertEqualIntA(a, ARCHIVE_OK,
296238856Smm	    archive_read_open_filename(a, refname, 10240));
297238856Smm
298238856Smm	/* Verify regular empty. */
299238856Smm	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
300299529Smm	assertEqualInt(archive_entry_is_encrypted(ae), 0);
301299529Smm	assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED);
302238856Smm	if (comp != STORE) {
303238856Smm		assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
304299529Smm		assertEqualInt(archive_entry_is_encrypted(ae), 0);
305299529Smm		assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED);
306238856Smm	}
307238856Smm	/* Verify regular file1. */
308238856Smm	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
309299529Smm	assertEqualInt(archive_entry_is_encrypted(ae), 0);
310299529Smm	assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED);
311238856Smm
312238856Smm	/* Verify regular file2. */
313238856Smm	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
314238856Smm	assertEqualInt((AE_IFREG | 0666), archive_entry_mode(ae));
315238856Smm	assertEqualString("dir2/file2", archive_entry_pathname(ae));
316238856Smm	assertEqualInt(0, archive_entry_uid(ae));
317238856Smm	assertEqualInt(0, archive_entry_gid(ae));
318238856Smm	assertEqualInt(file2_size, archive_entry_size(ae));
319238856Smm	assertEqualInt(file2_size, archive_read_data(a, buff, file2_size));
320238856Smm	assertEqualMem(buff, file2, file2_size);
321238856Smm
322238856Smm	/* End of archive. */
323238856Smm	assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae));
324238856Smm
325238856Smm	if (comp != STORE) {
326238856Smm		assertEqualInt(4, archive_file_count(a));
327238856Smm	} else {
328238856Smm		assertEqualInt(3, archive_file_count(a));
329238856Smm	}
330238856Smm
331238856Smm	/* Verify archive format. */
332248616Smm	assertEqualIntA(a, ARCHIVE_FILTER_NONE, archive_filter_code(a, 0));
333238856Smm	assertEqualIntA(a, ARCHIVE_FORMAT_CAB, archive_format(a));
334238856Smm
335238856Smm	/* Close the archive. */
336238856Smm	assertEqualInt(ARCHIVE_OK, archive_read_close(a));
337238856Smm	assertEqualInt(ARCHIVE_OK, archive_read_free(a));
338238856Smm}
339238856Smm
340238856Smm/*
341238856Smm * Skip all file like 'bsdtar tvf foo.cab'.
342238856Smm */
343238856Smmstatic void
344238856Smmverify3(const char *refname, enum comp_type comp)
345238856Smm{
346238856Smm	struct archive_entry *ae;
347238856Smm	struct archive *a;
348238856Smm	char zero[128];
349238856Smm
350238856Smm	memset(zero, 0, sizeof(zero));
351238856Smm	extract_reference_file(refname);
352238856Smm	assert((a = archive_read_new()) != NULL);
353238856Smm	assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a));
354238856Smm	assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a));
355238856Smm	assertEqualIntA(a, ARCHIVE_OK,
356238856Smm	    archive_read_open_filename(a, refname, 10240));
357238856Smm
358238856Smm	/* Verify regular empty. */
359238856Smm	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
360299529Smm	assertEqualInt(archive_entry_is_encrypted(ae), 0);
361299529Smm	assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED);
362238856Smm	if (comp != STORE) {
363238856Smm		assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
364299529Smm		assertEqualInt(archive_entry_is_encrypted(ae), 0);
365299529Smm		assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED);
366238856Smm	}
367238856Smm	/* Verify regular file1. */
368238856Smm	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
369299529Smm	assertEqualInt(archive_entry_is_encrypted(ae), 0);
370299529Smm	assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED);
371238856Smm
372238856Smm	/* Verify regular file2. */
373238856Smm	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
374299529Smm	assertEqualInt(archive_entry_is_encrypted(ae), 0);
375299529Smm	assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED);
376238856Smm
377238856Smm	/* End of archive. */
378238856Smm	assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae));
379238856Smm
380238856Smm	if (comp != STORE) {
381238856Smm		assertEqualInt(4, archive_file_count(a));
382238856Smm	} else {
383238856Smm		assertEqualInt(3, archive_file_count(a));
384238856Smm	}
385238856Smm
386238856Smm	/* Verify archive format. */
387248616Smm	assertEqualIntA(a, ARCHIVE_FILTER_NONE, archive_filter_code(a, 0));
388238856Smm	assertEqualIntA(a, ARCHIVE_FORMAT_CAB, archive_format(a));
389238856Smm
390238856Smm	/* Close the archive. */
391238856Smm	assertEqualInt(ARCHIVE_OK, archive_read_close(a));
392238856Smm	assertEqualInt(ARCHIVE_OK, archive_read_free(a));
393238856Smm}
394238856Smm
395231200SmmDEFINE_TEST(test_read_format_cab)
396231200Smm{
397231200Smm	/* Verify Cabinet file in no compression. */
398231200Smm	verify("test_read_format_cab_1.cab", STORE);
399238856Smm	verify2("test_read_format_cab_1.cab", STORE);
400238856Smm	verify3("test_read_format_cab_1.cab", STORE);
401231200Smm	/* Verify Cabinet file in MSZIP. */
402231200Smm	verify("test_read_format_cab_2.cab", MSZIP);
403238856Smm	verify2("test_read_format_cab_2.cab", MSZIP);
404238856Smm	verify3("test_read_format_cab_2.cab", MSZIP);
405231200Smm	/* Verify Cabinet file in LZX. */
406231200Smm	verify("test_read_format_cab_3.cab", LZX);
407238856Smm	verify2("test_read_format_cab_3.cab", LZX);
408238856Smm	verify3("test_read_format_cab_3.cab", LZX);
409231200Smm}
410231200Smm
411