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