test_read_format_cab.c revision 238856
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. */
263231200Smm	assertEqualIntA(a, ARCHIVE_COMPRESSION_NONE, archive_compression(a));
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
283238856Smm	memset(zero, 0, sizeof(zero));
284238856Smm	extract_reference_file(refname);
285238856Smm	assert((a = archive_read_new()) != NULL);
286238856Smm	assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a));
287238856Smm	assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a));
288238856Smm	assertEqualIntA(a, ARCHIVE_OK,
289238856Smm	    archive_read_open_filename(a, refname, 10240));
290238856Smm
291238856Smm	/* Verify regular empty. */
292238856Smm	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
293238856Smm	if (comp != STORE) {
294238856Smm		assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
295238856Smm	}
296238856Smm	/* Verify regular file1. */
297238856Smm	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
298238856Smm
299238856Smm	/* Verify regular file2. */
300238856Smm	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
301238856Smm	assertEqualInt((AE_IFREG | 0666), archive_entry_mode(ae));
302238856Smm	assertEqualString("dir2/file2", archive_entry_pathname(ae));
303238856Smm	assertEqualInt(0, archive_entry_uid(ae));
304238856Smm	assertEqualInt(0, archive_entry_gid(ae));
305238856Smm	assertEqualInt(file2_size, archive_entry_size(ae));
306238856Smm	assertEqualInt(file2_size, archive_read_data(a, buff, file2_size));
307238856Smm	assertEqualMem(buff, file2, file2_size);
308238856Smm
309238856Smm	/* End of archive. */
310238856Smm	assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae));
311238856Smm
312238856Smm	if (comp != STORE) {
313238856Smm		assertEqualInt(4, archive_file_count(a));
314238856Smm	} else {
315238856Smm		assertEqualInt(3, archive_file_count(a));
316238856Smm	}
317238856Smm
318238856Smm	/* Verify archive format. */
319238856Smm	assertEqualIntA(a, ARCHIVE_COMPRESSION_NONE, archive_compression(a));
320238856Smm	assertEqualIntA(a, ARCHIVE_FORMAT_CAB, archive_format(a));
321238856Smm
322238856Smm	/* Close the archive. */
323238856Smm	assertEqualInt(ARCHIVE_OK, archive_read_close(a));
324238856Smm	assertEqualInt(ARCHIVE_OK, archive_read_free(a));
325238856Smm}
326238856Smm
327238856Smm/*
328238856Smm * Skip all file like 'bsdtar tvf foo.cab'.
329238856Smm */
330238856Smmstatic void
331238856Smmverify3(const char *refname, enum comp_type comp)
332238856Smm{
333238856Smm	struct archive_entry *ae;
334238856Smm	struct archive *a;
335238856Smm	char zero[128];
336238856Smm
337238856Smm	memset(zero, 0, sizeof(zero));
338238856Smm	extract_reference_file(refname);
339238856Smm	assert((a = archive_read_new()) != NULL);
340238856Smm	assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a));
341238856Smm	assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a));
342238856Smm	assertEqualIntA(a, ARCHIVE_OK,
343238856Smm	    archive_read_open_filename(a, refname, 10240));
344238856Smm
345238856Smm	/* Verify regular empty. */
346238856Smm	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
347238856Smm	if (comp != STORE) {
348238856Smm		assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
349238856Smm	}
350238856Smm	/* Verify regular file1. */
351238856Smm	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
352238856Smm
353238856Smm	/* Verify regular file2. */
354238856Smm	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
355238856Smm
356238856Smm	/* End of archive. */
357238856Smm	assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae));
358238856Smm
359238856Smm	if (comp != STORE) {
360238856Smm		assertEqualInt(4, archive_file_count(a));
361238856Smm	} else {
362238856Smm		assertEqualInt(3, archive_file_count(a));
363238856Smm	}
364238856Smm
365238856Smm	/* Verify archive format. */
366238856Smm	assertEqualIntA(a, ARCHIVE_COMPRESSION_NONE, archive_compression(a));
367238856Smm	assertEqualIntA(a, ARCHIVE_FORMAT_CAB, archive_format(a));
368238856Smm
369238856Smm	/* Close the archive. */
370238856Smm	assertEqualInt(ARCHIVE_OK, archive_read_close(a));
371238856Smm	assertEqualInt(ARCHIVE_OK, archive_read_free(a));
372238856Smm}
373238856Smm
374231200SmmDEFINE_TEST(test_read_format_cab)
375231200Smm{
376231200Smm	/* Verify Cabinet file in no compression. */
377231200Smm	verify("test_read_format_cab_1.cab", STORE);
378238856Smm	verify2("test_read_format_cab_1.cab", STORE);
379238856Smm	verify3("test_read_format_cab_1.cab", STORE);
380231200Smm	/* Verify Cabinet file in MSZIP. */
381231200Smm	verify("test_read_format_cab_2.cab", MSZIP);
382238856Smm	verify2("test_read_format_cab_2.cab", MSZIP);
383238856Smm	verify3("test_read_format_cab_2.cab", MSZIP);
384231200Smm	/* Verify Cabinet file in LZX. */
385231200Smm	verify("test_read_format_cab_3.cab", LZX);
386238856Smm	verify2("test_read_format_cab_3.cab", LZX);
387238856Smm	verify3("test_read_format_cab_3.cab", LZX);
388231200Smm}
389231200Smm
390