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_set_options(a, "mtree:checkfs"));
62 	assertEqualIntA(a, ARCHIVE_OK,
63 	    archive_read_open_filename(a, reffile, 11));
64 
65 	/*
66 	 * Read "file", whose data is available on disk.
67 	 */
68 	f = fopen("file", "wb");
69 	assert(f != NULL);
70 	assertEqualInt(3, fwrite("hi\n", 1, 3, f));
71 	fclose(f);
72 	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
73 	assertEqualInt(archive_format(a), ARCHIVE_FORMAT_MTREE);
74 	assertEqualString(archive_entry_pathname(ae), "file");
75 	assertEqualInt(archive_entry_uid(ae), 18);
76 	assertEqualInt(AE_IFREG, archive_entry_filetype(ae));
77 	assertEqualInt(archive_entry_mode(ae), AE_IFREG | 0123);
78 	assertEqualInt(archive_entry_size(ae), 3);
79 	assertEqualInt(3, archive_read_data(a, buff, 3));
80 	assertEqualMem(buff, "hi\n", 3);
81 	assertEqualInt(archive_entry_is_encrypted(ae), 0);
82 	assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED);
83 
84 	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
85 	assertEqualString(archive_entry_pathname(ae), "dir");
86 	assertEqualInt(AE_IFDIR, archive_entry_filetype(ae));
87 	assertEqualInt(archive_entry_is_encrypted(ae), 0);
88 	assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED);
89 
90 	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
91 	assertEqualString(archive_entry_pathname(ae), "dir/file with space");
92 	assertEqualInt(archive_entry_is_encrypted(ae), 0);
93 	assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED);
94 
95 	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
96 	assertEqualString(archive_entry_pathname(ae), "file with space");
97 	assertEqualInt(archive_entry_is_encrypted(ae), 0);
98 	assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED);
99 
100 	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
101 	assertEqualString(archive_entry_pathname(ae), "dir2");
102 	assertEqualInt(archive_entry_is_encrypted(ae), 0);
103 	assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED);
104 
105 	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
106 	assertEqualString(archive_entry_pathname(ae), "dir2/dir3a");
107 	assertEqualInt(archive_entry_is_encrypted(ae), 0);
108 	assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED);
109 
110 	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
111 	assertEqualString(archive_entry_pathname(ae), "dir2/dir3a/indir3a");
112 	assertEqualInt(archive_entry_is_encrypted(ae), 0);
113 	assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED);
114 
115 	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
116 	assertEqualString(archive_entry_pathname(ae), "dir2/fullindir2");
117 	assertEqualInt(archive_entry_mode(ae), AE_IFREG | 0644);
118 	assertEqualInt(archive_entry_is_encrypted(ae), 0);
119 	assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED);
120 
121 	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
122 	assertEqualString(archive_entry_pathname(ae), "dir2/indir2");
123 	assertEqualInt(archive_entry_is_encrypted(ae), 0);
124 	assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED);
125 
126 	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
127 	assertEqualString(archive_entry_pathname(ae), "dir2/dir3b");
128 	assertEqualInt(archive_entry_is_encrypted(ae), 0);
129 	assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED);
130 
131 	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
132 	assertEqualString(archive_entry_pathname(ae), "dir2/dir3b/indir3b");
133 	assertEqualInt(archive_entry_is_encrypted(ae), 0);
134 	assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED);
135 
136 	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
137 	assertEqualString(archive_entry_pathname(ae), "dir2/dir3b/filename\\with_esc\b\t\fapes");
138 	assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
139 	assertEqualInt(archive_entry_is_encrypted(ae), 0);
140 	assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED);
141 
142 	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
143 	assertEqualString(archive_entry_pathname(ae), "notindir");
144 	assertEqualInt(archive_entry_is_encrypted(ae), 0);
145 	assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED);
146 
147 	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
148 	assertEqualString(archive_entry_pathname(ae), "dir2/emptyfile");
149 	assertEqualInt(archive_entry_size(ae), 0);
150 	assertEqualInt(archive_entry_is_encrypted(ae), 0);
151 	assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED);
152 
153 	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
154 	assertEqualString(archive_entry_pathname(ae), "dir2/smallfile");
155 	assertEqualInt(archive_entry_size(ae), 1);
156 	assertEqualInt(archive_entry_is_encrypted(ae), 0);
157 	assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED);
158 
159 	/* TODO: Mtree reader should probably return ARCHIVE_WARN for this. */
160 	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
161 	assertEqualString(archive_entry_pathname(ae), "dir2/toosmallfile");
162 	assertEqualInt(archive_entry_size(ae), -1);
163 	assertEqualInt(archive_entry_is_encrypted(ae), 0);
164 	assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED);
165 
166 	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
167 	assertEqualString(archive_entry_pathname(ae), "dir2/bigfile");
168 	assertEqualInt(archive_entry_size(ae), max_int64);
169 	assertEqualInt(archive_entry_is_encrypted(ae), 0);
170 	assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED);
171 
172 	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
173 	assertEqualString(archive_entry_pathname(ae), "dir2/toobigfile");
174 	/* Size in mtree is max_int64 + 1; should return max_int64. */
175 	assertEqualInt(archive_entry_size(ae), max_int64);
176 	assertEqualInt(archive_entry_is_encrypted(ae), 0);
177 	assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED);
178 
179 	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
180 	assertEqualString(archive_entry_pathname(ae), "dir2/veryoldfile");
181 	/* The value in the file is MIN_INT64_T, but time_t may be narrower. */
182 	/* Verify min_time is the smallest possible time_t. */
183 	min_time = archive_entry_mtime(ae);
184 	assert(min_time <= 0);
185 	/* Simply asserting min_time - 1 > 0 breaks with some compiler optimizations. */
186 	t = (time_t)((uintmax_t)min_time - 1);
187 	assert(t > 0);
188 	assertEqualInt(archive_entry_is_encrypted(ae), 0);
189 	assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED);
190 
191 	/* toooldfile is 1 sec older, which should overflow and get returned
192 	 * with the same value. */
193 	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
194 	assertEqualString(archive_entry_pathname(ae), "dir2/toooldfile");
195 	assertEqualInt(archive_entry_mtime(ae), min_time);
196 	assertEqualInt(archive_entry_is_encrypted(ae), 0);
197 	assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED);
198 
199 	assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae));
200 	assertEqualInt(20, archive_file_count(a));
201 	assertEqualInt(ARCHIVE_OK, archive_read_close(a));
202 	assertEqualInt(ARCHIVE_OK, archive_read_free(a));
203 }
204 
205 static void
206 test_read_format_mtree2(void)
207 {
208 	static char archive[] =
209 	    "#mtree\n"
210 	    "d type=dir content=.\n";
211 	struct archive_entry *ae;
212 	struct archive *a;
213 
214 	assert((a = archive_read_new()) != NULL);
215 	assertEqualIntA(a, ARCHIVE_OK,
216 	    archive_read_support_filter_all(a));
217 	assertEqualIntA(a, ARCHIVE_OK,
218 	    archive_read_support_format_all(a));
219 	assertEqualIntA(a, ARCHIVE_OK,
220 	    archive_read_set_options(a, "mtree:checkfs"));
221 	assertEqualIntA(a, ARCHIVE_OK,
222 	    archive_read_open_memory(a, archive, sizeof(archive)));
223 	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
224 	assertEqualInt(archive_format(a), ARCHIVE_FORMAT_MTREE);
225 	assertEqualString(archive_entry_pathname(ae), "d");
226 	assertEqualInt(archive_entry_filetype(ae), AE_IFDIR);
227 	assertEqualInt(archive_entry_is_encrypted(ae), 0);
228 	assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED);
229 	assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae));
230 	assertEqualInt(1, archive_file_count(a));
231 	assertEqualInt(ARCHIVE_OK, archive_read_close(a));
232 	assertEqualInt(ARCHIVE_OK, archive_read_free(a));
233 }
234 
235 /*
236  * Reported to libarchive.googlecode.com as Issue 121.
237  */
238 static void
239 test_read_format_mtree3(void)
240 {
241 	static char archive[] =
242 	    "#mtree\n"
243 	    "a type=file contents=file\n"
244 	    "b type=link link=a\n"
245 	    "c type=file contents=file\n";
246 	struct archive_entry *ae;
247 	struct archive *a;
248 
249 	assertMakeDir("mtree3", 0777);
250 	assertChdir("mtree3");
251 	assertMakeFile("file", 0644, "file contents");
252 
253 	assert((a = archive_read_new()) != NULL);
254 	assertEqualIntA(a, ARCHIVE_OK,
255 	    archive_read_support_filter_all(a));
256 	assertEqualIntA(a, ARCHIVE_OK,
257 	    archive_read_support_format_all(a));
258 	assertEqualIntA(a, ARCHIVE_OK,
259 	    archive_read_set_options(a, "mtree:checkfs"));
260 	assertEqualIntA(a, ARCHIVE_OK,
261 	    archive_read_open_memory(a, archive, sizeof(archive)));
262 	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
263 	assertEqualString(archive_entry_pathname(ae), "a");
264 	assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
265 	assertEqualInt(archive_entry_is_encrypted(ae), 0);
266 	assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED);
267 	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
268 	assertEqualString(archive_entry_pathname(ae), "b");
269 	assertEqualInt(archive_entry_filetype(ae), AE_IFLNK);
270 	assertEqualInt(archive_entry_is_encrypted(ae), 0);
271 	assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED);
272 	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
273 	assertEqualString(archive_entry_pathname(ae), "c");
274 	assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
275 	assertEqualInt(archive_entry_is_encrypted(ae), 0);
276 	assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED);
277 
278 	assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae));
279 	assertEqualInt(3, archive_file_count(a));
280 	assertEqualInt(ARCHIVE_OK, archive_read_close(a));
281 	assertEqualInt(ARCHIVE_OK, archive_read_free(a));
282 
283 	assertChdir("..");
284 }
285 
286 DEFINE_TEST(test_read_format_mtree)
287 {
288 	test_read_format_mtree1();
289 	test_read_format_mtree2();
290 	test_read_format_mtree3();
291 }
292 
293 DEFINE_TEST(test_read_format_mtree_filenames_only)
294 {
295 	static char archive[] =
296 	    "/set type=file mode=0644\n"
297 	    "./a\n"
298 	    "./b\n"
299 	    "./c\n"
300 	    "./d\n"
301 	    "./e\n"
302 	    "./f mode=0444\n";
303 	struct archive_entry *ae;
304 	struct archive *a;
305 
306 	assertMakeFile("file", 0644, "file contents");
307 
308 	assert((a = archive_read_new()) != NULL);
309 	assertEqualIntA(a, ARCHIVE_OK,
310 	    archive_read_support_filter_all(a));
311 	assertEqualIntA(a, ARCHIVE_OK,
312 	    archive_read_support_format_all(a));
313 	assertEqualIntA(a, ARCHIVE_OK,
314 	    archive_read_set_options(a, "mtree:checkfs"));
315 	assertEqualIntA(a, ARCHIVE_OK,
316 	    archive_read_open_memory(a, archive, sizeof(archive)));
317 	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
318 	assertEqualString(archive_entry_pathname(ae), "./a");
319 	assertEqualInt(archive_entry_mode(ae), AE_IFREG | 0644);
320 	assertEqualInt(archive_entry_is_encrypted(ae), 0);
321 	assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED);
322 	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
323 	assertEqualString(archive_entry_pathname(ae), "./b");
324 	assertEqualInt(archive_entry_mode(ae), AE_IFREG | 0644);
325 	assertEqualInt(archive_entry_is_encrypted(ae), 0);
326 	assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED);
327 	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
328 	assertEqualString(archive_entry_pathname(ae), "./c");
329 	assertEqualInt(archive_entry_mode(ae), AE_IFREG | 0644);
330 	assertEqualInt(archive_entry_is_encrypted(ae), 0);
331 	assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED);
332 	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
333 	assertEqualString(archive_entry_pathname(ae), "./d");
334 	assertEqualInt(archive_entry_mode(ae), AE_IFREG | 0644);
335 	assertEqualInt(archive_entry_is_encrypted(ae), 0);
336 	assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED);
337 	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
338 	assertEqualString(archive_entry_pathname(ae), "./e");
339 	assertEqualInt(archive_entry_mode(ae), AE_IFREG | 0644);
340 	assertEqualInt(archive_entry_is_encrypted(ae), 0);
341 	assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED);
342 	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
343 	assertEqualString(archive_entry_pathname(ae), "./f");
344 	assertEqualInt(archive_entry_mode(ae), AE_IFREG | 0444);
345 	assertEqualInt(archive_entry_is_encrypted(ae), 0);
346 	assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED);
347 
348 	assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae));
349 	assertEqualInt(6, archive_file_count(a));
350 	assertEqualInt(ARCHIVE_OK, archive_read_close(a));
351 	assertEqualInt(ARCHIVE_OK, archive_read_free(a));
352 }
353 
354 DEFINE_TEST(test_read_format_mtree_nochange)
355 {
356 	static char archive[] =
357 	    "#mtree\n"
358 	    "./a type=file mode=0644 time=123\n"
359 	    "./b type=file mode=0644 time=234\n"
360 	    "./c type=file mode=0644 time=345\n";
361 	static char archive2[] =
362 	    "#mtree\n"
363 	    "./a type=file mode=0644 time=123 nochange\n"
364 	    "./b type=file mode=0644 time=234\n"
365 	    "./c type=file mode=0644 time=345 nochange\n";
366 	struct archive_entry *ae;
367 	struct archive *a;
368 
369 	assertMakeFile("a", 0640, "12345");
370 	assertMakeFile("b", 0664, "123456");
371 	assertMakeFile("c", 0755, "1234567");
372 
373 	/*
374 	 * Test 1. Read a mtree archive without `nochange' keyword.
375 	 */
376 	assert((a = archive_read_new()) != NULL);
377 	assertEqualIntA(a, ARCHIVE_OK,
378 	    archive_read_support_filter_all(a));
379 	assertEqualIntA(a, ARCHIVE_OK,
380 	    archive_read_support_format_all(a));
381 	assertEqualIntA(a, ARCHIVE_OK,
382 	    archive_read_set_options(a, "mtree:checkfs"));
383 	assertEqualIntA(a, ARCHIVE_OK,
384 	    archive_read_open_memory(a, archive, sizeof(archive)));
385 	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
386 	assertEqualString(archive_entry_pathname(ae), "./a");
387 	assertEqualInt(archive_entry_mode(ae), AE_IFREG | 0644);
388 	assertEqualInt(archive_entry_mtime(ae), 123);
389 	assertEqualInt(archive_entry_size(ae), 5);
390 	assertEqualInt(archive_entry_is_encrypted(ae), 0);
391 	assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED);
392 	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
393 	assertEqualString(archive_entry_pathname(ae), "./b");
394 	assertEqualInt(archive_entry_mode(ae), AE_IFREG | 0644);
395 	assertEqualInt(archive_entry_mtime(ae), 234);
396 	assertEqualInt(archive_entry_size(ae), 6);
397 	assertEqualInt(archive_entry_is_encrypted(ae), 0);
398 	assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED);
399 	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
400 	assertEqualString(archive_entry_pathname(ae), "./c");
401 	assertEqualInt(archive_entry_mode(ae), AE_IFREG | 0644);
402 	assertEqualInt(archive_entry_mtime(ae), 345);
403 	assertEqualInt(archive_entry_size(ae), 7);
404 	assertEqualInt(archive_entry_is_encrypted(ae), 0);
405 	assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED);
406 
407 	assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae));
408 	assertEqualInt(3, archive_file_count(a));
409 	assertEqualInt(ARCHIVE_OK, archive_read_close(a));
410 	assertEqualInt(ARCHIVE_OK, archive_read_free(a));
411 
412 	/*
413 	 * Test 2. Read a mtree archive with `nochange' keyword.
414 	 */
415 	assert((a = archive_read_new()) != NULL);
416 	assertEqualIntA(a, ARCHIVE_OK,
417 	    archive_read_support_filter_all(a));
418 	assertEqualIntA(a, ARCHIVE_OK,
419 	    archive_read_support_format_all(a));
420 	assertEqualIntA(a, ARCHIVE_OK,
421 	    archive_read_set_options(a, "mtree:checkfs"));
422 	assertEqualIntA(a, ARCHIVE_OK,
423 	    archive_read_open_memory(a, archive2, sizeof(archive2)));
424 	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
425 	assertEqualString(archive_entry_pathname(ae), "./a");
426 #if !defined(_WIN32) || defined(__CYGWIN__)
427 	assertEqualInt(archive_entry_mode(ae), AE_IFREG | 0640);
428 #endif
429 	assert(archive_entry_mtime(ae) != 123);
430 	assertEqualInt(archive_entry_size(ae), 5);
431 	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
432 	assertEqualString(archive_entry_pathname(ae), "./b");
433 	assertEqualInt(archive_entry_mode(ae), AE_IFREG | 0644);
434 	assertEqualInt(archive_entry_mtime(ae), 234);
435 	assertEqualInt(archive_entry_size(ae), 6);
436 	assertEqualInt(archive_entry_is_encrypted(ae), 0);
437 	assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED);
438 	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
439 	assertEqualString(archive_entry_pathname(ae), "./c");
440 #if !defined(_WIN32) || defined(__CYGWIN__)
441 	assertEqualInt(archive_entry_mode(ae), AE_IFREG | 0755);
442 #endif
443 	assert(archive_entry_mtime(ae) != 345);
444 	assertEqualInt(archive_entry_size(ae), 7);
445 	assertEqualInt(archive_entry_is_encrypted(ae), 0);
446 	assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED);
447 
448 	assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae));
449 	assertEqualInt(3, archive_file_count(a));
450 	assertEqualInt(ARCHIVE_OK, archive_read_close(a));
451 	assertEqualInt(ARCHIVE_OK, archive_read_free(a));
452 }
453 
454 DEFINE_TEST(test_read_format_mtree_nomagic_v1_form)
455 {
456 	const char reffile[] = "test_read_format_mtree_nomagic.mtree";
457 	char buff[16];
458 	struct archive_entry *ae;
459 	struct archive *a;
460 	FILE *f;
461 
462 	extract_reference_file(reffile);
463 
464 	assert((a = archive_read_new()) != NULL);
465 	assertEqualIntA(a, ARCHIVE_OK,
466 	    archive_read_support_filter_all(a));
467 	assertEqualIntA(a, ARCHIVE_OK,
468 	    archive_read_support_format_all(a));
469 	assertEqualIntA(a, ARCHIVE_OK,
470 	    archive_read_set_options(a, "mtree:checkfs"));
471 	assertEqualIntA(a, ARCHIVE_OK,
472 	    archive_read_open_filename(a, reffile, 11));
473 
474 	/*
475 	 * Read "file", whose data is available on disk.
476 	 */
477 	f = fopen("file", "wb");
478 	assert(f != NULL);
479 	assertEqualInt(3, fwrite("hi\n", 1, 3, f));
480 	fclose(f);
481 	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
482 	assertEqualInt(archive_format(a), ARCHIVE_FORMAT_MTREE);
483 	assertEqualString(archive_entry_pathname(ae), "file");
484 	assertEqualInt(archive_entry_uid(ae), 18);
485 	assertEqualInt(AE_IFREG, archive_entry_filetype(ae));
486 	assertEqualInt(archive_entry_mode(ae), AE_IFREG | 0123);
487 	assertEqualInt(archive_entry_size(ae), 3);
488 	assertEqualInt(3, archive_read_data(a, buff, 3));
489 	assertEqualMem(buff, "hi\n", 3);
490 	assertEqualInt(archive_entry_is_encrypted(ae), 0);
491 	assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED);
492 
493 	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
494 	assertEqualString(archive_entry_pathname(ae), "dir");
495 	assertEqualInt(AE_IFDIR, archive_entry_filetype(ae));
496 	assertEqualInt(archive_entry_is_encrypted(ae), 0);
497 	assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED);
498 
499 	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
500 	assertEqualString(archive_entry_pathname(ae), "dir/file with space");
501 	assertEqualInt(archive_entry_is_encrypted(ae), 0);
502 	assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED);
503 
504 	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
505 	assertEqualString(archive_entry_pathname(ae), "file with space");
506 	assertEqualInt(archive_entry_is_encrypted(ae), 0);
507 	assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED);
508 
509 	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
510 	assertEqualString(archive_entry_pathname(ae), "dir2");
511 	assertEqualInt(archive_entry_is_encrypted(ae), 0);
512 	assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED);
513 
514 	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
515 	assertEqualString(archive_entry_pathname(ae), "dir2/dir3a");
516 	assertEqualInt(archive_entry_is_encrypted(ae), 0);
517 	assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED);
518 
519 	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
520 	assertEqualString(archive_entry_pathname(ae), "dir2/dir3a/indir3a");
521 	assertEqualInt(archive_entry_is_encrypted(ae), 0);
522 	assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED);
523 
524 	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
525 	assertEqualString(archive_entry_pathname(ae), "dir2/fullindir2");
526 	assertEqualInt(archive_entry_mode(ae), AE_IFREG | 0644);
527 	assertEqualInt(archive_entry_is_encrypted(ae), 0);
528 	assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED);
529 
530 	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
531 	assertEqualString(archive_entry_pathname(ae), "dir2/indir2");
532 	assertEqualInt(archive_entry_is_encrypted(ae), 0);
533 	assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED);
534 
535 	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
536 	assertEqualString(archive_entry_pathname(ae), "dir2/dir3b");
537 	assertEqualInt(archive_entry_is_encrypted(ae), 0);
538 	assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED);
539 
540 	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
541 	assertEqualString(archive_entry_pathname(ae), "dir2/dir3b/indir3b");
542 	assertEqualInt(archive_entry_is_encrypted(ae), 0);
543 	assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED);
544 
545 	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
546 	assertEqualString(archive_entry_pathname(ae), "notindir");
547 	assertEqualInt(archive_entry_is_encrypted(ae), 0);
548 	assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED);
549 
550 	assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae));
551 	assertEqualInt(12, archive_file_count(a));
552 	assertEqualInt(ARCHIVE_OK, archive_read_close(a));
553 	assertEqualInt(ARCHIVE_OK, archive_read_free(a));
554 }
555 
556 /*
557  * Test for a format that NetBSD mtree -C generates.
558  */
559 DEFINE_TEST(test_read_format_mtree_nomagic_v2_form)
560 {
561 	const char reffile[] = "test_read_format_mtree_nomagic2.mtree";
562 	char buff[16];
563 	struct archive_entry *ae;
564 	struct archive *a;
565 	FILE *f;
566 
567 	extract_reference_file(reffile);
568 
569 	assert((a = archive_read_new()) != NULL);
570 	assertEqualIntA(a, ARCHIVE_OK,
571 	    archive_read_support_filter_all(a));
572 	assertEqualIntA(a, ARCHIVE_OK,
573 	    archive_read_support_format_all(a));
574 	assertEqualIntA(a, ARCHIVE_OK,
575 	    archive_read_set_options(a, "mtree:checkfs"));
576 	assertEqualIntA(a, ARCHIVE_OK,
577 	    archive_read_open_filename(a, reffile, 11));
578 
579 	/*
580 	 * Read "file", whose data is available on disk.
581 	 */
582 	f = fopen("file", "wb");
583 	assert(f != NULL);
584 	assertEqualInt(3, fwrite("hi\n", 1, 3, f));
585 	fclose(f);
586 	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
587 	assertEqualInt(archive_format(a), ARCHIVE_FORMAT_MTREE);
588 	assertEqualString(archive_entry_pathname(ae), "./file");
589 	assertEqualInt(archive_entry_uid(ae), 18);
590 	assertEqualInt(AE_IFREG, archive_entry_filetype(ae));
591 	assertEqualInt(archive_entry_mode(ae), AE_IFREG | 0123);
592 	assertEqualInt(archive_entry_size(ae), 3);
593 	assertEqualInt(3, archive_read_data(a, buff, 3));
594 	assertEqualMem(buff, "hi\n", 3);
595 
596 	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
597 	assertEqualString(archive_entry_pathname(ae), "./dir");
598 	assertEqualInt(archive_entry_mode(ae), AE_IFDIR | 0755);
599 
600 	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
601 	assertEqualString(archive_entry_pathname(ae), "./dir/file with space");
602 	assertEqualInt(archive_entry_uid(ae), 18);
603 	assertEqualInt(archive_entry_mode(ae), AE_IFREG | 0644);
604 
605 	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
606 	assertEqualString(archive_entry_pathname(ae), "./file with space");
607 	assertEqualInt(archive_entry_mode(ae), AE_IFREG | 0644);
608 
609 	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
610 	assertEqualString(archive_entry_pathname(ae), "./dir2");
611 	assertEqualInt(archive_entry_mode(ae), AE_IFDIR | 0755);
612 
613 	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
614 	assertEqualString(archive_entry_pathname(ae), "./dir2/dir3a");
615 	assertEqualInt(archive_entry_mode(ae), AE_IFDIR | 0755);
616 
617 	assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae));
618 	assertEqualInt(6, archive_file_count(a));
619 	assertEqualInt(ARCHIVE_OK, archive_read_close(a));
620 	assertEqualInt(ARCHIVE_OK, archive_read_free(a));
621 }
622 
623 /*
624  * Test for a format that NetBSD mtree -D generates.
625  */
626 DEFINE_TEST(test_read_format_mtree_nomagic_v2_netbsd_form)
627 {
628 	const char reffile[] = "test_read_format_mtree_nomagic3.mtree";
629 	char buff[16];
630 	struct archive_entry *ae;
631 	struct archive *a;
632 	FILE *f;
633 
634 	extract_reference_file(reffile);
635 
636 	assert((a = archive_read_new()) != NULL);
637 	assertEqualIntA(a, ARCHIVE_OK,
638 	    archive_read_support_filter_all(a));
639 	assertEqualIntA(a, ARCHIVE_OK,
640 	    archive_read_support_format_all(a));
641 	assertEqualIntA(a, ARCHIVE_OK,
642 	    archive_read_set_options(a, "mtree:checkfs"));
643 	assertEqualIntA(a, ARCHIVE_OK,
644 	    archive_read_open_filename(a, reffile, 11));
645 
646 	/*
647 	 * Read "file", whose data is available on disk.
648 	 */
649 	f = fopen("file", "wb");
650 	assert(f != NULL);
651 	assertEqualInt(3, fwrite("hi\n", 1, 3, f));
652 	fclose(f);
653 	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
654 	assertEqualInt(archive_format(a), ARCHIVE_FORMAT_MTREE);
655 	assertEqualString(archive_entry_pathname(ae), "./file");
656 	assertEqualInt(archive_entry_uid(ae), 18);
657 	assertEqualInt(AE_IFREG, archive_entry_filetype(ae));
658 	assertEqualInt(archive_entry_mode(ae), AE_IFREG | 0123);
659 	assertEqualInt(archive_entry_size(ae), 3);
660 	assertEqualInt(3, archive_read_data(a, buff, 3));
661 	assertEqualMem(buff, "hi\n", 3);
662 
663 	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
664 	assertEqualString(archive_entry_pathname(ae), "./dir");
665 	assertEqualInt(archive_entry_mode(ae), AE_IFDIR | 0755);
666 
667 	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
668 	assertEqualString(archive_entry_pathname(ae), "./dir/file with space");
669 	assertEqualInt(archive_entry_uid(ae), 18);
670 	assertEqualInt(archive_entry_mode(ae), AE_IFREG | 0644);
671 
672 	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
673 	assertEqualString(archive_entry_pathname(ae), "./file with space");
674 	assertEqualInt(archive_entry_mode(ae), AE_IFREG | 0644);
675 
676 	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
677 	assertEqualString(archive_entry_pathname(ae), "./dir2");
678 	assertEqualInt(archive_entry_mode(ae), AE_IFDIR | 0755);
679 
680 	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
681 	assertEqualString(archive_entry_pathname(ae), "./dir2/dir3a");
682 	assertEqualInt(archive_entry_mode(ae), AE_IFDIR | 0755);
683 
684 	assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae));
685 	assertEqualInt(6, archive_file_count(a));
686 	assertEqualInt(ARCHIVE_OK, archive_read_close(a));
687 	assertEqualInt(ARCHIVE_OK, archive_read_free(a));
688 }
689 
690 /*
691  * We should get a warning if the contents file doesn't exist.
692  */
693 DEFINE_TEST(test_read_format_mtree_nonexistent_contents_file)
694 {
695 	static char archive[] =
696 	    "#mtree\n"
697 	    "a type=file contents=nonexistent_file\n";
698 	struct archive_entry *ae;
699 	struct archive *a;
700 
701 	assert((a = archive_read_new()) != NULL);
702 	assertEqualIntA(a, ARCHIVE_OK,
703 	    archive_read_support_filter_all(a));
704 	assertEqualIntA(a, ARCHIVE_OK,
705 	    archive_read_support_format_all(a));
706 	assertEqualIntA(a, ARCHIVE_OK,
707 	    archive_read_set_options(a, "mtree:checkfs"));
708 	assertEqualIntA(a, ARCHIVE_OK,
709 	    archive_read_open_memory(a, archive, sizeof(archive)));
710 	assertEqualIntA(a, ARCHIVE_WARN, archive_read_next_header(a, &ae));
711 	assert(strlen(archive_error_string(a)) > 0);
712 	assertEqualString(archive_entry_pathname(ae), "a");
713 	assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
714 
715 	assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae));
716 	assertEqualInt(1, archive_file_count(a));
717 	assertEqualInt(ARCHIVE_OK, archive_read_close(a));
718 	assertEqualInt(ARCHIVE_OK, archive_read_free(a));
719 }
720 /*
721  * Check mtree file with non-printable ascii characters
722  */
723 DEFINE_TEST(test_read_format_mtree_noprint)
724 {
725 	const char reffile[] = "test_read_format_mtree_noprint.mtree";
726 	struct archive_entry *ae;
727 	struct archive *a;
728 
729 	extract_reference_file(reffile);
730 
731 	assert((a = archive_read_new()) != NULL);
732 	assertEqualIntA(a, ARCHIVE_OK,
733 	    archive_read_support_filter_all(a));
734 	assertEqualIntA(a, ARCHIVE_OK,
735 	    archive_read_support_format_all(a));
736 	assertEqualIntA(a, ARCHIVE_OK,
737 	    archive_read_open_filename(a, reffile, 11));
738 
739 	assertEqualIntA(a, ARCHIVE_FATAL, archive_read_next_header(a, &ae));
740 	assertEqualString("Can't parse line 3", archive_error_string(a));
741 
742 	assertEqualInt(ARCHIVE_OK, archive_read_close(a));
743 	assertEqualInt(ARCHIVE_OK, archive_read_free(a));
744 }
745