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 #if defined(__CYGWIN__) 28 # include <limits.h> 29 # include <sys/cygwin.h> 30 #endif 31 #if defined(_WIN32) && !defined(__CYGWIN__) 32 # include <direct.h> 33 #endif 34 35 /* 36 * Try to figure out how deep we can go in our tests. Assumes that 37 * the first call to this function has the longest starting cwd (which 38 * is currently "<testdir>/original"). This is mostly to work around 39 * limits in our Win32 support. 40 * 41 * Background: On Posix systems, PATH_MAX is merely a limit on the 42 * length of the string passed into a system call. By repeatedly 43 * calling chdir(), you can work with arbitrarily long paths on such 44 * systems. In contrast, Win32 APIs apply PATH_MAX limits to the full 45 * absolute path, so the permissible length of a system call argument 46 * varies with the cwd. Some APIs actually enforce limits 47 * significantly less than PATH_MAX to ensure that you can create 48 * files within the current working directory. The Win32 limits also 49 * apply to Cygwin before 1.7. 50 * 51 * Someday, I want to convert the Win32 support to use newer 52 * wide-character paths with '\\?\' prefix, which has a 32k PATH_MAX 53 * instead of the rather anemic 260 character limit of the older 54 * system calls. Then we can drop this mess (unless we want to 55 * continue to special-case Cygwin 1.5 and earlier). 56 */ 57 static int 58 compute_loop_max(void) 59 { 60 #if defined(_WIN32) && !defined(__CYGWIN__) 61 static int LOOP_MAX = 0; 62 char buf[MAX_PATH]; 63 size_t cwdlen; 64 65 if (LOOP_MAX == 0) { 66 assert(_getcwd(buf, MAX_PATH) != NULL); 67 cwdlen = strlen(buf); 68 /* 12 characters = length of 8.3 filename */ 69 /* 4 characters = length of "/../" used in symlink tests */ 70 /* 1 character = length of extra "/" separator */ 71 LOOP_MAX = MAX_PATH - (int)cwdlen - 12 - 4 - 1; 72 } 73 return LOOP_MAX; 74 #elif defined(__CYGWIN__) && !defined(HAVE_CYGWIN_CONV_PATH) 75 static int LOOP_MAX = 0; 76 if (LOOP_MAX == 0) { 77 char wbuf[PATH_MAX]; 78 char pbuf[PATH_MAX]; 79 size_t wcwdlen; 80 size_t pcwdlen; 81 size_t cwdlen; 82 assert(getcwd(pbuf, PATH_MAX) != NULL); 83 pcwdlen = strlen(pbuf); 84 cygwin_conv_to_full_win32_path(pbuf, wbuf); 85 wcwdlen = strlen(wbuf); 86 cwdlen = ((wcwdlen > pcwdlen) ? wcwdlen : pcwdlen); 87 /* Cygwin helper needs an extra few characters. */ 88 LOOP_MAX = PATH_MAX - (int)cwdlen - 12 - 4 - 4; 89 } 90 return LOOP_MAX; 91 #else 92 /* cygwin-1.7 ends up here, along with "normal" unix */ 93 return 200; /* restore pre-r278 depth */ 94 #endif 95 } 96 97 /* filenames[i] is a distinctive filename of length i. */ 98 /* To simplify interpreting failures, each filename ends with a 99 * decimal integer which is the length of the filename. E.g., A 100 * filename ending in "_92" is 92 characters long. To detect errors 101 * which drop or misplace characters, the filenames use a repeating 102 * "abcdefghijklmnopqrstuvwxyz..." pattern. */ 103 static char *filenames[201]; 104 105 static void 106 compute_filenames(void) 107 { 108 char buff[250]; 109 size_t i,j; 110 111 filenames[0] = strdup(""); 112 filenames[1] = strdup("1"); 113 filenames[2] = strdup("a2"); 114 for (i = 3; i < sizeof(filenames)/sizeof(filenames[0]); ++i) { 115 /* Fill with "abcdefghij..." */ 116 for (j = 0; j < i; ++j) 117 buff[j] = 'a' + (j % 26); 118 buff[j--] = '\0'; 119 /* Work from the end to fill in the number portion. */ 120 buff[j--] = '0' + (i % 10); 121 if (i > 9) { 122 buff[j--] = '0' + ((i / 10) % 10); 123 if (i > 99) 124 buff[j--] = '0' + (char)(i / 100); 125 } 126 buff[j] = '_'; 127 /* Guard against obvious screwups in the above code. */ 128 assertEqualInt(strlen(buff), i); 129 filenames[i] = strdup(buff); 130 } 131 } 132 133 static void 134 create_tree(void) 135 { 136 char buff[260]; 137 char buff2[260]; 138 int i; 139 int LOOP_MAX; 140 141 compute_filenames(); 142 143 /* Log that we'll be omitting some checks. */ 144 if (!canSymlink()) { 145 skipping("Symlink checks"); 146 } 147 148 assertMakeDir("original", 0775); 149 assertEqualInt(0, chdir("original")); 150 LOOP_MAX = compute_loop_max(); 151 152 assertMakeDir("f", 0775); 153 assertMakeDir("l", 0775); 154 assertMakeDir("m", 0775); 155 assertMakeDir("s", 0775); 156 assertMakeDir("d", 0775); 157 158 for (i = 1; i < LOOP_MAX; i++) { 159 failure("Internal sanity check failed: i = %d", i); 160 assert(filenames[i] != NULL); 161 162 snprintf(buff, sizeof(buff), "f/%s", filenames[i]); 163 assertMakeFile(buff, 0777, buff); 164 165 /* Create a link named "l/abcdef..." to the above. */ 166 snprintf(buff2, sizeof(buff2), "l/%s", filenames[i]); 167 assertMakeHardlink(buff2, buff); 168 169 /* Create a link named "m/abcdef..." to the above. */ 170 snprintf(buff2, sizeof(buff2), "m/%s", filenames[i]); 171 assertMakeHardlink(buff2, buff); 172 173 if (canSymlink()) { 174 /* Create a symlink named "s/abcdef..." to the above. */ 175 snprintf(buff, sizeof(buff), "s/%s", filenames[i]); 176 snprintf(buff2, sizeof(buff2), "../f/%s", filenames[i]); 177 failure("buff=\"%s\" buff2=\"%s\"", buff, buff2); 178 assertMakeSymlink(buff, buff2, 0); 179 } 180 /* Create a dir named "d/abcdef...". */ 181 buff[0] = 'd'; 182 failure("buff=\"%s\"", buff); 183 assertMakeDir(buff, 0775); 184 } 185 186 assertEqualInt(0, chdir("..")); 187 } 188 189 #define LIMIT_NONE 200 190 #define LIMIT_USTAR 100 191 192 static void 193 verify_tree(size_t limit) 194 { 195 char name1[260]; 196 char name2[260]; 197 size_t i, LOOP_MAX; 198 199 LOOP_MAX = compute_loop_max(); 200 201 /* Generate the names we know should be there and verify them. */ 202 for (i = 1; i < LOOP_MAX; i++) { 203 /* Verify a file named "f/abcdef..." */ 204 snprintf(name1, sizeof(name1), "f/%s", filenames[i]); 205 if (i <= limit) { 206 assertFileExists(name1); 207 assertFileContents(name1, (int)strlen(name1), name1); 208 } 209 210 snprintf(name2, sizeof(name2), "l/%s", filenames[i]); 211 if (i + 2 <= limit) { 212 /* Verify hardlink "l/abcdef..." */ 213 assertIsHardlink(name1, name2); 214 /* Verify hardlink "m/abcdef..." */ 215 name2[0] = 'm'; 216 assertIsHardlink(name1, name2); 217 } 218 219 if (canSymlink()) { 220 /* Verify symlink "s/abcdef..." */ 221 snprintf(name1, sizeof(name1), "s/%s", filenames[i]); 222 snprintf(name2, sizeof(name2), "../f/%s", filenames[i]); 223 if (strlen(name2) <= limit) 224 assertIsSymlink(name1, name2, 0); 225 } 226 227 /* Verify dir "d/abcdef...". */ 228 snprintf(name1, sizeof(name1), "d/%s", filenames[i]); 229 if (i + 1 <= limit) { /* +1 for trailing slash */ 230 if (assertIsDir(name1, -1)) { 231 /* TODO: opendir/readdir this 232 * directory and make sure 233 * it's empty. 234 */ 235 } 236 } 237 } 238 239 #if !defined(_WIN32) || defined(__CYGWIN__) 240 { 241 const char *dp; 242 /* Now make sure nothing is there that shouldn't be. */ 243 for (dp = "dflms"; *dp != '\0'; ++dp) { 244 DIR *d; 245 struct dirent *de; 246 char dir[2]; 247 dir[0] = *dp; dir[1] = '\0'; 248 d = opendir(dir); 249 failure("Unable to open dir '%s'", dir); 250 if (!assert(d != NULL)) 251 continue; 252 while ((de = readdir(d)) != NULL) { 253 char *p = de->d_name; 254 if (p[0] == '.') 255 continue; 256 switch(dp[0]) { 257 case 'l': case 'm': case 'd': 258 failure("strlen(p)=%zu", strlen(p)); 259 assert(strlen(p) < limit); 260 assertEqualString(p, 261 filenames[strlen(p)]); 262 break; 263 case 'f': case 's': 264 failure("strlen(p)=%zu", strlen(p)); 265 assert(strlen(p) < limit + 1); 266 assertEqualString(p, 267 filenames[strlen(p)]); 268 break; 269 default: 270 failure("File %s shouldn't be here", p); 271 assert(0); 272 } 273 } 274 closedir(d); 275 } 276 } 277 #endif 278 } 279 280 static void 281 copy_basic(void) 282 { 283 int r; 284 285 /* NOTE: for proper operation on cygwin-1.5 and windows, the 286 * length of the name of the directory below, "plain", must be 287 * less than or equal to the length of the name of the original 288 * directory, "original" This restriction derives from the 289 * extremely limited pathname lengths on those platforms. 290 */ 291 assertMakeDir("plain", 0775); 292 assertEqualInt(0, chdir("plain")); 293 294 /* 295 * Use the tar program to create an archive. 296 */ 297 r = systemf("%s cf archive -C ../original f d l m s >pack.out 2>pack.err", 298 testprog); 299 failure("Error invoking \"%s cf\"", testprog); 300 assertEqualInt(r, 0); 301 302 /* Verify that nothing went to stdout or stderr. */ 303 assertEmptyFile("pack.err"); 304 assertEmptyFile("pack.out"); 305 306 /* 307 * Use tar to unpack the archive into another directory. 308 */ 309 r = systemf("%s xf archive >unpack.out 2>unpack.err", testprog); 310 failure("Error invoking %s xf archive", testprog); 311 assertEqualInt(r, 0); 312 313 /* Verify that nothing went to stdout or stderr. */ 314 assertEmptyFile("unpack.err"); 315 assertEmptyFile("unpack.out"); 316 317 verify_tree(LIMIT_NONE); 318 assertEqualInt(0, chdir("..")); 319 } 320 321 static void 322 copy_ustar(void) 323 { 324 const char *target = "ustar"; 325 int r; 326 327 /* NOTE: for proper operation on cygwin-1.5 and windows, the 328 * length of the name of the directory below, "ustar", must be 329 * less than or equal to the length of the name of the original 330 * directory, "original" This restriction derives from the 331 * extremely limited pathname lengths on those platforms. 332 */ 333 assertMakeDir(target, 0775); 334 assertEqualInt(0, chdir(target)); 335 336 /* 337 * Use the tar program to create an archive. 338 */ 339 r = systemf("%s cf archive --format=ustar -C ../original f d l m s >pack.out 2>pack.err", 340 testprog); 341 failure("Error invoking \"%s cf archive --format=ustar\"", testprog); 342 assertEqualInt(r, 0); 343 344 /* Verify that nothing went to stdout. */ 345 assertEmptyFile("pack.out"); 346 /* Stderr is non-empty, since there are a bunch of files 347 * with filenames too long to archive. */ 348 349 /* 350 * Use tar to unpack the archive into another directory. 351 */ 352 r = systemf("%s xf archive >unpack.out 2>unpack.err", testprog); 353 failure("Error invoking %s xf archive", testprog); 354 assertEqualInt(r, 0); 355 356 /* Verify that nothing went to stdout or stderr. */ 357 assertEmptyFile("unpack.err"); 358 assertEmptyFile("unpack.out"); 359 360 verify_tree(LIMIT_USTAR); 361 assertEqualInt(0, chdir("../..")); 362 } 363 364 DEFINE_TEST(test_copy) 365 { 366 assertUmask(0); 367 create_tree(); /* Create sample files in "original" dir. */ 368 369 /* Test simple "tar -c | tar -x" pipeline copy. */ 370 copy_basic(); 371 372 /* Same, but constrain to ustar format. */ 373 copy_ustar(); 374 } 375