1 /*-
2 * SPDX-License-Identifier: BSD-2-Clause
3 *
4 * Copyright (c) 2003-2007 Tim Kientzle
5 * All rights reserved.
6 */
7 #include "test.h"
8
9 /*
10 * tar -x -P should follow existing symlinks for dirs, but not other
11 * content. Plain tar -x should remove symlinks when they're in the
12 * way of a dir extraction.
13 */
14
DEFINE_TEST(test_symlink_dir)15 DEFINE_TEST(test_symlink_dir)
16 {
17 assertUmask(0);
18
19 assertMakeDir("source", 0755);
20 assertMakeFile("source/file", 0755, "a");
21 assertMakeFile("source/file2", 0755, "ab");
22 assertMakeDir("source/dir", 0755);
23 assertMakeDir("source/dir/d", 0755);
24 assertMakeFile("source/dir/f", 0755, "abc");
25 assertMakeDir("source/dir2", 0755);
26 assertMakeDir("source/dir2/d2", 0755);
27 assertMakeFile("source/dir2/f2", 0755, "abcd");
28 assertMakeDir("source/dir3", 0755);
29 assertMakeDir("source/dir3/d3", 0755);
30 assertMakeFile("source/dir3/f3", 0755, "abcde");
31 assertMakeDir("source/dir4", 0755);
32 assertMakeFile("source/dir4/file3", 0755, "abcdef");
33 assertMakeHardlink("source/dir4/file4", "source/dir4/file3");
34
35 assertEqualInt(0,
36 systemf("%s -cf test.tar -C source dir dir2 dir3 file file2",
37 testprog));
38
39 /* Second archive with hardlinks */
40 assertEqualInt(0,
41 systemf("%s -cf test2.tar -C source dir4", testprog));
42
43 /*
44 * Extract with -x and without -P.
45 */
46 assertMakeDir("dest1", 0755);
47 /* "dir" is a symlink to an existing "dest1/real_dir" */
48 assertMakeDir("dest1/real_dir", 0755);
49 if (canSymlink()) {
50 assertMakeSymlink("dest1/dir", "real_dir", 1);
51 /* "dir2" is a symlink to a non-existing "real_dir2" */
52 assertMakeSymlink("dest1/dir2", "real_dir2", 1);
53 } else {
54 skipping("Symlinks are not supported on this platform");
55 }
56 /* "dir3" is a symlink to an existing "non_dir3" */
57 assertMakeFile("dest1/non_dir3", 0755, "abcdef");
58 if (canSymlink())
59 assertMakeSymlink("dest1/dir3", "non_dir3", 1);
60 /* "file" is a symlink to existing "real_file" */
61 assertMakeFile("dest1/real_file", 0755, "abcdefg");
62 if (canSymlink()) {
63 assertMakeSymlink("dest1/file", "real_file", 0);
64 /* "file2" is a symlink to non-existing "real_file2" */
65 assertMakeSymlink("dest1/file2", "real_file2", 0);
66 }
67 assertEqualInt(0, systemf("%s -xf test.tar -C dest1", testprog));
68
69 /* dest1/dir symlink should be replaced */
70 failure("symlink to dir was followed when it shouldn't be");
71 assertIsDir("dest1/dir", -1);
72 /* dest1/dir2 symlink should be replaced */
73 failure("Broken symlink wasn't replaced with dir");
74 assertIsDir("dest1/dir2", -1);
75 /* dest1/dir3 symlink should be replaced */
76 failure("Symlink to non-dir wasn't replaced with dir");
77 assertIsDir("dest1/dir3", -1);
78 /* dest1/file symlink should be replaced */
79 failure("Symlink to existing file should be replaced");
80 assertIsReg("dest1/file", -1);
81 /* dest1/file2 symlink should be replaced */
82 failure("Symlink to non-existing file should be replaced");
83 assertIsReg("dest1/file2", -1);
84
85 /*
86 * Extract with both -x and -P
87 */
88 assertMakeDir("dest2", 0755);
89 /* "dir" is a symlink to existing "real_dir" */
90 assertMakeDir("dest2/real_dir", 0755);
91 if (canSymlink())
92 assertMakeSymlink("dest2/dir", "real_dir", 1);
93 /* "dir2" is a symlink to a non-existing "real_dir2" */
94 if (canSymlink())
95 assertMakeSymlink("dest2/dir2", "real_dir2", 1);
96 /* "dir3" is a symlink to an existing "non_dir3" */
97 assertMakeFile("dest2/non_dir3", 0755, "abcdefgh");
98 if (canSymlink())
99 assertMakeSymlink("dest2/dir3", "non_dir3", 1);
100 /* "file" is a symlink to existing "real_file" */
101 assertMakeFile("dest2/real_file", 0755, "abcdefghi");
102 if (canSymlink())
103 assertMakeSymlink("dest2/file", "real_file", 0);
104 /* "file2" is a symlink to non-existing "real_file2" */
105 if (canSymlink())
106 assertMakeSymlink("dest2/file2", "real_file2", 0);
107 assertEqualInt(0, systemf("%s -xPf test.tar -C dest2", testprog));
108
109 /* "dir4" is a symlink to existing "real_dir" */
110 if (canSymlink())
111 assertMakeSymlink("dest2/dir4", "real_dir", 1);
112 assertEqualInt(0, systemf("%s -xPf test2.tar -C dest2", testprog));
113
114 /* dest2/dir and dest2/dir4 symlinks should be followed */
115 if (canSymlink()) {
116 assertIsSymlink("dest2/dir", "real_dir", 1);
117 assertIsSymlink("dest2/dir4", "real_dir", 1);
118 assertIsDir("dest2/real_dir", -1);
119 }
120
121 /* Contents of 'dir' should be restored */
122 assertIsDir("dest2/dir/d", -1);
123 assertIsReg("dest2/dir/f", -1);
124 assertFileSize("dest2/dir/f", 3);
125 /* dest2/dir2 symlink should be removed */
126 failure("Broken symlink wasn't replaced with dir");
127 assertIsDir("dest2/dir2", -1);
128 /* dest2/dir3 symlink should be removed */
129 failure("Symlink to non-dir wasn't replaced with dir");
130 assertIsDir("dest2/dir3", -1);
131 /* dest2/file symlink should be removed;
132 * even -P shouldn't follow symlinks for files */
133 failure("Symlink to existing file should be removed");
134 assertIsReg("dest2/file", -1);
135 /* dest2/file2 symlink should be removed */
136 failure("Symlink to non-existing file should be removed");
137 assertIsReg("dest2/file2", -1);
138
139 /* dest2/dir4/file3 and dest2/dir4/file4 should be hard links */
140 assertIsHardlink("dest2/dir4/file3", "dest2/dir4/file4");
141 }
142