Index: src/add.c ================================================================== --- src/add.c +++ src/add.c @@ -108,11 +108,11 @@ }else{ char *zFullname = mprintf("%s%s", g.zLocalRoot, zPath); db_multi_exec( "INSERT INTO vfile(vid,deleted,rid,mrid,pathname,isexe,islink)" "VALUES(%d,0,0,0,%Q,%d,%d)", - vid, zPath, file_isexe(zFullname), file_islink(zFullname)); + vid, zPath, file_wd_isexe(zFullname), file_wd_islink(zFullname)); fossil_free(zFullname); } if( db_changes() ){ fossil_print("ADDED %s\n", zPath); return 1; @@ -426,11 +426,11 @@ const char * zFile; const char * zPath; zFile = db_column_text(&q, 0); zPath = db_column_text(&q, 1); - if( !file_isfile_or_link(zPath) ){ + if( !file_wd_isfile_or_link(zPath) ){ if( !isTest ){ db_multi_exec("UPDATE vfile SET deleted=1 WHERE pathname=%Q", zFile); } fossil_print("DELETED %s\n", zFile); nDelete++; Index: src/blob.c ================================================================== --- src/blob.c +++ src/blob.c @@ -681,11 +681,11 @@ FILE *in; if( zFilename==0 || zFilename[0]==0 || (zFilename[0]=='-' && zFilename[1]==0) ){ return blob_read_from_channel(pBlob, stdin, -1); } - size = file_size(zFilename); + size = file_wd_size(zFilename); blob_zero(pBlob); if( size<0 ){ fossil_fatal("no such file: %s", zFilename); } if( size==0 ){ Index: src/checkin.c ================================================================== --- src/checkin.c +++ src/checkin.c @@ -64,11 +64,11 @@ } } blob_append(report, zPrefix, nPrefix); if( isDeleted ){ blob_appendf(report, "DELETED %s\n", zDisplayName); - }else if( !file_isfile_or_link(zFullName) ){ + }else if( !file_wd_isfile_or_link(zFullName) ){ if( file_access(zFullName, 0)==0 ){ blob_appendf(report, "NOT_A_FILE %s\n", zDisplayName); if( missingIsFatal ){ fossil_warning("not a file: %s", zDisplayName); nErr++; @@ -227,11 +227,11 @@ fossil_print("%s\n", zPathname); }else if( isNew ){ fossil_print("ADDED %s\n", zPathname); }else if( isDeleted ){ fossil_print("DELETED %s\n", zPathname); - }else if( !file_isfile_or_link(zFullName) ){ + }else if( !file_wd_isfile_or_link(zFullName) ){ if( file_access(zFullName, 0)==0 ){ fossil_print("NOT_A_FILE %s\n", zPathname); }else{ fossil_print("MISSING %s\n", zPathname); } @@ -661,16 +661,16 @@ ** the filesystem. On windows, the "executable" bit is retained ** unchanged from the original. */ blob_resize(&filename, nBasename); blob_append(&filename, zName, -1); - isexe = file_isexe(blob_str(&filename)); + isexe = file_wd_isexe(blob_str(&filename)); /* For unix, check if the file on the filesystem is symlink. ** On windows, the bit is retained unchanged from original. */ - isLink = file_islink(blob_str(&filename)); + isLink = file_wd_islink(blob_str(&filename)); #endif if( isexe ){ zPerm = " x"; }else if( isLink ){ zPerm = " l"; /* note: symlinks don't have executable bit on unix */ @@ -1071,11 +1071,11 @@ zFullname = db_column_text(&q, 1); rid = db_column_int(&q, 2); crnlOk = db_column_int(&q, 3); blob_zero(&content); - if( file_islink(zFullname) ){ + if( file_wd_islink(zFullname) ){ /* Instead of file content, put link destination path */ blob_read_link(&content, zFullname); }else{ blob_read_from_file(&content, zFullname); } Index: src/checkout.c ================================================================== --- src/checkout.c +++ src/checkout.c @@ -113,11 +113,11 @@ manifest_file_rewind(pManifest); while( (pFile = manifest_file_next(pManifest, 0))!=0 ){ int isExe; blob_append(&filename, pFile->zName, -1); isExe = pFile->zPerm && strstr(pFile->zPerm, "x"); - file_setexe(blob_str(&filename), isExe); + file_wd_setexe(blob_str(&filename), isExe); set_or_clear_isexe(pFile->zName, vid, isExe); blob_resize(&filename, baseLen); } blob_reset(&filename); manifest_destroy(pManifest); Index: src/diffcmd.c ================================================================== --- src/diffcmd.c +++ src/diffcmd.c @@ -71,14 +71,14 @@ Blob file2; /* Content of zFile2 */ const char *zName2; /* Name of zFile2 for display */ /* Read content of zFile2 into memory */ blob_zero(&file2); - if( file_size(zFile2)<0 ){ + if( file_wd_size(zFile2)<0 ){ zName2 = "/dev/null"; }else{ - if( file_islink(zFile2) ){ + if( file_wd_islink(zFile2) ){ blob_read_link(&file2, zFile2); }else{ blob_read_from_file(&file2, zFile2); } zName2 = zName; @@ -193,11 +193,11 @@ Blob fname; Blob content; int isLink; file_tree_name(zFileTreeName, &fname, 1); historical_version_of_file(zFrom, blob_str(&fname), &content, &isLink, 0, 0); - if( !isLink != !file_islink(zFrom) ){ + if( !isLink != !file_wd_islink(zFrom) ){ diff_printf("cannot compute difference between symlink and regular file\n"); }else{ diff_file(&content, zFileTreeName, zFileTreeName, zDiffCmd, ignoreEolWs); } blob_reset(&content); @@ -288,11 +288,11 @@ srcid = 0; if( !asNewFile ){ showDiff = 0; } } if( showDiff ){ Blob content; - if( !isLink != !file_islink(zFullName) ){ + if( !isLink != !file_wd_islink(zFullName) ){ diff_print_index(zPathname); diff_printf("--- %s\n+++ %s\n", zPathname, zPathname); diff_printf("cannot compute difference between symlink and regular file\n"); continue; } Index: src/file.c ================================================================== --- src/file.c +++ src/file.c @@ -13,11 +13,16 @@ ** drh@hwaci.com ** http://www.hwaci.com/drh/ ** ******************************************************************************* ** -** File utilities +** File utilities. +** +** Functions named file_* are generic functions that always follow symlinks. +** +** Functions named file_wd_* are to be used for files inside working +** directories. They follow symlinks depending on 'allow-symlinks' setting. */ #include "config.h" #include #include #include @@ -32,98 +37,126 @@ ** larger than 2GB. */ #if defined(_WIN32) && defined(__MSVCRT__) # define stat _stati64 #endif +/* +** On Windows S_ISLNK always returns FALSE. +*/ +#if defined(_WIN32) +# define S_ISLNK(x) (0) +#endif static int fileStatValid = 0; static struct stat fileStat; -static int fossil_stat(const char *zFilename, struct stat *buf){ +/* +** Fill stat buf with information received from stat() or lstat(). +** lstat() is called on Unix if isWd is TRUE and allow-symlinks setting is on. +** +*/ +static int fossil_stat(const char *zFilename, struct stat *buf, int isWd){ #if !defined(_WIN32) - if( g.allowSymlinks ){ + if( isWd && g.allowSymlinks ){ return lstat(zFilename, buf); }else{ return stat(zFilename, buf); } #else - return stat(zFilename, buf); + int rc = 0; + char *zMbcs = fossil_utf8_to_mbcs(zFilename); + rc = stat(zMbcs, buf); + fossil_mbcs_free(zMbcs); + return rc; #endif } /* ** Fill in the fileStat variable for the file named zFilename. ** If zFilename==0, then use the previous value of fileStat if ** there is a previous value. ** +** If isWd is TRUE, do lstat() instead of stat() if allow-symlinks is on. +** ** Return the number of errors. No error messages are generated. */ -static int getStat(const char *zFilename){ +static int getStat(const char *zFilename, int isWd){ int rc = 0; if( zFilename==0 ){ if( fileStatValid==0 ) rc = 1; }else{ - char *zMbcs = fossil_utf8_to_mbcs(zFilename); - if( fossil_stat(zMbcs, &fileStat)!=0 ){ + if( fossil_stat(zFilename, &fileStat, isWd)!=0 ){ fileStatValid = 0; rc = 1; }else{ fileStatValid = 1; rc = 0; } - fossil_mbcs_free(zMbcs); } return rc; } - /* ** Return the size of a file in bytes. Return -1 if the file does not ** exist. If zFilename is NULL, return the size of the most recently ** stat-ed file. */ i64 file_size(const char *zFilename){ - return getStat(zFilename) ? -1 : fileStat.st_size; + return getStat(zFilename, 0) ? -1 : fileStat.st_size; +} + +/* +** Same as file_size(), but takes into account symlinks. +*/ +i64 file_wd_size(const char *zFilename){ + return getStat(zFilename, 1) ? -1 : fileStat.st_size; } /* ** Return the modification time for a file. Return -1 if the file ** does not exist. If zFilename is NULL return the size of the most ** recently stat-ed file. */ i64 file_mtime(const char *zFilename){ - return getStat(zFilename) ? -1 : fileStat.st_mtime; + return getStat(zFilename, 0) ? -1 : fileStat.st_mtime; +} + +/* +** Same as file_mtime(), but takes into account symlinks. +*/ +i64 file_wd_mtime(const char *zFilename){ + return getStat(zFilename, 1) ? -1 : fileStat.st_mtime; } /* ** Return TRUE if the named file is an ordinary file or symlink ** and symlinks are allowed. ** Return false for directories, devices, fifos, etc. */ -int file_isfile_or_link(const char *zFilename){ -#if !defined(_WIN32) - if ( g.allowSymlinks ){ - return getStat(zFilename) ? 0 : S_ISREG(fileStat.st_mode) || S_ISLNK(fileStat.st_mode); - } -#endif - return getStat(zFilename) ? 0 : S_ISREG(fileStat.st_mode); +int file_wd_isfile_or_link(const char *zFilename){ + return getStat(zFilename, 1) ? 0 : S_ISREG(fileStat.st_mode) || + S_ISLNK(fileStat.st_mode); } /* ** Return TRUE if the named file is an ordinary file. Return false ** for directories, devices, fifos, symlinks, etc. */ int file_isfile(const char *zFilename){ - return getStat(zFilename) ? 0 : S_ISREG(fileStat.st_mode); + return getStat(zFilename, 0) ? 0 : S_ISREG(fileStat.st_mode); +} + +int file_wd_isfile(const char *zFilename){ + return getStat(zFilename, 1) ? 0 : S_ISREG(fileStat.st_mode); } /* ** Create symlink to file on Unix, or plain-text file with ** symlink target if "allow-symlinks" is off or we're on Windows. ** ** Arguments: target file (symlink will point to it), link file **/ -void create_symlink(const char *zTargetFile, const char *zLinkFile){ +void symlink_create(const char *zTargetFile, const char *zLinkFile){ #if !defined(_WIN32) if( g.allowSymlinks ){ int i, nName; char *zName, zBuf[1000]; @@ -157,19 +190,29 @@ blob_set(&content, zTargetFile); blob_write_to_file(&content, zLinkFile); blob_reset(&content); } } + +/* +** Copy symbolic link from zFrom to zTo. +*/ +void symlink_copy(const char *zFrom, const char *zTo){ + Blob content; + blob_read_link(&content, zFrom); + symlink_create(blob_str(&content), zTo); + blob_reset(&content); +} /* ** Return file permissions (normal, executable, or symlink): ** - PERM_EXE if file is executable; ** - PERM_LNK on Unix if file is symlink and allow-symlinks option is on; ** - PERM_REG for all other cases (regular file, directory, fifo, etc). */ -int file_perm(const char *zFilename){ - if( getStat(zFilename) ) return PERM_REG; +int file_wd_perm(const char *zFilename){ + if( getStat(zFilename, 1) ) return PERM_REG; #if defined(_WIN32) # if defined(__DMC__) || defined(_MSC_VER) # define S_IXUSR _S_IEXEC # endif if( S_ISREG(fileStat.st_mode) && ((S_IXUSR)&fileStat.st_mode)!=0 ) @@ -189,22 +232,22 @@ /* ** Return TRUE if the named file is an executable. Return false ** for directories, devices, fifos, symlinks, etc. */ -int file_isexe(const char *zFilename){ - return file_perm(zFilename)==PERM_EXE; +int file_wd_isexe(const char *zFilename){ + return file_wd_perm(zFilename)==PERM_EXE; } /* ** Return TRUE if the named file is a symlink and symlinks are allowed. ** Return false for all other cases. ** ** On Windows, always return False. */ -int file_islink(const char *zFilename){ - return file_perm(zFilename)==PERM_LNK; +int file_wd_islink(const char *zFilename){ + return file_wd_perm(zFilename)==PERM_LNK; } /* ** Return 1 if zFilename is a directory. Return 0 if zFilename ** does not exist. Return 2 if zFilename exists but is something @@ -214,25 +257,35 @@ int rc; if( zFilename ){ char *zFN = mprintf("%s", zFilename); file_simplify_name(zFN, -1); - rc = getStat(zFN); + rc = getStat(zFN, 0); + free(zFN); + }else{ + rc = getStat(0, 0); + } + return rc ? 0 : (S_ISDIR(fileStat.st_mode) ? 1 : 2); +} + +/* +** Same as file_isdir(), but takes into account symlinks. +*/ +int file_wd_isdir(const char *zFilename){ + int rc; + + if( zFilename ){ + char *zFN = mprintf("%s", zFilename); + file_simplify_name(zFN, -1); + rc = getStat(zFN, 1); free(zFN); }else{ - rc = getStat(0); - } -#if !defined(_WIN32) - if( g.allowSymlinks ){ - return rc ? 0 : (S_ISDIR(fileStat.st_mode) && !S_ISLNK(fileStat.st_mode) ? 1 : 2); - }else{ - return rc ? 0 : (S_ISDIR(fileStat.st_mode) ? 1 : 2); - } -#else - return rc ? 0 : (S_ISDIR(fileStat.st_mode) ? 1 : 2); -#endif -} + rc = getStat(0, 1); + } + return rc ? 0 : (S_ISDIR(fileStat.st_mode) ? 1 : 2); +} + /* ** Wrapper around the access() system call. */ int file_access(const char *zFilename, int flags){ @@ -300,15 +353,15 @@ /* ** Set or clear the execute bit on a file. Return true if a change ** occurred and false if this routine is a no-op. */ -int file_setexe(const char *zFilename, int onoff){ +int file_wd_setexe(const char *zFilename, int onoff){ int rc = 0; #if !defined(_WIN32) struct stat buf; - if( fossil_stat(zFilename, &buf)!=0 || S_ISLNK(buf.st_mode) ) return 0; + if( fossil_stat(zFilename, &buf, 1)!=0 || S_ISLNK(buf.st_mode) ) return 0; if( onoff ){ int targetMode = (buf.st_mode & 0444)>>2; if( (buf.st_mode & 0111)!=targetMode ){ chmod(zFilename, buf.st_mode | targetMode); rc = 1; @@ -569,19 +622,19 @@ char zBuf[100]; const char *zName = g.argv[i]; file_canonical_name(zName, &x); fossil_print("[%s] -> [%s]\n", zName, blob_buffer(&x)); blob_reset(&x); - sqlite3_snprintf(sizeof(zBuf), zBuf, "%lld", file_size(zName)); + sqlite3_snprintf(sizeof(zBuf), zBuf, "%lld", file_wd_size(zName)); fossil_print(" file_size = %s\n", zBuf); - sqlite3_snprintf(sizeof(zBuf), zBuf, "%lld", file_mtime(zName)); + sqlite3_snprintf(sizeof(zBuf), zBuf, "%lld", file_wd_mtime(zName)); fossil_print(" file_mtime = %s\n", zBuf); - fossil_print(" file_isfile = %d\n", file_isfile(zName)); - fossil_print(" file_isfile_or_link = %d\n", file_isfile_or_link(zName)); - fossil_print(" file_islink = %d\n", file_islink(zName)); - fossil_print(" file_isexe = %d\n", file_isexe(zName)); - fossil_print(" file_isdir = %d\n", file_isdir(zName)); + fossil_print(" file_isfile = %d\n", file_wd_isfile(zName)); + fossil_print(" file_isfile_or_link = %d\n",file_wd_isfile_or_link(zName)); + fossil_print(" file_islink = %d\n", file_wd_islink(zName)); + fossil_print(" file_isexe = %d\n", file_wd_isexe(zName)); + fossil_print(" file_isdir = %d\n", file_wd_isdir(zName)); } } /* ** Return TRUE if the given filename is canonical. @@ -846,11 +899,11 @@ Blob onDisk; iSize = file_size(zName); if( iSize<0 ) return 0; if( iSize!=blob_size(pContent) ) return 0; - if( file_islink(zName) ){ + if( file_wd_islink(zName) ){ blob_read_link(&onDisk, zName); }else{ blob_read_from_file(&onDisk, zName); } rc = blob_compare(&onDisk, pContent); Index: src/merge.c ================================================================== --- src/merge.c +++ src/merge.c @@ -391,11 +391,11 @@ fossil_print("MERGE %s (pivot=%d v1=%d v2=%d)\n", zName, ridp, ridm, ridv); }else{ fossil_print("MERGE %s\n", zName); } - if( islinkv || islinkm /* || file_islink(zFullPath) */ ){ + if( islinkv || islinkm /* || file_wd_islink(zFullPath) */ ){ fossil_print("***** Cannot merge symlink %s\n", zName); nConflict++; }else{ undo_save(zName); zFullPath = mprintf("%s/%s", g.zLocalRoot, zName); @@ -408,11 +408,11 @@ rc = merge_3way(&p, zFullPath, &m, &r); } if( rc>=0 ){ if( !nochangeFlag ){ blob_write_to_file(&r, zFullPath); - file_setexe(zFullPath, isExe); + file_wd_setexe(zFullPath, isExe); } db_multi_exec("UPDATE vfile SET mtime=0 WHERE id=%d", idv); if( rc>0 ){ fossil_print("***** %d merge conflicts in %s\n", rc, zName); nConflict++; @@ -480,11 +480,15 @@ " WHERE id=%d AND vid=%d", zNewName, idv, vid ); if( !nochangeFlag ){ char *zFullOldPath = mprintf("%s%s", g.zLocalRoot, zOldName); char *zFullNewPath = mprintf("%s%s", g.zLocalRoot, zNewName); - file_copy(zFullOldPath, zFullNewPath); + if( file_wd_islink(zFullOldPath) ){ + symlink_copy(zFullOldPath, zFullNewPath); + }else{ + file_copy(zFullOldPath, zFullNewPath); + } file_delete(zFullOldPath); free(zFullNewPath); free(zFullOldPath); } } Index: src/merge3.c ================================================================== --- src/merge3.c +++ src/merge3.c @@ -422,11 +422,11 @@ azSubst[4] = "%merge"; azSubst[5] = zOther; azSubst[6] = "%output"; azSubst[7] = zOut; zCmd = string_subst(zGMerge, 8, azSubst); printf("%s\n", zCmd); fflush(stdout); fossil_system(zCmd); - if( file_size(zOut)>=0 ){ + if( file_wd_size(zOut)>=0 ){ blob_read_from_file(pOut, zOut); file_delete(zPivot); file_delete(zOrig); file_delete(zOther); file_delete(zOut); Index: src/sha1.c ================================================================== --- src/sha1.c +++ src/sha1.c @@ -281,11 +281,11 @@ FILE *in; SHA1Context ctx; unsigned char zResult[20]; char zBuf[10240]; - if( file_islink(zFilename) ){ + if( file_wd_islink(zFilename) ){ /* Instead of file content, return sha1 of link destination path */ Blob destinationPath; int rc; blob_read_link(&destinationPath, zFilename); Index: src/stash.c ================================================================== --- src/stash.c +++ src/stash.c @@ -89,11 +89,11 @@ int rid = db_column_int(&q, 3); const char *zName = db_column_text(&q, 4); const char *zOrig = db_column_text(&q, 5); char *zPath = mprintf("%s%s", g.zLocalRoot, zName); Blob content; - int isNewLink = file_islink(zPath); + int isNewLink = file_wd_islink(zPath); db_bind_int(&ins, ":rid", rid); db_bind_int(&ins, ":isadd", rid==0); db_bind_int(&ins, ":isrm", deleted); db_bind_int(&ins, ":isexe", db_column_int(&q, 1)); @@ -200,18 +200,18 @@ undo_save(zNew); blob_zero(&delta); if( rid==0 ){ db_ephemeral_blob(&q, 6, &delta); blob_write_to_file(&delta, zNPath); - file_setexe(zNPath, isExec); + file_wd_setexe(zNPath, isExec); fossil_print("ADD %s\n", zNew); }else if( isRemoved ){ fossil_print("DELETE %s\n", zOrig); file_delete(zOPath); }else{ Blob a, b, out, disk; - int isNewLink = file_islink(zOPath); + int isNewLink = file_wd_islink(zOPath); db_ephemeral_blob(&q, 6, &delta); if( isNewLink ){ blob_read_link(&disk, zOPath); }else{ blob_read_from_file(&disk, zOPath); @@ -221,15 +221,15 @@ if( blob_compare(&disk, &a)==0 && isLink == isNewLink ){ if( isLink || isNewLink ){ file_delete(zNPath); } if( isLink ){ - create_symlink(blob_str(&b), zNPath); + symlink_create(blob_str(&b), zNPath); }else{ blob_write_to_file(&b, zNPath); } - file_setexe(zNPath, isExec); + file_wd_setexe(zNPath, isExec); fossil_print("UPDATE %s\n", zNew); }else{ int rc; if( isLink || isNewLink ){ rc = -1; @@ -237,11 +237,11 @@ fossil_print("***** Cannot merge symlink %s\n", zNew); }else{ rc = merge_3way(&a, zOPath, &b, &out); blob_write_to_file(&out, zNPath); blob_reset(&out); - file_setexe(zNPath, isExec); + file_wd_setexe(zNPath, isExec); } if( rc ){ fossil_print("CONFLICT %s\n", zNew); nConflict++; }else{ @@ -290,20 +290,20 @@ fossil_print("ADDED %s\n", zNew); diff_print_index(zNew); diff_file_mem(&empty, &delta, zNew, zDiffCmd, 0); }else if( isRemoved ){ fossil_print("DELETE %s\n", zOrig); - if( file_islink(zOPath) ){ + if( file_wd_islink(zOPath) ){ blob_read_link(&delta, zOPath); }else{ blob_read_from_file(&delta, zOPath); } diff_print_index(zNew); diff_file_mem(&delta, &empty, zOrig, zDiffCmd, 0); }else{ Blob a, b, disk; - int isOrigLink = file_islink(zOPath); + int isOrigLink = file_wd_islink(zOPath); db_ephemeral_blob(&q, 6, &delta); if( isOrigLink ){ blob_read_link(&disk, zOPath); }else{ blob_read_from_file(&disk, zOPath); Index: src/tar.c ================================================================== --- src/tar.c +++ src/tar.c @@ -416,11 +416,11 @@ /* ** COMMAND: test-tarball ** -** Generate a GZIP-compresssed tarball in the file given by the first argument +** Generate a GZIP-compressed tarball in the file given by the first argument ** that contains files given in the second and subsequent arguments. */ void test_tarball_cmd(void){ int i; Blob zip; @@ -432,11 +432,11 @@ tar_begin(); for(i=3; i=0; + new_link = file_wd_islink(zFullname); + new_exists = file_wd_size(zFullname)>=0; if( new_exists ){ if( new_link ){ blob_read_link(¤t, zFullname); }else{ blob_read_from_file(¤t, zFullname); } - new_exe = file_isexe(zFullname); + new_exe = file_wd_isexe(zFullname); }else{ blob_zero(¤t); new_exe = 0; } blob_zero(&new); @@ -74,15 +74,15 @@ } if( new_exists && (new_link || old_link) ){ file_delete(zFullname); } if( old_link ){ - create_symlink(blob_str(&new), zFullname); + symlink_create(blob_str(&new), zFullname); }else{ blob_write_to_file(&new, zFullname); } - file_setexe(zFullname, old_exe); + file_wd_setexe(zFullname, old_exe); }else{ fossil_print("DELETE %s\n", zPathname); file_delete(zFullname); } blob_reset(&new); @@ -270,17 +270,17 @@ int isLink; Stmt q; if( !undoActive ) return; zFullname = mprintf("%s%s", g.zLocalRoot, zPathname); - existsFlag = file_size(zFullname)>=0; - isLink = file_islink(zFullname); + existsFlag = file_wd_size(zFullname)>=0; + isLink = file_wd_islink(zFullname); db_prepare(&q, "INSERT OR IGNORE INTO" " undo(pathname,redoflag,existsflag,isExe,isLink,content)" " VALUES(%Q,0,%d,%d,%d,:c)", - zPathname, existsFlag, file_isexe(zFullname), isLink + zPathname, existsFlag, file_wd_isexe(zFullname), isLink ); if( existsFlag ){ if( isLink ){ blob_read_link(&content, zFullname); }else{ Index: src/update.c ================================================================== --- src/update.c +++ src/update.c @@ -367,11 +367,11 @@ }else if( idt>0 && idv>0 && ridt!=ridv && chnged==0 ){ /* The file is unedited. Change it to the target version */ undo_save(zName); fossil_print("UPDATE %s\n", zName); if( !nochangeFlag ) vfile_to_disk(0, idt, 0, 0); - }else if( idt>0 && idv>0 && file_size(zFullPath)<0 ){ + }else if( idt>0 && idv>0 && file_wd_size(zFullPath)<0 ){ /* The file missing from the local check-out. Restore it to the ** version that appears in the target. */ fossil_print("UPDATE %s\n", zName); undo_save(zName); if( !nochangeFlag ) vfile_to_disk(0, idt, 0, 0); @@ -398,11 +398,11 @@ if( nameChng ){ fossil_print("MERGE %s -> %s\n", zName, zNewName); }else{ fossil_print("MERGE %s\n", zName); } - if( islinkv || islinkt /* || file_islink(zFullPath) */ ){ + if( islinkv || islinkt /* || file_wd_islink(zFullPath) */ ){ fossil_print("***** Cannot merge symlink %s\n", zNewName); nConflict++; }else{ undo_save(zName); content_get(ridt, &t); @@ -409,20 +409,20 @@ content_get(ridv, &v); rc = merge_3way(&v, zFullPath, &t, &r); if( rc>=0 ){ if( !nochangeFlag ){ blob_write_to_file(&r, zFullNewPath); - file_setexe(zFullNewPath, isexe); + file_wd_setexe(zFullNewPath, isexe); } if( rc>0 ){ fossil_print("***** %d merge conflicts in %s\n", rc, zNewName); nConflict++; } }else{ if( !nochangeFlag ){ blob_write_to_file(&t, zFullNewPath); - file_setexe(zFullNewPath, isexe); + file_wd_setexe(zFullNewPath, isexe); } fossil_print("***** Cannot merge binary file %s\n", zNewName); nConflict++; } } @@ -668,21 +668,21 @@ } db_multi_exec("DELETE FROM vfile WHERE pathname=%Q", zFile); }else{ sqlite3_int64 mtime; undo_save(zFile); - if( file_size(zFull)>=0 && (isLink || file_islink(zFull)) ){ + if( file_wd_size(zFull)>=0 && (isLink || file_wd_islink(zFull)) ){ file_delete(zFull); } if( isLink ){ - create_symlink(blob_str(&record), zFull); + symlink_create(blob_str(&record), zFull); }else{ blob_write_to_file(&record, zFull); } - file_setexe(zFull, isExe); + file_wd_setexe(zFull, isExe); fossil_print("REVERTED: %s\n", zFile); - mtime = file_mtime(zFull); + mtime = file_wd_mtime(zFull); db_multi_exec( "UPDATE vfile" " SET mtime=%lld, chnged=0, deleted=0, isexe=%d, islink=%d, mrid=rid," " pathname=coalesce(origname,pathname), origname=NULL" " WHERE pathname=%Q", Index: src/vfile.c ================================================================== --- src/vfile.c +++ src/vfile.c @@ -166,11 +166,11 @@ isDeleted = db_column_int(&q, 3); oldChnged = db_column_int(&q, 4); oldMtime = db_column_int64(&q, 7); if( isDeleted ){ chnged = 1; - }else if( !file_isfile_or_link(zName) && file_size(0)>=0 ){ + }else if( !file_wd_isfile_or_link(zName) && file_wd_size(0)>=0 ){ if( notFileIsFatal ){ fossil_warning("not an ordinary file: %s", zName); nErr++; } chnged = 1; @@ -179,12 +179,12 @@ }else if( rid==0 ){ chnged = 1; } if( chnged!=1 ){ i64 origSize = db_column_int64(&q, 6); - currentMtime = file_mtime(0); - if( origSize!=file_size(0) ){ + currentMtime = file_wd_mtime(0); + if( origSize!=file_wd_size(0) ){ /* A file size change is definitive - the file has changed. No ** need to check the sha1sum */ chnged = 1; } } @@ -247,17 +247,17 @@ isExe = db_column_int(&q, 3); isLink = db_column_int(&q, 4); content_get(rid, &content); if( file_is_the_same(&content, zName) ){ blob_reset(&content); - if( file_setexe(zName, isExe) ){ + if( file_wd_setexe(zName, isExe) ){ db_multi_exec("UPDATE vfile SET mtime=%lld WHERE id=%d", - file_mtime(zName), id); + file_wd_mtime(zName), id); } continue; } - if( promptFlag && file_size(zName)>=0 ){ + if( promptFlag && file_wd_size(zName)>=0 ){ Blob ans; char *zMsg; char cReply; zMsg = mprintf("overwrite %s (a=always/y/N)? ", zName); prompt_user(zMsg, &ans); @@ -276,22 +276,22 @@ if( verbose ) fossil_print("%s\n", &zName[nRepos]); if( file_isdir(zName) == 1 ){ /*TODO(dchest): remove directories? */ fossil_fatal("%s is directory, cannot overwrite\n", zName); } - if( file_size(zName)>=0 && (isLink || file_islink(zName)) ){ + if( file_wd_size(zName)>=0 && (isLink || file_wd_islink(zName)) ){ file_delete(zName); } if( isLink ){ - create_symlink(blob_str(&content), zName); + symlink_create(blob_str(&content), zName); }else{ blob_write_to_file(&content, zName); } - file_setexe(zName, isExe); + file_wd_setexe(zName, isExe); blob_reset(&content); db_multi_exec("UPDATE vfile SET mtime=%lld WHERE id=%d", - file_mtime(zName), id); + file_wd_mtime(zName), id); } db_finalize(&q); } @@ -393,11 +393,11 @@ /* do nothing */ }else if( file_isdir(zPath)==1 ){ if( !vfile_top_of_checkout(zPath) ){ vfile_scan(pPath, nPrefix, allFlag, pIgnore); } - }else if( file_isfile_or_link(zPath) ){ + }else if( file_wd_isfile_or_link(zPath) ){ db_bind_text(&ins, ":file", &zPath[nPrefix+1]); db_step(&ins); db_reset(&ins); } blob_resize(pPath, origSize); @@ -452,11 +452,11 @@ const char *zName = db_column_text(&q, 1); int isSelected = db_column_int(&q, 3); if( isSelected ){ md5sum_step_text(zName, -1); - if( file_islink(zFullpath) ){ + if( file_wd_islink(zFullpath) ){ /* Instead of file content, use link destination path */ Blob pathBuf; sqlite3_snprintf(sizeof(zBuf), zBuf, " %ld\n", blob_read_link(&pathBuf, zFullpath)); @@ -524,11 +524,11 @@ const char *zFullpath = db_column_text(&q, 0); const char *zName = db_column_text(&q, 1); int rid = db_column_int(&q, 2); blob_zero(&disk); - if( file_islink(zFullpath) ){ + if( file_wd_islink(zFullpath) ){ rc = blob_read_link(&disk, zFullpath); }else{ rc = blob_read_from_file(&disk, zFullpath); } if( rc<0 ){ Index: src/zip.c ================================================================== --- src/zip.c +++ src/zip.c @@ -291,11 +291,11 @@ } zip_open(); for(i=3; i