1 /*-
2 * Copyright (c) 2003-2007 Tim Kientzle
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 #define UMASK 022
28
29 #ifndef S_IFLNK
30 #define S_IFLNK 0120000
31 #endif
32
33 /*
34 * Exercise security checks that should prevent certain
35 * writes.
36 */
37
DEFINE_TEST(test_write_disk_secure)38 DEFINE_TEST(test_write_disk_secure)
39 {
40 struct archive *a;
41 struct archive_entry *ae;
42 #if defined(HAVE_LCHMOD) && defined(HAVE_SYMLINK) && \
43 defined(S_IRUSR) && defined(S_IWUSR) && defined(S_IXUSR)
44 int working_lchmod;
45 #endif
46
47 if (!canSymlink()) {
48 skipping("Can't test symlinks on this filesystem");
49 return;
50 }
51
52 /* Start with a known umask. */
53 assertUmask(UMASK);
54
55 /* Create an archive_write_disk object. */
56 assert((a = archive_write_disk_new()) != NULL);
57
58 /* Write a regular dir to it. */
59 assert((ae = archive_entry_new()) != NULL);
60 archive_entry_copy_pathname(ae, "dir");
61 archive_entry_set_mode(ae, S_IFDIR | 0777);
62 assert(0 == archive_write_header(a, ae));
63 archive_entry_free(ae);
64 assert(0 == archive_write_finish_entry(a));
65
66 /* Write a symlink to the dir above. */
67 assert((ae = archive_entry_new()) != NULL);
68 archive_entry_copy_pathname(ae, "link_to_dir");
69 archive_entry_set_mode(ae, S_IFLNK | 0777);
70 archive_entry_set_symlink(ae, "dir");
71 archive_entry_set_symlink_type(ae, AE_SYMLINK_TYPE_DIRECTORY);
72 archive_write_disk_set_options(a, 0);
73 assert(0 == archive_write_header(a, ae));
74 assert(0 == archive_write_finish_entry(a));
75
76 /*
77 * Without security checks, we should be able to
78 * extract a file through the link.
79 */
80 assert(archive_entry_clear(ae) != NULL);
81 archive_entry_copy_pathname(ae, "link_to_dir/filea");
82 archive_entry_set_mode(ae, S_IFREG | 0777);
83 assert(0 == archive_write_header(a, ae));
84 assert(0 == archive_write_finish_entry(a));
85
86 /* But with security checks enabled, this should fail. */
87 assert(archive_entry_clear(ae) != NULL);
88 archive_entry_copy_pathname(ae, "link_to_dir/fileb");
89 archive_entry_set_mode(ae, S_IFREG | 0777);
90 archive_write_disk_set_options(a, ARCHIVE_EXTRACT_SECURE_SYMLINKS);
91 failure("Extracting a file through a symlink should fail here.");
92 assertEqualInt(ARCHIVE_FAILED, archive_write_header(a, ae));
93 archive_entry_free(ae);
94 assert(0 == archive_write_finish_entry(a));
95
96 /* These tests hardcode the location of /tmp. skip them on Windows for now. */
97 #if !defined(_WIN32) || defined(__CYGWIN__)
98 /* Write an absolute symlink to /tmp. */
99 assert((ae = archive_entry_new()) != NULL);
100 archive_entry_copy_pathname(ae, "/tmp/libarchive_test-test_write_disk_secure-absolute_symlink");
101 archive_entry_set_mode(ae, S_IFLNK | 0777);
102 archive_entry_set_symlink(ae, "/tmp");
103 archive_entry_set_symlink_type(ae, AE_SYMLINK_TYPE_DIRECTORY);
104 archive_write_disk_set_options(a, 0);
105 assert(0 == archive_write_header(a, ae));
106 assert(0 == archive_write_finish_entry(a));
107
108 /* With security checks enabled, this should fail. */
109 assert(archive_entry_clear(ae) != NULL);
110 archive_entry_copy_pathname(ae, "/tmp/libarchive_test-test_write_disk_secure-absolute_symlink/libarchive_test-test_write_disk_secure-absolute_symlink_path.tmp");
111 archive_entry_set_mode(ae, S_IFREG | 0777);
112 archive_write_disk_set_options(a, ARCHIVE_EXTRACT_SECURE_SYMLINKS);
113 failure("Extracting a file through an absolute symlink should fail here.");
114 assertEqualInt(ARCHIVE_FAILED, archive_write_header(a, ae));
115 archive_entry_free(ae);
116 assertFileNotExists("/tmp/libarchive_test-test_write_disk_secure-absolute_symlink/libarchive_test-test_write_disk_secure-absolute_symlink_path.tmp");
117 assert(0 == unlink("/tmp/libarchive_test-test_write_disk_secure-absolute_symlink"));
118 unlink("/tmp/libarchive_test-test_write_disk_secure-absolute_symlink_path.tmp");
119 #endif
120
121 /* Create another link. */
122 assert((ae = archive_entry_new()) != NULL);
123 archive_entry_copy_pathname(ae, "link_to_dir2");
124 archive_entry_set_mode(ae, S_IFLNK | 0777);
125 archive_entry_set_symlink(ae, "dir");
126 archive_entry_set_symlink_type(ae, AE_SYMLINK_TYPE_DIRECTORY);
127 archive_write_disk_set_options(a, 0);
128 assert(0 == archive_write_header(a, ae));
129 assert(0 == archive_write_finish_entry(a));
130
131 /*
132 * With symlink check and unlink option, it should remove
133 * the link and create the dir.
134 */
135 assert(archive_entry_clear(ae) != NULL);
136 archive_entry_copy_pathname(ae, "link_to_dir2/filec");
137 archive_entry_set_mode(ae, S_IFREG | 0777);
138 archive_write_disk_set_options(a, ARCHIVE_EXTRACT_SECURE_SYMLINKS | ARCHIVE_EXTRACT_UNLINK);
139 assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae));
140 archive_entry_free(ae);
141 assert(0 == archive_write_finish_entry(a));
142
143 /* Create a nested symlink. */
144 assert((ae = archive_entry_new()) != NULL);
145 archive_entry_copy_pathname(ae, "dir/nested_link_to_dir");
146 archive_entry_set_mode(ae, S_IFLNK | 0777);
147 archive_entry_set_symlink(ae, "../dir");
148 archive_entry_set_symlink_type(ae, AE_SYMLINK_TYPE_DIRECTORY);
149 archive_write_disk_set_options(a, 0);
150 assert(0 == archive_write_header(a, ae));
151 assert(0 == archive_write_finish_entry(a));
152
153 /* But with security checks enabled, this should fail. */
154 assert(archive_entry_clear(ae) != NULL);
155 archive_entry_copy_pathname(ae, "dir/nested_link_to_dir/filed");
156 archive_entry_set_mode(ae, S_IFREG | 0777);
157 archive_write_disk_set_options(a, ARCHIVE_EXTRACT_SECURE_SYMLINKS);
158 failure("Extracting a file through a symlink should fail here.");
159 assertEqualInt(ARCHIVE_FAILED, archive_write_header(a, ae));
160 archive_entry_free(ae);
161 assert(0 == archive_write_finish_entry(a));
162
163 /*
164 * Without security checks, extracting a dir over a link to a
165 * dir should follow the link.
166 */
167 /* Create a symlink to a dir. */
168 assert((ae = archive_entry_new()) != NULL);
169 archive_entry_copy_pathname(ae, "link_to_dir3");
170 archive_entry_set_mode(ae, S_IFLNK | 0777);
171 archive_entry_set_symlink(ae, "dir");
172 archive_entry_set_symlink_type(ae, AE_SYMLINK_TYPE_DIRECTORY);
173 archive_write_disk_set_options(a, 0);
174 assert(0 == archive_write_header(a, ae));
175 assert(0 == archive_write_finish_entry(a));
176 /* Extract a dir whose name matches the symlink. */
177 assert(archive_entry_clear(ae) != NULL);
178 archive_entry_copy_pathname(ae, "link_to_dir3");
179 archive_entry_set_mode(ae, S_IFDIR | 0777);
180 assert(0 == archive_write_header(a, ae));
181 assert(0 == archive_write_finish_entry(a));
182 /* Verify link was followed. */
183 assertIsSymlink("link_to_dir3", "dir", 1);
184 archive_entry_free(ae);
185
186 /*
187 * As above, but a broken link, so the link should get replaced.
188 */
189 /* Create a symlink to a dir. */
190 assert((ae = archive_entry_new()) != NULL);
191 archive_entry_copy_pathname(ae, "link_to_dir4");
192 archive_entry_set_mode(ae, S_IFLNK | 0777);
193 archive_entry_set_symlink(ae, "nonexistent_dir");
194 archive_entry_set_symlink_type(ae, AE_SYMLINK_TYPE_DIRECTORY);
195 archive_write_disk_set_options(a, 0);
196 assert(0 == archive_write_header(a, ae));
197 assert(0 == archive_write_finish_entry(a));
198 /* Extract a dir whose name matches the symlink. */
199 assert(archive_entry_clear(ae) != NULL);
200 archive_entry_copy_pathname(ae, "link_to_dir4");
201 archive_entry_set_mode(ae, S_IFDIR | 0777);
202 assert(0 == archive_write_header(a, ae));
203 assert(0 == archive_write_finish_entry(a));
204 /* Verify link was replaced. */
205 assertIsDir("link_to_dir4", -1);
206 archive_entry_free(ae);
207
208 /*
209 * As above, but a link to a non-dir, so the link should get replaced.
210 */
211 /* Create a regular file and a symlink to it */
212 assert((ae = archive_entry_new()) != NULL);
213 archive_entry_copy_pathname(ae, "non_dir");
214 archive_entry_set_mode(ae, S_IFREG | 0777);
215 archive_write_disk_set_options(a, 0);
216 assert(0 == archive_write_header(a, ae));
217 assert(0 == archive_write_finish_entry(a));
218 /* Create symlink to the file. */
219 archive_entry_copy_pathname(ae, "link_to_dir5");
220 archive_entry_set_mode(ae, S_IFLNK | 0777);
221 archive_entry_set_symlink(ae, "non_dir");
222 archive_entry_set_symlink_type(ae, AE_SYMLINK_TYPE_FILE);
223 archive_write_disk_set_options(a, 0);
224 assert(0 == archive_write_header(a, ae));
225 assert(0 == archive_write_finish_entry(a));
226 /* Extract a dir whose name matches the symlink. */
227 assert(archive_entry_clear(ae) != NULL);
228 archive_entry_copy_pathname(ae, "link_to_dir5");
229 archive_entry_set_mode(ae, S_IFDIR | 0777);
230 assert(0 == archive_write_header(a, ae));
231 assert(0 == archive_write_finish_entry(a));
232 /* Verify link was replaced. */
233 assertIsDir("link_to_dir5", -1);
234 archive_entry_free(ae);
235
236 /* These tests hardcode the location of /tmp. skip them on Windows for now. */
237 #if !defined(_WIN32) || defined(__CYGWIN__)
238 /*
239 * Without security checks, we should be able to
240 * extract an absolute path.
241 */
242 assert((ae = archive_entry_new()) != NULL);
243 archive_entry_copy_pathname(ae, "/tmp/libarchive_test-test_write_disk_secure-absolute_path.tmp");
244 archive_entry_set_mode(ae, S_IFREG | 0777);
245 assert(0 == archive_write_header(a, ae));
246 assert(0 == archive_write_finish_entry(a));
247 assertFileExists("/tmp/libarchive_test-test_write_disk_secure-absolute_path.tmp");
248 assert(0 == unlink("/tmp/libarchive_test-test_write_disk_secure-absolute_path.tmp"));
249
250 /* But with security checks enabled, this should fail. */
251 assert(archive_entry_clear(ae) != NULL);
252 archive_entry_copy_pathname(ae, "/tmp/libarchive_test-test_write_disk_secure-absolute_path.tmp");
253 archive_entry_set_mode(ae, S_IFREG | 0777);
254 archive_write_disk_set_options(a, ARCHIVE_EXTRACT_SECURE_NOABSOLUTEPATHS);
255 failure("Extracting an absolute path should fail here.");
256 assertEqualInt(ARCHIVE_FAILED, archive_write_header(a, ae));
257 archive_entry_free(ae);
258 assert(0 == archive_write_finish_entry(a));
259 assertFileNotExists("/tmp/libarchive_test-test_write_disk_secure-absolute_path.tmp");
260 #endif
261
262 assertEqualInt(ARCHIVE_OK, archive_write_free(a));
263
264 /* Test the entries on disk. */
265 assertIsDir("dir", 0755);
266 assertIsSymlink("link_to_dir", "dir", 1);
267
268 #if defined(HAVE_SYMLINK) && defined(HAVE_LCHMOD) && \
269 defined(S_IRUSR) && defined(S_IWUSR) && defined(S_IXUSR)
270 /* Verify if we are able to lchmod() */
271 if (symlink("dir", "testlink_to_dir") == 0) {
272 if (lchmod("testlink_to_dir",
273 S_IRUSR | S_IWUSR | S_IXUSR) != 0) {
274 switch (errno) {
275 case ENOTSUP:
276 case ENOSYS:
277 #if ENOTSUP != EOPNOTSUPP
278 case EOPNOTSUPP:
279 #endif
280 working_lchmod = 0;
281 break;
282 default:
283 working_lchmod = 1;
284 }
285 } else
286 working_lchmod = 1;
287 } else
288 working_lchmod = 0;
289
290 if (working_lchmod) {
291 struct stat st;
292 assert(0 == lstat("link_to_dir", &st));
293 failure("link_to_dir: st.st_mode=%o", st.st_mode);
294 assert((st.st_mode & 07777) == 0755);
295 }
296 #endif
297
298 assertIsReg("dir/filea", 0755);
299 assertFileNotExists("dir/fileb");
300 assertIsDir("link_to_dir2", 0755);
301 assertIsReg("link_to_dir2/filec", 0755);
302 assertFileNotExists("dir/filed");
303 }
304
305 /*
306 * This is a simplified variant of the above test which never turns off secure
307 * symlinks. It is designed to test quirks in the Windows implementation of
308 * archive_write_disk; however, its behavior under test should not be exclusive
309 * to Windows.
310 */
DEFINE_TEST(test_write_disk_secure_symlinks_only)311 DEFINE_TEST(test_write_disk_secure_symlinks_only)
312 {
313 struct archive *a;
314 struct archive_entry *ae;
315 const int default_options = ARCHIVE_EXTRACT_SECURE_SYMLINKS;
316
317 if (!canSymlink()) {
318 skipping("Can't test symlinks on this filesystem");
319 return;
320 }
321
322 /* Start with a known umask. */
323 assertUmask(UMASK);
324
325 /* Create an archive_write_disk object. */
326 assert((a = archive_write_disk_new()) != NULL);
327 archive_write_disk_set_options(a, default_options);
328
329 /* Write a regular dir to it. */
330 assert((ae = archive_entry_new()) != NULL);
331 archive_entry_copy_pathname(ae, "dir");
332 archive_entry_set_mode(ae, S_IFDIR | 0777);
333 assert(0 == archive_write_header(a, ae));
334 archive_entry_free(ae);
335 assert(0 == archive_write_finish_entry(a));
336 assertIsDir("dir", -1);
337
338 /* Write a symlink to the dir above. */
339 assert((ae = archive_entry_new()) != NULL);
340 archive_entry_copy_pathname(ae, "link_to_dir");
341 archive_entry_set_mode(ae, S_IFLNK | 0777);
342 archive_entry_set_symlink(ae, "dir");
343 archive_entry_set_symlink_type(ae, AE_SYMLINK_TYPE_DIRECTORY);
344 assert(0 == archive_write_header(a, ae));
345 assert(0 == archive_write_finish_entry(a));
346 assertIsSymlink("link_to_dir", "dir", 1);
347
348 /* With security checks enabled, this should fail. */
349 assert(archive_entry_clear(ae) != NULL);
350 archive_entry_copy_pathname(ae, "link_to_dir/fileb");
351 archive_entry_set_mode(ae, S_IFREG | 0777);
352 failure("Extracting a file through a symlink should fail here.");
353 assertEqualInt(ARCHIVE_FAILED, archive_write_header(a, ae));
354 archive_entry_free(ae);
355 assert(0 == archive_write_finish_entry(a));
356 assertFileNotExists("dir/fileb");
357
358 /* Create another link. */
359 assert((ae = archive_entry_new()) != NULL);
360 archive_entry_copy_pathname(ae, "link_to_dir2");
361 archive_entry_set_mode(ae, S_IFLNK | 0777);
362 archive_entry_set_symlink(ae, "dir");
363 archive_entry_set_symlink_type(ae, AE_SYMLINK_TYPE_DIRECTORY);
364 assert(0 == archive_write_header(a, ae));
365 assert(0 == archive_write_finish_entry(a));
366 assertIsSymlink("link_to_dir2", "dir", 1);
367
368 /*
369 * With symlink check and unlink option, it should remove
370 * the link and create the dir.
371 */
372 assert(archive_entry_clear(ae) != NULL);
373 archive_entry_copy_pathname(ae, "link_to_dir2/filec");
374 archive_entry_set_mode(ae, S_IFREG | 0777);
375 archive_write_disk_set_options(a, default_options | ARCHIVE_EXTRACT_UNLINK);
376 assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae));
377 archive_entry_free(ae);
378 assert(0 == archive_write_finish_entry(a));
379 assertIsDir("link_to_dir2", -1);
380 assertIsReg("link_to_dir2/filec", -1);
381
382 /*
383 * Restore the prior security mode.
384 */
385 archive_write_disk_set_options(a, default_options);
386
387 /* Create a nested symlink. */
388 assert((ae = archive_entry_new()) != NULL);
389 archive_entry_copy_pathname(ae, "dir/nested_link_to_dir");
390 archive_entry_set_mode(ae, S_IFLNK | 0777);
391 archive_entry_set_symlink(ae, "../dir");
392 archive_entry_set_symlink_type(ae, AE_SYMLINK_TYPE_DIRECTORY);
393 assert(0 == archive_write_header(a, ae));
394 assert(0 == archive_write_finish_entry(a));
395 assertIsSymlink("dir/nested_link_to_dir", "../dir", -1);
396
397 /* With security checks enabled, this should fail. */
398 assert(archive_entry_clear(ae) != NULL);
399 archive_entry_copy_pathname(ae, "dir/nested_link_to_dir/filed");
400 archive_entry_set_mode(ae, S_IFREG | 0777);
401 failure("Extracting a file through a symlink should fail here.");
402 assertEqualInt(ARCHIVE_FAILED, archive_write_header(a, ae));
403 archive_entry_free(ae);
404 assert(0 == archive_write_finish_entry(a));
405 assertFileNotExists("dir/filed");
406
407 /* Create a symlink to a dir. */
408 assert((ae = archive_entry_new()) != NULL);
409 archive_entry_copy_pathname(ae, "link_to_dir3");
410 archive_entry_set_mode(ae, S_IFLNK | 0777);
411 archive_entry_set_symlink(ae, "dir");
412 archive_entry_set_symlink_type(ae, AE_SYMLINK_TYPE_DIRECTORY);
413 assert(0 == archive_write_header(a, ae));
414 assert(0 == archive_write_finish_entry(a));
415 assertIsSymlink("link_to_dir3", "dir", 1);
416 /* Extract a dir whose name matches the symlink. */
417 assert(archive_entry_clear(ae) != NULL);
418 archive_entry_copy_pathname(ae, "link_to_dir3");
419 archive_entry_set_mode(ae, S_IFDIR | 0777);
420 assert(0 == archive_write_header(a, ae));
421 assert(0 == archive_write_finish_entry(a));
422 archive_entry_free(ae);
423 assertIsDir("link_to_dir3", -1);
424
425 /*
426 * As above, but a broken link, so the link should get replaced.
427 */
428
429 /* Create a symlink to a dir. */
430 assert((ae = archive_entry_new()) != NULL);
431 archive_entry_copy_pathname(ae, "link_to_dir4");
432 archive_entry_set_mode(ae, S_IFLNK | 0777);
433 archive_entry_set_symlink(ae, "nonexistent_dir");
434 archive_entry_set_symlink_type(ae, AE_SYMLINK_TYPE_DIRECTORY);
435 assert(0 == archive_write_header(a, ae));
436 assert(0 == archive_write_finish_entry(a));
437 assertIsSymlink("link_to_dir4", "nonexistent_dir", 1);
438 /* Extract a dir whose name matches the symlink. */
439 assert(archive_entry_clear(ae) != NULL);
440 archive_entry_copy_pathname(ae, "link_to_dir4");
441 archive_entry_set_mode(ae, S_IFDIR | 0777);
442 assert(0 == archive_write_header(a, ae));
443 assert(0 == archive_write_finish_entry(a));
444 archive_entry_free(ae);
445 assertIsDir("link_to_dir4", -1);
446
447 /*
448 * As above, but a link to a non-dir, so the link should get replaced.
449 * (file is named "link_to_dir" because we are transforming a link into a dir,)
450 */
451 /* Create a regular file and a symlink to it */
452 assert((ae = archive_entry_new()) != NULL);
453 archive_entry_copy_pathname(ae, "non_dir");
454 archive_entry_set_mode(ae, S_IFREG | 0777);
455 assert(0 == archive_write_header(a, ae));
456 assert(0 == archive_write_finish_entry(a));
457 assertIsReg("non_dir", -1);
458 /* Create symlink to the file. */
459 archive_entry_copy_pathname(ae, "link_to_dir5");
460 archive_entry_set_mode(ae, S_IFLNK | 0777);
461 archive_entry_set_symlink(ae, "non_dir");
462 archive_entry_set_symlink_type(ae, AE_SYMLINK_TYPE_FILE);
463 assert(0 == archive_write_header(a, ae));
464 assert(0 == archive_write_finish_entry(a));
465 assertIsSymlink("link_to_dir5", "non_dir", 0);
466 /* Extract a dir whose name matches the symlink. */
467 assert(archive_entry_clear(ae) != NULL);
468 archive_entry_copy_pathname(ae, "link_to_dir5");
469 archive_entry_set_mode(ae, S_IFDIR | 0777);
470 assert(0 == archive_write_header(a, ae));
471 assert(0 == archive_write_finish_entry(a));
472 archive_entry_free(ae);
473 assertIsDir("link_to_dir5", -1);
474
475 /*
476 * Create a link to a (technically safe) directory, then replace it, then write through it.
477 * Exercises the safety cache to ensure that it does not treat new entries as safe.
478 */
479 assert((ae = archive_entry_new()) != NULL);
480 archive_entry_copy_pathname(ae, "link_to_dir6");
481 archive_entry_set_mode(ae, S_IFLNK | 0777);
482 archive_entry_set_symlink(ae, "dir");
483 archive_entry_set_symlink_type(ae, AE_SYMLINK_TYPE_DIRECTORY);
484 assert(0 == archive_write_header(a, ae));
485 assert(0 == archive_write_finish_entry(a));
486 assertIsSymlink("link_to_dir6", "dir", 1);
487 /* Replace it. */
488 assert(archive_entry_clear(ae) != NULL);
489 archive_entry_copy_pathname(ae, "link_to_dir6");
490 archive_entry_set_mode(ae, S_IFLNK | 0777);
491 archive_entry_set_symlink(ae, "dir");
492 archive_entry_set_symlink_type(ae, AE_SYMLINK_TYPE_DIRECTORY);
493 assert(0 == archive_write_header(a, ae));
494 assert(0 == archive_write_finish_entry(a));
495 assertIsSymlink("link_to_dir6", "dir", 1);
496 /* Extract through it. */
497 assert(archive_entry_clear(ae) != NULL);
498 archive_entry_copy_pathname(ae, "link_to_dir6/filee");
499 archive_entry_set_mode(ae, S_IFREG | 0777);
500 assertEqualInt(ARCHIVE_FAILED, archive_write_header(a, ae));
501 archive_entry_free(ae);
502 assertFileNotExists("dir/filee");
503
504 /*
505 * Create an empty directory, then replace it, then write through it.
506 * Exercises the safety cache to ensure that it does not treat new entries as safe.
507 */
508 assert((ae = archive_entry_new()) != NULL);
509 archive_entry_copy_pathname(ae, "link_to_dir7");
510 archive_entry_set_mode(ae, S_IFDIR | 0777);
511 assert(0 == archive_write_header(a, ae));
512 assert(0 == archive_write_finish_entry(a));
513 assertIsDir("link_to_dir7", -1);
514 /* Replace it. */
515 assert(archive_entry_clear(ae) != NULL);
516 archive_entry_copy_pathname(ae, "link_to_dir7");
517 archive_entry_set_mode(ae, S_IFLNK | 0777);
518 archive_entry_set_symlink(ae, "dir");
519 archive_entry_set_symlink_type(ae, AE_SYMLINK_TYPE_DIRECTORY);
520 assert(0 == archive_write_header(a, ae));
521 assert(0 == archive_write_finish_entry(a));
522 assertIsSymlink("link_to_dir7", "dir", 1);
523 /* Extract through it. */
524 assert(archive_entry_clear(ae) != NULL);
525 archive_entry_copy_pathname(ae, "link_to_dir7/filef");
526 archive_entry_set_mode(ae, S_IFREG | 0777);
527 assertEqualInt(ARCHIVE_FAILED, archive_write_header(a, ae));
528 archive_entry_free(ae);
529 assertFileNotExists("dir/filef");
530
531 assertEqualInt(ARCHIVE_OK, archive_write_free(a));
532 }
533