xref: /freebsd/contrib/libarchive/libarchive/test/test_write_format_xar.c (revision 185becb1e1bd2657c156f78aeb52edac05ba5fb5)
1 /*-
2  * Copyright (c) 2003-2008 Tim Kientzle
3  * Copyright (c) 2010 Michihiro NAKAJIMA
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
16  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18  * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
19  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25  */
26 #include "test.h"
27 
28 #define __LIBARCHIVE_TEST
29 #include "archive_write_private.h"
30 
31 #include <locale.h>
32 
33 static void
test_xar(const char * option)34 test_xar(const char *option)
35 {
36 	char buff2[64];
37 	size_t buffsize = 4096;
38 	char *buff;
39 	struct archive_entry *ae;
40 	struct archive *a;
41 	size_t used;
42 	const char *name;
43 	const void *value;
44 	size_t size;
45 
46 	/* Create a new archive in memory. */
47 	assert((a = archive_write_new()) != NULL);
48 	if (archive_write_set_format_xar(a) != ARCHIVE_OK) {
49 		skipping("xar is not supported on this platform");
50 		assertEqualInt(ARCHIVE_OK, archive_write_free(a));
51 		return;
52 	}
53 	assertA(0 == archive_write_add_filter_none(a));
54 	if (option != NULL &&
55 	    archive_write_set_options(a, option) != ARCHIVE_OK) {
56 		skipping("option `%s` is not supported on this platform", option);
57 		assertEqualInt(ARCHIVE_OK, archive_write_free(a));
58 		return;
59 	}
60 
61 	buff = malloc(buffsize);
62 	assert(buff != NULL);
63 
64 	assertA(0 == archive_write_open_memory(a, buff, buffsize, &used));
65 
66 	/*
67 	 * "file" has a bunch of attributes and 8 bytes of data and
68 	 * 7 bytes of xattr data and 3 bytes of xattr.
69 	 */
70 	assert((ae = archive_entry_new()) != NULL);
71 	archive_entry_set_atime(ae, 2, 20);
72 	archive_entry_set_ctime(ae, 4, 40);
73 	archive_entry_set_mtime(ae, 5, 50);
74 	archive_entry_copy_pathname(ae, "file");
75 	archive_entry_set_mode(ae, AE_IFREG | 0755);
76 	archive_entry_set_nlink(ae, 2);
77 	archive_entry_set_size(ae, 8);
78 	archive_entry_xattr_add_entry(ae, "user.data1", "ABCDEFG", 7);
79 	archive_entry_xattr_add_entry(ae, "user.data2", "XYZ", 3);
80 	assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae));
81 	archive_entry_free(ae);
82 	assertEqualIntA(a, 8, archive_write_data(a, "12345678", 9));
83 
84 	/*
85 	 * "file2" is symbolic link to file
86 	 */
87 	assert((ae = archive_entry_new()) != NULL);
88 	archive_entry_set_atime(ae, 2, 20);
89 	archive_entry_set_ctime(ae, 4, 40);
90 	archive_entry_set_mtime(ae, 5, 50);
91 	archive_entry_copy_pathname(ae, "file2");
92 	archive_entry_copy_symlink(ae, "file");
93 	archive_entry_set_mode(ae, AE_IFLNK | 0755);
94 	archive_entry_set_size(ae, 0);
95 	assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae));
96 	archive_entry_free(ae);
97 
98 	/*
99 	 * "dir/file" has a bunch of attributes and 8 bytes of data.
100 	 */
101 	assert((ae = archive_entry_new()) != NULL);
102 	archive_entry_set_atime(ae, 2, 20);
103 	archive_entry_set_ctime(ae, 4, 40);
104 	archive_entry_set_mtime(ae, 5, 50);
105 	archive_entry_copy_pathname(ae, "dir/../../dir/file");
106 	archive_entry_set_mode(ae, AE_IFREG | 0755);
107 	archive_entry_set_size(ae, 8);
108 	assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae));
109 	archive_entry_free(ae);
110 	assertEqualIntA(a, 8, archive_write_data(a, "abcdefgh", 9));
111 
112 	/*
113 	 * "dir/dir2/file4" is hard link to file
114 	 */
115 	assert((ae = archive_entry_new()) != NULL);
116 	archive_entry_set_atime(ae, 2, 20);
117 	archive_entry_set_ctime(ae, 4, 40);
118 	archive_entry_set_mtime(ae, 5, 50);
119 	archive_entry_copy_pathname(ae, "dir/..//dir/dir2/file4");
120 	archive_entry_copy_hardlink(ae, "file");
121 	archive_entry_set_mode(ae, AE_IFREG | 0755);
122 	archive_entry_set_nlink(ae, 2);
123 	archive_entry_set_size(ae, 0);
124 	assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae));
125 	archive_entry_free(ae);
126 
127 	/*
128 	 * "dir/dir3" is a directory
129 	 */
130 	assert((ae = archive_entry_new()) != NULL);
131 	archive_entry_set_atime(ae, 2, 20);
132 	archive_entry_set_ctime(ae, 4, 40);
133 	archive_entry_set_mtime(ae, 5, 50);
134 	archive_entry_copy_pathname(ae, "dir/dir3");
135 	archive_entry_set_mode(ae, AE_IFDIR | 0755);
136 	archive_entry_unset_size(ae);
137 	assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae));
138 	archive_entry_free(ae);
139 
140 	/*
141 	 * Add a wrong path "dir/dir2/file4/wrong"
142 	 */
143 	assert((ae = archive_entry_new()) != NULL);
144 	archive_entry_set_atime(ae, 2, 20);
145 	archive_entry_set_ctime(ae, 4, 40);
146 	archive_entry_set_mtime(ae, 5, 50);
147 	archive_entry_copy_pathname(ae, "dir/dir2/file4/wrong");
148 	archive_entry_set_mode(ae, AE_IFREG | 0755);
149 	archive_entry_set_nlink(ae, 1);
150 	archive_entry_set_size(ae, 0);
151 	assertEqualIntA(a, ARCHIVE_FAILED, archive_write_header(a, ae));
152 	archive_entry_free(ae);
153 
154 	/*
155 	 * "dir/file{UNICODE}" has a name that requires base64 encoding
156 	 */
157 	assert((ae = archive_entry_new()) != NULL);
158 	archive_entry_set_atime(ae, 2, 20);
159 	archive_entry_set_ctime(ae, 4, 40);
160 	archive_entry_set_mtime(ae, 5, 50);
161 	archive_entry_copy_pathname_w(ae, L"dir/file\U0001F574");
162 	archive_entry_set_mode(ae, AE_IFREG | 0755);
163 	archive_entry_set_size(ae, 8);
164 	assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae));
165 	archive_entry_free(ae);
166 	assertEqualIntA(a, 8, archive_write_data(a, "ghijklmn", 9));
167 
168 	/*
169 	 * XXX TODO XXX Archive directory, other file types.
170 	 * Archive extended attributes, ACLs, other metadata.
171 	 * Verify they get read back correctly.
172 	 */
173 
174 	/* Close out the archive. */
175 	assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a));
176 	assertEqualInt(ARCHIVE_OK, archive_write_free(a));
177 
178 	/*
179 	 *
180 	 * Now, read the data back.
181 	 *
182 	 */
183 	assert((a = archive_read_new()) != NULL);
184 	assertEqualIntA(a, 0, archive_read_support_format_all(a));
185 	assertEqualIntA(a, 0, archive_read_support_filter_all(a));
186 	assertEqualIntA(a, 0, archive_read_open_memory(a, buff, used));
187 
188 	/*
189 	 * Read "file"
190 	 */
191 	assertEqualIntA(a, 0, archive_read_next_header(a, &ae));
192 	assertEqualInt(2, archive_entry_atime(ae));
193 	assertEqualInt(0, archive_entry_atime_nsec(ae));
194 	assertEqualInt(4, archive_entry_ctime(ae));
195 	assertEqualInt(0, archive_entry_ctime_nsec(ae));
196 	assertEqualInt(5, archive_entry_mtime(ae));
197 	assertEqualInt(0, archive_entry_mtime_nsec(ae));
198 	assertEqualString("file", archive_entry_pathname(ae));
199 	assert((AE_IFREG | 0755) == archive_entry_mode(ae));
200 	assertEqualInt(2, archive_entry_nlink(ae));
201 	assertEqualInt(8, archive_entry_size(ae));
202 	assertEqualInt(2, archive_entry_xattr_reset(ae));
203 	assertEqualInt(ARCHIVE_OK,
204 	    archive_entry_xattr_next(ae, &name, &value, &size));
205 	assertEqualString("user.data2", name);
206 	assertEqualMem(value, "XYZ", 3);
207 	assertEqualInt(ARCHIVE_OK,
208 	    archive_entry_xattr_next(ae, &name, &value, &size));
209 	assertEqualString("user.data1", name);
210 	assertEqualMem(value, "ABCDEFG", 7);
211 	assertEqualIntA(a, 8, archive_read_data(a, buff2, 10));
212 	assertEqualMem(buff2, "12345678", 8);
213 
214 	/*
215 	 * Read "file2"
216 	 */
217 	assertEqualIntA(a, 0, archive_read_next_header(a, &ae));
218 	assert(archive_entry_atime_is_set(ae));
219 	assertEqualInt(2, archive_entry_atime(ae));
220 	assertEqualInt(0, archive_entry_atime_nsec(ae));
221 	assert(archive_entry_ctime_is_set(ae));
222 	assertEqualInt(4, archive_entry_ctime(ae));
223 	assertEqualInt(0, archive_entry_ctime_nsec(ae));
224 	assert(archive_entry_mtime_is_set(ae));
225 	assertEqualInt(5, archive_entry_mtime(ae));
226 	assertEqualInt(0, archive_entry_mtime_nsec(ae));
227 	assertEqualString("file2", archive_entry_pathname(ae));
228 	assertEqualString("file", archive_entry_symlink(ae));
229 	assert((AE_IFLNK | 0755) == archive_entry_mode(ae));
230 	assertEqualInt(0, archive_entry_size(ae));
231 
232 	/*
233 	 * Read "dir/file3"
234 	 */
235 	assertEqualIntA(a, 0, archive_read_next_header(a, &ae));
236 	assertEqualInt(2, archive_entry_atime(ae));
237 	assertEqualInt(0, archive_entry_atime_nsec(ae));
238 	assertEqualInt(4, archive_entry_ctime(ae));
239 	assertEqualInt(0, archive_entry_ctime_nsec(ae));
240 	assertEqualInt(5, archive_entry_mtime(ae));
241 	assertEqualInt(0, archive_entry_mtime_nsec(ae));
242 	assertEqualString("dir/file", archive_entry_pathname(ae));
243 	assert((AE_IFREG | 0755) == archive_entry_mode(ae));
244 	assertEqualInt(8, archive_entry_size(ae));
245 	assertEqualIntA(a, 8, archive_read_data(a, buff2, 10));
246 	assertEqualMem(buff2, "abcdefgh", 8);
247 
248 	/*
249 	 * Read "dir/dir2/file4"
250 	 */
251 	assertEqualIntA(a, 0, archive_read_next_header(a, &ae));
252 	assert(archive_entry_atime_is_set(ae));
253 	assertEqualInt(2, archive_entry_atime(ae));
254 	assertEqualInt(0, archive_entry_atime_nsec(ae));
255 	assert(archive_entry_ctime_is_set(ae));
256 	assertEqualInt(4, archive_entry_ctime(ae));
257 	assertEqualInt(0, archive_entry_ctime_nsec(ae));
258 	assert(archive_entry_mtime_is_set(ae));
259 	assertEqualInt(5, archive_entry_mtime(ae));
260 	assertEqualInt(0, archive_entry_mtime_nsec(ae));
261 	assertEqualString("dir/dir2/file4", archive_entry_pathname(ae));
262 	assertEqualString("file", archive_entry_hardlink(ae));
263 	assert((AE_IFREG | 0755) == archive_entry_mode(ae));
264 	assertEqualInt(2, archive_entry_nlink(ae));
265 	assertEqualInt(0, archive_entry_size(ae));
266 
267 	/*
268 	 * Read "dir/dir3"
269 	 */
270 	assertEqualIntA(a, 0, archive_read_next_header(a, &ae));
271 	assert(archive_entry_atime_is_set(ae));
272 	assertEqualInt(2, archive_entry_atime(ae));
273 	assertEqualInt(0, archive_entry_atime_nsec(ae));
274 	assert(archive_entry_ctime_is_set(ae));
275 	assertEqualInt(4, archive_entry_ctime(ae));
276 	assertEqualInt(0, archive_entry_ctime_nsec(ae));
277 	assert(archive_entry_mtime_is_set(ae));
278 	assertEqualInt(5, archive_entry_mtime(ae));
279 	assertEqualInt(0, archive_entry_mtime_nsec(ae));
280 	assertEqualString("dir/dir3", archive_entry_pathname(ae));
281 	assert((AE_IFDIR | 0755) == archive_entry_mode(ae));
282 
283 	/*
284 	 * Read "dir/file{UNICODE}"
285 	 */
286 	assertEqualIntA(a, 0, archive_read_next_header(a, &ae));
287 	assertEqualInt(2, archive_entry_atime(ae));
288 	assertEqualInt(0, archive_entry_atime_nsec(ae));
289 	assertEqualInt(4, archive_entry_ctime(ae));
290 	assertEqualInt(0, archive_entry_ctime_nsec(ae));
291 	assertEqualInt(5, archive_entry_mtime(ae));
292 	assertEqualInt(0, archive_entry_mtime_nsec(ae));
293 	assertEqualWString(L"dir/file\U0001F574", archive_entry_pathname_w(ae));
294 	assert((AE_IFREG | 0755) == archive_entry_mode(ae));
295 	assertEqualInt(8, archive_entry_size(ae));
296 	assertEqualIntA(a, 8, archive_read_data(a, buff2, 10));
297 	assertEqualMem(buff2, "ghijklmn", 8);
298 
299 	/*
300 	 * Verify the end of the archive.
301 	 */
302 	assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae));
303 	assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a));
304 	assertEqualInt(ARCHIVE_OK, archive_read_free(a));
305 
306 	free(buff);
307 }
308 
DEFINE_TEST(test_write_format_xar)309 DEFINE_TEST(test_write_format_xar)
310 {
311 	/* xar mandates the use of UTF-8 XML; if we cannot
312 	 * use UTF-8, perhaps we should not write xar. */
313 	if (NULL == setlocale(LC_ALL, "en_US.UTF-8")) {
314 		skipping("en_US.UTF-8 locale not available on this system.");
315 		return;
316 	}
317 
318 	/* Default mode. */
319 	test_xar(NULL);
320 
321 	/* Disable TOC checksum. */
322 	test_xar("!toc-checksum");
323 	test_xar("toc-checksum=none");
324 #ifdef ARCHIVE_HAS_SHA1
325 	/* Specify TOC checksum type to sha1. */
326 	test_xar("toc-checksum=sha1");
327 #endif
328 #ifdef ARCHIVE_HAS_MD5
329 	/* Specify TOC checksum type to md5. */
330 	test_xar("toc-checksum=md5");
331 #endif
332 #ifdef ARCHIVE_HAS_SHA256
333 	/* Specify TOC checksum type to sha256. */
334 	test_xar("toc-checksum=sha256");
335 #endif
336 #ifdef ARCHIVE_HAS_SHA512
337 	/* Specify TOC checksum type to sha512. */
338 	test_xar("toc-checksum=sha512");
339 #endif
340 
341 	/* Disable file checksum. */
342 	test_xar("!checksum");
343 	test_xar("checksum=none");
344 #ifdef ARCHIVE_HAS_SHA1
345 	/* Specify file checksum type to sha1. */
346 	test_xar("checksum=sha1");
347 #endif
348 #ifdef ARCHIVE_HAS_MD5
349 	/* Specify file checksum type to md5. */
350 	test_xar("checksum=md5");
351 #endif
352 #ifdef ARCHIVE_HAS_SHA256
353 	/* Specify file checksum type to sha256. */
354 	test_xar("checksum=sha256");
355 #endif
356 #ifdef ARCHIVE_HAS_SHA512
357 	/* Specify file checksum type to sha512. */
358 	test_xar("checksum=sha512");
359 #endif
360 
361 	/* Disable compression. */
362 	test_xar("!compression");
363 	test_xar("compression=none");
364 	/* Specify compression type to gzip. */
365 	test_xar("compression=gzip");
366 	test_xar("compression=gzip,compression-level=1");
367 	test_xar("compression=gzip,compression-level=9");
368 	/* Specify compression type to bzip2. */
369 	test_xar("compression=bzip2");
370 	test_xar("compression=bzip2,compression-level=1");
371 	test_xar("compression=bzip2,compression-level=9");
372 	/* Specify compression type to lzma. */
373 	test_xar("compression=lzma");
374 	test_xar("compression=lzma,compression-level=1");
375 	test_xar("compression=lzma,compression-level=9");
376 	/* Specify compression type to xz. */
377 	test_xar("compression=xz");
378 	test_xar("compression=xz,compression-level=1");
379 	test_xar("compression=xz,compression-level=9");
380 }
381 
DEFINE_TEST(test_write_format_xar_entry_trunc)382 DEFINE_TEST(test_write_format_xar_entry_trunc)
383 {
384 	struct archive *a;
385 	struct archive_entry *ae;
386 	unsigned char buff[1024];
387 	size_t used = 0;
388 
389 	assert((a = archive_write_new()) != NULL);
390 	if (archive_write_set_format_xar(a) != ARCHIVE_OK) {
391 		skipping("xar is not supported on this platform");
392 		assertEqualInt(ARCHIVE_OK, archive_write_free(a));
393 		return;
394 	}
395 	assertEqualIntA(a, ARCHIVE_OK, archive_write_add_filter_none(a));
396 	assertEqualIntA(a, ARCHIVE_OK,
397 	    archive_write_open_memory(a, buff, sizeof(buff), &used));
398 
399 	assert((ae = archive_entry_new()) != NULL);
400 	archive_entry_set_pathname(ae, "foo");
401 	archive_entry_set_mode(ae, S_IFREG | 0644);
402 	archive_entry_set_size(ae, 1028);
403 	assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae));
404 	archive_entry_free(ae);
405 	assertEqualIntA(a, 3, archive_write_data(a, "foo", 3));
406 
407 	assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a));
408 	assertEqualInt(ARCHIVE_OK, archive_write_free(a));
409 }
410 
DEFINE_TEST(test_write_format_xar_unregister)411 DEFINE_TEST(test_write_format_xar_unregister)
412 {
413 	struct archive *a;
414 	struct archive_write *aw;
415 
416 	assert((a = archive_write_new()) != NULL);
417 	if (archive_write_set_format_xar(a) != ARCHIVE_OK) {
418 		skipping("xar is not supported on this platform");
419 		assertEqualInt(ARCHIVE_OK, archive_write_free(a));
420 		return;
421 	}
422 
423 	aw = (struct archive_write *)a;
424 	assert(aw->format_data != NULL);
425 	assert(aw->format_free != NULL);
426 
427 	assertEqualIntA(a, ARCHIVE_OK,
428 	    __archive_write_unregister_format(aw));
429 
430 	assert(aw->format_data == NULL);
431 	assert(aw->format_name == NULL);
432 	assert(aw->format_init == NULL);
433 	assert(aw->format_options == NULL);
434 	assert(aw->format_finish_entry == NULL);
435 	assert(aw->format_write_header == NULL);
436 	assert(aw->format_write_data == NULL);
437 	assert(aw->format_close == NULL);
438 	assert(aw->format_free == NULL);
439 	assertEqualInt(0, aw->archive.archive_format);
440 	assert(aw->archive.archive_format_name == NULL);
441 
442 	assertEqualIntA(a, ARCHIVE_FAILED,
443 	    archive_write_set_format_option(a, NULL, "compression",
444 	        "gzip"));
445 
446 	assertEqualIntA(a, ARCHIVE_OK,
447 	    __archive_write_unregister_format(aw));
448 	assertEqualInt(ARCHIVE_OK, archive_write_free(a));
449 }
450