Fossil SCM
Start of experimental changes to support directory symlinks.
Commit
d6debf638c055e35b06e692709e1b2783977b0d5
Parent
3bb04c90dc7209e…
1 file changed
+23
-11
+23
-11
| --- src/file.c | ||
| +++ src/file.c | ||
| @@ -293,24 +293,36 @@ | ||
| 293 | 293 | } |
| 294 | 294 | return rc ? 0 : (S_ISDIR(fileStat.st_mode) ? 1 : 2); |
| 295 | 295 | } |
| 296 | 296 | |
| 297 | 297 | /* |
| 298 | -** Same as file_isdir(), but takes into account symlinks. | |
| 298 | +** Same as file_isdir(), but takes into account symlinks. Return 1 if | |
| 299 | +** zFilename is a directory -OR- a symlink that points to a directory. | |
| 300 | +** Return 0 if zFilename does not exist. Return 2 if zFilename exists | |
| 301 | +** but is something other than a directory. | |
| 299 | 302 | */ |
| 300 | 303 | int file_wd_isdir(const char *zFilename){ |
| 301 | 304 | int rc; |
| 305 | + char *zFN; | |
| 302 | 306 | |
| 303 | - if( zFilename ){ | |
| 304 | - char *zFN = mprintf("%s", zFilename); | |
| 305 | - file_simplify_name(zFN, -1, 0); | |
| 306 | - rc = getStat(zFN, 1); | |
| 307 | - free(zFN); | |
| 307 | + zFN = mprintf("%s", zFilename); | |
| 308 | + file_simplify_name(zFN, -1, 0); | |
| 309 | + rc = getStat(zFN, 1); | |
| 310 | + if( rc ){ | |
| 311 | + rc = 0; /* It does not exist at all. */ | |
| 312 | + }else if( S_ISDIR(fileStat.st_mode) ){ | |
| 313 | + rc = 1; /* It exists and is a real directory. */ | |
| 314 | + }else if( S_ISLNK(fileStat.st_mode) ){ | |
| 315 | + Blob content; | |
| 316 | + blob_read_link(&content, zFN); /* It exists and is a link. */ | |
| 317 | + rc = file_wd_isdir(blob_str(&content)); /* Points to directory? */ | |
| 318 | + blob_reset(&content); | |
| 308 | 319 | }else{ |
| 309 | - rc = getStat(0, 1); | |
| 320 | + rc = 2; /* It exists and is something else. */ | |
| 310 | 321 | } |
| 311 | - return rc ? 0 : (S_ISDIR(fileStat.st_mode) ? 1 : 2); | |
| 322 | + free(zFN); | |
| 323 | + return rc; | |
| 312 | 324 | } |
| 313 | 325 | |
| 314 | 326 | |
| 315 | 327 | /* |
| 316 | 328 | ** Wrapper around the access() system call. |
| @@ -471,16 +483,16 @@ | ||
| 471 | 483 | #if !defined(_WIN32) |
| 472 | 484 | struct stat buf; |
| 473 | 485 | if( fossil_stat(zFilename, &buf, 1)!=0 || S_ISLNK(buf.st_mode) ) return 0; |
| 474 | 486 | if( onoff ){ |
| 475 | 487 | int targetMode = (buf.st_mode & 0444)>>2; |
| 476 | - if( (buf.st_mode & 0100) == 0 ){ | |
| 488 | + if( (buf.st_mode & 0100)==0 ){ | |
| 477 | 489 | chmod(zFilename, buf.st_mode | targetMode); |
| 478 | 490 | rc = 1; |
| 479 | 491 | } |
| 480 | 492 | }else{ |
| 481 | - if( (buf.st_mode & 0100) != 0 ){ | |
| 493 | + if( (buf.st_mode & 0100)!=0 ){ | |
| 482 | 494 | chmod(zFilename, buf.st_mode & ~0111); |
| 483 | 495 | rc = 1; |
| 484 | 496 | } |
| 485 | 497 | } |
| 486 | 498 | #endif /* _WIN32 */ |
| @@ -600,11 +612,11 @@ | ||
| 600 | 612 | ** The if stops us from trying to create a directory of a drive letter |
| 601 | 613 | ** C: in this example. |
| 602 | 614 | */ |
| 603 | 615 | if( !(i==2 && zName[1]==':') ){ |
| 604 | 616 | #endif |
| 605 | - if( file_mkdir(zName, forceFlag) && file_isdir(zName)!=1 ){ | |
| 617 | + if( file_mkdir(zName, forceFlag) && file_wd_isdir(zName)!=1 ){ | |
| 606 | 618 | if (errorReturn <= 0) { |
| 607 | 619 | fossil_fatal_recursive("unable to create directory %s", zName); |
| 608 | 620 | } |
| 609 | 621 | rc = errorReturn; |
| 610 | 622 | break; |
| 611 | 623 |
| --- src/file.c | |
| +++ src/file.c | |
| @@ -293,24 +293,36 @@ | |
| 293 | } |
| 294 | return rc ? 0 : (S_ISDIR(fileStat.st_mode) ? 1 : 2); |
| 295 | } |
| 296 | |
| 297 | /* |
| 298 | ** Same as file_isdir(), but takes into account symlinks. |
| 299 | */ |
| 300 | int file_wd_isdir(const char *zFilename){ |
| 301 | int rc; |
| 302 | |
| 303 | if( zFilename ){ |
| 304 | char *zFN = mprintf("%s", zFilename); |
| 305 | file_simplify_name(zFN, -1, 0); |
| 306 | rc = getStat(zFN, 1); |
| 307 | free(zFN); |
| 308 | }else{ |
| 309 | rc = getStat(0, 1); |
| 310 | } |
| 311 | return rc ? 0 : (S_ISDIR(fileStat.st_mode) ? 1 : 2); |
| 312 | } |
| 313 | |
| 314 | |
| 315 | /* |
| 316 | ** Wrapper around the access() system call. |
| @@ -471,16 +483,16 @@ | |
| 471 | #if !defined(_WIN32) |
| 472 | struct stat buf; |
| 473 | if( fossil_stat(zFilename, &buf, 1)!=0 || S_ISLNK(buf.st_mode) ) return 0; |
| 474 | if( onoff ){ |
| 475 | int targetMode = (buf.st_mode & 0444)>>2; |
| 476 | if( (buf.st_mode & 0100) == 0 ){ |
| 477 | chmod(zFilename, buf.st_mode | targetMode); |
| 478 | rc = 1; |
| 479 | } |
| 480 | }else{ |
| 481 | if( (buf.st_mode & 0100) != 0 ){ |
| 482 | chmod(zFilename, buf.st_mode & ~0111); |
| 483 | rc = 1; |
| 484 | } |
| 485 | } |
| 486 | #endif /* _WIN32 */ |
| @@ -600,11 +612,11 @@ | |
| 600 | ** The if stops us from trying to create a directory of a drive letter |
| 601 | ** C: in this example. |
| 602 | */ |
| 603 | if( !(i==2 && zName[1]==':') ){ |
| 604 | #endif |
| 605 | if( file_mkdir(zName, forceFlag) && file_isdir(zName)!=1 ){ |
| 606 | if (errorReturn <= 0) { |
| 607 | fossil_fatal_recursive("unable to create directory %s", zName); |
| 608 | } |
| 609 | rc = errorReturn; |
| 610 | break; |
| 611 |
| --- src/file.c | |
| +++ src/file.c | |
| @@ -293,24 +293,36 @@ | |
| 293 | } |
| 294 | return rc ? 0 : (S_ISDIR(fileStat.st_mode) ? 1 : 2); |
| 295 | } |
| 296 | |
| 297 | /* |
| 298 | ** Same as file_isdir(), but takes into account symlinks. Return 1 if |
| 299 | ** zFilename is a directory -OR- a symlink that points to a directory. |
| 300 | ** Return 0 if zFilename does not exist. Return 2 if zFilename exists |
| 301 | ** but is something other than a directory. |
| 302 | */ |
| 303 | int file_wd_isdir(const char *zFilename){ |
| 304 | int rc; |
| 305 | char *zFN; |
| 306 | |
| 307 | zFN = mprintf("%s", zFilename); |
| 308 | file_simplify_name(zFN, -1, 0); |
| 309 | rc = getStat(zFN, 1); |
| 310 | if( rc ){ |
| 311 | rc = 0; /* It does not exist at all. */ |
| 312 | }else if( S_ISDIR(fileStat.st_mode) ){ |
| 313 | rc = 1; /* It exists and is a real directory. */ |
| 314 | }else if( S_ISLNK(fileStat.st_mode) ){ |
| 315 | Blob content; |
| 316 | blob_read_link(&content, zFN); /* It exists and is a link. */ |
| 317 | rc = file_wd_isdir(blob_str(&content)); /* Points to directory? */ |
| 318 | blob_reset(&content); |
| 319 | }else{ |
| 320 | rc = 2; /* It exists and is something else. */ |
| 321 | } |
| 322 | free(zFN); |
| 323 | return rc; |
| 324 | } |
| 325 | |
| 326 | |
| 327 | /* |
| 328 | ** Wrapper around the access() system call. |
| @@ -471,16 +483,16 @@ | |
| 483 | #if !defined(_WIN32) |
| 484 | struct stat buf; |
| 485 | if( fossil_stat(zFilename, &buf, 1)!=0 || S_ISLNK(buf.st_mode) ) return 0; |
| 486 | if( onoff ){ |
| 487 | int targetMode = (buf.st_mode & 0444)>>2; |
| 488 | if( (buf.st_mode & 0100)==0 ){ |
| 489 | chmod(zFilename, buf.st_mode | targetMode); |
| 490 | rc = 1; |
| 491 | } |
| 492 | }else{ |
| 493 | if( (buf.st_mode & 0100)!=0 ){ |
| 494 | chmod(zFilename, buf.st_mode & ~0111); |
| 495 | rc = 1; |
| 496 | } |
| 497 | } |
| 498 | #endif /* _WIN32 */ |
| @@ -600,11 +612,11 @@ | |
| 612 | ** The if stops us from trying to create a directory of a drive letter |
| 613 | ** C: in this example. |
| 614 | */ |
| 615 | if( !(i==2 && zName[1]==':') ){ |
| 616 | #endif |
| 617 | if( file_mkdir(zName, forceFlag) && file_wd_isdir(zName)!=1 ){ |
| 618 | if (errorReturn <= 0) { |
| 619 | fossil_fatal_recursive("unable to create directory %s", zName); |
| 620 | } |
| 621 | rc = errorReturn; |
| 622 | break; |
| 623 |