test_read_format_cab.c revision 248616
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__FBSDID("$FreeBSD");
27
28#ifdef HAVE_LIBZ
29static const int libz_enabled = 1;
30#else
31static const int libz_enabled = 0;
32#endif
33
34/*
35Execute the following command to rebuild the data for this program:
36   tail -n +44 test_read_format_cab.c | /bin/sh
37And following works are:
381. Move /tmp/cab/cab.zip to Windows PC
392. Extract cab.zip
403. Open command prompt and change current directory where you extracted cab.zip
414. Execute cab.bat
425. Then you will see that there is a cabinet file, test.cab
436. Move test.cab to posix platform
447. Extract test.cab with this version of bsdtar
458. Execute the following command to make uuencoded files.
46 uuencode test_read_format_cab_1.cab test_read_format_cab_1.cab > test_read_format_cab_1.cab.uu
47 uuencode test_read_format_cab_2.cab test_read_format_cab_2.cab > test_read_format_cab_2.cab.uu
48 uuencode test_read_format_cab_3.cab test_read_format_cab_3.cab > test_read_format_cab_3.cab.uu
49
50#!/bin/sh
51#
52# How to make test data.
53#
54# Temporary directory.
55base=/tmp/cab
56# Owner id
57owner=1001
58# Group id
59group=1001
60#
61# Make contents of a cabinet file.
62#
63rm -rf ${base}
64mkdir ${base}
65mkdir ${base}/dir1
66mkdir ${base}/dir2
67#
68touch ${base}/empty
69cat > ${base}/dir1/file1 << END
70                          file 1 contents
71hello
72hello
73hello
74END
75#
76cat > ${base}/dir2/file2 << END
77                          file 2 contents
78hello
79hello
80hello
81hello
82hello
83hello
84END
85#
86dd if=/dev/zero of=${base}/zero bs=1 count=33000 > /dev/null 2>&1
87#
88cab1=test_read_format_cab_1.cab
89cab2=test_read_format_cab_2.cab
90cab3=test_read_format_cab_3.cab
91#
92#
93cat > ${base}/mkcab1 << END
94.Set Compress=OFF
95.Set DiskDirectory1=.
96.Set InfDate=1980-01-02
97.Set InfTime=00:00:00
98.Set CabinetName1=${cab1}
99empty
100.Set DestinationDir=dir1
101dir1/file1
102.Set DestinationDir=dir2
103dir2/file2
104END
105#
106cat > ${base}/mkcab2 << END
107.Set CompressionType=MSZIP
108.Set DiskDirectory1=.
109.Set InfDate=1980-01-02
110.Set InfTime=00:00:00
111.Set CabinetName1=${cab2}
112empty
113zero
114.Set DestinationDir=dir1
115dir1/file1
116.Set DestinationDir=dir2
117dir2/file2
118END
119#
120cat > ${base}/mkcab3 << END
121.Set CompressionType=LZX
122.Set DiskDirectory1=.
123.Set InfDate=1980-01-02
124.Set InfTime=00:00:00
125.Set CabinetName1=${cab3}
126empty
127zero
128.Set DestinationDir=dir1
129dir1/file1
130.Set DestinationDir=dir2
131dir2/file2
132END
133#
134cat > ${base}/mkcab4 << END
135.Set CompressionType=MSZIP
136.Set DiskDirectory1=.
137.Set CabinetName1=test.cab
138${cab1}
139${cab2}
140${cab3}
141END
142#
143cat > ${base}/cab.bat << END
144makecab.exe /F mkcab1
145makecab.exe /F mkcab2
146makecab.exe /F mkcab3
147makecab.exe /F mkcab4
148del setup.inf setup.rpt
149del empty zero dir1\file1 dir2\file2 mkcab1 mkcab2 mkcab3 mkcab4
150del ${cab1} ${cab2} ${cab3}
151rmdir dir1 dir2
152END
153#
154f=cab.zip
155(cd ${base}; zip -q -c $f empty zero dir1/file1 dir2/file2 mkcab1 mkcab2 mkcab3 mkcab4 cab.bat)
156#
157exit 1
158*/
159
160static const char file1[] = {
161"                          file 1 contents\n"
162"hello\n"
163"hello\n"
164"hello\n"
165};
166#define file1_size (sizeof(file1)-1)
167static const char file2[] = {
168"                          file 2 contents\n"
169"hello\n"
170"hello\n"
171"hello\n"
172"hello\n"
173"hello\n"
174"hello\n"
175};
176#define file2_size (sizeof(file2)-1)
177
178enum comp_type {
179	STORE = 0,
180	MSZIP,
181	LZX
182};
183static void
184verify(const char *refname, enum comp_type comp)
185{
186	struct archive_entry *ae;
187	struct archive *a;
188	char buff[128];
189	char zero[128];
190	size_t s;
191
192	memset(zero, 0, sizeof(zero));
193	extract_reference_file(refname);
194	assert((a = archive_read_new()) != NULL);
195	assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a));
196	assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a));
197	assertEqualIntA(a, ARCHIVE_OK,
198	    archive_read_open_filename(a, refname, 10240));
199
200	/* Verify regular empty. */
201	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
202	assertEqualInt((AE_IFREG | 0666), archive_entry_mode(ae));
203	assertEqualString("empty", archive_entry_pathname(ae));
204	assertEqualInt(0, archive_entry_uid(ae));
205	assertEqualInt(0, archive_entry_gid(ae));
206	assertEqualInt(0, archive_entry_size(ae));
207
208	if (comp != STORE) {
209		/* Verify regular zero.
210		 * Maximum CFDATA size is 32768, so we need over 32768 bytes
211		 * file to check if we properly handle multiple CFDATA.
212		 */
213		assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
214		assertEqualInt((AE_IFREG | 0666), archive_entry_mode(ae));
215		assertEqualString("zero", archive_entry_pathname(ae));
216		assertEqualInt(0, archive_entry_uid(ae));
217		assertEqualInt(0, archive_entry_gid(ae));
218		assertEqualInt(33000, archive_entry_size(ae));
219		for (s = 0; s + sizeof(buff) < 33000; s+= sizeof(buff)) {
220			ssize_t rsize = archive_read_data(a, buff, sizeof(buff));
221			if (comp == MSZIP && rsize == ARCHIVE_FATAL && !libz_enabled) {
222				skipping("Skipping CAB format(MSZIP) check: %s",
223				    archive_error_string(a));
224				goto finish;
225			}
226			assertEqualInt(sizeof(buff), rsize);
227			assertEqualMem(buff, zero, sizeof(buff));
228		}
229		assertEqualInt(33000 - s, archive_read_data(a, buff, 33000 - s));
230		assertEqualMem(buff, zero, 33000 - s);
231	}
232
233	/* Verify regular file1. */
234	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
235	assertEqualInt((AE_IFREG | 0666), archive_entry_mode(ae));
236	assertEqualString("dir1/file1", archive_entry_pathname(ae));
237	assertEqualInt(0, archive_entry_uid(ae));
238	assertEqualInt(0, archive_entry_gid(ae));
239	assertEqualInt(file1_size, archive_entry_size(ae));
240	assertEqualInt(file1_size, archive_read_data(a, buff, file1_size));
241	assertEqualMem(buff, file1, file1_size);
242
243	/* Verify regular file2. */
244	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
245	assertEqualInt((AE_IFREG | 0666), archive_entry_mode(ae));
246	assertEqualString("dir2/file2", archive_entry_pathname(ae));
247	assertEqualInt(0, archive_entry_uid(ae));
248	assertEqualInt(0, archive_entry_gid(ae));
249	assertEqualInt(file2_size, archive_entry_size(ae));
250	assertEqualInt(file2_size, archive_read_data(a, buff, file2_size));
251	assertEqualMem(buff, file2, file2_size);
252
253	/* End of archive. */
254	assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae));
255
256	if (comp != STORE) {
257		assertEqualInt(4, archive_file_count(a));
258	} else {
259		assertEqualInt(3, archive_file_count(a));
260	}
261
262	/* Verify archive format. */
263	assertEqualIntA(a, ARCHIVE_FILTER_NONE, archive_filter_code(a, 0));
264	assertEqualIntA(a, ARCHIVE_FORMAT_CAB, archive_format(a));
265
266	/* Close the archive. */
267finish:
268	assertEqualInt(ARCHIVE_OK, archive_read_close(a));
269	assertEqualInt(ARCHIVE_OK, archive_read_free(a));
270}
271
272/*
273 * Skip beginning files and Read the last file.
274 */
275static void
276verify2(const char *refname, enum comp_type comp)
277{
278	struct archive_entry *ae;
279	struct archive *a;
280	char buff[128];
281	char zero[128];
282
283	if (comp == MSZIP && !libz_enabled) {
284		skipping("Skipping CAB format(MSZIP) check for %s",
285		  refname);
286		return;
287	}
288	memset(zero, 0, sizeof(zero));
289	extract_reference_file(refname);
290	assert((a = archive_read_new()) != NULL);
291	assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a));
292	assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a));
293	assertEqualIntA(a, ARCHIVE_OK,
294	    archive_read_open_filename(a, refname, 10240));
295
296	/* Verify regular empty. */
297	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
298	if (comp != STORE) {
299		assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
300	}
301	/* Verify regular file1. */
302	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
303
304	/* Verify regular file2. */
305	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
306	assertEqualInt((AE_IFREG | 0666), archive_entry_mode(ae));
307	assertEqualString("dir2/file2", archive_entry_pathname(ae));
308	assertEqualInt(0, archive_entry_uid(ae));
309	assertEqualInt(0, archive_entry_gid(ae));
310	assertEqualInt(file2_size, archive_entry_size(ae));
311	assertEqualInt(file2_size, archive_read_data(a, buff, file2_size));
312	assertEqualMem(buff, file2, file2_size);
313
314	/* End of archive. */
315	assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae));
316
317	if (comp != STORE) {
318		assertEqualInt(4, archive_file_count(a));
319	} else {
320		assertEqualInt(3, archive_file_count(a));
321	}
322
323	/* Verify archive format. */
324	assertEqualIntA(a, ARCHIVE_FILTER_NONE, archive_filter_code(a, 0));
325	assertEqualIntA(a, ARCHIVE_FORMAT_CAB, archive_format(a));
326
327	/* Close the archive. */
328	assertEqualInt(ARCHIVE_OK, archive_read_close(a));
329	assertEqualInt(ARCHIVE_OK, archive_read_free(a));
330}
331
332/*
333 * Skip all file like 'bsdtar tvf foo.cab'.
334 */
335static void
336verify3(const char *refname, enum comp_type comp)
337{
338	struct archive_entry *ae;
339	struct archive *a;
340	char zero[128];
341
342	memset(zero, 0, sizeof(zero));
343	extract_reference_file(refname);
344	assert((a = archive_read_new()) != NULL);
345	assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a));
346	assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a));
347	assertEqualIntA(a, ARCHIVE_OK,
348	    archive_read_open_filename(a, refname, 10240));
349
350	/* Verify regular empty. */
351	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
352	if (comp != STORE) {
353		assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
354	}
355	/* Verify regular file1. */
356	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
357
358	/* Verify regular file2. */
359	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
360
361	/* End of archive. */
362	assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae));
363
364	if (comp != STORE) {
365		assertEqualInt(4, archive_file_count(a));
366	} else {
367		assertEqualInt(3, archive_file_count(a));
368	}
369
370	/* Verify archive format. */
371	assertEqualIntA(a, ARCHIVE_FILTER_NONE, archive_filter_code(a, 0));
372	assertEqualIntA(a, ARCHIVE_FORMAT_CAB, archive_format(a));
373
374	/* Close the archive. */
375	assertEqualInt(ARCHIVE_OK, archive_read_close(a));
376	assertEqualInt(ARCHIVE_OK, archive_read_free(a));
377}
378
379DEFINE_TEST(test_read_format_cab)
380{
381	/* Verify Cabinet file in no compression. */
382	verify("test_read_format_cab_1.cab", STORE);
383	verify2("test_read_format_cab_1.cab", STORE);
384	verify3("test_read_format_cab_1.cab", STORE);
385	/* Verify Cabinet file in MSZIP. */
386	verify("test_read_format_cab_2.cab", MSZIP);
387	verify2("test_read_format_cab_2.cab", MSZIP);
388	verify3("test_read_format_cab_2.cab", MSZIP);
389	/* Verify Cabinet file in LZX. */
390	verify("test_read_format_cab_3.cab", LZX);
391	verify2("test_read_format_cab_3.cab", LZX);
392	verify3("test_read_format_cab_3.cab", LZX);
393}
394
395