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
verify(const char * refname,enum comp_type comp)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
verify2(const char * refname,enum comp_type comp)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
verify3(const char * refname,enum comp_type comp)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
DEFINE_TEST(test_read_format_cab)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