2 * Copyright (c) 2003-2007 Tim Kientzle
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
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.
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.
26 __FBSDID("$FreeBSD$");
28 #if defined(_WIN32) && !defined(__CYGWIN__)
29 /* Execution bits, Group members bits and others bits do not work. */
31 #define E_MASK (~0177)
38 * Exercise hardlink recreation.
40 * File permissions are chosen so that the authoritive entry
41 * has the correct permission and the non-authoritive versions
42 * are just writeable files.
44 DEFINE_TEST(test_write_disk_hardlink)
46 #if ARCHIVE_VERSION_NUMBER < 1009000
47 skipping("archive_write_disk_hardlink tests");
49 static const char data[]="abcdefghijklmnopqrstuvwxyz";
51 struct archive_entry *ae;
54 /* Force the umask to something predictable. */
57 /* Write entries to disk. */
58 assert((ad = archive_write_disk_new()) != NULL);
61 * First, use a tar-like approach; a regular file, then
62 * a separate "hardlink" entry.
66 assert((ae = archive_entry_new()) != NULL);
67 archive_entry_copy_pathname(ae, "link1a");
68 archive_entry_set_mode(ae, S_IFREG | 0755);
69 archive_entry_set_size(ae, sizeof(data));
70 assertEqualIntA(ad, 0, archive_write_header(ad, ae));
71 assertEqualInt(sizeof(data),
72 archive_write_data(ad, data, sizeof(data)));
73 assertEqualIntA(ad, 0, archive_write_finish_entry(ad));
74 archive_entry_free(ae);
76 /* Link. Size of zero means this doesn't carry data. */
77 assert((ae = archive_entry_new()) != NULL);
78 archive_entry_copy_pathname(ae, "link1b");
79 archive_entry_set_mode(ae, S_IFREG | 0642);
80 archive_entry_set_size(ae, 0);
81 archive_entry_copy_hardlink(ae, "link1a");
82 assertEqualIntA(ad, 0, archive_write_header(ad, ae));
83 assertEqualInt(ARCHIVE_WARN,
84 archive_write_data(ad, data, sizeof(data)));
85 assertEqualIntA(ad, 0, archive_write_finish_entry(ad));
86 archive_entry_free(ae);
89 * Repeat tar approach test, but use unset to mark the
90 * hardlink as having no data.
94 assert((ae = archive_entry_new()) != NULL);
95 archive_entry_copy_pathname(ae, "link2a");
96 archive_entry_set_mode(ae, S_IFREG | 0755);
97 archive_entry_set_size(ae, sizeof(data));
98 assertEqualIntA(ad, 0, archive_write_header(ad, ae));
99 assertEqualInt(sizeof(data),
100 archive_write_data(ad, data, sizeof(data)));
101 assertEqualIntA(ad, 0, archive_write_finish_entry(ad));
102 archive_entry_free(ae);
104 /* Link. Unset size means this doesn't carry data. */
105 assert((ae = archive_entry_new()) != NULL);
106 archive_entry_copy_pathname(ae, "link2b");
107 archive_entry_set_mode(ae, S_IFREG | 0642);
108 archive_entry_unset_size(ae);
109 archive_entry_copy_hardlink(ae, "link2a");
110 assertEqualIntA(ad, 0, archive_write_header(ad, ae));
111 assertEqualInt(ARCHIVE_WARN,
112 archive_write_data(ad, data, sizeof(data)));
113 assertEqualIntA(ad, 0, archive_write_finish_entry(ad));
114 archive_entry_free(ae);
117 * Second, try an old-cpio-like approach; a regular file, then
118 * another identical one (which has been marked hardlink).
122 assert((ae = archive_entry_new()) != NULL);
123 archive_entry_copy_pathname(ae, "link3a");
124 archive_entry_set_mode(ae, S_IFREG | 0600);
125 archive_entry_set_size(ae, sizeof(data));
126 assertEqualIntA(ad, 0, archive_write_header(ad, ae));
127 assertEqualInt(sizeof(data), archive_write_data(ad, data, sizeof(data)));
128 assertEqualIntA(ad, 0, archive_write_finish_entry(ad));
129 archive_entry_free(ae);
132 assert((ae = archive_entry_new()) != NULL);
133 archive_entry_copy_pathname(ae, "link3b");
134 archive_entry_set_mode(ae, S_IFREG | 0755);
135 archive_entry_set_size(ae, sizeof(data));
136 archive_entry_copy_hardlink(ae, "link3a");
137 assertEqualIntA(ad, 0, archive_write_header(ad, ae));
138 assertEqualInt(sizeof(data), archive_write_data(ad, data, sizeof(data)));
139 assertEqualIntA(ad, 0, archive_write_finish_entry(ad));
140 archive_entry_free(ae);
143 * Finally, try a new-cpio-like approach, where the initial
144 * regular file is empty and the hardlink has the data.
148 assert((ae = archive_entry_new()) != NULL);
149 archive_entry_copy_pathname(ae, "link4a");
150 archive_entry_set_mode(ae, S_IFREG | 0600);
151 archive_entry_set_size(ae, 0);
152 assertEqualIntA(ad, 0, archive_write_header(ad, ae));
153 #if ARCHIVE_VERSION_NUMBER < 3000000
154 assertEqualInt(ARCHIVE_WARN, archive_write_data(ad, data, 1));
156 assertEqualInt(-1, archive_write_data(ad, data, 1));
158 assertEqualIntA(ad, 0, archive_write_finish_entry(ad));
159 archive_entry_free(ae);
162 assert((ae = archive_entry_new()) != NULL);
163 archive_entry_copy_pathname(ae, "link4b");
164 archive_entry_set_mode(ae, S_IFREG | 0755);
165 archive_entry_set_size(ae, sizeof(data));
166 archive_entry_copy_hardlink(ae, "link4a");
167 assertEqualIntA(ad, 0, archive_write_header(ad, ae));
168 assertEqualInt(sizeof(data), archive_write_data(ad, data, sizeof(data)));
169 assertEqualIntA(ad, 0, archive_write_finish_entry(ad));
170 archive_entry_free(ae);
171 #if ARCHIVE_VERSION_NUMBER < 2000000
172 archive_write_finish(ad);
174 assertEqualInt(0, archive_write_finish(ad));
177 /* Test the entries on disk. */
180 assert(0 == stat("link1a", &st));
181 /* If the hardlink was successfully created and the archive
182 * doesn't carry data for it, we consider it to be
183 * non-authoritive for meta data as well. This is consistent
184 * with GNU tar and BSD pax. */
185 assertEqualInt(st.st_mode & E_MASK, (S_IFREG | 0755) & ~UMASK);
186 assertEqualInt(st.st_size, sizeof(data));
187 assertEqualInt(st.st_nlink, 2);
189 assert(0 == stat("link1b", &st2));
190 assertEqualInt(st.st_mode, st2.st_mode);
191 assertEqualInt(st.st_size, st2.st_size);
192 assertEqualInt(st.st_nlink, st2.st_nlink);
193 assertEqualInt(st.st_ino, st2.st_ino);
194 assertEqualInt(st.st_dev, st2.st_dev);
196 /* Test #2: Should produce identical results to test #1 */
197 /* Note that marking a hardlink with size = 0 is treated the
198 * same as having an unset size. This is partly for backwards
199 * compatibility (we used to not have unset tracking, so
200 * relied on size == 0) and partly to match the model used by
201 * common file formats that store a size of zero for
203 assert(0 == stat("link2a", &st));
204 assertEqualInt(st.st_mode & E_MASK, (S_IFREG | 0755) & ~UMASK);
205 assertEqualInt(st.st_size, sizeof(data));
206 assertEqualInt(st.st_nlink, 2);
208 assert(0 == stat("link2b", &st2));
209 assertEqualInt(st.st_mode, st2.st_mode);
210 assertEqualInt(st.st_size, st2.st_size);
211 assertEqualInt(st.st_nlink, st2.st_nlink);
212 assertEqualInt(st.st_ino, st2.st_ino);
213 assertEqualInt(st.st_dev, st2.st_dev);
216 assert(0 == stat("link3a", &st));
217 assertEqualInt(st.st_mode & E_MASK, (S_IFREG | 0755) & ~UMASK);
218 assertEqualInt(st.st_size, sizeof(data));
219 assertEqualInt(st.st_nlink, 2);
221 assert(0 == stat("link3b", &st2));
222 assertEqualInt(st2.st_mode & E_MASK, (S_IFREG | 0755) & ~UMASK);
223 assertEqualInt(st2.st_size, sizeof(data));
224 assertEqualInt(st2.st_nlink, 2);
225 assertEqualInt(st.st_ino, st2.st_ino);
226 assertEqualInt(st.st_dev, st2.st_dev);
229 assert(0 == stat("link4a", &st));
230 assertEqualInt(st.st_mode & E_MASK, (S_IFREG | 0755) & ~UMASK);
231 assertEqualInt(st.st_size, sizeof(data));
232 assertEqualInt(st.st_nlink, 2);
234 assert(0 == stat("link4b", &st2));
235 assertEqualInt(st2.st_mode & E_MASK, (S_IFREG | 0755) & ~UMASK);
236 assertEqualInt(st2.st_size, sizeof(data));
237 assertEqualInt(st2.st_nlink, 2);
238 assertEqualInt(st.st_ino, st2.st_ino);
239 assertEqualInt(st.st_dev, st2.st_dev);