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#ifdef HAVE_LIBZ
29231200Smmstatic const int libz_enabled = 1;
30231200Smm#else
31231200Smmstatic const int libz_enabled = 0;
32231200Smm#endif
33231200Smm
34231200Smm/*
35231200SmmExecute the following command to rebuild the data for this program:
36231200Smm   tail -n +44 test_read_format_cab.c | /bin/sh
37231200SmmAnd following works are:
38231200Smm1. Move /tmp/cab/cab.zip to Windows PC
39231200Smm2. Extract cab.zip
40231200Smm3. Open command prompt and change current directory where you extracted cab.zip
41231200Smm4. Execute cab.bat
42231200Smm5. Then you will see that there is a cabinet file, test.cab
43231200Smm6. Move test.cab to posix platform
44231200Smm7. Extract test.cab with this version of bsdtar
45231200Smm8. Execute the following command to make uuencoded files.
46231200Smm uuencode test_read_format_cab_1.cab test_read_format_cab_1.cab > test_read_format_cab_1.cab.uu
47231200Smm uuencode test_read_format_cab_2.cab test_read_format_cab_2.cab > test_read_format_cab_2.cab.uu
48231200Smm uuencode test_read_format_cab_3.cab test_read_format_cab_3.cab > test_read_format_cab_3.cab.uu
49231200Smm
50231200Smm#!/bin/sh
51231200Smm#
52231200Smm# How to make test data.
53231200Smm#
54231200Smm# Temporary directory.
55231200Smmbase=/tmp/cab
56231200Smm# Owner id
57231200Smmowner=1001
58231200Smm# Group id
59231200Smmgroup=1001
60231200Smm#
61231200Smm# Make contents of a cabinet file.
62231200Smm#
63231200Smmrm -rf ${base}
64231200Smmmkdir ${base}
65231200Smmmkdir ${base}/dir1
66231200Smmmkdir ${base}/dir2
67231200Smm#
68231200Smmtouch ${base}/empty
69231200Smmcat > ${base}/dir1/file1 << END
70231200Smm                          file 1 contents
71231200Smmhello
72231200Smmhello
73231200Smmhello
74231200SmmEND
75231200Smm#
76231200Smmcat > ${base}/dir2/file2 << END
77231200Smm                          file 2 contents
78231200Smmhello
79231200Smmhello
80231200Smmhello
81231200Smmhello
82231200Smmhello
83231200Smmhello
84231200SmmEND
85231200Smm#
86231200Smmdd if=/dev/zero of=${base}/zero bs=1 count=33000 > /dev/null 2>&1
87231200Smm#
88231200Smmcab1=test_read_format_cab_1.cab
89231200Smmcab2=test_read_format_cab_2.cab
90231200Smmcab3=test_read_format_cab_3.cab
91231200Smm#
92231200Smm#
93231200Smmcat > ${base}/mkcab1 << END
94231200Smm.Set Compress=OFF
95231200Smm.Set DiskDirectory1=.
96231200Smm.Set InfDate=1980-01-02
97231200Smm.Set InfTime=00:00:00
98231200Smm.Set CabinetName1=${cab1}
99231200Smmempty
100231200Smm.Set DestinationDir=dir1
101231200Smmdir1/file1
102231200Smm.Set DestinationDir=dir2
103231200Smmdir2/file2
104231200SmmEND
105231200Smm#
106231200Smmcat > ${base}/mkcab2 << END
107231200Smm.Set CompressionType=MSZIP
108231200Smm.Set DiskDirectory1=.
109231200Smm.Set InfDate=1980-01-02
110231200Smm.Set InfTime=00:00:00
111231200Smm.Set CabinetName1=${cab2}
112231200Smmempty
113231200Smmzero
114231200Smm.Set DestinationDir=dir1
115231200Smmdir1/file1
116231200Smm.Set DestinationDir=dir2
117231200Smmdir2/file2
118231200SmmEND
119231200Smm#
120231200Smmcat > ${base}/mkcab3 << END
121231200Smm.Set CompressionType=LZX
122231200Smm.Set DiskDirectory1=.
123231200Smm.Set InfDate=1980-01-02
124231200Smm.Set InfTime=00:00:00
125231200Smm.Set CabinetName1=${cab3}
126231200Smmempty
127231200Smmzero
128231200Smm.Set DestinationDir=dir1
129231200Smmdir1/file1
130231200Smm.Set DestinationDir=dir2
131231200Smmdir2/file2
132231200SmmEND
133231200Smm#
134231200Smmcat > ${base}/mkcab4 << END
135231200Smm.Set CompressionType=MSZIP
136231200Smm.Set DiskDirectory1=.
137231200Smm.Set CabinetName1=test.cab
138231200Smm${cab1}
139231200Smm${cab2}
140231200Smm${cab3}
141231200SmmEND
142231200Smm#
143231200Smmcat > ${base}/cab.bat << END
144231200Smmmakecab.exe /F mkcab1
145231200Smmmakecab.exe /F mkcab2
146231200Smmmakecab.exe /F mkcab3
147231200Smmmakecab.exe /F mkcab4
148231200Smmdel setup.inf setup.rpt
149231200Smmdel empty zero dir1\file1 dir2\file2 mkcab1 mkcab2 mkcab3 mkcab4
150231200Smmdel ${cab1} ${cab2} ${cab3}
151231200Smmrmdir dir1 dir2
152231200SmmEND
153231200Smm#
154231200Smmf=cab.zip
155231200Smm(cd ${base}; zip -q -c $f empty zero dir1/file1 dir2/file2 mkcab1 mkcab2 mkcab3 mkcab4 cab.bat)
156231200Smm#
157231200Smmexit 1
158231200Smm*/
159231200Smm
160231200Smmstatic const char file1[] = {
161231200Smm"                          file 1 contents\n"
162231200Smm"hello\n"
163231200Smm"hello\n"
164231200Smm"hello\n"
165231200Smm};
166231200Smm#define file1_size (sizeof(file1)-1)
167231200Smmstatic const char file2[] = {
168231200Smm"                          file 2 contents\n"
169231200Smm"hello\n"
170231200Smm"hello\n"
171231200Smm"hello\n"
172231200Smm"hello\n"
173231200Smm"hello\n"
174231200Smm"hello\n"
175231200Smm};
176231200Smm#define file2_size (sizeof(file2)-1)
177231200Smm
178231200Smmenum comp_type {
179231200Smm	STORE = 0,
180231200Smm	MSZIP,
181231200Smm	LZX
182231200Smm};
183231200Smmstatic void
184231200Smmverify(const char *refname, enum comp_type comp)
185231200Smm{
186231200Smm	struct archive_entry *ae;
187231200Smm	struct archive *a;
188231200Smm	char buff[128];
189231200Smm	char zero[128];
190231200Smm	size_t s;
191231200Smm
192231200Smm	memset(zero, 0, sizeof(zero));
193231200Smm	extract_reference_file(refname);
194231200Smm	assert((a = archive_read_new()) != NULL);
195231200Smm	assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a));
196231200Smm	assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a));
197231200Smm	assertEqualIntA(a, ARCHIVE_OK,
198231200Smm	    archive_read_open_filename(a, refname, 10240));
199231200Smm
200231200Smm	/* Verify regular empty. */
201231200Smm	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
202238856Smm	assertEqualInt((AE_IFREG | 0666), archive_entry_mode(ae));
203231200Smm	assertEqualString("empty", archive_entry_pathname(ae));
204231200Smm	assertEqualInt(0, archive_entry_uid(ae));
205231200Smm	assertEqualInt(0, archive_entry_gid(ae));
206231200Smm	assertEqualInt(0, archive_entry_size(ae));
207231200Smm
208231200Smm	if (comp != STORE) {
209231200Smm		/* Verify regular zero.
210231200Smm		 * Maximum CFDATA size is 32768, so we need over 32768 bytes
211231200Smm		 * file to check if we properly handle multiple CFDATA.
212231200Smm		 */
213231200Smm		assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
214238856Smm		assertEqualInt((AE_IFREG | 0666), archive_entry_mode(ae));
215231200Smm		assertEqualString("zero", archive_entry_pathname(ae));
216231200Smm		assertEqualInt(0, archive_entry_uid(ae));
217231200Smm		assertEqualInt(0, archive_entry_gid(ae));
218231200Smm		assertEqualInt(33000, archive_entry_size(ae));
219231200Smm		for (s = 0; s + sizeof(buff) < 33000; s+= sizeof(buff)) {
220231200Smm			ssize_t rsize = archive_read_data(a, buff, sizeof(buff));
221231200Smm			if (comp == MSZIP && rsize == ARCHIVE_FATAL && !libz_enabled) {
222231200Smm				skipping("Skipping CAB format(MSZIP) check: %s",
223231200Smm				    archive_error_string(a));
224231200Smm				goto finish;
225231200Smm			}
226231200Smm			assertEqualInt(sizeof(buff), rsize);
227231200Smm			assertEqualMem(buff, zero, sizeof(buff));
228231200Smm		}
229231200Smm		assertEqualInt(33000 - s, archive_read_data(a, buff, 33000 - s));
230231200Smm		assertEqualMem(buff, zero, 33000 - s);
231231200Smm	}
232231200Smm
233231200Smm	/* Verify regular file1. */
234231200Smm	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
235238856Smm	assertEqualInt((AE_IFREG | 0666), archive_entry_mode(ae));
236231200Smm	assertEqualString("dir1/file1", archive_entry_pathname(ae));
237231200Smm	assertEqualInt(0, archive_entry_uid(ae));
238231200Smm	assertEqualInt(0, archive_entry_gid(ae));
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));
249231200Smm	assertEqualInt(file2_size, archive_entry_size(ae));
250231200Smm	assertEqualInt(file2_size, archive_read_data(a, buff, file2_size));
251231200Smm	assertEqualMem(buff, file2, file2_size);
252231200Smm
253231200Smm	/* End of archive. */
254231200Smm	assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae));
255231200Smm
256231200Smm	if (comp != STORE) {
257231200Smm		assertEqualInt(4, archive_file_count(a));
258231200Smm	} else {
259231200Smm		assertEqualInt(3, archive_file_count(a));
260231200Smm	}
261231200Smm
262231200Smm	/* Verify archive format. */
263248616Smm	assertEqualIntA(a, ARCHIVE_FILTER_NONE, archive_filter_code(a, 0));
264231200Smm	assertEqualIntA(a, ARCHIVE_FORMAT_CAB, archive_format(a));
265231200Smm
266231200Smm	/* Close the archive. */
267231200Smmfinish:
268231200Smm	assertEqualInt(ARCHIVE_OK, archive_read_close(a));
269231200Smm	assertEqualInt(ARCHIVE_OK, archive_read_free(a));
270231200Smm}
271231200Smm
272238856Smm/*
273238856Smm * Skip beginning files and Read the last file.
274238856Smm */
275238856Smmstatic void
276238856Smmverify2(const char *refname, enum comp_type comp)
277238856Smm{
278238856Smm	struct archive_entry *ae;
279238856Smm	struct archive *a;
280238856Smm	char buff[128];
281238856Smm	char zero[128];
282238856Smm
283248616Smm	if (comp == MSZIP && !libz_enabled) {
284248616Smm		skipping("Skipping CAB format(MSZIP) check for %s",
285248616Smm		  refname);
286248616Smm		return;
287248616Smm	}
288238856Smm	memset(zero, 0, sizeof(zero));
289238856Smm	extract_reference_file(refname);
290238856Smm	assert((a = archive_read_new()) != NULL);
291238856Smm	assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a));
292238856Smm	assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a));
293238856Smm	assertEqualIntA(a, ARCHIVE_OK,
294238856Smm	    archive_read_open_filename(a, refname, 10240));
295238856Smm
296238856Smm	/* Verify regular empty. */
297238856Smm	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
298238856Smm	if (comp != STORE) {
299238856Smm		assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
300238856Smm	}
301238856Smm	/* Verify regular file1. */
302238856Smm	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
303238856Smm
304238856Smm	/* Verify regular file2. */
305238856Smm	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
306238856Smm	assertEqualInt((AE_IFREG | 0666), archive_entry_mode(ae));
307238856Smm	assertEqualString("dir2/file2", archive_entry_pathname(ae));
308238856Smm	assertEqualInt(0, archive_entry_uid(ae));
309238856Smm	assertEqualInt(0, archive_entry_gid(ae));
310238856Smm	assertEqualInt(file2_size, archive_entry_size(ae));
311238856Smm	assertEqualInt(file2_size, archive_read_data(a, buff, file2_size));
312238856Smm	assertEqualMem(buff, file2, file2_size);
313238856Smm
314238856Smm	/* End of archive. */
315238856Smm	assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae));
316238856Smm
317238856Smm	if (comp != STORE) {
318238856Smm		assertEqualInt(4, archive_file_count(a));
319238856Smm	} else {
320238856Smm		assertEqualInt(3, archive_file_count(a));
321238856Smm	}
322238856Smm
323238856Smm	/* Verify archive format. */
324248616Smm	assertEqualIntA(a, ARCHIVE_FILTER_NONE, archive_filter_code(a, 0));
325238856Smm	assertEqualIntA(a, ARCHIVE_FORMAT_CAB, archive_format(a));
326238856Smm
327238856Smm	/* Close the archive. */
328238856Smm	assertEqualInt(ARCHIVE_OK, archive_read_close(a));
329238856Smm	assertEqualInt(ARCHIVE_OK, archive_read_free(a));
330238856Smm}
331238856Smm
332238856Smm/*
333238856Smm * Skip all file like 'bsdtar tvf foo.cab'.
334238856Smm */
335238856Smmstatic void
336238856Smmverify3(const char *refname, enum comp_type comp)
337238856Smm{
338238856Smm	struct archive_entry *ae;
339238856Smm	struct archive *a;
340238856Smm	char zero[128];
341238856Smm
342238856Smm	memset(zero, 0, sizeof(zero));
343238856Smm	extract_reference_file(refname);
344238856Smm	assert((a = archive_read_new()) != NULL);
345238856Smm	assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a));
346238856Smm	assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a));
347238856Smm	assertEqualIntA(a, ARCHIVE_OK,
348238856Smm	    archive_read_open_filename(a, refname, 10240));
349238856Smm
350238856Smm	/* Verify regular empty. */
351238856Smm	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
352238856Smm	if (comp != STORE) {
353238856Smm		assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
354238856Smm	}
355238856Smm	/* Verify regular file1. */
356238856Smm	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
357238856Smm
358238856Smm	/* Verify regular file2. */
359238856Smm	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
360238856Smm
361238856Smm	/* End of archive. */
362238856Smm	assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae));
363238856Smm
364238856Smm	if (comp != STORE) {
365238856Smm		assertEqualInt(4, archive_file_count(a));
366238856Smm	} else {
367238856Smm		assertEqualInt(3, archive_file_count(a));
368238856Smm	}
369238856Smm
370238856Smm	/* Verify archive format. */
371248616Smm	assertEqualIntA(a, ARCHIVE_FILTER_NONE, archive_filter_code(a, 0));
372238856Smm	assertEqualIntA(a, ARCHIVE_FORMAT_CAB, archive_format(a));
373238856Smm
374238856Smm	/* Close the archive. */
375238856Smm	assertEqualInt(ARCHIVE_OK, archive_read_close(a));
376238856Smm	assertEqualInt(ARCHIVE_OK, archive_read_free(a));
377238856Smm}
378238856Smm
379231200SmmDEFINE_TEST(test_read_format_cab)
380231200Smm{
381231200Smm	/* Verify Cabinet file in no compression. */
382231200Smm	verify("test_read_format_cab_1.cab", STORE);
383238856Smm	verify2("test_read_format_cab_1.cab", STORE);
384238856Smm	verify3("test_read_format_cab_1.cab", STORE);
385231200Smm	/* Verify Cabinet file in MSZIP. */
386231200Smm	verify("test_read_format_cab_2.cab", MSZIP);
387238856Smm	verify2("test_read_format_cab_2.cab", MSZIP);
388238856Smm	verify3("test_read_format_cab_2.cab", MSZIP);
389231200Smm	/* Verify Cabinet file in LZX. */
390231200Smm	verify("test_read_format_cab_3.cab", LZX);
391238856Smm	verify2("test_read_format_cab_3.cab", LZX);
392238856Smm	verify3("test_read_format_cab_3.cab", LZX);
393231200Smm}
394231200Smm
395