Check-in [c05f6afaf2]
Not logged in

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Merge fixes and refactoring from symlinks branch.
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1:c05f6afaf22849c99af333f88583435a473e8ba5
User & Date: dmitry 2011-09-08 13:02:40
Context
2011-09-08
13:07
Remove unused variable from ticket_cmd(). check-in: a0b3769b01 user: dmitry tags: trunk
13:02
Merge fixes and refactoring from symlinks branch. check-in: c05f6afaf2 user: dmitry tags: trunk
12:59
Fix Windows build. Closed-Leaf check-in: 4e586a2d8e user: dmitry tags: symlinks
2011-09-06
13:23
Close A and LI tags when displaying new and deleted files in timeline. check-in: 8d703ff956 user: dmitry tags: trunk
Changes

Changes to src/add.c.

   106    106       db_multi_exec("UPDATE vfile SET deleted=0"
   107    107                     " WHERE pathname=%Q COLLATE %s", zPath, zCollate);
   108    108     }else{
   109    109       char *zFullname = mprintf("%s%s", g.zLocalRoot, zPath);
   110    110       db_multi_exec(
   111    111         "INSERT INTO vfile(vid,deleted,rid,mrid,pathname,isexe,islink)"
   112    112         "VALUES(%d,0,0,0,%Q,%d,%d)",
   113         -      vid, zPath, file_isexe(zFullname), file_islink(zFullname));
          113  +      vid, zPath, file_wd_isexe(zFullname), file_wd_islink(zFullname));
   114    114       fossil_free(zFullname);
   115    115     }
   116    116     if( db_changes() ){
   117    117       fossil_print("ADDED  %s\n", zPath);
   118    118       return 1;
   119    119     }else{
   120    120       fossil_print("SKIP   %s\n", zPath);
................................................................................
   424    424     );
   425    425     while( db_step(&q)==SQLITE_ROW ){
   426    426       const char * zFile;
   427    427       const char * zPath;
   428    428   
   429    429       zFile = db_column_text(&q, 0);
   430    430       zPath = db_column_text(&q, 1);
   431         -    if( !file_isfile_or_link(zPath) ){
          431  +    if( !file_wd_isfile_or_link(zPath) ){
   432    432         if( !isTest ){
   433    433           db_multi_exec("UPDATE vfile SET deleted=1 WHERE pathname=%Q", zFile);
   434    434         }
   435    435         fossil_print("DELETED  %s\n", zFile);
   436    436         nDelete++;
   437    437       }
   438    438     }

Changes to src/blob.c.

   679    679   int blob_read_from_file(Blob *pBlob, const char *zFilename){
   680    680     int size, got;
   681    681     FILE *in;
   682    682     if( zFilename==0 || zFilename[0]==0
   683    683           || (zFilename[0]=='-' && zFilename[1]==0) ){
   684    684       return blob_read_from_channel(pBlob, stdin, -1);
   685    685     }
   686         -  size = file_size(zFilename);
          686  +  size = file_wd_size(zFilename);
   687    687     blob_zero(pBlob);
   688    688     if( size<0 ){
   689    689       fossil_fatal("no such file: %s", zFilename);
   690    690     }
   691    691     if( size==0 ){
   692    692       return 0;
   693    693     }

Changes to src/checkin.c.

    62     62         if( zDisplayName[0]=='.' && zDisplayName[1]=='/' ){
    63     63           zDisplayName += 2;  /* no unnecessary ./ prefix */
    64     64         }
    65     65       }
    66     66       blob_append(report, zPrefix, nPrefix);
    67     67       if( isDeleted ){
    68     68         blob_appendf(report, "DELETED    %s\n", zDisplayName);
    69         -    }else if( !file_isfile_or_link(zFullName) ){
           69  +    }else if( !file_wd_isfile_or_link(zFullName) ){
    70     70         if( file_access(zFullName, 0)==0 ){
    71     71           blob_appendf(report, "NOT_A_FILE %s\n", zDisplayName);
    72     72           if( missingIsFatal ){
    73     73             fossil_warning("not a file: %s", zDisplayName);
    74     74             nErr++;
    75     75           }
    76     76         }else{
................................................................................
   225    225       char *zFullName = mprintf("%s%s", g.zLocalRoot, zPathname);
   226    226       if( isBrief ){
   227    227         fossil_print("%s\n", zPathname);
   228    228       }else if( isNew ){
   229    229         fossil_print("ADDED      %s\n", zPathname);
   230    230       }else if( isDeleted ){
   231    231         fossil_print("DELETED    %s\n", zPathname);
   232         -    }else if( !file_isfile_or_link(zFullName) ){
          232  +    }else if( !file_wd_isfile_or_link(zFullName) ){
   233    233         if( file_access(zFullName, 0)==0 ){
   234    234           fossil_print("NOT_A_FILE %s\n", zPathname);
   235    235         }else{
   236    236           fossil_print("MISSING    %s\n", zPathname);
   237    237         }
   238    238       }else if( chnged ){
   239    239         fossil_print("EDITED     %s\n", zPathname);
................................................................................
   659    659   #if !defined(_WIN32)
   660    660       /* For unix, extract the "executable" permission bit directly from
   661    661       ** the filesystem.  On windows, the "executable" bit is retained
   662    662       ** unchanged from the original. 
   663    663       */
   664    664       blob_resize(&filename, nBasename);
   665    665       blob_append(&filename, zName, -1);
   666         -    isexe = file_isexe(blob_str(&filename));
          666  +    isexe = file_wd_isexe(blob_str(&filename));
   667    667       
   668    668       /* For unix, check if the file on the filesystem is symlink.
   669    669       ** On windows, the bit is retained unchanged from original. 
   670    670       */
   671         -    isLink = file_islink(blob_str(&filename));
          671  +    isLink = file_wd_islink(blob_str(&filename));
   672    672   #endif
   673    673       if( isexe ){
   674    674         zPerm = " x";
   675    675       }else if( isLink ){
   676    676         zPerm = " l"; /* note: symlinks don't have executable bit on unix */
   677    677       }else{
   678    678         zPerm = "";
................................................................................
  1069   1069   
  1070   1070       id = db_column_int(&q, 0);
  1071   1071       zFullname = db_column_text(&q, 1);
  1072   1072       rid = db_column_int(&q, 2);
  1073   1073       crnlOk = db_column_int(&q, 3);
  1074   1074   
  1075   1075       blob_zero(&content);
  1076         -    if( file_islink(zFullname) ){
         1076  +    if( file_wd_islink(zFullname) ){
  1077   1077         /* Instead of file content, put link destination path */
  1078   1078         blob_read_link(&content, zFullname);
  1079   1079       }else{
  1080   1080         blob_read_from_file(&content, zFullname);        
  1081   1081       }
  1082   1082       if( !crnlOk ) cr_warning(&content, zFullname);
  1083   1083       nrid = content_put(&content);

Changes to src/checkout.c.

   111    111     blob_appendf(&filename, "%s/", g.zLocalRoot);
   112    112     baseLen = blob_size(&filename);
   113    113     manifest_file_rewind(pManifest);
   114    114     while( (pFile = manifest_file_next(pManifest, 0))!=0 ){
   115    115       int isExe;
   116    116       blob_append(&filename, pFile->zName, -1);
   117    117       isExe = pFile->zPerm && strstr(pFile->zPerm, "x");
   118         -    file_setexe(blob_str(&filename), isExe);
          118  +    file_wd_setexe(blob_str(&filename), isExe);
   119    119       set_or_clear_isexe(pFile->zName, vid, isExe);
   120    120       blob_resize(&filename, baseLen);
   121    121     }
   122    122     blob_reset(&filename);
   123    123     manifest_destroy(pManifest);
   124    124   }
   125    125   

Changes to src/diffcmd.c.

    69     69     if( zDiffCmd==0 ){
    70     70       Blob out;                 /* Diff output text */
    71     71       Blob file2;               /* Content of zFile2 */
    72     72       const char *zName2;       /* Name of zFile2 for display */
    73     73   
    74     74       /* Read content of zFile2 into memory */
    75     75       blob_zero(&file2);
    76         -    if( file_size(zFile2)<0 ){
           76  +    if( file_wd_size(zFile2)<0 ){
    77     77         zName2 = "/dev/null";
    78     78       }else{
    79         -      if( file_islink(zFile2) ){
           79  +      if( file_wd_islink(zFile2) ){
    80     80           blob_read_link(&file2, zFile2);
    81     81         }else{
    82     82           blob_read_from_file(&file2, zFile2);
    83     83         }
    84     84         zName2 = zName;
    85     85       }
    86     86   
................................................................................
   191    191     const char *zFileTreeName
   192    192   ){
   193    193     Blob fname;
   194    194     Blob content;
   195    195     int isLink;
   196    196     file_tree_name(zFileTreeName, &fname, 1);
   197    197     historical_version_of_file(zFrom, blob_str(&fname), &content, &isLink, 0, 0);
   198         -  if( !isLink != !file_islink(zFrom) ){
          198  +  if( !isLink != !file_wd_islink(zFrom) ){
   199    199       diff_printf("cannot compute difference between symlink and regular file\n");
   200    200     }else{
   201    201       diff_file(&content, zFileTreeName, zFileTreeName, zDiffCmd, ignoreEolWs);
   202    202     }
   203    203     blob_reset(&content);
   204    204     blob_reset(&fname);
   205    205   }
................................................................................
   286    286       }else if( isChnged==3 ){
   287    287         diff_printf("ADDED_BY_MERGE %s\n", zPathname);
   288    288         srcid = 0;
   289    289         if( !asNewFile ){ showDiff = 0; }
   290    290       }
   291    291       if( showDiff ){
   292    292         Blob content;
   293         -      if( !isLink != !file_islink(zFullName) ){
          293  +      if( !isLink != !file_wd_islink(zFullName) ){
   294    294           diff_print_index(zPathname);
   295    295           diff_printf("--- %s\n+++ %s\n", zPathname, zPathname);
   296    296           diff_printf("cannot compute difference between symlink and regular file\n");
   297    297           continue;
   298    298         }
   299    299         if( srcid>0 ){
   300    300           content_get(srcid, &content);

Changes to src/file.c.

    11     11   **
    12     12   ** Author contact information:
    13     13   **   drh@hwaci.com
    14     14   **   http://www.hwaci.com/drh/
    15     15   **
    16     16   *******************************************************************************
    17     17   **
    18         -** File utilities
           18  +** File utilities.
           19  +**
           20  +** Functions named file_* are generic functions that always follow symlinks.
           21  +**
           22  +** Functions named file_wd_* are to be used for files inside working
           23  +** directories. They follow symlinks depending on 'allow-symlinks' setting.
    19     24   */
    20     25   #include "config.h"
    21     26   #include <sys/types.h>
    22     27   #include <sys/stat.h>
    23     28   #include <unistd.h>
    24     29   #include <string.h>
    25     30   #include <errno.h>
................................................................................
    30     35   **
    31     36   ** Use _stati64 rather than stat on windows, in order to handle files
    32     37   ** larger than 2GB.
    33     38   */
    34     39   #if defined(_WIN32) && defined(__MSVCRT__)
    35     40   # define stat _stati64
    36     41   #endif
           42  +/*
           43  +** On Windows S_ISLNK always returns FALSE.
           44  +*/
           45  +#if defined(_WIN32)
           46  +# define S_ISLNK(x) (0)
           47  +#endif
    37     48   static int fileStatValid = 0;
    38     49   static struct stat fileStat;
    39     50   
    40         -static int fossil_stat(const char *zFilename, struct stat *buf){
           51  +/*
           52  +** Fill stat buf with information received from stat() or lstat().
           53  +** lstat() is called on Unix if isWd is TRUE and allow-symlinks setting is on.
           54  +**
           55  +*/
           56  +static int fossil_stat(const char *zFilename, struct stat *buf, int isWd){
    41     57   #if !defined(_WIN32)
    42         -  if( g.allowSymlinks ){
           58  +  if( isWd && g.allowSymlinks ){
    43     59       return lstat(zFilename, buf);
    44     60     }else{
    45     61       return stat(zFilename, buf);
    46     62     }
    47     63   #else
    48         -  return stat(zFilename, buf);
           64  +  int rc = 0;
           65  +  char *zMbcs = fossil_utf8_to_mbcs(zFilename);
           66  +  rc = stat(zMbcs, buf);
           67  +  fossil_mbcs_free(zMbcs);
           68  +  return rc;
    49     69   #endif
    50     70   }
    51     71   
    52     72   /*
    53     73   ** Fill in the fileStat variable for the file named zFilename.
    54     74   ** If zFilename==0, then use the previous value of fileStat if
    55     75   ** there is a previous value.
    56     76   **
           77  +** If isWd is TRUE, do lstat() instead of stat() if allow-symlinks is on.
           78  +**
    57     79   ** Return the number of errors.  No error messages are generated.
    58     80   */
    59         -static int getStat(const char *zFilename){
           81  +static int getStat(const char *zFilename, int isWd){
    60     82     int rc = 0;
    61     83     if( zFilename==0 ){
    62     84       if( fileStatValid==0 ) rc = 1;
    63     85     }else{
    64         -    char *zMbcs = fossil_utf8_to_mbcs(zFilename);
    65         -    if( fossil_stat(zMbcs, &fileStat)!=0 ){
           86  +    if( fossil_stat(zFilename, &fileStat, isWd)!=0 ){
    66     87         fileStatValid = 0;
    67     88         rc = 1;
    68     89       }else{
    69     90         fileStatValid = 1;
    70     91         rc = 0;
    71     92       }
    72         -    fossil_mbcs_free(zMbcs);
    73     93     }
    74     94     return rc;
    75     95   }
    76         -
    77     96   
    78     97   /*
    79     98   ** Return the size of a file in bytes.  Return -1 if the file does not
    80     99   ** exist.  If zFilename is NULL, return the size of the most recently
    81    100   ** stat-ed file.
    82    101   */
    83    102   i64 file_size(const char *zFilename){
    84         -  return getStat(zFilename) ? -1 : fileStat.st_size;
          103  +  return getStat(zFilename, 0) ? -1 : fileStat.st_size;
          104  +}
          105  +
          106  +/*
          107  +** Same as file_size(), but takes into account symlinks.
          108  +*/
          109  +i64 file_wd_size(const char *zFilename){
          110  +  return getStat(zFilename, 1) ? -1 : fileStat.st_size;  
    85    111   }
    86    112   
    87    113   /*
    88    114   ** Return the modification time for a file.  Return -1 if the file
    89    115   ** does not exist.  If zFilename is NULL return the size of the most
    90    116   ** recently stat-ed file.
    91    117   */
    92    118   i64 file_mtime(const char *zFilename){
    93         -  return getStat(zFilename) ? -1 : fileStat.st_mtime;
          119  +  return getStat(zFilename, 0) ? -1 : fileStat.st_mtime;
          120  +}
          121  +
          122  +/*
          123  +** Same as file_mtime(), but takes into account symlinks.
          124  +*/
          125  +i64 file_wd_mtime(const char *zFilename){
          126  +  return getStat(zFilename, 1) ? -1 : fileStat.st_mtime;
    94    127   }
    95    128   
    96    129   /*
    97    130   ** Return TRUE if the named file is an ordinary file or symlink 
    98    131   ** and symlinks are allowed.
    99    132   ** Return false for directories, devices, fifos, etc.
   100    133   */
   101         -int file_isfile_or_link(const char *zFilename){
   102         -#if !defined(_WIN32)
   103         -  if ( g.allowSymlinks ){
   104         -    return getStat(zFilename) ? 0 : S_ISREG(fileStat.st_mode) || S_ISLNK(fileStat.st_mode);
   105         -  }
   106         -#endif
   107         -  return getStat(zFilename) ? 0 : S_ISREG(fileStat.st_mode);    
          134  +int file_wd_isfile_or_link(const char *zFilename){
          135  +  return getStat(zFilename, 1) ? 0 : S_ISREG(fileStat.st_mode) ||
          136  +                                     S_ISLNK(fileStat.st_mode);
   108    137   }
   109    138   
   110    139   /*
   111    140   ** Return TRUE if the named file is an ordinary file.  Return false
   112    141   ** for directories, devices, fifos, symlinks, etc.
   113    142   */
   114    143   int file_isfile(const char *zFilename){
   115         -  return getStat(zFilename) ? 0 : S_ISREG(fileStat.st_mode);
          144  +  return getStat(zFilename, 0) ? 0 : S_ISREG(fileStat.st_mode);
          145  +}
          146  +
          147  +int file_wd_isfile(const char *zFilename){
          148  +  return getStat(zFilename, 1) ? 0 : S_ISREG(fileStat.st_mode);
   116    149   }
   117    150   
   118    151   /*
   119    152   ** Create symlink to file on Unix, or plain-text file with
   120    153   ** symlink target if "allow-symlinks" is off or we're on Windows.
   121    154   **
   122    155   ** Arguments: target file (symlink will point to it), link file
   123    156   **/
   124         -void create_symlink(const char *zTargetFile, const char *zLinkFile){
          157  +void symlink_create(const char *zTargetFile, const char *zLinkFile){
   125    158   #if !defined(_WIN32)
   126    159     if( g.allowSymlinks ){
   127    160       int i, nName;
   128    161       char *zName, zBuf[1000];
   129    162   
   130    163       nName = strlen(zLinkFile);
   131    164       if( nName>=sizeof(zBuf) ){
................................................................................
   155    188     {
   156    189       Blob content;
   157    190       blob_set(&content, zTargetFile);
   158    191       blob_write_to_file(&content, zLinkFile);
   159    192       blob_reset(&content);
   160    193     }
   161    194   }
          195  +
          196  +/*
          197  +** Copy symbolic link from zFrom to zTo.
          198  +*/
          199  +void symlink_copy(const char *zFrom, const char *zTo){
          200  +  Blob content;
          201  +  blob_read_link(&content, zFrom);
          202  +  symlink_create(blob_str(&content), zTo);
          203  +  blob_reset(&content);
          204  +}
   162    205   
   163    206   /*
   164    207   ** Return file permissions (normal, executable, or symlink):
   165    208   **   - PERM_EXE if file is executable;
   166    209   **   - PERM_LNK on Unix if file is symlink and allow-symlinks option is on;
   167    210   **   - PERM_REG for all other cases (regular file, directory, fifo, etc).
   168    211   */
   169         -int file_perm(const char *zFilename){
   170         -  if( getStat(zFilename) ) return PERM_REG;
          212  +int file_wd_perm(const char *zFilename){
          213  +  if( getStat(zFilename, 1) ) return PERM_REG;
   171    214   #if defined(_WIN32)
   172    215   #  if defined(__DMC__) || defined(_MSC_VER)
   173    216   #    define S_IXUSR  _S_IEXEC
   174    217   #  endif
   175    218     if( S_ISREG(fileStat.st_mode) && ((S_IXUSR)&fileStat.st_mode)!=0 )
   176    219       return PERM_EXE;
   177    220     else
................................................................................
   187    230   #endif
   188    231   }
   189    232   
   190    233   /*
   191    234   ** Return TRUE if the named file is an executable.  Return false
   192    235   ** for directories, devices, fifos, symlinks, etc.
   193    236   */
   194         -int file_isexe(const char *zFilename){
   195         -  return file_perm(zFilename)==PERM_EXE;
          237  +int file_wd_isexe(const char *zFilename){
          238  +  return file_wd_perm(zFilename)==PERM_EXE;
   196    239   }
   197    240   
   198    241   /*
   199    242   ** Return TRUE if the named file is a symlink and symlinks are allowed.
   200    243   ** Return false for all other cases.
   201    244   **
   202    245   ** On Windows, always return False.
   203    246   */
   204         -int file_islink(const char *zFilename){
   205         -  return file_perm(zFilename)==PERM_LNK;
          247  +int file_wd_islink(const char *zFilename){
          248  +  return file_wd_perm(zFilename)==PERM_LNK;
   206    249   }
   207    250   
   208    251   /*
   209    252   ** Return 1 if zFilename is a directory.  Return 0 if zFilename
   210    253   ** does not exist.  Return 2 if zFilename exists but is something
   211    254   ** other than a directory.
   212    255   */
   213    256   int file_isdir(const char *zFilename){
   214    257     int rc;
   215    258   
   216    259     if( zFilename ){
   217    260       char *zFN = mprintf("%s", zFilename);
   218    261       file_simplify_name(zFN, -1);
   219         -    rc = getStat(zFN);
          262  +    rc = getStat(zFN, 0);
          263  +    free(zFN);
          264  +  }else{
          265  +    rc = getStat(0, 0);
          266  +  }
          267  +  return rc ? 0 : (S_ISDIR(fileStat.st_mode) ? 1 : 2);
          268  +}
          269  +
          270  +/*
          271  +** Same as file_isdir(), but takes into account symlinks.
          272  +*/
          273  +int file_wd_isdir(const char *zFilename){
          274  +  int rc;
          275  +
          276  +  if( zFilename ){
          277  +    char *zFN = mprintf("%s", zFilename);
          278  +    file_simplify_name(zFN, -1);
          279  +    rc = getStat(zFN, 1);
   220    280       free(zFN);
   221    281     }else{
   222         -    rc = getStat(0);
          282  +    rc = getStat(0, 1);
   223    283     }
   224         -#if !defined(_WIN32)
   225         -  if( g.allowSymlinks ){
   226         -    return rc ? 0 : (S_ISDIR(fileStat.st_mode) && !S_ISLNK(fileStat.st_mode) ? 1 : 2);
   227         -  }else{
   228         -    return rc ? 0 : (S_ISDIR(fileStat.st_mode) ? 1 : 2);    
   229         -  }
   230         -#else
   231    284     return rc ? 0 : (S_ISDIR(fileStat.st_mode) ? 1 : 2);
   232         -#endif
   233    285   }
          286  +
   234    287   
   235    288   /*
   236    289   ** Wrapper around the access() system call.
   237    290   */
   238    291   int file_access(const char *zFilename, int flags){
   239    292     char *zMbcs = fossil_utf8_to_mbcs(zFilename);
   240    293     int rc = access(zMbcs, flags);
................................................................................
   298    351     fclose(out);
   299    352   }
   300    353   
   301    354   /*
   302    355   ** Set or clear the execute bit on a file.  Return true if a change
   303    356   ** occurred and false if this routine is a no-op.
   304    357   */
   305         -int file_setexe(const char *zFilename, int onoff){
          358  +int file_wd_setexe(const char *zFilename, int onoff){
   306    359     int rc = 0;
   307    360   #if !defined(_WIN32)
   308    361     struct stat buf;
   309         -  if( fossil_stat(zFilename, &buf)!=0 || S_ISLNK(buf.st_mode) ) return 0;
          362  +  if( fossil_stat(zFilename, &buf, 1)!=0 || S_ISLNK(buf.st_mode) ) return 0;
   310    363     if( onoff ){
   311    364       int targetMode = (buf.st_mode & 0444)>>2;
   312    365       if( (buf.st_mode & 0111)!=targetMode ){
   313    366         chmod(zFilename, buf.st_mode | targetMode);
   314    367         rc = 1;
   315    368       }
   316    369     }else{
................................................................................
   567    620     blob_zero(&x);
   568    621     for(i=2; i<g.argc; i++){
   569    622       char zBuf[100];
   570    623       const char *zName = g.argv[i];
   571    624       file_canonical_name(zName, &x);
   572    625       fossil_print("[%s] -> [%s]\n", zName, blob_buffer(&x));
   573    626       blob_reset(&x);
   574         -    sqlite3_snprintf(sizeof(zBuf), zBuf, "%lld", file_size(zName));
          627  +    sqlite3_snprintf(sizeof(zBuf), zBuf, "%lld", file_wd_size(zName));
   575    628       fossil_print("  file_size   = %s\n", zBuf);
   576         -    sqlite3_snprintf(sizeof(zBuf), zBuf, "%lld", file_mtime(zName));
          629  +    sqlite3_snprintf(sizeof(zBuf), zBuf, "%lld", file_wd_mtime(zName));
   577    630       fossil_print("  file_mtime  = %s\n", zBuf);
   578         -    fossil_print("  file_isfile = %d\n", file_isfile(zName));
   579         -    fossil_print("  file_isfile_or_link = %d\n", file_isfile_or_link(zName));
   580         -    fossil_print("  file_islink = %d\n", file_islink(zName));
   581         -    fossil_print("  file_isexe  = %d\n", file_isexe(zName));
   582         -    fossil_print("  file_isdir  = %d\n", file_isdir(zName));
          631  +    fossil_print("  file_isfile = %d\n", file_wd_isfile(zName));
          632  +    fossil_print("  file_isfile_or_link = %d\n",file_wd_isfile_or_link(zName));
          633  +    fossil_print("  file_islink = %d\n", file_wd_islink(zName));
          634  +    fossil_print("  file_isexe  = %d\n", file_wd_isexe(zName));
          635  +    fossil_print("  file_isdir  = %d\n", file_wd_isdir(zName));
   583    636     }
   584    637   }
   585    638   
   586    639   /*
   587    640   ** Return TRUE if the given filename is canonical.
   588    641   **
   589    642   ** Canonical names are full pathnames using "/" not "\" and which
................................................................................
   844    897     i64 iSize;
   845    898     int rc;
   846    899     Blob onDisk;
   847    900   
   848    901     iSize = file_size(zName);
   849    902     if( iSize<0 ) return 0;
   850    903     if( iSize!=blob_size(pContent) ) return 0;
   851         -  if( file_islink(zName) ){
          904  +  if( file_wd_islink(zName) ){
   852    905       blob_read_link(&onDisk, zName);
   853    906     }else{
   854    907       blob_read_from_file(&onDisk, zName);
   855    908     }
   856    909     rc = blob_compare(&onDisk, pContent);
   857    910     blob_reset(&onDisk);
   858    911     return rc==0;

Changes to src/merge.c.

   389    389       /* Do a 3-way merge of idp->idm into idp->idv.  The results go into idv. */
   390    390       if( detailFlag ){
   391    391         fossil_print("MERGE %s  (pivot=%d v1=%d v2=%d)\n", 
   392    392                      zName, ridp, ridm, ridv);
   393    393       }else{
   394    394         fossil_print("MERGE %s\n", zName);
   395    395       }
   396         -    if( islinkv || islinkm /* || file_islink(zFullPath) */ ){
          396  +    if( islinkv || islinkm /* || file_wd_islink(zFullPath) */ ){
   397    397         fossil_print("***** Cannot merge symlink %s\n", zName);
   398    398         nConflict++;        
   399    399       }else{
   400    400         undo_save(zName);
   401    401         zFullPath = mprintf("%s/%s", g.zLocalRoot, zName);
   402    402         content_get(ridp, &p);
   403    403         content_get(ridm, &m);
................................................................................
   406    406           blob_zero(&r);
   407    407         }else{
   408    408           rc = merge_3way(&p, zFullPath, &m, &r);
   409    409         }
   410    410         if( rc>=0 ){
   411    411           if( !nochangeFlag ){
   412    412             blob_write_to_file(&r, zFullPath);
   413         -          file_setexe(zFullPath, isExe);
          413  +          file_wd_setexe(zFullPath, isExe);
   414    414           }
   415    415           db_multi_exec("UPDATE vfile SET mtime=0 WHERE id=%d", idv);
   416    416           if( rc>0 ){
   417    417             fossil_print("***** %d merge conflicts in %s\n", rc, zName);
   418    418             nConflict++;
   419    419           }
   420    420         }else{
................................................................................
   478    478       db_multi_exec(
   479    479         "UPDATE vfile SET pathname=%Q, origname=coalesce(origname,pathname)"
   480    480         " WHERE id=%d AND vid=%d", zNewName, idv, vid
   481    481       );
   482    482       if( !nochangeFlag ){
   483    483         char *zFullOldPath = mprintf("%s%s", g.zLocalRoot, zOldName);
   484    484         char *zFullNewPath = mprintf("%s%s", g.zLocalRoot, zNewName);
   485         -      file_copy(zFullOldPath, zFullNewPath);
          485  +      if( file_wd_islink(zFullOldPath) ){
          486  +        symlink_copy(zFullOldPath, zFullNewPath);
          487  +      }else{
          488  +        file_copy(zFullOldPath, zFullNewPath);
          489  +      }
   486    490         file_delete(zFullOldPath);
   487    491         free(zFullNewPath);
   488    492         free(zFullOldPath);
   489    493       }
   490    494     }
   491    495     db_finalize(&q);
   492    496   

Changes to src/merge3.c.

   420    420         azSubst[0] = "%baseline";  azSubst[1] = zPivot;
   421    421         azSubst[2] = "%original";  azSubst[3] = zOrig;
   422    422         azSubst[4] = "%merge";     azSubst[5] = zOther;
   423    423         azSubst[6] = "%output";    azSubst[7] = zOut;
   424    424         zCmd = string_subst(zGMerge, 8, azSubst);
   425    425         printf("%s\n", zCmd); fflush(stdout);
   426    426         fossil_system(zCmd);
   427         -      if( file_size(zOut)>=0 ){
          427  +      if( file_wd_size(zOut)>=0 ){
   428    428           blob_read_from_file(pOut, zOut);
   429    429           file_delete(zPivot);
   430    430           file_delete(zOrig);
   431    431           file_delete(zOther);
   432    432           file_delete(zOut);
   433    433         }
   434    434         fossil_free(zCmd);

Changes to src/sha1.c.

   279    279   */
   280    280   int sha1sum_file(const char *zFilename, Blob *pCksum){
   281    281     FILE *in;
   282    282     SHA1Context ctx;
   283    283     unsigned char zResult[20];
   284    284     char zBuf[10240];
   285    285   
   286         -  if( file_islink(zFilename) ){
          286  +  if( file_wd_islink(zFilename) ){
   287    287       /* Instead of file content, return sha1 of link destination path */
   288    288       Blob destinationPath;
   289    289       int rc;
   290    290       
   291    291       blob_read_link(&destinationPath, zFilename);
   292    292       rc = sha1sum_blob(&destinationPath, pCksum);
   293    293       blob_reset(&destinationPath);

Changes to src/stash.c.

    87     87     while( db_step(&q)==SQLITE_ROW ){
    88     88       int deleted = db_column_int(&q, 0);
    89     89       int rid = db_column_int(&q, 3);
    90     90       const char *zName = db_column_text(&q, 4);
    91     91       const char *zOrig = db_column_text(&q, 5);
    92     92       char *zPath = mprintf("%s%s", g.zLocalRoot, zName);
    93     93       Blob content;
    94         -    int isNewLink = file_islink(zPath);
           94  +    int isNewLink = file_wd_islink(zPath);
    95     95   
    96     96       db_bind_int(&ins, ":rid", rid);
    97     97       db_bind_int(&ins, ":isadd", rid==0);
    98     98       db_bind_int(&ins, ":isrm", deleted);
    99     99       db_bind_int(&ins, ":isexe", db_column_int(&q, 1));
   100    100       db_bind_int(&ins, ":islink", db_column_int(&q, 2));
   101    101       db_bind_text(&ins, ":orig", zOrig);
................................................................................
   198    198       char *zNPath = mprintf("%s%s", g.zLocalRoot, zNew);
   199    199       Blob delta;
   200    200       undo_save(zNew);
   201    201       blob_zero(&delta);
   202    202       if( rid==0 ){
   203    203         db_ephemeral_blob(&q, 6, &delta);
   204    204         blob_write_to_file(&delta, zNPath);
   205         -      file_setexe(zNPath, isExec);
          205  +      file_wd_setexe(zNPath, isExec);
   206    206         fossil_print("ADD %s\n", zNew);
   207    207       }else if( isRemoved ){
   208    208         fossil_print("DELETE %s\n", zOrig);
   209    209         file_delete(zOPath);
   210    210       }else{
   211    211         Blob a, b, out, disk;
   212         -      int isNewLink = file_islink(zOPath);
          212  +      int isNewLink = file_wd_islink(zOPath);
   213    213         db_ephemeral_blob(&q, 6, &delta);
   214    214         if( isNewLink ){
   215    215           blob_read_link(&disk, zOPath);
   216    216         }else{
   217    217           blob_read_from_file(&disk, zOPath);
   218    218         }
   219    219         content_get(rid, &a);
   220    220         blob_delta_apply(&a, &delta, &b);
   221    221         if( blob_compare(&disk, &a)==0 && isLink == isNewLink ){
   222    222           if( isLink || isNewLink ){
   223    223             file_delete(zNPath);
   224    224           }
   225    225           if( isLink ){
   226         -          create_symlink(blob_str(&b), zNPath);
          226  +          symlink_create(blob_str(&b), zNPath);
   227    227           }else{
   228    228             blob_write_to_file(&b, zNPath);          
   229    229           }
   230         -        file_setexe(zNPath, isExec);
          230  +        file_wd_setexe(zNPath, isExec);
   231    231           fossil_print("UPDATE %s\n", zNew);
   232    232         }else{
   233    233           int rc;
   234    234           if( isLink || isNewLink ){
   235    235             rc = -1;
   236    236             blob_zero(&b); /* because we reset it later */
   237    237             fossil_print("***** Cannot merge symlink %s\n", zNew);
   238    238           }else{
   239    239             rc = merge_3way(&a, zOPath, &b, &out);
   240    240             blob_write_to_file(&out, zNPath);          
   241    241             blob_reset(&out);
   242         -          file_setexe(zNPath, isExec);
          242  +          file_wd_setexe(zNPath, isExec);
   243    243           }
   244    244           if( rc ){
   245    245             fossil_print("CONFLICT %s\n", zNew);
   246    246             nConflict++;
   247    247           }else{
   248    248             fossil_print("MERGE %s\n", zNew);
   249    249           }
................................................................................
   288    288       if( rid==0 ){
   289    289         db_ephemeral_blob(&q, 6, &delta);
   290    290         fossil_print("ADDED %s\n", zNew);
   291    291         diff_print_index(zNew);
   292    292         diff_file_mem(&empty, &delta, zNew, zDiffCmd, 0);
   293    293       }else if( isRemoved ){
   294    294         fossil_print("DELETE %s\n", zOrig);
   295         -      if( file_islink(zOPath) ){
          295  +      if( file_wd_islink(zOPath) ){
   296    296           blob_read_link(&delta, zOPath);
   297    297         }else{
   298    298           blob_read_from_file(&delta, zOPath);
   299    299         }
   300    300         diff_print_index(zNew);
   301    301         diff_file_mem(&delta, &empty, zOrig, zDiffCmd, 0);
   302    302       }else{
   303    303         Blob a, b, disk;
   304         -      int isOrigLink = file_islink(zOPath);
          304  +      int isOrigLink = file_wd_islink(zOPath);
   305    305         db_ephemeral_blob(&q, 6, &delta);
   306    306         if( isOrigLink ){
   307    307           blob_read_link(&disk, zOPath);
   308    308         }else{
   309    309           blob_read_from_file(&disk, zOPath);        
   310    310         }
   311    311         fossil_print("CHANGED %s\n", zNew);

Changes to src/tar.c.

   414    414     blob_reset(&tball.pax);
   415    415   }
   416    416   
   417    417   
   418    418   /*
   419    419   ** COMMAND: test-tarball
   420    420   **
   421         -** Generate a GZIP-compresssed tarball in the file given by the first argument
          421  +** Generate a GZIP-compressed tarball in the file given by the first argument
   422    422   ** that contains files given in the second and subsequent arguments.
   423    423   */
   424    424   void test_tarball_cmd(void){
   425    425     int i;
   426    426     Blob zip;
   427    427     Blob file;
   428    428     if( g.argc<3 ){
................................................................................
   430    430     }
   431    431     sqlite3_open(":memory:", &g.db);
   432    432     tar_begin();
   433    433     for(i=3; i<g.argc; i++){
   434    434       blob_zero(&file);
   435    435       blob_read_from_file(&file, g.argv[i]);
   436    436       tar_add_file(g.argv[i], &file,
   437         -                 file_perm(g.argv[i]), file_mtime(g.argv[i]));
          437  +                 file_wd_perm(g.argv[i]), file_wd_mtime(g.argv[i]));
   438    438       blob_reset(&file);
   439    439     }
   440    440     tar_finish(&zip);
   441    441     blob_write_to_file(&zip, g.argv[2]);
   442    442   }
   443    443   
   444    444   /*

Changes to src/undo.c.

    43     43       int new_exe;
    44     44       int new_link;
    45     45       int old_link;
    46     46       Blob current;
    47     47       Blob new;
    48     48       zFullname = mprintf("%s/%s", g.zLocalRoot, zPathname);
    49     49       old_link = db_column_int(&q, 3);
    50         -    new_link = file_islink(zFullname);
    51         -    new_exists = file_size(zFullname)>=0;
           50  +    new_link = file_wd_islink(zFullname);
           51  +    new_exists = file_wd_size(zFullname)>=0;
    52     52       if( new_exists ){
    53     53         if( new_link ){
    54     54           blob_read_link(&current, zFullname);
    55     55         }else{
    56     56           blob_read_from_file(&current, zFullname);        
    57     57         }
    58         -      new_exe = file_isexe(zFullname);
           58  +      new_exe = file_wd_isexe(zFullname);
    59     59       }else{
    60     60         blob_zero(&current);
    61     61         new_exe = 0;
    62     62       }
    63     63       blob_zero(&new);
    64     64       old_exists = db_column_int(&q, 1);
    65     65       old_exe = db_column_int(&q, 2);
................................................................................
    72     72         }else{
    73     73           fossil_print("NEW %s\n", zPathname);
    74     74         }
    75     75         if( new_exists && (new_link || old_link) ){
    76     76           file_delete(zFullname);
    77     77         }
    78     78         if( old_link ){
    79         -        create_symlink(blob_str(&new), zFullname);
           79  +        symlink_create(blob_str(&new), zFullname);
    80     80         }else{
    81     81           blob_write_to_file(&new, zFullname);
    82     82         }
    83         -      file_setexe(zFullname, old_exe);
           83  +      file_wd_setexe(zFullname, old_exe);
    84     84       }else{
    85     85         fossil_print("DELETE %s\n", zPathname);
    86     86         file_delete(zFullname);
    87     87       }
    88     88       blob_reset(&new);
    89     89       free(zFullname);
    90     90       db_finalize(&q);
................................................................................
   268    268     Blob content;
   269    269     int existsFlag;
   270    270     int isLink;
   271    271     Stmt q;
   272    272   
   273    273     if( !undoActive ) return;
   274    274     zFullname = mprintf("%s%s", g.zLocalRoot, zPathname);
   275         -  existsFlag = file_size(zFullname)>=0;
   276         -  isLink = file_islink(zFullname);
          275  +  existsFlag = file_wd_size(zFullname)>=0;
          276  +  isLink = file_wd_islink(zFullname);
   277    277     db_prepare(&q,
   278    278       "INSERT OR IGNORE INTO"
   279    279       "   undo(pathname,redoflag,existsflag,isExe,isLink,content)"
   280    280       " VALUES(%Q,0,%d,%d,%d,:c)",
   281         -    zPathname, existsFlag, file_isexe(zFullname), isLink
          281  +    zPathname, existsFlag, file_wd_isexe(zFullname), isLink
   282    282     );
   283    283     if( existsFlag ){
   284    284       if( isLink ){
   285    285         blob_read_link(&content, zFullname); 
   286    286       }else{
   287    287         blob_read_from_file(&content, zFullname);
   288    288       }

Changes to src/update.c.

   365    365         undo_save(zName);
   366    366         if( !nochangeFlag ) vfile_to_disk(0, idt, 0, 0);
   367    367       }else if( idt>0 && idv>0 && ridt!=ridv && chnged==0 ){
   368    368         /* The file is unedited.  Change it to the target version */
   369    369         undo_save(zName);
   370    370         fossil_print("UPDATE %s\n", zName);
   371    371         if( !nochangeFlag ) vfile_to_disk(0, idt, 0, 0);
   372         -    }else if( idt>0 && idv>0 && file_size(zFullPath)<0 ){
          372  +    }else if( idt>0 && idv>0 && file_wd_size(zFullPath)<0 ){
   373    373         /* The file missing from the local check-out. Restore it to the
   374    374         ** version that appears in the target. */
   375    375         fossil_print("UPDATE %s\n", zName);
   376    376         undo_save(zName);
   377    377         if( !nochangeFlag ) vfile_to_disk(0, idt, 0, 0);
   378    378       }else if( idt==0 && idv>0 ){
   379    379         if( ridv==0 ){
................................................................................
   396    396         Blob r, t, v;
   397    397         int rc;
   398    398         if( nameChng ){
   399    399           fossil_print("MERGE %s -> %s\n", zName, zNewName);
   400    400         }else{
   401    401           fossil_print("MERGE %s\n", zName);
   402    402         }
   403         -      if( islinkv || islinkt /* || file_islink(zFullPath) */ ){
          403  +      if( islinkv || islinkt /* || file_wd_islink(zFullPath) */ ){
   404    404           fossil_print("***** Cannot merge symlink %s\n", zNewName);
   405    405           nConflict++;        
   406    406         }else{
   407    407           undo_save(zName);
   408    408           content_get(ridt, &t);
   409    409           content_get(ridv, &v);
   410    410           rc = merge_3way(&v, zFullPath, &t, &r);
   411    411           if( rc>=0 ){
   412    412             if( !nochangeFlag ){
   413    413               blob_write_to_file(&r, zFullNewPath);
   414         -            file_setexe(zFullNewPath, isexe);
          414  +            file_wd_setexe(zFullNewPath, isexe);
   415    415             }
   416    416             if( rc>0 ){
   417    417               fossil_print("***** %d merge conflicts in %s\n", rc, zNewName);
   418    418               nConflict++;
   419    419             }
   420    420           }else{
   421    421             if( !nochangeFlag ){
   422    422               blob_write_to_file(&t, zFullNewPath);
   423         -            file_setexe(zFullNewPath, isexe);
          423  +            file_wd_setexe(zFullNewPath, isexe);
   424    424             }
   425    425             fossil_print("***** Cannot merge binary file %s\n", zNewName);
   426    426             nConflict++;
   427    427           }
   428    428         }
   429    429         if( nameChng && !nochangeFlag ) file_delete(zFullPath);
   430    430         blob_reset(&v);
................................................................................
   666    666           file_delete(zFull);
   667    667           fossil_print("DELETE: %s\n", zFile);
   668    668         }
   669    669         db_multi_exec("DELETE FROM vfile WHERE pathname=%Q", zFile);
   670    670       }else{
   671    671         sqlite3_int64 mtime;
   672    672         undo_save(zFile);
   673         -      if( file_size(zFull)>=0 && (isLink || file_islink(zFull)) ){
          673  +      if( file_wd_size(zFull)>=0 && (isLink || file_wd_islink(zFull)) ){
   674    674           file_delete(zFull);
   675    675         }
   676    676         if( isLink ){
   677         -        create_symlink(blob_str(&record), zFull);
          677  +        symlink_create(blob_str(&record), zFull);
   678    678         }else{
   679    679           blob_write_to_file(&record, zFull);
   680    680         }
   681         -      file_setexe(zFull, isExe);
          681  +      file_wd_setexe(zFull, isExe);
   682    682         fossil_print("REVERTED: %s\n", zFile);
   683         -      mtime = file_mtime(zFull);
          683  +      mtime = file_wd_mtime(zFull);
   684    684         db_multi_exec(
   685    685            "UPDATE vfile"
   686    686            "   SET mtime=%lld, chnged=0, deleted=0, isexe=%d, islink=%d, mrid=rid,"
   687    687            "       pathname=coalesce(origname,pathname), origname=NULL"     
   688    688            " WHERE pathname=%Q",
   689    689            mtime, isExe, isLink, zFile
   690    690         );

Changes to src/vfile.c.

   164    164       zName = db_column_text(&q, 1);
   165    165       rid = db_column_int(&q, 2);
   166    166       isDeleted = db_column_int(&q, 3);
   167    167       oldChnged = db_column_int(&q, 4);
   168    168       oldMtime = db_column_int64(&q, 7);
   169    169       if( isDeleted ){
   170    170         chnged = 1;
   171         -    }else if( !file_isfile_or_link(zName) && file_size(0)>=0 ){
          171  +    }else if( !file_wd_isfile_or_link(zName) && file_wd_size(0)>=0 ){
   172    172         if( notFileIsFatal ){
   173    173           fossil_warning("not an ordinary file: %s", zName);
   174    174           nErr++;
   175    175         }
   176    176         chnged = 1;
   177    177       }else if( oldChnged>=2 ){
   178    178         chnged = oldChnged;
   179    179       }else if( rid==0 ){
   180    180         chnged = 1;
   181    181       }
   182    182       if( chnged!=1 ){
   183    183         i64 origSize = db_column_int64(&q, 6);
   184         -      currentMtime = file_mtime(0);
   185         -      if( origSize!=file_size(0) ){
          184  +      currentMtime = file_wd_mtime(0);
          185  +      if( origSize!=file_wd_size(0) ){
   186    186           /* A file size change is definitive - the file has changed.  No
   187    187           ** need to check the sha1sum */
   188    188           chnged = 1;
   189    189         }
   190    190       }
   191    191       if( chnged!=1 && (checkMtime==0 || currentMtime!=oldMtime) ){
   192    192         db_ephemeral_blob(&q, 5, &origCksum);
................................................................................
   245    245       zName = db_column_text(&q, 1);
   246    246       rid = db_column_int(&q, 2);
   247    247       isExe = db_column_int(&q, 3);
   248    248       isLink = db_column_int(&q, 4);
   249    249       content_get(rid, &content);
   250    250       if( file_is_the_same(&content, zName) ){
   251    251         blob_reset(&content);
   252         -      if( file_setexe(zName, isExe) ){
          252  +      if( file_wd_setexe(zName, isExe) ){
   253    253           db_multi_exec("UPDATE vfile SET mtime=%lld WHERE id=%d",
   254         -                      file_mtime(zName), id);
          254  +                      file_wd_mtime(zName), id);
   255    255         }
   256    256         continue;
   257    257       }
   258         -    if( promptFlag && file_size(zName)>=0 ){
          258  +    if( promptFlag && file_wd_size(zName)>=0 ){
   259    259         Blob ans;
   260    260         char *zMsg;
   261    261         char cReply;
   262    262         zMsg = mprintf("overwrite %s (a=always/y/N)? ", zName);
   263    263         prompt_user(zMsg, &ans);
   264    264         free(zMsg);
   265    265         cReply = blob_str(&ans)[0];
................................................................................
   274    274         }
   275    275       }
   276    276       if( verbose ) fossil_print("%s\n", &zName[nRepos]);
   277    277       if( file_isdir(zName) == 1 ){
   278    278         /*TODO(dchest): remove directories? */
   279    279         fossil_fatal("%s is directory, cannot overwrite\n", zName);
   280    280       }    
   281         -    if( file_size(zName)>=0 && (isLink || file_islink(zName)) ){
          281  +    if( file_wd_size(zName)>=0 && (isLink || file_wd_islink(zName)) ){
   282    282         file_delete(zName);
   283    283       }
   284    284       if( isLink ){
   285         -      create_symlink(blob_str(&content), zName);
          285  +      symlink_create(blob_str(&content), zName);
   286    286       }else{
   287    287         blob_write_to_file(&content, zName);
   288    288       }
   289         -    file_setexe(zName, isExe);
          289  +    file_wd_setexe(zName, isExe);
   290    290       blob_reset(&content);
   291    291       db_multi_exec("UPDATE vfile SET mtime=%lld WHERE id=%d",
   292         -                  file_mtime(zName), id);
          292  +                  file_wd_mtime(zName), id);
   293    293     }
   294    294     db_finalize(&q);
   295    295   }
   296    296   
   297    297   
   298    298   /*
   299    299   ** Delete from the disk every file in VFILE vid.
................................................................................
   391    391         zPath = blob_str(pPath);
   392    392         if( glob_match(pIgnore, &zPath[nPrefix+1]) ){
   393    393           /* do nothing */
   394    394         }else if( file_isdir(zPath)==1 ){
   395    395           if( !vfile_top_of_checkout(zPath) ){
   396    396             vfile_scan(pPath, nPrefix, allFlag, pIgnore);
   397    397           }
   398         -      }else if( file_isfile_or_link(zPath) ){
          398  +      }else if( file_wd_isfile_or_link(zPath) ){
   399    399           db_bind_text(&ins, ":file", &zPath[nPrefix+1]);
   400    400           db_step(&ins);
   401    401           db_reset(&ins);
   402    402         }
   403    403         blob_resize(pPath, origSize);
   404    404       }
   405    405       closedir(d);
................................................................................
   450    450     while( db_step(&q)==SQLITE_ROW ){
   451    451       const char *zFullpath = db_column_text(&q, 0);
   452    452       const char *zName = db_column_text(&q, 1);
   453    453       int isSelected = db_column_int(&q, 3);
   454    454   
   455    455       if( isSelected ){
   456    456         md5sum_step_text(zName, -1);
   457         -      if( file_islink(zFullpath) ){
          457  +      if( file_wd_islink(zFullpath) ){
   458    458           /* Instead of file content, use link destination path */
   459    459           Blob pathBuf;
   460    460   
   461    461           sqlite3_snprintf(sizeof(zBuf), zBuf, " %ld\n", 
   462    462                            blob_read_link(&pathBuf, zFullpath));
   463    463           md5sum_step_text(zBuf, -1);
   464    464           md5sum_step_text(blob_str(&pathBuf), -1);
................................................................................
   522    522     md5sum_init();
   523    523     while( db_step(&q)==SQLITE_ROW ){
   524    524       const char *zFullpath = db_column_text(&q, 0);
   525    525       const char *zName = db_column_text(&q, 1);
   526    526       int rid = db_column_int(&q, 2);
   527    527   
   528    528       blob_zero(&disk);
   529         -    if( file_islink(zFullpath) ){
          529  +    if( file_wd_islink(zFullpath) ){
   530    530         rc = blob_read_link(&disk, zFullpath);
   531    531       }else{
   532    532         rc = blob_read_from_file(&disk, zFullpath);
   533    533       }
   534    534       if( rc<0 ){
   535    535         fossil_print("ERROR: cannot read file [%s]\n", zFullpath);
   536    536         blob_reset(&disk);

Changes to src/zip.c.

   289    289     if( g.argc<3 ){
   290    290       usage("ARCHIVE FILE....");
   291    291     }
   292    292     zip_open();
   293    293     for(i=3; i<g.argc; i++){
   294    294       blob_zero(&file);
   295    295       blob_read_from_file(&file, g.argv[i]);
   296         -    zip_add_file(g.argv[i], &file, file_perm(g.argv[i]));
          296  +    zip_add_file(g.argv[i], &file, file_wd_perm(g.argv[i]));
   297    297       blob_reset(&file);
   298    298     }
   299    299     zip_close(&zip);
   300    300     blob_write_to_file(&zip, g.argv[2]);
   301    301   }
   302    302   
   303    303   /*