1 /*-
2  * Copyright (c) 2010-2012 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 #include <limits.h>
28 #if defined(_WIN32) && !defined(__CYGWIN__)
29 # if !defined(__BORLANDC__)
30 #  define getcwd _getcwd
31 # endif
32 #endif
33 
34 /*
35  * Test if the current filesystem is mounted with noatime option.
36  */
37 static int
atimeIsUpdated(void)38 atimeIsUpdated(void)
39 {
40 	const char *fn = "fs_noatime";
41 	struct stat st;
42 #if defined(_WIN32) && !defined(CYGWIN)
43 	char *buff = NULL;
44 	char *ptr;
45 	int r;
46 
47 	r = systemf("fsutil behavior query disableLastAccess > query_atime");
48 	if (r == 0) {
49 		buff = slurpfile(NULL, "query_atime");
50 		if (buff != NULL) {
51 			ptr = buff;
52 			while(*ptr != '\0' && !isdigit(*ptr)) {
53 				ptr++;
54 			}
55 			if (*ptr == '0') {
56 				free(buff);
57 				return(1);
58 			} else if (*ptr == '1' || *ptr == '2') {
59 				free(buff);
60 				return(0);
61 			}
62 			free(buff);
63 		}
64 	}
65 #endif
66 	if (!assertMakeFile(fn, 0666, "a"))
67 		return (0);
68 	if (!assertUtimes(fn, 1, 0, 1, 0))
69 		return (0);
70 	/* Test the file contents in order to update its atime. */
71 	if (!assertTextFileContents("a", fn))
72 		return (0);
73 	if (stat(fn, &st) != 0)
74 		return (0);
75 	/* Is atime updated? */
76 	if (st.st_atime > 1)
77 		return (1);
78 	return (0);
79 }
80 
81 static void
test_basic(void)82 test_basic(void)
83 {
84 	struct archive *a;
85 	struct archive_entry *ae;
86 	const void *p;
87 	char *initial_cwd, *cwd;
88 	size_t size;
89 	int64_t offset;
90 	int file_count;
91 #if defined(_WIN32) && !defined(__CYGWIN__)
92 	wchar_t *wcwd, *wp, *fullpath;
93 #endif
94 
95 	assertMakeDir("dir1", 0755);
96 	assertMakeFile("dir1/file1", 0644, "0123456789");
97 	assertMakeFile("dir1/file2", 0644, "hello world");
98 	assertMakeDir("dir1/sub1", 0755);
99 	assertMakeFile("dir1/sub1/file1", 0644, "0123456789");
100 	assertMakeDir("dir1/sub2", 0755);
101 	assertMakeFile("dir1/sub2/file1", 0644, "0123456789");
102 	assertMakeFile("dir1/sub2/file2", 0644, "0123456789");
103 	assertMakeDir("dir1/sub2/sub1", 0755);
104 	assertMakeDir("dir1/sub2/sub2", 0755);
105 	assertMakeDir("dir1/sub2/sub3", 0755);
106 	assertMakeFile("dir1/sub2/sub3/file", 0644, "xyz");
107 	file_count = 12;
108 
109 	assert((ae = archive_entry_new()) != NULL);
110 	assert((a = archive_read_disk_new()) != NULL);
111 	assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_open(a, "dir1"));
112 
113 	while (file_count--) {
114 		assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header2(a, ae));
115 		if (strcmp(archive_entry_pathname(ae), "dir1") == 0) {
116 			assertEqualInt(archive_entry_filetype(ae), AE_IFDIR);
117 			assertEqualInt(1, archive_read_disk_can_descend(a));
118 		} else if (strcmp(archive_entry_pathname(ae),
119 		    "dir1/file1") == 0) {
120 			assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
121 			assertEqualInt(archive_entry_size(ae), 10);
122 			assertEqualIntA(a, ARCHIVE_OK,
123 			    archive_read_data_block(a, &p, &size, &offset));
124 			assertEqualInt((int)size, 10);
125 			assertEqualInt((int)offset, 0);
126 			assertEqualMem(p, "0123456789", 10);
127 			assertEqualInt(ARCHIVE_EOF,
128 			    archive_read_data_block(a, &p, &size, &offset));
129 			assertEqualInt((int)size, 0);
130 			assertEqualInt((int)offset, 10);
131 			assertEqualInt(0, archive_read_disk_can_descend(a));
132 		} else if (strcmp(archive_entry_pathname(ae),
133 		    "dir1/file2") == 0) {
134 			assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
135 			assertEqualInt(archive_entry_size(ae), 11);
136 			assertEqualIntA(a, ARCHIVE_OK,
137 			    archive_read_data_block(a, &p, &size, &offset));
138 			assertEqualInt((int)size, 11);
139 			assertEqualInt((int)offset, 0);
140 			assertEqualMem(p, "hello world", 11);
141 			assertEqualInt(ARCHIVE_EOF,
142 			    archive_read_data_block(a, &p, &size, &offset));
143 			assertEqualInt((int)size, 0);
144 			assertEqualInt((int)offset, 11);
145 			assertEqualInt(0, archive_read_disk_can_descend(a));
146 		} else if (strcmp(archive_entry_pathname(ae),
147 		    "dir1/sub1") == 0) {
148 			assertEqualInt(archive_entry_filetype(ae), AE_IFDIR);
149 			assertEqualInt(1, archive_read_disk_can_descend(a));
150 		} else if (strcmp(archive_entry_pathname(ae),
151 		    "dir1/sub1/file1") == 0) {
152 			assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
153 			assertEqualInt(archive_entry_size(ae), 10);
154 			assertEqualIntA(a, ARCHIVE_OK,
155 			    archive_read_data_block(a, &p, &size, &offset));
156 			assertEqualInt((int)size, 10);
157 			assertEqualInt((int)offset, 0);
158 			assertEqualMem(p, "0123456789", 10);
159 			assertEqualInt(ARCHIVE_EOF,
160 			    archive_read_data_block(a, &p, &size, &offset));
161 			assertEqualInt((int)size, 0);
162 			assertEqualInt((int)offset, 10);
163 			assertEqualInt(0, archive_read_disk_can_descend(a));
164 		} else if (strcmp(archive_entry_pathname(ae),
165 		    "dir1/sub2") == 0) {
166 			assertEqualInt(archive_entry_filetype(ae), AE_IFDIR);
167 			assertEqualInt(1, archive_read_disk_can_descend(a));
168 		} else if (strcmp(archive_entry_pathname(ae),
169 		    "dir1/sub2/file1") == 0) {
170 			assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
171 			assertEqualInt(archive_entry_size(ae), 10);
172 			assertEqualIntA(a, ARCHIVE_OK,
173 			    archive_read_data_block(a, &p, &size, &offset));
174 			assertEqualInt((int)size, 10);
175 			assertEqualInt((int)offset, 0);
176 			assertEqualMem(p, "0123456789", 10);
177 			assertEqualInt(ARCHIVE_EOF,
178 			    archive_read_data_block(a, &p, &size, &offset));
179 			assertEqualInt((int)size, 0);
180 			assertEqualInt((int)offset, 10);
181 			assertEqualInt(0, archive_read_disk_can_descend(a));
182 		} else if (strcmp(archive_entry_pathname(ae),
183 		    "dir1/sub2/file2") == 0) {
184 			assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
185 			assertEqualInt(archive_entry_size(ae), 10);
186 			assertEqualIntA(a, ARCHIVE_OK,
187 			    archive_read_data_block(a, &p, &size, &offset));
188 			assertEqualInt((int)size, 10);
189 			assertEqualInt((int)offset, 0);
190 			assertEqualMem(p, "0123456789", 10);
191 			assertEqualInt(ARCHIVE_EOF,
192 			    archive_read_data_block(a, &p, &size, &offset));
193 			assertEqualInt((int)size, 0);
194 			assertEqualInt((int)offset, 10);
195 			assertEqualInt(0, archive_read_disk_can_descend(a));
196 		} else if (strcmp(archive_entry_pathname(ae),
197 		    "dir1/sub2/sub1") == 0) {
198 			assertEqualInt(archive_entry_filetype(ae), AE_IFDIR);
199 			assertEqualInt(1, archive_read_disk_can_descend(a));
200 		} else if (strcmp(archive_entry_pathname(ae),
201 		    "dir1/sub2/sub2") == 0) {
202 			assertEqualInt(archive_entry_filetype(ae), AE_IFDIR);
203 			assertEqualInt(1, archive_read_disk_can_descend(a));
204 		} else if (strcmp(archive_entry_pathname(ae),
205 		    "dir1/sub2/sub3") == 0) {
206 			assertEqualInt(archive_entry_filetype(ae), AE_IFDIR);
207 			assertEqualInt(1, archive_read_disk_can_descend(a));
208 		} else if (strcmp(archive_entry_pathname(ae),
209 		    "dir1/sub2/sub3/file") == 0) {
210 			assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
211 			assertEqualInt(archive_entry_size(ae), 3);
212 			assertEqualIntA(a, ARCHIVE_OK,
213 			    archive_read_data_block(a, &p, &size, &offset));
214 			assertEqualInt((int)size, 3);
215 			assertEqualInt((int)offset, 0);
216 			assertEqualMem(p, "xyz", 3);
217 			assertEqualInt(ARCHIVE_EOF,
218 			    archive_read_data_block(a, &p, &size, &offset));
219 			assertEqualInt((int)size, 0);
220 			assertEqualInt((int)offset, 3);
221 			assertEqualInt(0, archive_read_disk_can_descend(a));
222 		}
223 		if (archive_entry_filetype(ae) == AE_IFDIR) {
224 			/* Descend into the current object */
225 			assertEqualIntA(a, ARCHIVE_OK,
226 			    archive_read_disk_descend(a));
227 		}
228 	}
229 	/* There is no entry. */
230 	assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header2(a, ae));
231 
232 	/* Close the disk object. */
233 	assertEqualInt(ARCHIVE_OK, archive_read_close(a));
234 
235 	/*
236 	 * Test that call archive_read_disk_open_w, wchar_t version.
237 	 */
238 	assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_open_w(a, L"dir1"));
239 
240 	file_count = 12;
241 	while (file_count--) {
242 		assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header2(a, ae));
243 		if (wcscmp(archive_entry_pathname_w(ae), L"dir1") == 0) {
244 			assertEqualInt(archive_entry_filetype(ae), AE_IFDIR);
245 			assertEqualInt(1, archive_read_disk_can_descend(a));
246 		} else if (wcscmp(archive_entry_pathname_w(ae),
247 		    L"dir1/file1") == 0) {
248 			assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
249 			assertEqualInt(archive_entry_size(ae), 10);
250 			assertEqualIntA(a, ARCHIVE_OK,
251 			    archive_read_data_block(a, &p, &size, &offset));
252 			assertEqualInt((int)size, 10);
253 			assertEqualInt((int)offset, 0);
254 			assertEqualMem(p, "0123456789", 10);
255 			assertEqualInt(ARCHIVE_EOF,
256 			    archive_read_data_block(a, &p, &size, &offset));
257 			assertEqualInt((int)size, 0);
258 			assertEqualInt((int)offset, 10);
259 			assertEqualInt(0, archive_read_disk_can_descend(a));
260 		} else if (wcscmp(archive_entry_pathname_w(ae),
261 		    L"dir1/file2") == 0) {
262 			assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
263 			assertEqualInt(archive_entry_size(ae), 11);
264 			assertEqualIntA(a, ARCHIVE_OK,
265 			    archive_read_data_block(a, &p, &size, &offset));
266 			assertEqualInt((int)size, 11);
267 			assertEqualInt((int)offset, 0);
268 			assertEqualMem(p, "hello world", 11);
269 			assertEqualInt(ARCHIVE_EOF,
270 			    archive_read_data_block(a, &p, &size, &offset));
271 			assertEqualInt((int)size, 0);
272 			assertEqualInt((int)offset, 11);
273 			assertEqualInt(0, archive_read_disk_can_descend(a));
274 		} else if (wcscmp(archive_entry_pathname_w(ae),
275 		    L"dir1/sub1") == 0) {
276 			assertEqualInt(archive_entry_filetype(ae), AE_IFDIR);
277 			assertEqualInt(1, archive_read_disk_can_descend(a));
278 		} else if (wcscmp(archive_entry_pathname_w(ae),
279 		    L"dir1/sub1/file1") == 0) {
280 			assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
281 			assertEqualInt(archive_entry_size(ae), 10);
282 			assertEqualIntA(a, ARCHIVE_OK,
283 			    archive_read_data_block(a, &p, &size, &offset));
284 			assertEqualInt((int)size, 10);
285 			assertEqualInt((int)offset, 0);
286 			assertEqualMem(p, "0123456789", 10);
287 			assertEqualInt(ARCHIVE_EOF,
288 			    archive_read_data_block(a, &p, &size, &offset));
289 			assertEqualInt((int)size, 0);
290 			assertEqualInt((int)offset, 10);
291 			assertEqualInt(0, archive_read_disk_can_descend(a));
292 		} else if (wcscmp(archive_entry_pathname_w(ae),
293 		    L"dir1/sub2") == 0) {
294 			assertEqualInt(archive_entry_filetype(ae), AE_IFDIR);
295 			assertEqualInt(1, archive_read_disk_can_descend(a));
296 		} else if (wcscmp(archive_entry_pathname_w(ae),
297 		    L"dir1/sub2/file1") == 0) {
298 			assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
299 			assertEqualInt(archive_entry_size(ae), 10);
300 			assertEqualIntA(a, ARCHIVE_OK,
301 			    archive_read_data_block(a, &p, &size, &offset));
302 			assertEqualInt((int)size, 10);
303 			assertEqualInt((int)offset, 0);
304 			assertEqualMem(p, "0123456789", 10);
305 			assertEqualInt(ARCHIVE_EOF,
306 			    archive_read_data_block(a, &p, &size, &offset));
307 			assertEqualInt((int)size, 0);
308 			assertEqualInt((int)offset, 10);
309 			assertEqualInt(0, archive_read_disk_can_descend(a));
310 		} else if (wcscmp(archive_entry_pathname_w(ae),
311 		    L"dir1/sub2/file2") == 0) {
312 			assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
313 			assertEqualInt(archive_entry_size(ae), 10);
314 			assertEqualIntA(a, ARCHIVE_OK,
315 			    archive_read_data_block(a, &p, &size, &offset));
316 			assertEqualInt((int)size, 10);
317 			assertEqualInt((int)offset, 0);
318 			assertEqualMem(p, "0123456789", 10);
319 			assertEqualInt(ARCHIVE_EOF,
320 			    archive_read_data_block(a, &p, &size, &offset));
321 			assertEqualInt((int)size, 0);
322 			assertEqualInt((int)offset, 10);
323 			assertEqualInt(0, archive_read_disk_can_descend(a));
324 		} else if (wcscmp(archive_entry_pathname_w(ae),
325 		    L"dir1/sub2/sub1") == 0) {
326 			assertEqualInt(archive_entry_filetype(ae), AE_IFDIR);
327 			assertEqualInt(1, archive_read_disk_can_descend(a));
328 		} else if (wcscmp(archive_entry_pathname_w(ae),
329 		    L"dir1/sub2/sub2") == 0) {
330 			assertEqualInt(archive_entry_filetype(ae), AE_IFDIR);
331 			assertEqualInt(1, archive_read_disk_can_descend(a));
332 		} else if (wcscmp(archive_entry_pathname_w(ae),
333 		    L"dir1/sub2/sub3") == 0) {
334 			assertEqualInt(archive_entry_filetype(ae), AE_IFDIR);
335 			assertEqualInt(1, archive_read_disk_can_descend(a));
336 		} else if (wcscmp(archive_entry_pathname_w(ae),
337 		    L"dir1/sub2/sub3/file") == 0) {
338 			assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
339 			assertEqualInt(archive_entry_size(ae), 3);
340 			assertEqualIntA(a, ARCHIVE_OK,
341 			    archive_read_data_block(a, &p, &size, &offset));
342 			assertEqualInt((int)size, 3);
343 			assertEqualInt((int)offset, 0);
344 			assertEqualMem(p, "xyz", 3);
345 			assertEqualInt(ARCHIVE_EOF,
346 			    archive_read_data_block(a, &p, &size, &offset));
347 			assertEqualInt((int)size, 0);
348 			assertEqualInt((int)offset, 3);
349 			assertEqualInt(0, archive_read_disk_can_descend(a));
350 		}
351 		if (archive_entry_filetype(ae) == AE_IFDIR) {
352 			/* Descend into the current object */
353 			assertEqualIntA(a, ARCHIVE_OK,
354 			    archive_read_disk_descend(a));
355 		}
356 	}
357 	/* There is no entry. */
358 	assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header2(a, ae));
359 
360 	/* Close the disk object. */
361 	assertEqualInt(ARCHIVE_OK, archive_read_close(a));
362 
363 	/*
364 	 * Test that call archive_read_disk_open with a regular file.
365 	 */
366 	assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_open(a, "dir1/file1"));
367 
368 	/* dir1/file1 */
369 	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header2(a, ae));
370 	assertEqualInt(0, archive_read_disk_can_descend(a));
371 	assertEqualString(archive_entry_pathname(ae), "dir1/file1");
372 	assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
373 	assertEqualInt(archive_entry_size(ae), 10);
374 	assertEqualIntA(a, ARCHIVE_OK,
375 	    archive_read_data_block(a, &p, &size, &offset));
376 	assertEqualInt((int)size, 10);
377 	assertEqualInt((int)offset, 0);
378 	assertEqualMem(p, "0123456789", 10);
379 
380 	/* There is no entry. */
381 	assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header2(a, ae));
382 
383 	/* Close the disk object. */
384 	assertEqualInt(ARCHIVE_OK, archive_read_close(a));
385 
386 
387 #if defined(_WIN32) && !defined(__CYGWIN__)
388 	/*
389 	 * Test for wildcard '*' or '?'
390 	 */
391 	assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_open(a, "dir1/*1"));
392 
393 	/* dir1/file1 */
394 	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header2(a, ae));
395 	assertEqualInt(0, archive_read_disk_can_descend(a));
396 	assertEqualString(archive_entry_pathname(ae), "dir1/file1");
397 	assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
398 	assertEqualInt(archive_entry_size(ae), 10);
399 	assertEqualIntA(a, ARCHIVE_OK,
400 	    archive_read_data_block(a, &p, &size, &offset));
401 	assertEqualInt((int)size, 10);
402 	assertEqualInt((int)offset, 0);
403 	assertEqualMem(p, "0123456789", 10);
404 
405 	/* dir1/sub1 */
406 	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header2(a, ae));
407 	assertEqualInt(1, archive_read_disk_can_descend(a));
408 	assertEqualString(archive_entry_pathname(ae), "dir1/sub1");
409 	assertEqualInt(archive_entry_filetype(ae), AE_IFDIR);
410 
411 	/* Descend into the current object */
412 	assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_descend(a));
413 
414 	/* dir1/sub1/file1 */
415 	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header2(a, ae));
416 	assertEqualInt(0, archive_read_disk_can_descend(a));
417 	assertEqualString(archive_entry_pathname(ae), "dir1/sub1/file1");
418 	assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
419 	assertEqualInt(archive_entry_size(ae), 10);
420 	assertEqualIntA(a, ARCHIVE_OK,
421 	    archive_read_data_block(a, &p, &size, &offset));
422 	assertEqualInt((int)size, 10);
423 	assertEqualInt((int)offset, 0);
424 	assertEqualMem(p, "0123456789", 10);
425 
426 	/* There is no entry. */
427 	assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header2(a, ae));
428 
429 	/* Close the disk object. */
430 	assertEqualInt(ARCHIVE_OK, archive_read_close(a));
431 
432 	/*
433 	 * Test for a full-path beginning with "//?/"
434 	 */
435 	wcwd = _wgetcwd(NULL, 0);
436 	fullpath = malloc(sizeof(wchar_t) * (wcslen(wcwd) + 32));
437 	wcscpy(fullpath, L"//?/");
438 	wcscat(fullpath, wcwd);
439 	wcscat(fullpath, L"/dir1/file1");
440 	free(wcwd);
441 	assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_open_w(a, fullpath));
442 	while ((wcwd = wcschr(fullpath, L'\\')) != NULL)
443 		*wcwd = L'/';
444 
445 	/* dir1/file1 */
446 	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header2(a, ae));
447 	assertEqualInt(0, archive_read_disk_can_descend(a));
448 	assertEqualWString(archive_entry_pathname_w(ae), fullpath);
449 	assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
450 	assertEqualInt(archive_entry_size(ae), 10);
451 	assertEqualIntA(a, ARCHIVE_OK,
452 	    archive_read_data_block(a, &p, &size, &offset));
453 	assertEqualInt((int)size, 10);
454 	assertEqualInt((int)offset, 0);
455 	assertEqualMem(p, "0123456789", 10);
456 
457 	/* There is no entry. */
458 	assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header2(a, ae));
459 
460 	/* Close the disk object. */
461 	assertEqualInt(ARCHIVE_OK, archive_read_close(a));
462 	free(fullpath);
463 
464 	/*
465 	 * Test for wild card '*' or '?' with "//?/" prefix.
466 	 */
467 	wcwd = _wgetcwd(NULL, 0);
468 	fullpath = malloc(sizeof(wchar_t) * (wcslen(wcwd) + 32));
469 	wcscpy(fullpath, L"//?/");
470 	wcscat(fullpath, wcwd);
471 	wcscat(fullpath, L"/dir1/*1");
472 	free(wcwd);
473 	assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_open_w(a, fullpath));
474 	while ((wcwd = wcschr(fullpath, L'\\')) != NULL)
475 		*wcwd = L'/';
476 
477 	/* dir1/file1 */
478 	wp = wcsrchr(fullpath, L'/');
479 	wcscpy(wp+1, L"file1");
480 	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header2(a, ae));
481 	assertEqualInt(0, archive_read_disk_can_descend(a));
482 	assertEqualWString(archive_entry_pathname_w(ae), fullpath);
483 	assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
484 	assertEqualInt(archive_entry_size(ae), 10);
485 	assertEqualIntA(a, ARCHIVE_OK,
486 	    archive_read_data_block(a, &p, &size, &offset));
487 	assertEqualInt((int)size, 10);
488 	assertEqualInt((int)offset, 0);
489 	assertEqualMem(p, "0123456789", 10);
490 
491 	/* dir1/sub1 */
492 	wcscpy(wp+1, L"sub1");
493 	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header2(a, ae));
494 	assertEqualInt(1, archive_read_disk_can_descend(a));
495 	assertEqualWString(archive_entry_pathname_w(ae), fullpath);
496 	assertEqualInt(archive_entry_filetype(ae), AE_IFDIR);
497 
498 	/* Descend into the current object */
499 	assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_descend(a));
500 
501 	/* dir1/sub1/file1 */
502 	wcscpy(wp+1, L"sub1/file1");
503 	assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header2(a, ae));
504 	assertEqualInt(0, archive_read_disk_can_descend(a));
505 	assertEqualWString(archive_entry_pathname_w(ae), fullpath);
506 	assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
507 	assertEqualInt(archive_entry_size(ae), 10);
508 	assertEqualIntA(a, ARCHIVE_OK,
509 	    archive_read_data_block(a, &p, &size, &offset));
510 	assertEqualInt((int)size, 10);
511 	assertEqualInt((int)offset, 0);
512 	assertEqualMem(p, "0123456789", 10);
513 
514 	/* There is no entry. */
515 	assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header2(a, ae));
516 
517 	/* Close the disk object. */
518 	assertEqualInt(ARCHIVE_OK, archive_read_close(a));
519 	free(fullpath);
520 
521 #endif
522 
523 	/*
524 	 * We should be on the initial directory where we performed
525 	 * archive_read_disk_new() after we perform archive_read_free()
526 	 * even if we broke off the directory traversals.
527 	 */
528 
529 	/* Save current working directory. */
530 #if defined(PATH_MAX) && !defined(__GLIBC__)
531 	initial_cwd = getcwd(NULL, PATH_MAX);/* Solaris getcwd needs the size. */
532 #else
533 	initial_cwd = getcwd(NULL, 0);
534 #endif
535 
536 	assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_open(a, "dir1"));
537 
538 	/* Step in a deep directory. */
539 	file_count = 12;
540 	while (file_count--) {
541 		assertEqualIntA(a, ARCHIVE_OK,
542 		    archive_read_next_header2(a, ae));
543 		if (strcmp(archive_entry_pathname(ae),
544 		    "dir1/sub1/file1") == 0)
545 			/*
546 			 * We are on an another directory at this time.
547 			 */
548 			break;
549 		if (archive_entry_filetype(ae) == AE_IFDIR) {
550 			/* Descend into the current object */
551 			assertEqualIntA(a, ARCHIVE_OK,
552 			    archive_read_disk_descend(a));
553 		}
554 	}
555 	/* Destroy the disk object. */
556 	assertEqualInt(ARCHIVE_OK, archive_read_free(a));
557 
558 	/* We should be on the initial working directory. */
559 	failure(
560 	    "Current working directory does not return to the initial"
561 	    "directory");
562 #if defined(PATH_MAX) && !defined(__GLIBC__)
563 	cwd = getcwd(NULL, PATH_MAX);/* Solaris getcwd needs the size. */
564 #else
565 	cwd = getcwd(NULL, 0);
566 #endif
567 	assertEqualString(initial_cwd, cwd);
568 	free(initial_cwd);
569 	free(cwd);
570 
571 	archive_entry_free(ae);
572 }
573 
574 static void
test_symlink_hybrid(void)575 test_symlink_hybrid(void)
576 {
577 	struct archive *a;
578 	struct archive_entry *ae;
579 	const void *p;
580 	size_t size;
581 	int64_t offset;
582 	int file_count;
583 
584 	if (!canSymlink()) {
585 		skipping("Can't test symlinks on this filesystem");
586 		return;
587 	}
588 
589 	/*
590 	 * Create a sample archive.
591 	 */
592 	assertMakeDir("h", 0755);
593 	assertChdir("h");
594 	assertMakeDir("d1", 0755);
595 	assertMakeSymlink("ld1", "d1", 1);
596 	assertMakeFile("d1/file1", 0644, "d1/file1");
597 	assertMakeFile("d1/file2", 0644, "d1/file2");
598 	assertMakeSymlink("d1/link1", "file1", 0);
599 	assertMakeSymlink("d1/linkX", "fileX", 0);
600 	assertMakeSymlink("link2", "d1/file2", 0);
601 	assertMakeSymlink("linkY", "d1/fileY", 0);
602 	assertChdir("..");
603 
604 	assert((ae = archive_entry_new()) != NULL);
605 	assert((a = archive_read_disk_new()) != NULL);
606 	assertEqualIntA(a, ARCHIVE_OK,
607 	    archive_read_disk_set_symlink_hybrid(a));
608 
609 	/*
610 	 * Specified file is a symbolic link file.
611 	 */
612 	assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_open(a, "h/ld1"));
613 	file_count = 5;
614 
615 	while (file_count--) {
616 		assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header2(a, ae));
617 		if (strcmp(archive_entry_pathname(ae), "h/ld1") == 0) {
618 			assertEqualInt(archive_entry_filetype(ae), AE_IFDIR);
619 		} else if (strcmp(archive_entry_pathname(ae),
620 		    "h/ld1/file1") == 0) {
621 			assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
622 			assertEqualInt(archive_entry_size(ae), 8);
623 			assertEqualIntA(a, ARCHIVE_OK,
624 			    archive_read_data_block(a, &p, &size, &offset));
625 			assertEqualInt((int)size, 8);
626 			assertEqualInt((int)offset, 0);
627 			assertEqualMem(p, "d1/file1", 8);
628 			assertEqualInt(ARCHIVE_EOF,
629 			    archive_read_data_block(a, &p, &size, &offset));
630 			assertEqualInt((int)size, 0);
631 			assertEqualInt((int)offset, 8);
632 		} else if (strcmp(archive_entry_pathname(ae),
633 		    "h/ld1/file2") == 0) {
634 			assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
635 			assertEqualInt(archive_entry_size(ae), 8);
636 			assertEqualIntA(a, ARCHIVE_OK,
637 			    archive_read_data_block(a, &p, &size, &offset));
638 			assertEqualInt((int)size, 8);
639 			assertEqualInt((int)offset, 0);
640 			assertEqualMem(p, "d1/file2", 8);
641 			assertEqualInt(ARCHIVE_EOF,
642 			    archive_read_data_block(a, &p, &size, &offset));
643 			assertEqualInt((int)size, 0);
644 			assertEqualInt((int)offset, 8);
645 		} else if (strcmp(archive_entry_pathname(ae),
646 		    "h/ld1/link1") == 0) {
647 			assertEqualInt(archive_entry_filetype(ae), AE_IFLNK);
648 		} else if (strcmp(archive_entry_pathname(ae),
649 		    "h/ld1/linkX") == 0) {
650 			assertEqualInt(archive_entry_filetype(ae), AE_IFLNK);
651 		}
652 		if (archive_entry_filetype(ae) == AE_IFDIR) {
653 			/* Descend into the current object */
654 			assertEqualIntA(a, ARCHIVE_OK,
655 			    archive_read_disk_descend(a));
656 		}
657 	}
658 	/* There is no entry. */
659 	assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header2(a, ae));
660 	/* Close the disk object. */
661 	assertEqualInt(ARCHIVE_OK, archive_read_close(a));
662 
663 	/*
664 	 * Specified file is a directory and it has symbolic files.
665 	 */
666 	assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_open(a, "h"));
667 	file_count = 9;
668 
669 	while (file_count--) {
670 		assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header2(a, ae));
671 		if (strcmp(archive_entry_pathname(ae), "h") == 0) {
672 			assertEqualInt(archive_entry_filetype(ae), AE_IFDIR);
673 		} else if (strcmp(archive_entry_pathname(ae), "h/d1") == 0) {
674 			assertEqualInt(archive_entry_filetype(ae), AE_IFDIR);
675 		} else if (strcmp(archive_entry_pathname(ae),
676 		    "h/d1/file1") == 0) {
677 			assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
678 			assertEqualInt(archive_entry_size(ae), 8);
679 			assertEqualIntA(a, ARCHIVE_OK,
680 			    archive_read_data_block(a, &p, &size, &offset));
681 			assertEqualInt((int)size, 8);
682 			assertEqualInt((int)offset, 0);
683 			assertEqualMem(p, "d1/file1", 8);
684 			assertEqualInt(ARCHIVE_EOF,
685 			    archive_read_data_block(a, &p, &size, &offset));
686 			assertEqualInt((int)size, 0);
687 			assertEqualInt((int)offset, 8);
688 		} else if (strcmp(archive_entry_pathname(ae),
689 		    "h/d1/file2") == 0) {
690 			assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
691 			assertEqualInt(archive_entry_size(ae), 8);
692 			assertEqualIntA(a, ARCHIVE_OK,
693 			    archive_read_data_block(a, &p, &size, &offset));
694 			assertEqualInt((int)size, 8);
695 			assertEqualInt((int)offset, 0);
696 			assertEqualMem(p, "d1/file2", 8);
697 			assertEqualInt(ARCHIVE_EOF,
698 			    archive_read_data_block(a, &p, &size, &offset));
699 			assertEqualInt((int)size, 0);
700 			assertEqualInt((int)offset, 8);
701 		} else if (strcmp(archive_entry_pathname(ae), "h/ld1") == 0) {
702 			assertEqualInt(archive_entry_filetype(ae), AE_IFLNK);
703 		} else if (strcmp(archive_entry_pathname(ae),
704 		    "h/d1/link1") == 0) {
705 			assertEqualInt(archive_entry_filetype(ae), AE_IFLNK);
706 		} else if (strcmp(archive_entry_pathname(ae),
707 		    "h/d1/linkX") == 0) {
708 			assertEqualInt(archive_entry_filetype(ae), AE_IFLNK);
709 		} else if (strcmp(archive_entry_pathname(ae),
710 		    "h/link2") == 0) {
711 			assertEqualInt(archive_entry_filetype(ae), AE_IFLNK);
712 		} else if (strcmp(archive_entry_pathname(ae),
713 		    "h/linkY") == 0) {
714 			assertEqualInt(archive_entry_filetype(ae), AE_IFLNK);
715 		}
716 		if (archive_entry_filetype(ae) == AE_IFDIR) {
717 			/* Descend into the current object */
718 			assertEqualIntA(a, ARCHIVE_OK,
719 			    archive_read_disk_descend(a));
720 		}
721 	}
722 	/* There is no entry. */
723 	assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header2(a, ae));
724 	/* Close the disk object. */
725 	assertEqualInt(ARCHIVE_OK, archive_read_close(a));
726 	/* Destroy the disk object. */
727 	assertEqualInt(ARCHIVE_OK, archive_read_free(a));
728 	archive_entry_free(ae);
729 }
730 
731 static void
test_symlink_logical(void)732 test_symlink_logical(void)
733 {
734 	struct archive *a;
735 	struct archive_entry *ae;
736 	const void *p;
737 	size_t size;
738 	int64_t offset;
739 	int file_count;
740 
741 	if (!canSymlink()) {
742 		skipping("Can't test symlinks on this filesystem");
743 		return;
744 	}
745 
746 	/*
747 	 * Create a sample archive.
748 	 */
749 	assertMakeDir("l", 0755);
750 	assertChdir("l");
751 	assertMakeDir("d1", 0755);
752 	assertMakeSymlink("ld1", "d1", 1);
753 	assertMakeFile("d1/file1", 0644, "d1/file1");
754 	assertMakeFile("d1/file2", 0644, "d1/file2");
755 	assertMakeSymlink("d1/link1", "file1", 0);
756 	assertMakeSymlink("d1/linkX", "fileX", 0);
757 	assertMakeSymlink("link2", "d1/file2", 0);
758 	assertMakeSymlink("linkY", "d1/fileY", 0);
759 	assertChdir("..");
760 
761 	/* Note: this test uses archive_read_next_header()
762 	   instead of archive_read_next_header2() */
763 	assert((a = archive_read_disk_new()) != NULL);
764 	assertEqualIntA(a, ARCHIVE_OK,
765 	    archive_read_disk_set_symlink_logical(a));
766 
767 	/*
768 	 * Specified file is a symbolic link file.
769 	 */
770 	assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_open(a, "l/ld1"));
771 	file_count = 5;
772 
773 	while (file_count--) {
774 		assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
775 		if (strcmp(archive_entry_pathname(ae), "l/ld1") == 0) {
776 			assertEqualInt(archive_entry_filetype(ae), AE_IFDIR);
777 		} else if (strcmp(archive_entry_pathname(ae),
778 		    "l/ld1/file1") == 0) {
779 			assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
780 			assertEqualInt(archive_entry_size(ae), 8);
781 			assertEqualIntA(a, ARCHIVE_OK,
782 			    archive_read_data_block(a, &p, &size, &offset));
783 			assertEqualInt((int)size, 8);
784 			assertEqualInt((int)offset, 0);
785 			assertEqualMem(p, "d1/file1", 8);
786 			assertEqualInt(ARCHIVE_EOF,
787 			    archive_read_data_block(a, &p, &size, &offset));
788 			assertEqualInt((int)size, 0);
789 			assertEqualInt((int)offset, 8);
790 		} else if (strcmp(archive_entry_pathname(ae),
791 		    "l/ld1/file2") == 0) {
792 			assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
793 			assertEqualInt(archive_entry_size(ae), 8);
794 			assertEqualIntA(a, ARCHIVE_OK,
795 			    archive_read_data_block(a, &p, &size, &offset));
796 			assertEqualInt((int)size, 8);
797 			assertEqualInt((int)offset, 0);
798 			assertEqualMem(p, "d1/file2", 8);
799 			assertEqualInt(ARCHIVE_EOF,
800 			    archive_read_data_block(a, &p, &size, &offset));
801 			assertEqualInt((int)size, 0);
802 			assertEqualInt((int)offset, 8);
803 		} else if (strcmp(archive_entry_pathname(ae),
804 		    "l/ld1/link1") == 0) {
805 			assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
806 			assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
807 			assertEqualInt(archive_entry_size(ae), 8);
808 			assertEqualIntA(a, ARCHIVE_OK,
809 			    archive_read_data_block(a, &p, &size, &offset));
810 			assertEqualInt((int)size, 8);
811 			assertEqualInt((int)offset, 0);
812 			assertEqualMem(p, "d1/file1", 8);
813 			assertEqualInt(ARCHIVE_EOF,
814 			    archive_read_data_block(a, &p, &size, &offset));
815 			assertEqualInt((int)size, 0);
816 			assertEqualInt((int)offset, 8);
817 		} else if (strcmp(archive_entry_pathname(ae),
818 		    "l/ld1/linkX") == 0) {
819 			assertEqualInt(archive_entry_filetype(ae), AE_IFLNK);
820 		}
821 		if (archive_entry_filetype(ae) == AE_IFDIR) {
822 			/* Descend into the current object */
823 			assertEqualIntA(a, ARCHIVE_OK,
824 			    archive_read_disk_descend(a));
825 		}
826 	}
827 	/* There is no entry. */
828 	assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae));
829 	/* Close the disk object. */
830 	assertEqualInt(ARCHIVE_OK, archive_read_close(a));
831 
832 	/*
833 	 * Specified file is a directory and it has symbolic files.
834 	 */
835 	assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_open(a, "l"));
836 	file_count = 13;
837 
838 	while (file_count--) {
839 		assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
840 		if (strcmp(archive_entry_pathname(ae), "l") == 0) {
841 			assertEqualInt(archive_entry_filetype(ae), AE_IFDIR);
842 		} else if (strcmp(archive_entry_pathname(ae), "l/d1") == 0) {
843 			assertEqualInt(archive_entry_filetype(ae), AE_IFDIR);
844 		} else if (strcmp(archive_entry_pathname(ae),
845 		    "l/d1/file1") == 0) {
846 			assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
847 			assertEqualInt(archive_entry_size(ae), 8);
848 			assertEqualIntA(a, ARCHIVE_OK,
849 			    archive_read_data_block(a, &p, &size, &offset));
850 			assertEqualInt((int)size, 8);
851 			assertEqualInt((int)offset, 0);
852 			assertEqualMem(p, "d1/file1", 8);
853 			assertEqualInt(ARCHIVE_EOF,
854 			    archive_read_data_block(a, &p, &size, &offset));
855 			assertEqualInt((int)size, 0);
856 			assertEqualInt((int)offset, 8);
857 		} else if (strcmp(archive_entry_pathname(ae),
858 		    "l/d1/file2") == 0) {
859 			assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
860 			assertEqualInt(archive_entry_size(ae), 8);
861 			assertEqualIntA(a, ARCHIVE_OK,
862 			    archive_read_data_block(a, &p, &size, &offset));
863 			assertEqualInt((int)size, 8);
864 			assertEqualInt((int)offset, 0);
865 			assertEqualMem(p, "d1/file2", 8);
866 			assertEqualInt(ARCHIVE_EOF,
867 			    archive_read_data_block(a, &p, &size, &offset));
868 			assertEqualInt((int)size, 0);
869 			assertEqualInt((int)offset, 8);
870 		} else if (strcmp(archive_entry_pathname(ae),
871 		    "l/d1/link1") == 0) {
872 			assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
873 			assertEqualInt(archive_entry_size(ae), 8);
874 			assertEqualIntA(a, ARCHIVE_OK,
875 			    archive_read_data_block(a, &p, &size, &offset));
876 			assertEqualInt((int)size, 8);
877 			assertEqualInt((int)offset, 0);
878 			assertEqualMem(p, "d1/file1", 8);
879 			assertEqualInt(ARCHIVE_EOF,
880 			    archive_read_data_block(a, &p, &size, &offset));
881 			assertEqualInt((int)size, 0);
882 			assertEqualInt((int)offset, 8);
883 		} else if (strcmp(archive_entry_pathname(ae),
884 		    "l/d1/linkX") == 0) {
885 			assertEqualInt(archive_entry_filetype(ae), AE_IFLNK);
886 		} else if (strcmp(archive_entry_pathname(ae), "l/ld1") == 0) {
887 			assertEqualInt(archive_entry_filetype(ae), AE_IFDIR);
888 		} else if (strcmp(archive_entry_pathname(ae),
889 		    "l/ld1/file1") == 0) {
890 			assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
891 			assertEqualInt(archive_entry_size(ae), 8);
892 			assertEqualIntA(a, ARCHIVE_OK,
893 			    archive_read_data_block(a, &p, &size, &offset));
894 			assertEqualInt((int)size, 8);
895 			assertEqualInt((int)offset, 0);
896 			assertEqualMem(p, "d1/file1", 8);
897 			assertEqualInt(ARCHIVE_EOF,
898 			    archive_read_data_block(a, &p, &size, &offset));
899 			assertEqualInt((int)size, 0);
900 			assertEqualInt((int)offset, 8);
901 		} else if (strcmp(archive_entry_pathname(ae),
902 		    "l/ld1/file2") == 0) {
903 			assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
904 			assertEqualInt(archive_entry_size(ae), 8);
905 			assertEqualIntA(a, ARCHIVE_OK,
906 			    archive_read_data_block(a, &p, &size, &offset));
907 			assertEqualInt((int)size, 8);
908 			assertEqualInt((int)offset, 0);
909 			assertEqualMem(p, "d1/file2", 8);
910 			assertEqualInt(ARCHIVE_EOF,
911 			    archive_read_data_block(a, &p, &size, &offset));
912 			assertEqualInt((int)size, 0);
913 			assertEqualInt((int)offset, 8);
914 		} else if (strcmp(archive_entry_pathname(ae),
915 		    "l/ld1/link1") == 0) {
916 			assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
917 			assertEqualInt(archive_entry_size(ae), 8);
918 			assertEqualIntA(a, ARCHIVE_OK,
919 			    archive_read_data_block(a, &p, &size, &offset));
920 			assertEqualInt((int)size, 8);
921 			assertEqualInt((int)offset, 0);
922 			assertEqualMem(p, "d1/file1", 8);
923 			assertEqualInt(ARCHIVE_EOF,
924 			    archive_read_data_block(a, &p, &size, &offset));
925 			assertEqualInt((int)size, 0);
926 			assertEqualInt((int)offset, 8);
927 		} else if (strcmp(archive_entry_pathname(ae),
928 		    "l/ld1/linkX") == 0) {
929 			assertEqualInt(archive_entry_filetype(ae), AE_IFLNK);
930 		} else if (strcmp(archive_entry_pathname(ae),
931 		    "l/link2") == 0) {
932 			assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
933 			assertEqualInt(archive_entry_size(ae), 8);
934 			assertEqualIntA(a, ARCHIVE_OK,
935 			    archive_read_data_block(a, &p, &size, &offset));
936 			assertEqualInt((int)size, 8);
937 			assertEqualInt((int)offset, 0);
938 			assertEqualMem(p, "d1/file2", 8);
939 			assertEqualInt(ARCHIVE_EOF,
940 			    archive_read_data_block(a, &p, &size, &offset));
941 			assertEqualInt((int)size, 0);
942 			assertEqualInt((int)offset, 8);
943 		} else if (strcmp(archive_entry_pathname(ae),
944 		    "l/linkY") == 0) {
945 			assertEqualInt(archive_entry_filetype(ae), AE_IFLNK);
946 		}
947 		if (archive_entry_filetype(ae) == AE_IFDIR) {
948 			/* Descend into the current object */
949 			assertEqualIntA(a, ARCHIVE_OK,
950 			    archive_read_disk_descend(a));
951 		}
952 	}
953 	/* There is no entry. */
954 	assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae));
955 	/* Close the disk object. */
956 	assertEqualInt(ARCHIVE_OK, archive_read_close(a));
957 	/* Destroy the disk object. */
958 	assertEqualInt(ARCHIVE_OK, archive_read_free(a));
959 }
960 
961 static void
test_symlink_logical_loop(void)962 test_symlink_logical_loop(void)
963 {
964 	struct archive *a;
965 	struct archive_entry *ae;
966 	const void *p;
967 	size_t size;
968 	int64_t offset;
969 	int file_count;
970 
971 	if (!canSymlink()) {
972 		skipping("Can't test symlinks on this filesystem");
973 		return;
974 	}
975 
976 	/*
977 	 * Create a sample archive.
978 	 */
979 	assertMakeDir("l2", 0755);
980 	assertChdir("l2");
981 	assertMakeDir("d1", 0755);
982 	assertMakeDir("d1/d2", 0755);
983 	assertMakeDir("d1/d2/d3", 0755);
984 	assertMakeDir("d2", 0755);
985 	assertMakeFile("d2/file1", 0644, "d2/file1");
986 	assertMakeSymlink("d1/d2/ld1", "../../d1", 1);
987 	assertMakeSymlink("d1/d2/ld2", "../../d2", 1);
988 	assertChdir("..");
989 
990 	assert((ae = archive_entry_new()) != NULL);
991 	assert((a = archive_read_disk_new()) != NULL);
992 	assertEqualIntA(a, ARCHIVE_OK,
993 	    archive_read_disk_set_symlink_logical(a));
994 
995 	/*
996 	 * Specified file is a symbolic link file.
997 	 */
998 	assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_open(a, "l2/d1"));
999 	file_count = 6;
1000 
1001 	while (file_count--) {
1002 		assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header2(a, ae));
1003 		if (strcmp(archive_entry_pathname(ae), "l2/d1") == 0) {
1004 			assertEqualInt(archive_entry_filetype(ae), AE_IFDIR);
1005 		} else if (strcmp(archive_entry_pathname(ae), "l2/d1/d2") == 0) {
1006 			assertEqualInt(archive_entry_filetype(ae), AE_IFDIR);
1007 		} else if (strcmp(archive_entry_pathname(ae), "l2/d1/d2/d3") == 0) {
1008 			assertEqualInt(archive_entry_filetype(ae), AE_IFDIR);
1009 		} else if (strcmp(archive_entry_pathname(ae), "l2/d1/d2/ld1") == 0) {
1010 			assertEqualInt(archive_entry_filetype(ae), AE_IFLNK);
1011 		} else if (strcmp(archive_entry_pathname(ae), "l2/d1/d2/ld2") == 0) {
1012 			assertEqualInt(archive_entry_filetype(ae), AE_IFDIR);
1013 		} else if (strcmp(archive_entry_pathname(ae),
1014 		    "l2/d1/d2/ld2/file1") == 0) {
1015 			assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
1016 			assertEqualInt(archive_entry_size(ae), 8);
1017 			assertEqualIntA(a, ARCHIVE_OK,
1018 			    archive_read_data_block(a, &p, &size, &offset));
1019 			assertEqualInt((int)size, 8);
1020 			assertEqualInt((int)offset, 0);
1021 			assertEqualMem(p, "d2/file1", 8);
1022 			assertEqualInt(ARCHIVE_EOF,
1023 			    archive_read_data_block(a, &p, &size, &offset));
1024 			assertEqualInt((int)size, 0);
1025 			assertEqualInt((int)offset, 8);
1026 		}
1027 		if (archive_entry_filetype(ae) == AE_IFDIR) {
1028 			/* Descend into the current object */
1029 			assertEqualIntA(a, ARCHIVE_OK,
1030 			    archive_read_disk_descend(a));
1031 		}
1032 	}
1033 	/* There is no entry. */
1034 	assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header2(a, ae));
1035 	/* Destroy the disk object. */
1036 	assertEqualInt(ARCHIVE_OK, archive_read_free(a));
1037 	archive_entry_free(ae);
1038 }
1039 
1040 static void
test_restore_atime(void)1041 test_restore_atime(void)
1042 {
1043 	struct archive *a;
1044 	struct archive_entry *ae;
1045 	const void *p;
1046 	size_t size;
1047 	int64_t offset;
1048 	int file_count;
1049 	const char *skip_test_restore_atime;
1050 
1051         skip_test_restore_atime = getenv("SKIP_TEST_RESTORE_ATIME");
1052         if (skip_test_restore_atime != NULL) {
1053                 skipping("Skipping restore atime tests due to "
1054                     "SKIP_TEST_RESTORE_ATIME environment variable");
1055                 return;
1056         }
1057 	if (!atimeIsUpdated()) {
1058 		skipping("Can't test restoring atime on this filesystem");
1059 		return;
1060 	}
1061 
1062 	assertMakeDir("at", 0755);
1063 	assertMakeFile("at/f1", 0644, "0123456789");
1064 	assertMakeFile("at/f2", 0644, "hello world");
1065 	assertMakeFile("at/fe", 0644, NULL);
1066 	assertUtimes("at/f1", 886600, 0, 886600, 0);
1067 	assertUtimes("at/f2", 886611, 0, 886611, 0);
1068 	assertUtimes("at/fe", 886611, 0, 886611, 0);
1069 	assertUtimes("at", 886622, 0, 886622, 0);
1070 	file_count = 4;
1071 
1072 	assert((ae = archive_entry_new()) != NULL);
1073 	assert((a = archive_read_disk_new()) != NULL);
1074 
1075 	/*
1076 	 * Test1: Traversals without archive_read_disk_set_atime_restored().
1077 	 */
1078 	failure("Directory traversals should work as well");
1079 	assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_open(a, "at"));
1080 	while (file_count--) {
1081 		assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header2(a, ae));
1082 		if (strcmp(archive_entry_pathname(ae), "at") == 0) {
1083 			assertEqualInt(archive_entry_filetype(ae), AE_IFDIR);
1084 		} else if (strcmp(archive_entry_pathname(ae), "at/f1") == 0) {
1085 			assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
1086 			assertEqualInt(archive_entry_size(ae), 10);
1087 			assertEqualIntA(a, ARCHIVE_OK,
1088 			    archive_read_data_block(a, &p, &size, &offset));
1089 			assertEqualInt((int)size, 10);
1090 			assertEqualInt((int)offset, 0);
1091 			assertEqualMem(p, "0123456789", 10);
1092 			assertEqualInt(ARCHIVE_EOF,
1093 			    archive_read_data_block(a, &p, &size, &offset));
1094 			assertEqualInt((int)size, 0);
1095 			assertEqualInt((int)offset, 10);
1096 		} else if (strcmp(archive_entry_pathname(ae), "at/f2") == 0) {
1097 			assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
1098 			assertEqualInt(archive_entry_size(ae), 11);
1099 			assertEqualIntA(a, ARCHIVE_OK,
1100 			    archive_read_data_block(a, &p, &size, &offset));
1101 			assertEqualInt((int)size, 11);
1102 			assertEqualInt((int)offset, 0);
1103 			assertEqualMem(p, "hello world", 11);
1104 			assertEqualInt(ARCHIVE_EOF,
1105 			    archive_read_data_block(a, &p, &size, &offset));
1106 			assertEqualInt((int)size, 0);
1107 			assertEqualInt((int)offset, 11);
1108 		} else if (strcmp(archive_entry_pathname(ae), "at/fe") == 0) {
1109 			assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
1110 			assertEqualInt(archive_entry_size(ae), 0);
1111 		}
1112 		if (archive_entry_filetype(ae) == AE_IFDIR) {
1113 			/* Descend into the current object */
1114 			assertEqualIntA(a, ARCHIVE_OK,
1115 			    archive_read_disk_descend(a));
1116 		}
1117 	}
1118 	/* There is no entry. */
1119 	failure("There must be no entry");
1120 	assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header2(a, ae));
1121 
1122 	/* On FreeBSD (and likely other systems), atime on
1123 	   dirs does not change when it is read. */
1124 	/* failure("Atime should be restored"); */
1125 	/* assertFileAtimeRecent("at"); */
1126 	failure("Atime should be restored");
1127 	assertFileAtimeRecent("at/f1");
1128 	failure("Atime should be restored");
1129 	assertFileAtimeRecent("at/f2");
1130 	failure("The atime of a empty file should not be changed");
1131 	assertFileAtime("at/fe", 886611, 0);
1132 
1133 	/* Close the disk object. */
1134 	assertEqualInt(ARCHIVE_OK, archive_read_close(a));
1135 
1136 	/*
1137 	 * Test2: Traversals with archive_read_disk_set_atime_restored().
1138 	 */
1139 	assertUtimes("at/f1", 886600, 0, 886600, 0);
1140 	assertUtimes("at/f2", 886611, 0, 886611, 0);
1141 	assertUtimes("at/fe", 886611, 0, 886611, 0);
1142 	assertUtimes("at", 886622, 0, 886622, 0);
1143 	file_count = 4;
1144 	assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_set_atime_restored(a));
1145 	assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_open(a, "at"));
1146 
1147 	failure("Directory traversals should work as well");
1148 	while (file_count--) {
1149 		assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header2(a, ae));
1150 		if (strcmp(archive_entry_pathname(ae), "at") == 0) {
1151 			assertEqualInt(archive_entry_filetype(ae), AE_IFDIR);
1152 		} else if (strcmp(archive_entry_pathname(ae), "at/f1") == 0) {
1153 			assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
1154 			assertEqualInt(archive_entry_size(ae), 10);
1155 			assertEqualIntA(a, ARCHIVE_OK,
1156 			    archive_read_data_block(a, &p, &size, &offset));
1157 			assertEqualInt((int)size, 10);
1158 			assertEqualInt((int)offset, 0);
1159 			assertEqualMem(p, "0123456789", 10);
1160 			assertEqualInt(ARCHIVE_EOF,
1161 			    archive_read_data_block(a, &p, &size, &offset));
1162 			assertEqualInt((int)size, 0);
1163 			assertEqualInt((int)offset, 10);
1164 		} else if (strcmp(archive_entry_pathname(ae), "at/f2") == 0) {
1165 			assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
1166 			assertEqualInt(archive_entry_size(ae), 11);
1167 			assertEqualIntA(a, ARCHIVE_OK,
1168 			    archive_read_data_block(a, &p, &size, &offset));
1169 			assertEqualInt((int)size, 11);
1170 			assertEqualInt((int)offset, 0);
1171 			assertEqualMem(p, "hello world", 11);
1172 			assertEqualInt(ARCHIVE_EOF,
1173 			    archive_read_data_block(a, &p, &size, &offset));
1174 			assertEqualInt((int)size, 0);
1175 			assertEqualInt((int)offset, 11);
1176 		} else if (strcmp(archive_entry_pathname(ae), "at/fe") == 0) {
1177 			assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
1178 			assertEqualInt(archive_entry_size(ae), 0);
1179 		}
1180 		if (archive_entry_filetype(ae) == AE_IFDIR) {
1181 			/* Descend into the current object */
1182 			assertEqualIntA(a, ARCHIVE_OK,
1183 			    archive_read_disk_descend(a));
1184 		}
1185 	}
1186 	/* There is no entry. */
1187 	failure("There must be no entry");
1188 	assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header2(a, ae));
1189 
1190 	failure("Atime should be restored");
1191 	assertFileAtime("at", 886622, 0);
1192 	failure("Atime should be restored");
1193 	assertFileAtime("at/f1", 886600, 0);
1194 	failure("Atime should be restored");
1195 	assertFileAtime("at/f2", 886611, 0);
1196 	failure("The atime of a empty file should not be changed");
1197 	assertFileAtime("at/fe", 886611, 0);
1198 
1199 	/* Close the disk object. */
1200 	assertEqualInt(ARCHIVE_OK, archive_read_close(a));
1201 
1202 	/*
1203 	 * Test3: Traversals with archive_read_disk_set_atime_restored() but
1204 	 * no data read as a listing.
1205 	 */
1206 	assertUtimes("at/f1", 886600, 0, 886600, 0);
1207 	assertUtimes("at/f2", 886611, 0, 886611, 0);
1208 	assertUtimes("at/fe", 886611, 0, 886611, 0);
1209 	assertUtimes("at", 886622, 0, 886622, 0);
1210 	file_count = 4;
1211 	assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_set_atime_restored(a));
1212 	assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_open(a, "at"));
1213 
1214 	failure("Directory traversals should work as well");
1215 	while (file_count--) {
1216 		assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header2(a, ae));
1217 		if (strcmp(archive_entry_pathname(ae), "at") == 0) {
1218 			assertEqualInt(archive_entry_filetype(ae), AE_IFDIR);
1219 		} else if (strcmp(archive_entry_pathname(ae), "at/f1") == 0) {
1220 			assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
1221 			assertEqualInt(archive_entry_size(ae), 10);
1222 		} else if (strcmp(archive_entry_pathname(ae), "at/f2") == 0) {
1223 			assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
1224 			assertEqualInt(archive_entry_size(ae), 11);
1225 		} else if (strcmp(archive_entry_pathname(ae), "at/fe") == 0) {
1226 			assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
1227 			assertEqualInt(archive_entry_size(ae), 0);
1228 		}
1229 		if (archive_entry_filetype(ae) == AE_IFDIR) {
1230 			/* Descend into the current object */
1231 			assertEqualIntA(a, ARCHIVE_OK,
1232 			    archive_read_disk_descend(a));
1233 		}
1234 	}
1235 	/* There is no entry. */
1236 	failure("There must be no entry");
1237 	assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header2(a, ae));
1238 
1239 	failure("Atime should be restored");
1240 	assertFileAtime("at", 886622, 0);
1241 	failure("Atime should be restored");
1242 	assertFileAtime("at/f1", 886600, 0);
1243 	failure("Atime should be restored");
1244 	assertFileAtime("at/f2", 886611, 0);
1245 	failure("The atime of a empty file should not be changed");
1246 	assertFileAtime("at/fe", 886611, 0);
1247 
1248 	if (!canNodump()) {
1249 		/* Destroy the disk object. */
1250 		assertEqualInt(ARCHIVE_OK, archive_read_free(a));
1251 		archive_entry_free(ae);
1252 		skipping("Can't test atime with nodump on this filesystem");
1253 		return;
1254 	}
1255 
1256 	/* Close the disk object. */
1257 	assertEqualInt(ARCHIVE_OK, archive_read_close(a));
1258 
1259 	/*
1260 	 * Test4: Traversals with ARCHIVE_READDISK_RESTORE_ATIME and
1261 	 * ARCHIVE_READDISK_HONOR_NODUMP
1262 	 */
1263 	assertSetNodump("at/f1");
1264 	assertSetNodump("at/f2");
1265 	assertUtimes("at/f1", 886600, 0, 886600, 0);
1266 	assertUtimes("at/f2", 886611, 0, 886611, 0);
1267 	assertUtimes("at/fe", 886611, 0, 886611, 0);
1268 	assertUtimes("at", 886622, 0, 886622, 0);
1269 	file_count = 2;
1270 	assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_set_behavior(a,
1271 		ARCHIVE_READDISK_RESTORE_ATIME | ARCHIVE_READDISK_HONOR_NODUMP));
1272 	assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_open(a, "at"));
1273 
1274 	failure("Directory traversals should work as well");
1275 	while (file_count--) {
1276 		assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header2(a, ae));
1277 		if (strcmp(archive_entry_pathname(ae), "at") == 0) {
1278 			assertEqualInt(archive_entry_filetype(ae), AE_IFDIR);
1279 		} else if (strcmp(archive_entry_pathname(ae), "at/fe") == 0) {
1280 			assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
1281 			assertEqualInt(archive_entry_size(ae), 0);
1282 		}
1283 		if (archive_entry_filetype(ae) == AE_IFDIR) {
1284 			/* Descend into the current object */
1285 			assertEqualIntA(a, ARCHIVE_OK,
1286 			    archive_read_disk_descend(a));
1287 		}
1288 	}
1289 	/* There is no entry. */
1290 	failure("There must be no entry");
1291 	assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header2(a, ae));
1292 
1293 	failure("Atime should be restored");
1294 	assertFileAtime("at", 886622, 0);
1295 	failure("Atime should be restored");
1296 	assertFileAtime("at/f1", 886600, 0);
1297 	failure("Atime should be restored");
1298 	assertFileAtime("at/f2", 886611, 0);
1299 	failure("The atime of a empty file should not be changed");
1300 	assertFileAtime("at/fe", 886611, 0);
1301 
1302 	/* Destroy the disk object. */
1303 	assertEqualInt(ARCHIVE_OK, archive_read_free(a));
1304 	archive_entry_free(ae);
1305 }
1306 
1307 static int
metadata_filter(struct archive * a,void * data,struct archive_entry * ae)1308 metadata_filter(struct archive *a, void *data, struct archive_entry *ae)
1309 {
1310 	(void)data; /* UNUSED */
1311 
1312 	failure("CTime should be set");
1313 	assertEqualInt(8, archive_entry_ctime_is_set(ae));
1314 	failure("MTime should be set");
1315 	assertEqualInt(16, archive_entry_mtime_is_set(ae));
1316 
1317 	if (archive_entry_mtime(ae) < 886611)
1318 		return (0);
1319 	if (archive_read_disk_can_descend(a)) {
1320 		/* Descend into the current object */
1321 		failure("archive_read_disk_can_descend should work"
1322 			" in metadata filter");
1323 		assertEqualIntA(a, 1, archive_read_disk_can_descend(a));
1324 		failure("archive_read_disk_descend should work"
1325 			" in metadata filter");
1326 		assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_descend(a));
1327 	}
1328 	return (1);
1329 }
1330 
1331 static void
test_callbacks(void)1332 test_callbacks(void)
1333 {
1334 	struct archive *a;
1335 	struct archive *m;
1336 	struct archive_entry *ae;
1337 	const void *p;
1338 	size_t size;
1339 	int64_t offset;
1340 	int file_count;
1341 
1342 	assertMakeDir("cb", 0755);
1343 	assertMakeFile("cb/f1", 0644, "0123456789");
1344 	assertMakeFile("cb/f2", 0644, "hello world");
1345 	assertMakeFile("cb/fe", 0644, NULL);
1346 	assertUtimes("cb/f1", 886600, 0, 886600, 0);
1347 	assertUtimes("cb/f2", 886611, 0, 886611, 0);
1348 	assertUtimes("cb/fe", 886611, 0, 886611, 0);
1349 	assertUtimes("cb", 886622, 0, 886622, 0);
1350 
1351 	assert((ae = archive_entry_new()) != NULL);
1352 	assert((a = archive_read_disk_new()) != NULL);
1353 	if (a == NULL) {
1354 		archive_entry_free(ae);
1355 		return;
1356 	}
1357 	assert((m = archive_match_new()) != NULL);
1358 	if (m == NULL) {
1359 		archive_entry_free(ae);
1360 		archive_read_free(a);
1361 		archive_match_free(m);
1362 		return;
1363 	}
1364 
1365 	/*
1366 	 * Test1: Traversals with a name filter.
1367 	 */
1368 	file_count = 3;
1369 	assertEqualIntA(m, ARCHIVE_OK,
1370 	    archive_match_exclude_pattern(m, "cb/f2"));
1371 	assertEqualIntA(a, ARCHIVE_OK,
1372 	    archive_read_disk_set_matching(a, m, NULL, NULL));
1373 	failure("Directory traversals should work as well");
1374 	assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_open(a, "cb"));
1375 	while (file_count--) {
1376 		archive_entry_clear(ae);
1377 		assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header2(a, ae));
1378 		failure("File 'cb/f2' should be exclueded");
1379 		assert(strcmp(archive_entry_pathname(ae), "cb/f2") != 0);
1380 		if (strcmp(archive_entry_pathname(ae), "cb") == 0) {
1381 			assertEqualInt(archive_entry_filetype(ae), AE_IFDIR);
1382 		} else if (strcmp(archive_entry_pathname(ae), "cb/f1") == 0) {
1383 			assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
1384 			assertEqualInt(archive_entry_size(ae), 10);
1385 			assertEqualIntA(a, ARCHIVE_OK,
1386 			    archive_read_data_block(a, &p, &size, &offset));
1387 			assertEqualInt((int)size, 10);
1388 			assertEqualInt((int)offset, 0);
1389 			assertEqualMem(p, "0123456789", 10);
1390 			assertEqualInt(ARCHIVE_EOF,
1391 			    archive_read_data_block(a, &p, &size, &offset));
1392 			assertEqualInt((int)size, 0);
1393 			assertEqualInt((int)offset, 10);
1394 		} else if (strcmp(archive_entry_pathname(ae), "cb/fe") == 0) {
1395 			assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
1396 			assertEqualInt(archive_entry_size(ae), 0);
1397 		}
1398 		if (archive_read_disk_can_descend(a)) {
1399 			/* Descend into the current object */
1400 			assertEqualIntA(a, ARCHIVE_OK,
1401 			    archive_read_disk_descend(a));
1402 		}
1403 	}
1404 	/* There is no entry. */
1405 	failure("There should be no entry");
1406 	assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header2(a, ae));
1407 
1408 	/* Close the disk object. */
1409 	assertEqualInt(ARCHIVE_OK, archive_read_close(a));
1410 
1411 	/* Reset name filter */
1412 	assertEqualIntA(a, ARCHIVE_OK,
1413 	    archive_read_disk_set_matching(a, NULL, NULL, NULL));
1414 
1415 	/*
1416 	 * Test2: Traversals with a metadata filter.
1417 	 */
1418 	assertUtimes("cb/f1", 886600, 0, 886600, 0);
1419 	assertUtimes("cb/f2", 886611, 0, 886611, 0);
1420 	assertUtimes("cb/fe", 886611, 0, 886611, 0);
1421 	assertUtimes("cb", 886622, 0, 886622, 0);
1422 	file_count = 3;
1423 	assertEqualIntA(a, ARCHIVE_OK,
1424 	    archive_read_disk_set_metadata_filter_callback(a, metadata_filter,
1425 		    NULL));
1426 	failure("Directory traversals should work as well");
1427 	assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_open(a, "cb"));
1428 
1429 	while (file_count--) {
1430 		archive_entry_clear(ae);
1431 		assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header2(a, ae));
1432 		failure("File 'cb/f1' should be excluded");
1433 		assert(strcmp(archive_entry_pathname(ae), "cb/f1") != 0);
1434 		if (strcmp(archive_entry_pathname(ae), "cb") == 0) {
1435 			assertEqualInt(archive_entry_filetype(ae), AE_IFDIR);
1436 		} else if (strcmp(archive_entry_pathname(ae), "cb/f2") == 0) {
1437 			assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
1438 			assertEqualInt(archive_entry_size(ae), 11);
1439 			assertEqualIntA(a, ARCHIVE_OK,
1440 			    archive_read_data_block(a, &p, &size, &offset));
1441 			assertEqualInt((int)size, 11);
1442 			assertEqualInt((int)offset, 0);
1443 			assertEqualMem(p, "hello world", 11);
1444 			assertEqualInt(ARCHIVE_EOF,
1445 			    archive_read_data_block(a, &p, &size, &offset));
1446 			assertEqualInt((int)size, 0);
1447 			assertEqualInt((int)offset, 11);
1448 		} else if (strcmp(archive_entry_pathname(ae), "cb/fe") == 0) {
1449 			assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
1450 			assertEqualInt(archive_entry_size(ae), 0);
1451 		}
1452 	}
1453 	/* There is no entry. */
1454 	failure("There should be no entry");
1455 	assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header2(a, ae));
1456 
1457 	/* Destroy the disk object. */
1458 	assertEqualInt(ARCHIVE_OK, archive_read_free(a));
1459 	assertEqualInt(ARCHIVE_OK, archive_match_free(m));
1460 	archive_entry_free(ae);
1461 }
1462 
1463 static void
test_nodump(void)1464 test_nodump(void)
1465 {
1466 	struct archive *a;
1467 	struct archive_entry *ae;
1468 	const void *p;
1469 	size_t size;
1470 	int64_t offset;
1471 	int file_count;
1472 
1473 	if (!canNodump()) {
1474 		skipping("Can't test nodump on this filesystem");
1475 		return;
1476 	}
1477 
1478 	assertMakeDir("nd", 0755);
1479 	assertMakeFile("nd/f1", 0644, "0123456789");
1480 	assertMakeFile("nd/f2", 0644, "hello world");
1481 	assertMakeFile("nd/fe", 0644, NULL);
1482 	assertSetNodump("nd/f2");
1483 	assertUtimes("nd/f1", 886600, 0, 886600, 0);
1484 	assertUtimes("nd/f2", 886611, 0, 886611, 0);
1485 	assertUtimes("nd/fe", 886611, 0, 886611, 0);
1486 	assertUtimes("nd", 886622, 0, 886622, 0);
1487 
1488 	assert((ae = archive_entry_new()) != NULL);
1489 	assert((a = archive_read_disk_new()) != NULL);
1490 
1491 	/*
1492 	 * Test1: Traversals without ARCHIVE_READDISK_HONOR_NODUMP
1493 	 */
1494 	failure("Directory traversals should work as well");
1495 	assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_open(a, "nd"));
1496 
1497 	file_count = 4;
1498 	while (file_count--) {
1499 		archive_entry_clear(ae);
1500 		assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header2(a, ae));
1501 		if (strcmp(archive_entry_pathname(ae), "nd") == 0) {
1502 			assertEqualInt(archive_entry_filetype(ae), AE_IFDIR);
1503 		} else if (strcmp(archive_entry_pathname(ae), "nd/f1") == 0) {
1504 			assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
1505 			assertEqualInt(archive_entry_size(ae), 10);
1506 			assertEqualIntA(a, ARCHIVE_OK,
1507 			    archive_read_data_block(a, &p, &size, &offset));
1508 			assertEqualInt((int)size, 10);
1509 			assertEqualInt((int)offset, 0);
1510 			assertEqualMem(p, "0123456789", 10);
1511 			assertEqualInt(ARCHIVE_EOF,
1512 			    archive_read_data_block(a, &p, &size, &offset));
1513 			assertEqualInt((int)size, 0);
1514 			assertEqualInt((int)offset, 10);
1515 		} else if (strcmp(archive_entry_pathname(ae), "nd/f2") == 0) {
1516 			assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
1517 			assertEqualInt(archive_entry_size(ae), 11);
1518 			assertEqualIntA(a, ARCHIVE_OK,
1519 			    archive_read_data_block(a, &p, &size, &offset));
1520 			assertEqualInt((int)size, 11);
1521 			assertEqualInt((int)offset, 0);
1522 			assertEqualMem(p, "hello world", 11);
1523 			assertEqualInt(ARCHIVE_EOF,
1524 			    archive_read_data_block(a, &p, &size, &offset));
1525 			assertEqualInt((int)size, 0);
1526 			assertEqualInt((int)offset, 11);
1527 		} else if (strcmp(archive_entry_pathname(ae), "nd/fe") == 0) {
1528 			assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
1529 			assertEqualInt(archive_entry_size(ae), 0);
1530 		}
1531 		if (archive_read_disk_can_descend(a)) {
1532 			/* Descend into the current object */
1533 			assertEqualIntA(a, ARCHIVE_OK,
1534 			    archive_read_disk_descend(a));
1535 		}
1536 	}
1537 	/* There is no entry. */
1538 	failure("There should be no entry");
1539 	assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header2(a, ae));
1540 
1541 	/* Close the disk object. */
1542 	assertEqualInt(ARCHIVE_OK, archive_read_close(a));
1543 
1544 	/*
1545 	 * Test2: Traversals with ARCHIVE_READDISK_HONOR_NODUMP
1546 	 */
1547 	assertUtimes("nd/f1", 886600, 0, 886600, 0);
1548 	assertUtimes("nd/f2", 886611, 0, 886611, 0);
1549 	assertUtimes("nd/fe", 886611, 0, 886611, 0);
1550 	assertUtimes("nd", 886622, 0, 886622, 0);
1551 
1552 	assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_set_behavior(a,
1553 		ARCHIVE_READDISK_RESTORE_ATIME | ARCHIVE_READDISK_HONOR_NODUMP));
1554 	failure("Directory traversals should work as well");
1555 	assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_open(a, "nd"));
1556 
1557 	file_count = 3;
1558 	while (file_count--) {
1559 		archive_entry_clear(ae);
1560 		assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header2(a, ae));
1561 		failure("File 'nd/f2' should be exclueded");
1562 		assert(strcmp(archive_entry_pathname(ae), "nd/f2") != 0);
1563 		if (strcmp(archive_entry_pathname(ae), "nd") == 0) {
1564 			assertEqualInt(archive_entry_filetype(ae), AE_IFDIR);
1565 		} else if (strcmp(archive_entry_pathname(ae), "nd/f1") == 0) {
1566 			assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
1567 			assertEqualInt(archive_entry_size(ae), 10);
1568 			assertEqualIntA(a, ARCHIVE_OK,
1569 			    archive_read_data_block(a, &p, &size, &offset));
1570 			assertEqualInt((int)size, 10);
1571 			assertEqualInt((int)offset, 0);
1572 			assertEqualMem(p, "0123456789", 10);
1573 			assertEqualInt(ARCHIVE_EOF,
1574 			    archive_read_data_block(a, &p, &size, &offset));
1575 			assertEqualInt((int)size, 0);
1576 			assertEqualInt((int)offset, 10);
1577 		} else if (strcmp(archive_entry_pathname(ae), "nd/fe") == 0) {
1578 			assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
1579 			assertEqualInt(archive_entry_size(ae), 0);
1580 		}
1581 		if (archive_read_disk_can_descend(a)) {
1582 			/* Descend into the current object */
1583 			assertEqualIntA(a, ARCHIVE_OK,
1584 			    archive_read_disk_descend(a));
1585 		}
1586 	}
1587 	/* There is no entry. */
1588 	failure("There should be no entry");
1589 	assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header2(a, ae));
1590 
1591 	failure("Atime should be restored");
1592 	assertFileAtime("nd/f2", 886611, 0);
1593 
1594 	/* Destroy the disk object. */
1595 	assertEqualInt(ARCHIVE_OK, archive_read_free(a));
1596 	archive_entry_free(ae);
1597 }
1598 
1599 static void
test_parent(void)1600 test_parent(void)
1601 {
1602 	struct archive *a;
1603 	struct archive_entry *ae;
1604 	const void *p;
1605 	size_t size;
1606 	int64_t offset;
1607 	int file_count;
1608 	int match_count;
1609 	int r;
1610 #if defined(O_PATH) || defined(O_SEARCH) || \
1611  (defined(__FreeBSD__) && defined(O_EXEC))
1612 	const char *ignore_traversals_test4;
1613 
1614 	ignore_traversals_test4 = getenv("IGNORE_TRAVERSALS_TEST4");
1615 #endif
1616 
1617 	assertMakeDir("lock", 0311);
1618 	assertMakeDir("lock/dir1", 0755);
1619 	assertMakeFile("lock/dir1/f1", 0644, "0123456789");
1620 	assertMakeDir("lock/lock2", 0311);
1621 	assertMakeDir("lock/lock2/dir1", 0755);
1622 	assertMakeFile("lock/lock2/dir1/f1", 0644, "0123456789");
1623 
1624 	assert((ae = archive_entry_new()) != NULL);
1625 	assert((a = archive_read_disk_new()) != NULL);
1626 
1627 	/*
1628 	 * Test1: Traverse lock/dir1 as .
1629 	 */
1630 	assertChdir("lock/dir1");
1631 
1632 	failure("Directory traversals should work as well");
1633 	assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_open(a, "."));
1634 
1635 	file_count = 2;
1636 	match_count = 0;
1637 	while (file_count--) {
1638 		archive_entry_clear(ae);
1639 		assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header2(a, ae));
1640 		if (strcmp(archive_entry_pathname(ae), ".") == 0) {
1641 			assertEqualInt(archive_entry_filetype(ae), AE_IFDIR);
1642 			++match_count;
1643 		} else if (strcmp(archive_entry_pathname(ae), "./f1") == 0) {
1644 			assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
1645 			assertEqualInt(archive_entry_size(ae), 10);
1646 			assertEqualIntA(a, ARCHIVE_OK,
1647 			    archive_read_data_block(a, &p, &size, &offset));
1648 			assertEqualInt((int)size, 10);
1649 			assertEqualInt((int)offset, 0);
1650 			assertEqualMem(p, "0123456789", 10);
1651 			assertEqualInt(ARCHIVE_EOF,
1652 			    archive_read_data_block(a, &p, &size, &offset));
1653 			assertEqualInt((int)size, 0);
1654 			assertEqualInt((int)offset, 10);
1655 			++match_count;
1656 		}
1657 		if (archive_read_disk_can_descend(a)) {
1658 			/* Descend into the current object */
1659 			assertEqualIntA(a, ARCHIVE_OK,
1660 			    archive_read_disk_descend(a));
1661 		}
1662 	}
1663 	failure("Did not match expected filenames");
1664 	assertEqualInt(match_count, 2);
1665 	/*
1666 	 * There is no entry. This will however fail if the directory traverse
1667 	 * tries to ascend past the initial directory, since it lacks permission
1668 	 * to do so.
1669 	 */
1670 	failure("There should be no entry and no error");
1671 	assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header2(a, ae));
1672 
1673 	/* Close the disk object. */
1674 	assertEqualInt(ARCHIVE_OK, archive_read_close(a));
1675 
1676 	assertChdir("../..");
1677 
1678 	/*
1679 	 * Test2: Traverse lock/dir1 directly
1680 	 */
1681 	failure("Directory traversals should work as well");
1682 	assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_open(a, "lock/dir1"));
1683 
1684 	file_count = 2;
1685 	match_count = 0;
1686 	while (file_count--) {
1687 		archive_entry_clear(ae);
1688 		assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header2(a, ae));
1689 		if (strcmp(archive_entry_pathname(ae), "lock/dir1") == 0) {
1690 			assertEqualInt(archive_entry_filetype(ae), AE_IFDIR);
1691 			++match_count;
1692 		} else if (strcmp(archive_entry_pathname(ae), "lock/dir1/f1") == 0) {
1693 			assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
1694 			assertEqualInt(archive_entry_size(ae), 10);
1695 			assertEqualIntA(a, ARCHIVE_OK,
1696 			    archive_read_data_block(a, &p, &size, &offset));
1697 			assertEqualInt((int)size, 10);
1698 			assertEqualInt((int)offset, 0);
1699 			assertEqualMem(p, "0123456789", 10);
1700 			assertEqualInt(ARCHIVE_EOF,
1701 			    archive_read_data_block(a, &p, &size, &offset));
1702 			assertEqualInt((int)size, 0);
1703 			assertEqualInt((int)offset, 10);
1704 			++match_count;
1705 		}
1706 		if (archive_read_disk_can_descend(a)) {
1707 			/* Descend into the current object */
1708 			assertEqualIntA(a, ARCHIVE_OK,
1709 			    archive_read_disk_descend(a));
1710 		}
1711 	}
1712 	failure("Did not match expected filenames");
1713 	assertEqualInt(match_count, 2);
1714 	/*
1715 	 * There is no entry. This will however fail if the directory traverse
1716 	 * tries to ascend past the initial directory, since it lacks permission
1717 	 * to do so.
1718 	 */
1719 	failure("There should be no entry and no error");
1720 	assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header2(a, ae));
1721 
1722 	/* Close the disk object. */
1723 	assertEqualInt(ARCHIVE_OK, archive_read_close(a));
1724 
1725 	/*
1726 	 * Test3: Traverse lock/dir1/.
1727 	 */
1728 	failure("Directory traversals should work as well");
1729 	assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_open(a, "lock/dir1/."));
1730 
1731 	file_count = 2;
1732 	match_count = 0;
1733 	while (file_count--) {
1734 		archive_entry_clear(ae);
1735 		assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header2(a, ae));
1736 		if (strcmp(archive_entry_pathname(ae), "lock/dir1/.") == 0) {
1737 			assertEqualInt(archive_entry_filetype(ae), AE_IFDIR);
1738 			++match_count;
1739 		} else if (strcmp(archive_entry_pathname(ae), "lock/dir1/./f1") == 0) {
1740 			assertEqualInt(archive_entry_filetype(ae), AE_IFREG);
1741 			assertEqualInt(archive_entry_size(ae), 10);
1742 			assertEqualIntA(a, ARCHIVE_OK,
1743 			    archive_read_data_block(a, &p, &size, &offset));
1744 			assertEqualInt((int)size, 10);
1745 			assertEqualInt((int)offset, 0);
1746 			assertEqualMem(p, "0123456789", 10);
1747 			assertEqualInt(ARCHIVE_EOF,
1748 			    archive_read_data_block(a, &p, &size, &offset));
1749 			assertEqualInt((int)size, 0);
1750 			assertEqualInt((int)offset, 10);
1751 			++match_count;
1752 		}
1753 		if (archive_read_disk_can_descend(a)) {
1754 			/* Descend into the current object */
1755 			assertEqualIntA(a, ARCHIVE_OK,
1756 			    archive_read_disk_descend(a));
1757 		}
1758 	}
1759 	failure("Did not match expected filenames");
1760 	assertEqualInt(match_count, 2);
1761 	/*
1762 	 * There is no entry. This will however fail if the directory traverse
1763 	 * tries to ascend past the initial directory, since it lacks permission
1764 	 * to do so.
1765 	 */
1766 	failure("There should be no entry and no error");
1767 	assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header2(a, ae));
1768 
1769 	/* Close the disk object. */
1770 	assertEqualInt(ARCHIVE_OK, archive_read_close(a));
1771 
1772 	/*
1773 	 * Test4: Traverse lock/lock2/dir1 from inside lock.
1774 	 *
1775 	 * This test is expected to fail on platforms with no O_EXEC or
1776 	 * equivalent (e.g. O_PATH on Linux or O_SEARCH on SunOS), because
1777 	 * the current traversal code can't handle the case where it can't
1778 	 * obtain an open fd for the initial current directory. We need to
1779 	 * check that condition here, because if O_EXEC _does_ exist, we don't
1780 	 * want to overlook any failure.
1781 	 */
1782 	assertChdir("lock");
1783 
1784 	failure("Directory traversals should work as well");
1785 	assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_open(a, "lock2/dir1"));
1786 
1787 	archive_entry_clear(ae);
1788 	r = archive_read_next_header2(a, ae);
1789 	if (r == ARCHIVE_FAILED) {
1790 #if defined(O_PATH) || defined(O_SEARCH) || \
1791  (defined(__FreeBSD__) && defined(O_EXEC))
1792 		if (ignore_traversals_test4 == NULL)
1793 			assertEqualIntA(a, ARCHIVE_OK, r);
1794 #endif
1795 		/* Close the disk object. */
1796 		archive_read_close(a);
1797 	} else {
1798 		file_count = 2;
1799 		match_count = 0;
1800 		while (file_count--) {
1801 			if (file_count == 0)
1802 				assertEqualIntA(a, ARCHIVE_OK,
1803 				    archive_read_next_header2(a, ae));
1804 			if (strcmp(archive_entry_pathname(ae),
1805 				"lock2/dir1") == 0) {
1806 				assertEqualInt(archive_entry_filetype(ae),
1807 				    AE_IFDIR);
1808 				++match_count;
1809 			} else if (strcmp(archive_entry_pathname(ae),
1810 				"lock2/dir1/f1") == 0) {
1811 				assertEqualInt(archive_entry_filetype(ae),
1812 				    AE_IFREG);
1813 				assertEqualInt(archive_entry_size(ae), 10);
1814 				assertEqualIntA(a, ARCHIVE_OK,
1815 				    archive_read_data_block(a, &p, &size,
1816 					&offset));
1817 				assertEqualInt((int)size, 10);
1818 				assertEqualInt((int)offset, 0);
1819 				assertEqualMem(p, "0123456789", 10);
1820 				assertEqualInt(ARCHIVE_EOF,
1821 				    archive_read_data_block(a, &p, &size,
1822 					&offset));
1823 				assertEqualInt((int)size, 0);
1824 				assertEqualInt((int)offset, 10);
1825 				++match_count;
1826 			}
1827 			if (archive_read_disk_can_descend(a)) {
1828 				/* Descend into the current object */
1829 				assertEqualIntA(a, ARCHIVE_OK,
1830 				    archive_read_disk_descend(a));
1831 			}
1832 		}
1833 		failure("Did not match expected filenames");
1834 		assertEqualInt(match_count, 2);
1835 		/*
1836 		 * There is no entry. This will however fail if the directory
1837 		 * traverse tries to ascend past the initial directory, since
1838 		 * it lacks permission to do so.
1839 		 */
1840 		failure("There should be no entry and no error");
1841 		assertEqualIntA(a, ARCHIVE_EOF,
1842 		    archive_read_next_header2(a, ae));
1843 
1844 		/* Close the disk object. */
1845 		assertEqualInt(ARCHIVE_OK, archive_read_close(a));
1846 	}
1847 
1848 	assertChdir("..");
1849 	assertChmod("lock", 0755);
1850 	assertChmod("lock/lock2", 0755);
1851 
1852 	/* Destroy the disk object. */
1853 	assertEqualInt(ARCHIVE_OK, archive_read_free(a));
1854 	archive_entry_free(ae);
1855 }
1856 
DEFINE_TEST(test_read_disk_directory_traversals)1857 DEFINE_TEST(test_read_disk_directory_traversals)
1858 {
1859 	/* Basic test. */
1860 	test_basic();
1861 	/* Test hybrid mode; follow symlink initially, then not. */
1862 	test_symlink_hybrid();
1863 	/* Test logical mode; follow all symlinks. */
1864 	test_symlink_logical();
1865 	/* Test logical mode; prevent loop in symlinks. */
1866 	test_symlink_logical_loop();
1867 	/* Test to restore atime. */
1868 	test_restore_atime();
1869 	/* Test callbacks. */
1870 	test_callbacks();
1871 	/* Test nodump. */
1872 	test_nodump();
1873 	/* Test parent overshoot. */
1874 	test_parent();
1875 }
1876