1 /*-
2  * Copyright (c) 2003-2007 Tim Kientzle
3  * Copyright (c) 2011-2012 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 __FBSDID("$FreeBSD$");
28 
29 static void
30 test_read_format_mtree1(void)
31 {
32 	const char reffile[] = "test_read_format_mtree.mtree";
33 	char buff[16];
34 	struct archive_entry *ae;
35 	struct archive *a;
36 	FILE *f;
37 	/* Compute max 64-bit signed twos-complement value
38 	 * without relying on overflow.  This assumes that long long
39 	 * is at least 64 bits. */
40 	static const long long max_int64 = ((((long long)1) << 62) - 1) + (((long long)1) << 62);
41 	time_t min_time;
42 	volatile time_t t;
43 
44 	extract_reference_file(reffile);
45 
46 	/*
47 	 * An access error occurred on some platform when mtree
48 	 * format handling open a directory. It is for through
49 	 * the routine which open a directory that we create
50 	 * "dir" and "dir2" directories.
51 	 */
52 	assertMakeDir("dir", 0775);
53 	assertMakeDir("dir2", 0775);
54 
55 	assert((a = archive_read_new()) != NULL);
56 	assertEqualIntA(a, ARCHIVE_OK,
57 	    archive_read_support_filter_all(a));
58 	assertEqualIntA(a, ARCHIVE_OK,
59 	    archive_read_support_format_all(a));
60 	assertEqualIntA(a, ARCHIVE_OK,
61 	    archive_read_open_filename(a, reffile, 11));
62 
63 	/*
64 	 * Read "file", whose data is available on disk.
65 	 */
66 	f = fopen("file", "wb");
67 	assert(f != NULL);
68 	assertEqualInt(3, fwrite("hi\n", 1, 3, f));
69 	fclose(f);
70 	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
71 	assertEqualInt(archive_format(a), ARCHIVE_FORMAT_MTREE);
72 	assertEqualString(archive_entry_pathname(ae), "file");
73 	assertEqualInt(archive_entry_uid(ae), 18);
74 	assertEqualInt(AE_IFREG, archive_entry_filetype(ae));
75 	assertEqualInt(archive_entry_mode(ae), AE_IFREG | 0123);
76 	assertEqualInt(archive_entry_size(ae), 3);
77 	assertEqualInt(3, archive_read_data(a, buff, 3));
78 	assertEqualMem(buff, "hi\n", 3);
79 
80 	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
81 	assertEqualString(archive_entry_pathname(ae), "dir");
82 	assertEqualInt(AE_IFDIR, archive_entry_filetype(ae));
83 
84 	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
85 	assertEqualString(archive_entry_pathname(ae), "dir/file with space");
86 
87 	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
88 	assertEqualString(archive_entry_pathname(ae), "file with space");
89 
90 	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
91 	assertEqualString(archive_entry_pathname(ae), "dir2");
92 
93 	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
94 	assertEqualString(archive_entry_pathname(ae), "dir2/dir3a");
95 
96 	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
97 	assertEqualString(archive_entry_pathname(ae), "dir2/dir3a/indir3a");
98 
99 	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
100 	assertEqualString(archive_entry_pathname(ae), "dir2/fullindir2");
101 	assertEqualInt(archive_entry_mode(ae), AE_IFREG | 0644);
102 
103 	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
104 	assertEqualString(archive_entry_pathname(ae), "dir2/indir2");
105 
106 	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
107 	assertEqualString(archive_entry_pathname(ae), "dir2/dir3b");
108 
109 	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
110 	assertEqualString(archive_entry_pathname(ae), "dir2/dir3b/indir3b");
111 
112 	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
113 	assertEqualString(archive_entry_pathname(ae), "notindir");
114 
115 	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
116 	assertEqualString(archive_entry_pathname(ae), "dir2/emptyfile");
117 	assertEqualInt(archive_entry_size(ae), 0);
118 
119 	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
120 	assertEqualString(archive_entry_pathname(ae), "dir2/smallfile");
121 	assertEqualInt(archive_entry_size(ae), 1);
122 
123 	/* TODO: Mtree reader should probably return ARCHIVE_WARN for this. */
124 	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
125 	assertEqualString(archive_entry_pathname(ae), "dir2/toosmallfile");
126 	assertEqualInt(archive_entry_size(ae), -1);
127 
128 	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
129 	assertEqualString(archive_entry_pathname(ae), "dir2/bigfile");
130 	assertEqualInt(archive_entry_size(ae), max_int64);
131 
132 	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
133 	assertEqualString(archive_entry_pathname(ae), "dir2/toobigfile");
134 	/* Size in mtree is max_int64 + 1; should return max_int64. */
135 	assertEqualInt(archive_entry_size(ae), max_int64);
136 
137 	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
138 	assertEqualString(archive_entry_pathname(ae), "dir2/veryoldfile");
139 	/* The value in the file is MIN_INT64_T, but time_t may be narrower. */
140 	/* Verify min_time is the smallest possible time_t. */
141 	min_time = archive_entry_mtime(ae);
142 	assert(min_time <= 0);
143 	/* Simply asserting min_time - 1 > 0 breaks with some compiler optimizations. */
144 	t = min_time - 1;
145 	assert(t > 0);
146 
147 	/* toooldfile is 1 sec older, which should overflow and get returned
148 	 * with the same value. */
149 	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
150 	assertEqualString(archive_entry_pathname(ae), "dir2/toooldfile");
151 	assertEqualInt(archive_entry_mtime(ae), min_time);
152 
153 	assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae));
154 	assertEqualInt(19, archive_file_count(a));
155 	assertEqualInt(ARCHIVE_OK, archive_read_close(a));
156 	assertEqualInt(ARCHIVE_OK, archive_read_free(a));
157 }
158 
159 static void
160 test_read_format_mtree2(void)
161 {
162 	static char archive[] =
163 	    "#mtree\n"
164 	    "d type=dir content=.\n";
165 	struct archive_entry *ae;
166 	struct archive *a;
167 
168 	assert((a = archive_read_new()) != NULL);
169 	assertEqualIntA(a, ARCHIVE_OK,
170 	    archive_read_support_filter_all(a));
171 	assertEqualIntA(a, ARCHIVE_OK,
172 	    archive_read_support_format_all(a));
173 	assertEqualIntA(a, ARCHIVE_OK,
174 	    archive_read_open_memory(a, archive, sizeof(archive)));
175 	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
176 	assertEqualInt(archive_format(a), ARCHIVE_FORMAT_MTREE);
177 	assertEqualString(archive_entry_pathname(ae), "d");
178 	assertEqualInt(archive_entry_filetype(ae), AE_IFDIR);
179 	assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae));
180 	assertEqualInt(1, archive_file_count(a));
181 	assertEqualInt(ARCHIVE_OK, archive_read_close(a));
182 	assertEqualInt(ARCHIVE_OK, archive_read_free(a));
183 }
184 
185 /*
186  * Reported to libarchive.googlecode.com as Issue 121.
187  */
188 static void
189 test_read_format_mtree3(void)
190 {
191 	static char archive[] =
192 	    "#mtree\n"
193 	    "a type=file contents=file\n"
194 	    "b type=link link=a\n"
195 	    "c type=file contents=file\n";
196 	struct archive_entry *ae;
197 	struct archive *a;
198 
199 	assertMakeDir("mtree3", 0777);
200 	assertChdir("mtree3");
201 	assertMakeFile("file", 0644, "file contents");
202 
203 	assert((a = archive_read_new()) != NULL);
204 	assertEqualIntA(a, ARCHIVE_OK,
205 	    archive_read_support_filter_all(a));
206 	assertEqualIntA(a, ARCHIVE_OK,
207 	    archive_read_support_format_all(a));
208 	assertEqualIntA(a, ARCHIVE_OK,
209 	    archive_read_open_memory(a, archive, sizeof(archive)));
210 	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
211 	assertEqualString(archive_entry_pathname(ae), "a");
212 	assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
213 	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
214 	assertEqualString(archive_entry_pathname(ae), "b");
215 	assertEqualInt(archive_entry_filetype(ae), AE_IFLNK);
216 	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
217 	assertEqualString(archive_entry_pathname(ae), "c");
218 	assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
219 
220 	assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae));
221 	assertEqualInt(3, archive_file_count(a));
222 	assertEqualInt(ARCHIVE_OK, archive_read_close(a));
223 	assertEqualInt(ARCHIVE_OK, archive_read_free(a));
224 
225 	assertChdir("..");
226 }
227 
228 DEFINE_TEST(test_read_format_mtree)
229 {
230 	test_read_format_mtree1();
231 	test_read_format_mtree2();
232 	test_read_format_mtree3();
233 }
234 
235 DEFINE_TEST(test_read_format_mtree_filenames_only)
236 {
237 	static char archive[] =
238 	    "/set type=file mode=0644\n"
239 	    "./a\n"
240 	    "./b\n"
241 	    "./c\n"
242 	    "./d\n"
243 	    "./e\n"
244 	    "./f mode=0444\n";
245 	struct archive_entry *ae;
246 	struct archive *a;
247 
248 	assertMakeFile("file", 0644, "file contents");
249 
250 	assert((a = archive_read_new()) != NULL);
251 	assertEqualIntA(a, ARCHIVE_OK,
252 	    archive_read_support_filter_all(a));
253 	assertEqualIntA(a, ARCHIVE_OK,
254 	    archive_read_support_format_all(a));
255 	assertEqualIntA(a, ARCHIVE_OK,
256 	    archive_read_open_memory(a, archive, sizeof(archive)));
257 	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
258 	assertEqualString(archive_entry_pathname(ae), "./a");
259 	assertEqualInt(archive_entry_mode(ae), AE_IFREG | 0644);
260 	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
261 	assertEqualString(archive_entry_pathname(ae), "./b");
262 	assertEqualInt(archive_entry_mode(ae), AE_IFREG | 0644);
263 	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
264 	assertEqualString(archive_entry_pathname(ae), "./c");
265 	assertEqualInt(archive_entry_mode(ae), AE_IFREG | 0644);
266 	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
267 	assertEqualString(archive_entry_pathname(ae), "./d");
268 	assertEqualInt(archive_entry_mode(ae), AE_IFREG | 0644);
269 	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
270 	assertEqualString(archive_entry_pathname(ae), "./e");
271 	assertEqualInt(archive_entry_mode(ae), AE_IFREG | 0644);
272 	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
273 	assertEqualString(archive_entry_pathname(ae), "./f");
274 	assertEqualInt(archive_entry_mode(ae), AE_IFREG | 0444);
275 
276 	assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae));
277 	assertEqualInt(6, archive_file_count(a));
278 	assertEqualInt(ARCHIVE_OK, archive_read_close(a));
279 	assertEqualInt(ARCHIVE_OK, archive_read_free(a));
280 }
281 
282 DEFINE_TEST(test_read_format_mtree_nochange)
283 {
284 	static char archive[] =
285 	    "#mtree\n"
286 	    "./a type=file mode=0644 time=123\n"
287 	    "./b type=file mode=0644 time=234\n"
288 	    "./c type=file mode=0644 time=345\n";
289 	static char archive2[] =
290 	    "#mtree\n"
291 	    "./a type=file mode=0644 time=123 nochange\n"
292 	    "./b type=file mode=0644 time=234\n"
293 	    "./c type=file mode=0644 time=345 nochange\n";
294 	struct archive_entry *ae;
295 	struct archive *a;
296 
297 	assertMakeFile("a", 0640, "12345");
298 	assertMakeFile("b", 0664, "123456");
299 	assertMakeFile("c", 0755, "1234567");
300 
301 	/*
302 	 * Test 1. Read a mtree archive without `nochange' keyword.
303 	 */
304 	assert((a = archive_read_new()) != NULL);
305 	assertEqualIntA(a, ARCHIVE_OK,
306 	    archive_read_support_filter_all(a));
307 	assertEqualIntA(a, ARCHIVE_OK,
308 	    archive_read_support_format_all(a));
309 	assertEqualIntA(a, ARCHIVE_OK,
310 	    archive_read_open_memory(a, archive, sizeof(archive)));
311 	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
312 	assertEqualString(archive_entry_pathname(ae), "./a");
313 	assertEqualInt(archive_entry_mode(ae), AE_IFREG | 0644);
314 	assertEqualInt(archive_entry_mtime(ae), 123);
315 	assertEqualInt(archive_entry_size(ae), 5);
316 	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
317 	assertEqualString(archive_entry_pathname(ae), "./b");
318 	assertEqualInt(archive_entry_mode(ae), AE_IFREG | 0644);
319 	assertEqualInt(archive_entry_mtime(ae), 234);
320 	assertEqualInt(archive_entry_size(ae), 6);
321 	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
322 	assertEqualString(archive_entry_pathname(ae), "./c");
323 	assertEqualInt(archive_entry_mode(ae), AE_IFREG | 0644);
324 	assertEqualInt(archive_entry_mtime(ae), 345);
325 	assertEqualInt(archive_entry_size(ae), 7);
326 
327 	assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae));
328 	assertEqualInt(3, archive_file_count(a));
329 	assertEqualInt(ARCHIVE_OK, archive_read_close(a));
330 	assertEqualInt(ARCHIVE_OK, archive_read_free(a));
331 
332 	/*
333 	 * Test 2. Read a mtree archive with `nochange' keyword.
334 	 */
335 	assert((a = archive_read_new()) != NULL);
336 	assertEqualIntA(a, ARCHIVE_OK,
337 	    archive_read_support_filter_all(a));
338 	assertEqualIntA(a, ARCHIVE_OK,
339 	    archive_read_support_format_all(a));
340 	assertEqualIntA(a, ARCHIVE_OK,
341 	    archive_read_open_memory(a, archive2, sizeof(archive2)));
342 	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
343 	assertEqualString(archive_entry_pathname(ae), "./a");
344 #if !defined(_WIN32) || defined(__CYGWIN__)
345 	assertEqualInt(archive_entry_mode(ae), AE_IFREG | 0640);
346 #endif
347 	assert(archive_entry_mtime(ae) != 123);
348 	assertEqualInt(archive_entry_size(ae), 5);
349 	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
350 	assertEqualString(archive_entry_pathname(ae), "./b");
351 	assertEqualInt(archive_entry_mode(ae), AE_IFREG | 0644);
352 	assertEqualInt(archive_entry_mtime(ae), 234);
353 	assertEqualInt(archive_entry_size(ae), 6);
354 	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
355 	assertEqualString(archive_entry_pathname(ae), "./c");
356 #if !defined(_WIN32) || defined(__CYGWIN__)
357 	assertEqualInt(archive_entry_mode(ae), AE_IFREG | 0755);
358 #endif
359 	assert(archive_entry_mtime(ae) != 345);
360 	assertEqualInt(archive_entry_size(ae), 7);
361 
362 	assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae));
363 	assertEqualInt(3, archive_file_count(a));
364 	assertEqualInt(ARCHIVE_OK, archive_read_close(a));
365 	assertEqualInt(ARCHIVE_OK, archive_read_free(a));
366 }
367 
368 DEFINE_TEST(test_read_format_mtree_nomagic_v1_form)
369 {
370 	const char reffile[] = "test_read_format_mtree_nomagic.mtree";
371 	char buff[16];
372 	struct archive_entry *ae;
373 	struct archive *a;
374 	FILE *f;
375 
376 	extract_reference_file(reffile);
377 
378 	assert((a = archive_read_new()) != NULL);
379 	assertEqualIntA(a, ARCHIVE_OK,
380 	    archive_read_support_filter_all(a));
381 	assertEqualIntA(a, ARCHIVE_OK,
382 	    archive_read_support_format_all(a));
383 	assertEqualIntA(a, ARCHIVE_OK,
384 	    archive_read_open_filename(a, reffile, 11));
385 
386 	/*
387 	 * Read "file", whose data is available on disk.
388 	 */
389 	f = fopen("file", "wb");
390 	assert(f != NULL);
391 	assertEqualInt(3, fwrite("hi\n", 1, 3, f));
392 	fclose(f);
393 	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
394 	assertEqualInt(archive_format(a), ARCHIVE_FORMAT_MTREE);
395 	assertEqualString(archive_entry_pathname(ae), "file");
396 	assertEqualInt(archive_entry_uid(ae), 18);
397 	assertEqualInt(AE_IFREG, archive_entry_filetype(ae));
398 	assertEqualInt(archive_entry_mode(ae), AE_IFREG | 0123);
399 	assertEqualInt(archive_entry_size(ae), 3);
400 	assertEqualInt(3, archive_read_data(a, buff, 3));
401 	assertEqualMem(buff, "hi\n", 3);
402 
403 	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
404 	assertEqualString(archive_entry_pathname(ae), "dir");
405 	assertEqualInt(AE_IFDIR, archive_entry_filetype(ae));
406 
407 	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
408 	assertEqualString(archive_entry_pathname(ae), "dir/file with space");
409 
410 	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
411 	assertEqualString(archive_entry_pathname(ae), "file with space");
412 
413 	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
414 	assertEqualString(archive_entry_pathname(ae), "dir2");
415 
416 	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
417 	assertEqualString(archive_entry_pathname(ae), "dir2/dir3a");
418 
419 	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
420 	assertEqualString(archive_entry_pathname(ae), "dir2/dir3a/indir3a");
421 
422 	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
423 	assertEqualString(archive_entry_pathname(ae), "dir2/fullindir2");
424 	assertEqualInt(archive_entry_mode(ae), AE_IFREG | 0644);
425 
426 	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
427 	assertEqualString(archive_entry_pathname(ae), "dir2/indir2");
428 
429 	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
430 	assertEqualString(archive_entry_pathname(ae), "dir2/dir3b");
431 
432 	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
433 	assertEqualString(archive_entry_pathname(ae), "dir2/dir3b/indir3b");
434 
435 	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
436 	assertEqualString(archive_entry_pathname(ae), "notindir");
437 
438 	assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae));
439 	assertEqualInt(12, archive_file_count(a));
440 	assertEqualInt(ARCHIVE_OK, archive_read_close(a));
441 	assertEqualInt(ARCHIVE_OK, archive_read_free(a));
442 }
443 
444 /*
445  * Test for a format that NetBSD mtree -C generates.
446  */
447 DEFINE_TEST(test_read_format_mtree_nomagic_v2_form)
448 {
449 	const char reffile[] = "test_read_format_mtree_nomagic2.mtree";
450 	char buff[16];
451 	struct archive_entry *ae;
452 	struct archive *a;
453 	FILE *f;
454 
455 	extract_reference_file(reffile);
456 
457 	assert((a = archive_read_new()) != NULL);
458 	assertEqualIntA(a, ARCHIVE_OK,
459 	    archive_read_support_filter_all(a));
460 	assertEqualIntA(a, ARCHIVE_OK,
461 	    archive_read_support_format_all(a));
462 	assertEqualIntA(a, ARCHIVE_OK,
463 	    archive_read_open_filename(a, reffile, 11));
464 
465 	/*
466 	 * Read "file", whose data is available on disk.
467 	 */
468 	f = fopen("file", "wb");
469 	assert(f != NULL);
470 	assertEqualInt(3, fwrite("hi\n", 1, 3, f));
471 	fclose(f);
472 	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
473 	assertEqualInt(archive_format(a), ARCHIVE_FORMAT_MTREE);
474 	assertEqualString(archive_entry_pathname(ae), "./file");
475 	assertEqualInt(archive_entry_uid(ae), 18);
476 	assertEqualInt(AE_IFREG, archive_entry_filetype(ae));
477 	assertEqualInt(archive_entry_mode(ae), AE_IFREG | 0123);
478 	assertEqualInt(archive_entry_size(ae), 3);
479 	assertEqualInt(3, archive_read_data(a, buff, 3));
480 	assertEqualMem(buff, "hi\n", 3);
481 
482 	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
483 	assertEqualString(archive_entry_pathname(ae), "./dir");
484 	assertEqualInt(archive_entry_mode(ae), AE_IFDIR | 0755);
485 
486 	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
487 	assertEqualString(archive_entry_pathname(ae), "./dir/file with space");
488 	assertEqualInt(archive_entry_uid(ae), 18);
489 	assertEqualInt(archive_entry_mode(ae), AE_IFREG | 0644);
490 
491 	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
492 	assertEqualString(archive_entry_pathname(ae), "./file with space");
493 	assertEqualInt(archive_entry_mode(ae), AE_IFREG | 0644);
494 
495 	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
496 	assertEqualString(archive_entry_pathname(ae), "./dir2");
497 	assertEqualInt(archive_entry_mode(ae), AE_IFDIR | 0755);
498 
499 	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
500 	assertEqualString(archive_entry_pathname(ae), "./dir2/dir3a");
501 	assertEqualInt(archive_entry_mode(ae), AE_IFDIR | 0755);
502 
503 	assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae));
504 	assertEqualInt(6, archive_file_count(a));
505 	assertEqualInt(ARCHIVE_OK, archive_read_close(a));
506 	assertEqualInt(ARCHIVE_OK, archive_read_free(a));
507 }
508 
509 /*
510  * Test for a format that NetBSD mtree -D generates.
511  */
512 DEFINE_TEST(test_read_format_mtree_nomagic_v2_netbsd_form)
513 {
514 	const char reffile[] = "test_read_format_mtree_nomagic3.mtree";
515 	char buff[16];
516 	struct archive_entry *ae;
517 	struct archive *a;
518 	FILE *f;
519 
520 	extract_reference_file(reffile);
521 
522 	assert((a = archive_read_new()) != NULL);
523 	assertEqualIntA(a, ARCHIVE_OK,
524 	    archive_read_support_filter_all(a));
525 	assertEqualIntA(a, ARCHIVE_OK,
526 	    archive_read_support_format_all(a));
527 	assertEqualIntA(a, ARCHIVE_OK,
528 	    archive_read_open_filename(a, reffile, 11));
529 
530 	/*
531 	 * Read "file", whose data is available on disk.
532 	 */
533 	f = fopen("file", "wb");
534 	assert(f != NULL);
535 	assertEqualInt(3, fwrite("hi\n", 1, 3, f));
536 	fclose(f);
537 	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
538 	assertEqualInt(archive_format(a), ARCHIVE_FORMAT_MTREE);
539 	assertEqualString(archive_entry_pathname(ae), "./file");
540 	assertEqualInt(archive_entry_uid(ae), 18);
541 	assertEqualInt(AE_IFREG, archive_entry_filetype(ae));
542 	assertEqualInt(archive_entry_mode(ae), AE_IFREG | 0123);
543 	assertEqualInt(archive_entry_size(ae), 3);
544 	assertEqualInt(3, archive_read_data(a, buff, 3));
545 	assertEqualMem(buff, "hi\n", 3);
546 
547 	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
548 	assertEqualString(archive_entry_pathname(ae), "./dir");
549 	assertEqualInt(archive_entry_mode(ae), AE_IFDIR | 0755);
550 
551 	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
552 	assertEqualString(archive_entry_pathname(ae), "./dir/file with space");
553 	assertEqualInt(archive_entry_uid(ae), 18);
554 	assertEqualInt(archive_entry_mode(ae), AE_IFREG | 0644);
555 
556 	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
557 	assertEqualString(archive_entry_pathname(ae), "./file with space");
558 	assertEqualInt(archive_entry_mode(ae), AE_IFREG | 0644);
559 
560 	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
561 	assertEqualString(archive_entry_pathname(ae), "./dir2");
562 	assertEqualInt(archive_entry_mode(ae), AE_IFDIR | 0755);
563 
564 	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
565 	assertEqualString(archive_entry_pathname(ae), "./dir2/dir3a");
566 	assertEqualInt(archive_entry_mode(ae), AE_IFDIR | 0755);
567 
568 	assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae));
569 	assertEqualInt(6, archive_file_count(a));
570 	assertEqualInt(ARCHIVE_OK, archive_read_close(a));
571 	assertEqualInt(ARCHIVE_OK, archive_read_free(a));
572 }
573 
574 /*
575  * We should get a warning if the contents file doesn't exist.
576  */
577 DEFINE_TEST(test_read_format_mtree_nonexistent_contents_file)
578 {
579 	static char archive[] =
580 	    "#mtree\n"
581 	    "a type=file contents=nonexistent_file\n";
582 	struct archive_entry *ae;
583 	struct archive *a;
584 
585 	assert((a = archive_read_new()) != NULL);
586 	assertEqualIntA(a, ARCHIVE_OK,
587 	    archive_read_support_filter_all(a));
588 	assertEqualIntA(a, ARCHIVE_OK,
589 	    archive_read_support_format_all(a));
590 	assertEqualIntA(a, ARCHIVE_OK,
591 	    archive_read_open_memory(a, archive, sizeof(archive)));
592 	assertEqualIntA(a, ARCHIVE_WARN, archive_read_next_header(a, &ae));
593 	assert(strlen(archive_error_string(a)) > 0);
594 	assertEqualString(archive_entry_pathname(ae), "a");
595 	assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
596 
597 	assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae));
598 	assertEqualInt(1, archive_file_count(a));
599 	assertEqualInt(ARCHIVE_OK, archive_read_close(a));
600 	assertEqualInt(ARCHIVE_OK, archive_read_free(a));
601 }
602 
603