test_write_disk_symlink.c revision 348607
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__FBSDID("$FreeBSD: stable/11/contrib/libarchive/libarchive/test/test_write_disk_symlink.c 348607 2019-06-04 10:35:54Z mm $");
27
28/*
29 * Exercise symlink recreation.
30 */
31DEFINE_TEST(test_write_disk_symlink)
32{
33	static const char data[]="abcdefghijklmnopqrstuvwxyz";
34	struct archive *ad;
35	struct archive_entry *ae;
36	int r;
37
38	if (!canSymlink()) {
39		skipping("Symlinks not supported");
40		return;
41	}
42
43	/* Write entries to disk. */
44	assert((ad = archive_write_disk_new()) != NULL);
45
46	/*
47	 * First, create a regular file then a symlink to that file.
48	 */
49
50	/* Regular file: link1a */
51	assert((ae = archive_entry_new()) != NULL);
52	archive_entry_copy_pathname(ae, "link1a");
53	archive_entry_set_mode(ae, AE_IFREG | 0755);
54	archive_entry_set_size(ae, sizeof(data));
55	assertEqualIntA(ad, 0, archive_write_header(ad, ae));
56	assertEqualInt(sizeof(data),
57	    archive_write_data(ad, data, sizeof(data)));
58	assertEqualIntA(ad, 0, archive_write_finish_entry(ad));
59	archive_entry_free(ae);
60
61	/* Symbolic Link: link1b -> link1a */
62	assert((ae = archive_entry_new()) != NULL);
63	archive_entry_copy_pathname(ae, "link1b");
64	archive_entry_set_mode(ae, AE_IFLNK | 0642);
65	archive_entry_set_size(ae, 0);
66	archive_entry_copy_symlink(ae, "link1a");
67	assertEqualIntA(ad, 0, r = archive_write_header(ad, ae));
68	if (r >= ARCHIVE_WARN)
69		assertEqualIntA(ad, 0, archive_write_finish_entry(ad));
70	archive_entry_free(ae);
71
72	/*
73	 * We should be able to do this in the other order as well,
74	 * of course.
75	 */
76
77	/* Symbolic link: link2b -> link2a */
78	assert((ae = archive_entry_new()) != NULL);
79	archive_entry_copy_pathname(ae, "link2b");
80	archive_entry_set_mode(ae, AE_IFLNK | 0642);
81	archive_entry_unset_size(ae);
82	archive_entry_copy_symlink(ae, "link2a");
83	assertEqualIntA(ad, 0, r = archive_write_header(ad, ae));
84	if (r >= ARCHIVE_WARN) {
85		assertEqualInt(ARCHIVE_WARN,
86		    archive_write_data(ad, data, sizeof(data)));
87		assertEqualIntA(ad, 0, archive_write_finish_entry(ad));
88	}
89	archive_entry_free(ae);
90
91	/* File: link2a */
92	assert((ae = archive_entry_new()) != NULL);
93	archive_entry_copy_pathname(ae, "link2a");
94	archive_entry_set_mode(ae, AE_IFREG | 0755);
95	archive_entry_set_size(ae, sizeof(data));
96	assertEqualIntA(ad, 0, archive_write_header(ad, ae));
97	assertEqualInt(sizeof(data),
98	    archive_write_data(ad, data, sizeof(data)));
99	assertEqualIntA(ad, 0, archive_write_finish_entry(ad));
100	archive_entry_free(ae);
101
102	/* Symbolic link: dot -> . */
103	assert((ae = archive_entry_new()) != NULL);
104	archive_entry_copy_pathname(ae, "dot");
105	archive_entry_set_mode(ae, AE_IFLNK | 0642);
106	archive_entry_unset_size(ae);
107	archive_entry_copy_symlink(ae, ".");
108	assertEqualIntA(ad, 0, r = archive_write_header(ad, ae));
109	if (r >= ARCHIVE_WARN)
110		assertEqualIntA(ad, 0, archive_write_finish_entry(ad));
111	archive_entry_free(ae);
112
113	/* Symbolic link: dotdot -> .. */
114	assert((ae = archive_entry_new()) != NULL);
115	archive_entry_copy_pathname(ae, "dotdot");
116	archive_entry_set_mode(ae, AE_IFLNK | 0642);
117	archive_entry_unset_size(ae);
118	archive_entry_copy_symlink(ae, "..");
119	assertEqualIntA(ad, 0, r = archive_write_header(ad, ae));
120	if (r >= ARCHIVE_WARN)
121		assertEqualIntA(ad, 0, archive_write_finish_entry(ad));
122	archive_entry_free(ae);
123
124	/* Symbolic link: slash -> / */
125	assert((ae = archive_entry_new()) != NULL);
126	archive_entry_copy_pathname(ae, "slash");
127	archive_entry_set_mode(ae, AE_IFLNK | 0642);
128	archive_entry_unset_size(ae);
129	archive_entry_copy_symlink(ae, "/");
130	assertEqualIntA(ad, 0, r = archive_write_header(ad, ae));
131	if (r >= ARCHIVE_WARN)
132		assertEqualIntA(ad, 0, archive_write_finish_entry(ad));
133	archive_entry_free(ae);
134
135	/* Symbolic link: sldot -> /. */
136	assert((ae = archive_entry_new()) != NULL);
137	archive_entry_copy_pathname(ae, "sldot");
138	archive_entry_set_mode(ae, AE_IFLNK | 0642);
139	archive_entry_unset_size(ae);
140	archive_entry_copy_symlink(ae, "/.");
141	assertEqualIntA(ad, 0, r = archive_write_header(ad, ae));
142	if (r >= ARCHIVE_WARN)
143		assertEqualIntA(ad, 0, archive_write_finish_entry(ad));
144	archive_entry_free(ae);
145
146	/* Symbolic link: sldotdot -> /.. */
147	assert((ae = archive_entry_new()) != NULL);
148	archive_entry_copy_pathname(ae, "sldotdot");
149	archive_entry_set_mode(ae, AE_IFLNK | 0642);
150	archive_entry_unset_size(ae);
151	archive_entry_copy_symlink(ae, "/..");
152	assertEqualIntA(ad, 0, r = archive_write_header(ad, ae));
153	if (r >= ARCHIVE_WARN)
154		assertEqualIntA(ad, 0, archive_write_finish_entry(ad));
155	archive_entry_free(ae);
156
157	/* Dir: d1 */
158	assert((ae = archive_entry_new()) != NULL);
159	archive_entry_copy_pathname(ae, "d1");
160	archive_entry_set_mode(ae, AE_IFDIR | 0777);
161	archive_entry_unset_size(ae);
162	assertEqualIntA(ad, 0, r = archive_write_header(ad, ae));
163	if (r >= ARCHIVE_WARN)
164		assertEqualIntA(ad, 0, archive_write_finish_entry(ad));
165	archive_entry_free(ae);
166
167	/* Symbolic link: d1nosl -> d1 */
168	assert((ae = archive_entry_new()) != NULL);
169	archive_entry_copy_pathname(ae, "d1nosl");
170	archive_entry_set_mode(ae, AE_IFLNK | 0642);
171	archive_entry_unset_size(ae);
172	archive_entry_copy_symlink(ae, "d1");
173	assertEqualIntA(ad, 0, r = archive_write_header(ad, ae));
174	if (r >= ARCHIVE_WARN)
175		assertEqualIntA(ad, 0, archive_write_finish_entry(ad));
176	archive_entry_free(ae);
177
178	/* Symbolic link: d1slash -> d1/ */
179	assert((ae = archive_entry_new()) != NULL);
180	archive_entry_copy_pathname(ae, "d1slash");
181	archive_entry_set_mode(ae, AE_IFLNK | 0642);
182	archive_entry_unset_size(ae);
183	archive_entry_copy_symlink(ae, "d1/");
184	assertEqualIntA(ad, 0, r = archive_write_header(ad, ae));
185	if (r >= ARCHIVE_WARN)
186		assertEqualIntA(ad, 0, archive_write_finish_entry(ad));
187	archive_entry_free(ae);
188
189	/* Symbolic link: d1sldot -> d1/. */
190	assert((ae = archive_entry_new()) != NULL);
191	archive_entry_copy_pathname(ae, "d1sldot");
192	archive_entry_set_mode(ae, AE_IFLNK | 0642);
193	archive_entry_unset_size(ae);
194	archive_entry_copy_symlink(ae, "d1/.");
195	assertEqualIntA(ad, 0, r = archive_write_header(ad, ae));
196	if (r >= ARCHIVE_WARN)
197		assertEqualIntA(ad, 0, archive_write_finish_entry(ad));
198	archive_entry_free(ae);
199
200	/* Symbolic link: d1slddot -> d1/.. */
201	assert((ae = archive_entry_new()) != NULL);
202	archive_entry_copy_pathname(ae, "d1slddot");
203	archive_entry_set_mode(ae, AE_IFLNK | 0642);
204	archive_entry_unset_size(ae);
205	archive_entry_copy_symlink(ae, "d1/..");
206	assertEqualIntA(ad, 0, r = archive_write_header(ad, ae));
207	if (r >= ARCHIVE_WARN)
208		assertEqualIntA(ad, 0, archive_write_finish_entry(ad));
209	archive_entry_free(ae);
210
211	/* Symbolic link: d1dir -> d1 */
212	assert((ae = archive_entry_new()) != NULL);
213	archive_entry_copy_pathname(ae, "d1dir");
214	archive_entry_set_mode(ae, AE_IFLNK | 0642);
215	archive_entry_set_symlink_type(ae, AE_SYMLINK_TYPE_DIRECTORY);
216	archive_entry_unset_size(ae);
217	archive_entry_copy_symlink(ae, "d1");
218	assertEqualIntA(ad, 0, r = archive_write_header(ad, ae));
219	if (r >= ARCHIVE_WARN)
220		assertEqualIntA(ad, 0, archive_write_finish_entry(ad));
221	archive_entry_free(ae);
222
223	/* Symbolic link: d1file -> d1 */
224	assert((ae = archive_entry_new()) != NULL);
225	archive_entry_copy_pathname(ae, "d1file");
226	archive_entry_set_mode(ae, AE_IFLNK | 0642);
227	archive_entry_set_symlink_type(ae, AE_SYMLINK_TYPE_FILE);
228	archive_entry_unset_size(ae);
229	archive_entry_copy_symlink(ae, "d1");
230	assertEqualIntA(ad, 0, r = archive_write_header(ad, ae));
231	if (r >= ARCHIVE_WARN)
232		assertEqualIntA(ad, 0, archive_write_finish_entry(ad));
233	archive_entry_free(ae);
234
235	assertEqualInt(ARCHIVE_OK, archive_write_free(ad));
236
237	/* Test the entries on disk. */
238
239	/* Test #1 */
240	assertIsReg("link1a", -1);
241	assertFileSize("link1a", sizeof(data));
242	assertFileNLinks("link1a", 1);
243	assertIsSymlink("link1b", "link1a", 0);
244
245	/* Test #2: Should produce identical results to test #1 */
246	assertIsReg("link2a", -1);
247	assertFileSize("link2a", sizeof(data));
248	assertFileNLinks("link2a", 1);
249	assertIsSymlink("link2b", "link2a", 0);
250
251	/* Test #3: Special symlinks */
252	assertIsSymlink("dot", ".", 1);
253	assertIsSymlink("dotdot", "..", 1);
254	assertIsSymlink("slash", "/", 1);
255	assertIsSymlink("sldot", "/.", 1);
256	assertIsSymlink("sldotdot", "/..", 1);
257
258	/* Test #4: Directory symlink mixed with . and .. */
259	assertIsDir("d1", -1);
260	/* On Windows, d1nosl should be a file symlink */
261	assertIsSymlink("d1nosl", "d1", 0);
262	assertIsSymlink("d1slash", "d1/", 1);
263	assertIsSymlink("d1sldot", "d1/.", 1);
264	assertIsSymlink("d1slddot", "d1/..", 1);
265
266	/* Test #5: symlink_type is set */
267	assertIsSymlink("d1dir", "d1", 1);
268	assertIsSymlink("d1file", "d1", 0);
269}
270