Fossil

Check-in [d7a583e6]
Login

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

Overview
Comment:Make the mtime-changes setting the default. Avoid redundant calls to stat().
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: d7a583e697fdbbb4e5e219434fc6e7a39f0bab1d
User & Date: drh 2010-01-20 20:35:11
References
2010-01-20
21:51
Fix a bug in file change detection introduced by check-in [d7a583e697]. Don't use that check-in, nor [30f23e3f5c]. check-in: 1abc8a94 user: drh tags: trunk
Context
2010-01-20
21:40
Require only ZIP permission (not ZIP permission plus check-out and history permission as formerely) in order to download a ZIP archive. Ticket [164e519962]. check-in: 30f23e3f user: drh tags: trunk
20:35
Make the mtime-changes setting the default. Avoid redundant calls to stat(). check-in: d7a583e6 user: drh tags: trunk
18:35
On windows, do not allow the "add" command to add files that differ from existing files only in case. Only works for ASCII. Ticket [36cb6b45fd9d]. check-in: 4b9455bf user: drh tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/db.c.

1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
**
**    localauth        If enabled, require that HTTP connections from
**                     127.0.0.1 be authenticated by password.  If
**                     false, all HTTP requests from localhost have
**                     unrestricted access to the repository.
**
**    mtime-changes    Use file modification times (mtimes) to detect when
**                     files have been modified.  
**
**    pgp-command      Command used to clear-sign manifests at check-in.
**                     The default is "gpg --clearsign -o ".
**
**    proxy            URL of the HTTP proxy.  If undefined or "off" then
**                     the "http_proxy" environment variable is consulted.
**                     If the http_proxy environment variable is undefined







|







1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
**
**    localauth        If enabled, require that HTTP connections from
**                     127.0.0.1 be authenticated by password.  If
**                     false, all HTTP requests from localhost have
**                     unrestricted access to the repository.
**
**    mtime-changes    Use file modification times (mtimes) to detect when
**                     files have been modified.  (Default "on".)
**
**    pgp-command      Command used to clear-sign manifests at check-in.
**                     The default is "gpg --clearsign -o ".
**
**    proxy            URL of the HTTP proxy.  If undefined or "off" then
**                     the "http_proxy" environment variable is consulted.
**                     If the http_proxy environment variable is undefined

Changes to src/file.c.

25
26
27
28
29
30
31





32
33
34



35

36
37
38



39

40
41
42









43
44
45
46
47

48
49
50

































51
52






53
54

55
56
57
58
59
60
61
..
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
...
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
*/
#include "config.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include "file.h"







/*
** Return the size of a file in bytes.  Return -1 if the file does not



** exist.

*/
i64 file_size(const char *zFilename){
  struct stat buf;



  if( stat(zFilename, &buf)!=0 ){

    return -1;
  }
  return buf.st_size;









}

/*
** Return the modification time for a file.  Return -1 if the file
** does not exist.

*/
i64 file_mtime(const char *zFilename){
  struct stat buf;

































  if( stat(zFilename, &buf)!=0 ){
    return -1;






  }
  return buf.st_mtime;

}

/*
** Return the tail of a file pathname.  The tail is the last component
** of the path.  For example, the tail of "/a/b/c.d" is "c.d".
*/
const char *file_tail(const char *z){
................................................................................
  while( (got=fread(zBuf, 1, sizeof(zBuf), in))>0 ){
    fwrite(zBuf, 1, got, out);
  }
  fclose(in);
  fclose(out);
}

/*
** Return TRUE if the named file is an ordinary file.  Return false
** for directories, devices, fifos, symlinks, etc.
*/
int file_isfile(const char *zFilename){
  struct stat buf;
  if( stat(zFilename, &buf)!=0 ){
    return 0;
  }
  return S_ISREG(buf.st_mode);
}

/*
** Return TRUE if the named file is an executable.  Return false
** for directories, devices, fifos, symlinks, etc.
*/
int file_isexe(const char *zFilename){
  struct stat buf;
  if( stat(zFilename, &buf)!=0 ){
    return 0;
  }
  if( !S_ISREG(buf.st_mode) ) return 0;
#ifdef __MINGW32__
  return ((S_IXUSR)&buf.st_mode)!=0;
#else
  return ((S_IXUSR|S_IXGRP|S_IXOTH)&buf.st_mode)!=0;
#endif
}

/*
** Set or clear the execute bit on a file.
*/
void file_setexe(const char *zFilename, int onoff){
#ifndef __MINGW32__
  struct stat buf;
  if( stat(zFilename, &buf)!=0 ) return;
................................................................................
    if( (buf.st_mode & 0111)!=0 ){
      chmod(zFilename, buf.st_mode & ~0111);
    }
  }
#endif
}

/*
** Return 1 if zFilename is a directory.  Return 0 if zFilename
** does not exist.  Return 2 if zFilename exists but is something
** other than a directory.
*/
int file_isdir(const char *zFilename){
  struct stat buf;
  int rc;
  char *zFN;

  zFN = mprintf("%s", zFilename);
  file_simplify_name(zFN, strlen(zFN));
  rc = stat(zFN, &buf);
  free(zFN);
  return rc!=0 ? 0 : (S_ISDIR(buf.st_mode) ? 1 : 2);
}

/*
** Create the directory named in the argument, if it does not already
** exist.  If forceFlag is 1, delete any prior non-directory object 
** with the same name.
**
** Return the number of errors.
*/







>
>
>
>
>


<
>
>
>
|
>

|
<
>
>
>
|
>
|
|
<
>
>
>
>
>
>
>
>
>




|
>


<
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
<
>
>
>
>
>
>

<
>







 







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







 







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







25
26
27
28
29
30
31
32
33
34
35
36
37
38

39
40
41
42
43
44
45

46
47
48
49
50
51
52

53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69

70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103

104
105
106
107
108
109
110

111
112
113
114
115
116
117
118
...
138
139
140
141
142
143
144





























145
146
147
148
149
150
151
...
157
158
159
160
161
162
163

















164
165
166
167
168
169
170
*/
#include "config.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include "file.h"

/*
** The file status information from the most recent stat() call.
*/
static struct stat fileStat;
static int fileStatValid = 0;

/*

** 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.
**
** Return the number of errors.  No error messages are generated.
*/
static int getStat(const char *zFilename){

  if( zFilename==0 ){
    if( fileStatValid==0 ) return 1;
  }else{
    if( stat(zFilename, &fileStat)!=0 ) return 1;
  }
  return 0;
}



/*
** 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 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 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 TRUE if the named file is an executable.  Return false
** for directories, devices, fifos, symlinks, etc.
*/
int file_isexe(const char *zFilename){
  if( getStat(zFilename) || !S_ISREG(fileStat.st_mode) ) return 0;
#ifdef __MINGW32__
  return ((S_IXUSR)&fileStat.st_mode)!=0;
#else
  return ((S_IXUSR|S_IXGRP|S_IXOTH)&fileStat.st_mode)!=0;
#endif
}


/*
** Return 1 if zFilename is a directory.  Return 0 if zFilename
** does not exist.  Return 2 if zFilename exists but is something
** other than a directory.
*/
int file_isdir(const char *zFilename){
  int rc;

  if( zFilename ){

    char *zFN = mprintf("%s", zFilename);
    file_simplify_name(zFN, strlen(zFN));
    rc = getStat(zFN);
    free(zFN);
  }else{
    rc = getStat(0);
  }

  return rc ? 0 : (S_ISDIR(fileStat.st_mode) ? 1 : 2);
}

/*
** Return the tail of a file pathname.  The tail is the last component
** of the path.  For example, the tail of "/a/b/c.d" is "c.d".
*/
const char *file_tail(const char *z){
................................................................................
  while( (got=fread(zBuf, 1, sizeof(zBuf), in))>0 ){
    fwrite(zBuf, 1, got, out);
  }
  fclose(in);
  fclose(out);
}






























/*
** Set or clear the execute bit on a file.
*/
void file_setexe(const char *zFilename, int onoff){
#ifndef __MINGW32__
  struct stat buf;
  if( stat(zFilename, &buf)!=0 ) return;
................................................................................
    if( (buf.st_mode & 0111)!=0 ){
      chmod(zFilename, buf.st_mode & ~0111);
    }
  }
#endif
}


















/*
** Create the directory named in the argument, if it does not already
** exist.  If forceFlag is 1, delete any prior non-directory object 
** with the same name.
**
** Return the number of errors.
*/

Changes to src/vfile.c.

144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
...
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
** If VFILE.DELETED is null or if VFILE.RID is zero, then we can assume
** the file has changed without having the check the on-disk image.
*/
void vfile_check_signature(int vid, int notFileIsFatal){
  int nErr = 0;
  Stmt q;
  Blob fileCksum, origCksum;
  int checkMtime = db_get_boolean("mtime-changes", 0);

  db_begin_transaction();
  db_prepare(&q, "SELECT id, %Q || pathname,"
                 "       vfile.mrid, deleted, chnged, uuid, mtime"
                 "  FROM vfile LEFT JOIN blob ON vfile.mrid=blob.rid"
                 " WHERE vid=%d ", g.zLocalRoot, vid);
  while( db_step(&q)==SQLITE_ROW ){
................................................................................

    id = db_column_int(&q, 0);
    zName = db_column_text(&q, 1);
    rid = db_column_int(&q, 2);
    isDeleted = db_column_int(&q, 3);
    oldChnged = db_column_int(&q, 4);
    oldMtime = db_column_int64(&q, 6);
    if( !file_isfile(zName) && file_size(zName)>=0 ){
      if( notFileIsFatal ){
        fossil_warning("not a ordinary file: %s", zName);
        nErr++;
      }
      chnged = 1;
    }else if( oldChnged>=2 ){
      chnged = oldChnged;
    }else if( isDeleted || rid==0 ){
      chnged = 1;
    }
    if( chnged!=1 ){
      currentMtime = file_mtime(zName);
    }
    if( chnged!=1 && (checkMtime==0 || currentMtime!=oldMtime) ){
      db_ephemeral_blob(&q, 5, &origCksum);
      if( sha1sum_file(zName, &fileCksum) ){
        blob_zero(&fileCksum);
      }
      if( blob_compare(&fileCksum, &origCksum) ){







|







 







|











|







144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
...
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
** If VFILE.DELETED is null or if VFILE.RID is zero, then we can assume
** the file has changed without having the check the on-disk image.
*/
void vfile_check_signature(int vid, int notFileIsFatal){
  int nErr = 0;
  Stmt q;
  Blob fileCksum, origCksum;
  int checkMtime = db_get_boolean("mtime-changes", 1);

  db_begin_transaction();
  db_prepare(&q, "SELECT id, %Q || pathname,"
                 "       vfile.mrid, deleted, chnged, uuid, mtime"
                 "  FROM vfile LEFT JOIN blob ON vfile.mrid=blob.rid"
                 " WHERE vid=%d ", g.zLocalRoot, vid);
  while( db_step(&q)==SQLITE_ROW ){
................................................................................

    id = db_column_int(&q, 0);
    zName = db_column_text(&q, 1);
    rid = db_column_int(&q, 2);
    isDeleted = db_column_int(&q, 3);
    oldChnged = db_column_int(&q, 4);
    oldMtime = db_column_int64(&q, 6);
    if( !file_isfile(zName) && file_size(0)>=0 ){
      if( notFileIsFatal ){
        fossil_warning("not a ordinary file: %s", zName);
        nErr++;
      }
      chnged = 1;
    }else if( oldChnged>=2 ){
      chnged = oldChnged;
    }else if( isDeleted || rid==0 ){
      chnged = 1;
    }
    if( chnged!=1 ){
      currentMtime = file_mtime(0);
    }
    if( chnged!=1 && (checkMtime==0 || currentMtime!=oldMtime) ){
      db_ephemeral_blob(&q, 5, &origCksum);
      if( sha1sum_file(zName, &fileCksum) ){
        blob_zero(&fileCksum);
      }
      if( blob_compare(&fileCksum, &origCksum) ){