Fossil SCM

Version 2.10.2

drh 2020-08-20 13:18 release
Commit 12d2ad00deb19c241515852cdab1f19e0fcdd283a3d642f5a77fe1a135e2b97d
+1 -1
--- VERSION
+++ VERSION
@@ -1,1 +1,1 @@
1
-2.10.1
1
+2.10.2
22
--- VERSION
+++ VERSION
@@ -1,1 +1,1 @@
1 2.10.1
2
--- VERSION
+++ VERSION
@@ -1,1 +1,1 @@
1 2.10.2
2
+1 -1
--- VERSION
+++ VERSION
@@ -1,1 +1,1 @@
1
-2.10.1
1
+2.10.2
22
--- VERSION
+++ VERSION
@@ -1,1 +1,1 @@
1 2.10.1
2
--- VERSION
+++ VERSION
@@ -1,1 +1,1 @@
1 2.10.2
2
+30 -10
--- src/add.c
+++ src/add.c
@@ -174,10 +174,11 @@
174174
*/
175175
static int add_one_file(
176176
const char *zPath, /* Tree-name of file to add. */
177177
int vid /* Add to this VFILE */
178178
){
179
+ int doSkip = 0;
179180
if( !file_is_simple_pathname(zPath, 1) ){
180181
fossil_warning("filename contains illegal characters: %s", zPath);
181182
return 0;
182183
}
183184
if( db_exists("SELECT 1 FROM vfile"
@@ -186,17 +187,22 @@
186187
" WHERE pathname=%Q %s AND deleted",
187188
zPath, filename_collation());
188189
}else{
189190
char *zFullname = mprintf("%s%s", g.zLocalRoot, zPath);
190191
int isExe = file_isexe(zFullname, RepoFILE);
191
- db_multi_exec(
192
- "INSERT INTO vfile(vid,deleted,rid,mrid,pathname,isexe,islink,mhash)"
193
- "VALUES(%d,0,0,0,%Q,%d,%d,NULL)",
194
- vid, zPath, isExe, file_islink(0));
192
+ if( file_nondir_objects_on_path(g.zLocalRoot, zFullname) ){
193
+ /* Do not add unsafe files to the vfile */
194
+ doSkip = 1;
195
+ }else{
196
+ db_multi_exec(
197
+ "INSERT INTO vfile(vid,deleted,rid,mrid,pathname,isexe,islink,mhash)"
198
+ "VALUES(%d,0,0,0,%Q,%d,%d,NULL)",
199
+ vid, zPath, isExe, file_islink(0));
200
+ }
195201
fossil_free(zFullname);
196202
}
197
- if( db_changes() ){
203
+ if( db_changes() && !doSkip ){
198204
fossil_print("ADDED %s\n", zPath);
199205
return 1;
200206
}else{
201207
fossil_print("SKIP %s\n", zPath);
202208
return 0;
@@ -204,11 +210,13 @@
204210
}
205211
206212
/*
207213
** Add all files in the sfile temp table.
208214
**
209
-** Automatically exclude the repository file.
215
+** Automatically exclude the repository file and any other files
216
+** with reserved names. Also exclude files that are beneath an
217
+** existing symlink.
210218
*/
211219
static int add_files_in_sfile(int vid){
212220
const char *zRepo; /* Name of the repository database file */
213221
int nAdd = 0; /* Number of files added */
214222
int i; /* Loop counter */
@@ -226,18 +234,30 @@
226234
if( filenames_are_case_sensitive() ){
227235
xCmp = fossil_strcmp;
228236
}else{
229237
xCmp = fossil_stricmp;
230238
}
231
- db_prepare(&loop, "SELECT pathname FROM sfile ORDER BY pathname");
239
+ db_prepare(&loop,
240
+ "SELECT pathname FROM sfile"
241
+ " WHERE pathname NOT IN ("
242
+ "SELECT sfile.pathname FROM vfile, sfile"
243
+ " WHERE vfile.islink"
244
+ " AND NOT vfile.deleted"
245
+ " AND sfile.pathname>(vfile.pathname||'/')"
246
+ " AND sfile.pathname<(vfile.pathname||'0'))"
247
+ " ORDER BY pathname");
232248
while( db_step(&loop)==SQLITE_ROW ){
233249
const char *zToAdd = db_column_text(&loop, 0);
234250
if( fossil_strcmp(zToAdd, zRepo)==0 ) continue;
235
- for(i=0; (zReserved = fossil_reserved_name(i, 0))!=0; i++){
236
- if( xCmp(zToAdd, zReserved)==0 ) break;
251
+ if( strchr(zToAdd,'/') ){
252
+ if( file_is_reserved_name(zToAdd, -1) ) continue;
253
+ }else{
254
+ for(i=0; (zReserved = fossil_reserved_name(i, 0))!=0; i++){
255
+ if( xCmp(zToAdd, zReserved)==0 ) break;
256
+ }
257
+ if( zReserved ) continue;
237258
}
238
- if( zReserved ) continue;
239259
nAdd += add_one_file(zToAdd, vid);
240260
}
241261
db_finalize(&loop);
242262
blob_reset(&repoName);
243263
return nAdd;
244264
--- src/add.c
+++ src/add.c
@@ -174,10 +174,11 @@
174 */
175 static int add_one_file(
176 const char *zPath, /* Tree-name of file to add. */
177 int vid /* Add to this VFILE */
178 ){
 
179 if( !file_is_simple_pathname(zPath, 1) ){
180 fossil_warning("filename contains illegal characters: %s", zPath);
181 return 0;
182 }
183 if( db_exists("SELECT 1 FROM vfile"
@@ -186,17 +187,22 @@
186 " WHERE pathname=%Q %s AND deleted",
187 zPath, filename_collation());
188 }else{
189 char *zFullname = mprintf("%s%s", g.zLocalRoot, zPath);
190 int isExe = file_isexe(zFullname, RepoFILE);
191 db_multi_exec(
192 "INSERT INTO vfile(vid,deleted,rid,mrid,pathname,isexe,islink,mhash)"
193 "VALUES(%d,0,0,0,%Q,%d,%d,NULL)",
194 vid, zPath, isExe, file_islink(0));
 
 
 
 
 
195 fossil_free(zFullname);
196 }
197 if( db_changes() ){
198 fossil_print("ADDED %s\n", zPath);
199 return 1;
200 }else{
201 fossil_print("SKIP %s\n", zPath);
202 return 0;
@@ -204,11 +210,13 @@
204 }
205
206 /*
207 ** Add all files in the sfile temp table.
208 **
209 ** Automatically exclude the repository file.
 
 
210 */
211 static int add_files_in_sfile(int vid){
212 const char *zRepo; /* Name of the repository database file */
213 int nAdd = 0; /* Number of files added */
214 int i; /* Loop counter */
@@ -226,18 +234,30 @@
226 if( filenames_are_case_sensitive() ){
227 xCmp = fossil_strcmp;
228 }else{
229 xCmp = fossil_stricmp;
230 }
231 db_prepare(&loop, "SELECT pathname FROM sfile ORDER BY pathname");
 
 
 
 
 
 
 
 
232 while( db_step(&loop)==SQLITE_ROW ){
233 const char *zToAdd = db_column_text(&loop, 0);
234 if( fossil_strcmp(zToAdd, zRepo)==0 ) continue;
235 for(i=0; (zReserved = fossil_reserved_name(i, 0))!=0; i++){
236 if( xCmp(zToAdd, zReserved)==0 ) break;
 
 
 
 
 
237 }
238 if( zReserved ) continue;
239 nAdd += add_one_file(zToAdd, vid);
240 }
241 db_finalize(&loop);
242 blob_reset(&repoName);
243 return nAdd;
244
--- src/add.c
+++ src/add.c
@@ -174,10 +174,11 @@
174 */
175 static int add_one_file(
176 const char *zPath, /* Tree-name of file to add. */
177 int vid /* Add to this VFILE */
178 ){
179 int doSkip = 0;
180 if( !file_is_simple_pathname(zPath, 1) ){
181 fossil_warning("filename contains illegal characters: %s", zPath);
182 return 0;
183 }
184 if( db_exists("SELECT 1 FROM vfile"
@@ -186,17 +187,22 @@
187 " WHERE pathname=%Q %s AND deleted",
188 zPath, filename_collation());
189 }else{
190 char *zFullname = mprintf("%s%s", g.zLocalRoot, zPath);
191 int isExe = file_isexe(zFullname, RepoFILE);
192 if( file_nondir_objects_on_path(g.zLocalRoot, zFullname) ){
193 /* Do not add unsafe files to the vfile */
194 doSkip = 1;
195 }else{
196 db_multi_exec(
197 "INSERT INTO vfile(vid,deleted,rid,mrid,pathname,isexe,islink,mhash)"
198 "VALUES(%d,0,0,0,%Q,%d,%d,NULL)",
199 vid, zPath, isExe, file_islink(0));
200 }
201 fossil_free(zFullname);
202 }
203 if( db_changes() && !doSkip ){
204 fossil_print("ADDED %s\n", zPath);
205 return 1;
206 }else{
207 fossil_print("SKIP %s\n", zPath);
208 return 0;
@@ -204,11 +210,13 @@
210 }
211
212 /*
213 ** Add all files in the sfile temp table.
214 **
215 ** Automatically exclude the repository file and any other files
216 ** with reserved names. Also exclude files that are beneath an
217 ** existing symlink.
218 */
219 static int add_files_in_sfile(int vid){
220 const char *zRepo; /* Name of the repository database file */
221 int nAdd = 0; /* Number of files added */
222 int i; /* Loop counter */
@@ -226,18 +234,30 @@
234 if( filenames_are_case_sensitive() ){
235 xCmp = fossil_strcmp;
236 }else{
237 xCmp = fossil_stricmp;
238 }
239 db_prepare(&loop,
240 "SELECT pathname FROM sfile"
241 " WHERE pathname NOT IN ("
242 "SELECT sfile.pathname FROM vfile, sfile"
243 " WHERE vfile.islink"
244 " AND NOT vfile.deleted"
245 " AND sfile.pathname>(vfile.pathname||'/')"
246 " AND sfile.pathname<(vfile.pathname||'0'))"
247 " ORDER BY pathname");
248 while( db_step(&loop)==SQLITE_ROW ){
249 const char *zToAdd = db_column_text(&loop, 0);
250 if( fossil_strcmp(zToAdd, zRepo)==0 ) continue;
251 if( strchr(zToAdd,'/') ){
252 if( file_is_reserved_name(zToAdd, -1) ) continue;
253 }else{
254 for(i=0; (zReserved = fossil_reserved_name(i, 0))!=0; i++){
255 if( xCmp(zToAdd, zReserved)==0 ) break;
256 }
257 if( zReserved ) continue;
258 }
 
259 nAdd += add_one_file(zToAdd, vid);
260 }
261 db_finalize(&loop);
262 blob_reset(&repoName);
263 return nAdd;
264
+30 -10
--- src/add.c
+++ src/add.c
@@ -174,10 +174,11 @@
174174
*/
175175
static int add_one_file(
176176
const char *zPath, /* Tree-name of file to add. */
177177
int vid /* Add to this VFILE */
178178
){
179
+ int doSkip = 0;
179180
if( !file_is_simple_pathname(zPath, 1) ){
180181
fossil_warning("filename contains illegal characters: %s", zPath);
181182
return 0;
182183
}
183184
if( db_exists("SELECT 1 FROM vfile"
@@ -186,17 +187,22 @@
186187
" WHERE pathname=%Q %s AND deleted",
187188
zPath, filename_collation());
188189
}else{
189190
char *zFullname = mprintf("%s%s", g.zLocalRoot, zPath);
190191
int isExe = file_isexe(zFullname, RepoFILE);
191
- db_multi_exec(
192
- "INSERT INTO vfile(vid,deleted,rid,mrid,pathname,isexe,islink,mhash)"
193
- "VALUES(%d,0,0,0,%Q,%d,%d,NULL)",
194
- vid, zPath, isExe, file_islink(0));
192
+ if( file_nondir_objects_on_path(g.zLocalRoot, zFullname) ){
193
+ /* Do not add unsafe files to the vfile */
194
+ doSkip = 1;
195
+ }else{
196
+ db_multi_exec(
197
+ "INSERT INTO vfile(vid,deleted,rid,mrid,pathname,isexe,islink,mhash)"
198
+ "VALUES(%d,0,0,0,%Q,%d,%d,NULL)",
199
+ vid, zPath, isExe, file_islink(0));
200
+ }
195201
fossil_free(zFullname);
196202
}
197
- if( db_changes() ){
203
+ if( db_changes() && !doSkip ){
198204
fossil_print("ADDED %s\n", zPath);
199205
return 1;
200206
}else{
201207
fossil_print("SKIP %s\n", zPath);
202208
return 0;
@@ -204,11 +210,13 @@
204210
}
205211
206212
/*
207213
** Add all files in the sfile temp table.
208214
**
209
-** Automatically exclude the repository file.
215
+** Automatically exclude the repository file and any other files
216
+** with reserved names. Also exclude files that are beneath an
217
+** existing symlink.
210218
*/
211219
static int add_files_in_sfile(int vid){
212220
const char *zRepo; /* Name of the repository database file */
213221
int nAdd = 0; /* Number of files added */
214222
int i; /* Loop counter */
@@ -226,18 +234,30 @@
226234
if( filenames_are_case_sensitive() ){
227235
xCmp = fossil_strcmp;
228236
}else{
229237
xCmp = fossil_stricmp;
230238
}
231
- db_prepare(&loop, "SELECT pathname FROM sfile ORDER BY pathname");
239
+ db_prepare(&loop,
240
+ "SELECT pathname FROM sfile"
241
+ " WHERE pathname NOT IN ("
242
+ "SELECT sfile.pathname FROM vfile, sfile"
243
+ " WHERE vfile.islink"
244
+ " AND NOT vfile.deleted"
245
+ " AND sfile.pathname>(vfile.pathname||'/')"
246
+ " AND sfile.pathname<(vfile.pathname||'0'))"
247
+ " ORDER BY pathname");
232248
while( db_step(&loop)==SQLITE_ROW ){
233249
const char *zToAdd = db_column_text(&loop, 0);
234250
if( fossil_strcmp(zToAdd, zRepo)==0 ) continue;
235
- for(i=0; (zReserved = fossil_reserved_name(i, 0))!=0; i++){
236
- if( xCmp(zToAdd, zReserved)==0 ) break;
251
+ if( strchr(zToAdd,'/') ){
252
+ if( file_is_reserved_name(zToAdd, -1) ) continue;
253
+ }else{
254
+ for(i=0; (zReserved = fossil_reserved_name(i, 0))!=0; i++){
255
+ if( xCmp(zToAdd, zReserved)==0 ) break;
256
+ }
257
+ if( zReserved ) continue;
237258
}
238
- if( zReserved ) continue;
239259
nAdd += add_one_file(zToAdd, vid);
240260
}
241261
db_finalize(&loop);
242262
blob_reset(&repoName);
243263
return nAdd;
244264
--- src/add.c
+++ src/add.c
@@ -174,10 +174,11 @@
174 */
175 static int add_one_file(
176 const char *zPath, /* Tree-name of file to add. */
177 int vid /* Add to this VFILE */
178 ){
 
179 if( !file_is_simple_pathname(zPath, 1) ){
180 fossil_warning("filename contains illegal characters: %s", zPath);
181 return 0;
182 }
183 if( db_exists("SELECT 1 FROM vfile"
@@ -186,17 +187,22 @@
186 " WHERE pathname=%Q %s AND deleted",
187 zPath, filename_collation());
188 }else{
189 char *zFullname = mprintf("%s%s", g.zLocalRoot, zPath);
190 int isExe = file_isexe(zFullname, RepoFILE);
191 db_multi_exec(
192 "INSERT INTO vfile(vid,deleted,rid,mrid,pathname,isexe,islink,mhash)"
193 "VALUES(%d,0,0,0,%Q,%d,%d,NULL)",
194 vid, zPath, isExe, file_islink(0));
 
 
 
 
 
195 fossil_free(zFullname);
196 }
197 if( db_changes() ){
198 fossil_print("ADDED %s\n", zPath);
199 return 1;
200 }else{
201 fossil_print("SKIP %s\n", zPath);
202 return 0;
@@ -204,11 +210,13 @@
204 }
205
206 /*
207 ** Add all files in the sfile temp table.
208 **
209 ** Automatically exclude the repository file.
 
 
210 */
211 static int add_files_in_sfile(int vid){
212 const char *zRepo; /* Name of the repository database file */
213 int nAdd = 0; /* Number of files added */
214 int i; /* Loop counter */
@@ -226,18 +234,30 @@
226 if( filenames_are_case_sensitive() ){
227 xCmp = fossil_strcmp;
228 }else{
229 xCmp = fossil_stricmp;
230 }
231 db_prepare(&loop, "SELECT pathname FROM sfile ORDER BY pathname");
 
 
 
 
 
 
 
 
232 while( db_step(&loop)==SQLITE_ROW ){
233 const char *zToAdd = db_column_text(&loop, 0);
234 if( fossil_strcmp(zToAdd, zRepo)==0 ) continue;
235 for(i=0; (zReserved = fossil_reserved_name(i, 0))!=0; i++){
236 if( xCmp(zToAdd, zReserved)==0 ) break;
 
 
 
 
 
237 }
238 if( zReserved ) continue;
239 nAdd += add_one_file(zToAdd, vid);
240 }
241 db_finalize(&loop);
242 blob_reset(&repoName);
243 return nAdd;
244
--- src/add.c
+++ src/add.c
@@ -174,10 +174,11 @@
174 */
175 static int add_one_file(
176 const char *zPath, /* Tree-name of file to add. */
177 int vid /* Add to this VFILE */
178 ){
179 int doSkip = 0;
180 if( !file_is_simple_pathname(zPath, 1) ){
181 fossil_warning("filename contains illegal characters: %s", zPath);
182 return 0;
183 }
184 if( db_exists("SELECT 1 FROM vfile"
@@ -186,17 +187,22 @@
187 " WHERE pathname=%Q %s AND deleted",
188 zPath, filename_collation());
189 }else{
190 char *zFullname = mprintf("%s%s", g.zLocalRoot, zPath);
191 int isExe = file_isexe(zFullname, RepoFILE);
192 if( file_nondir_objects_on_path(g.zLocalRoot, zFullname) ){
193 /* Do not add unsafe files to the vfile */
194 doSkip = 1;
195 }else{
196 db_multi_exec(
197 "INSERT INTO vfile(vid,deleted,rid,mrid,pathname,isexe,islink,mhash)"
198 "VALUES(%d,0,0,0,%Q,%d,%d,NULL)",
199 vid, zPath, isExe, file_islink(0));
200 }
201 fossil_free(zFullname);
202 }
203 if( db_changes() && !doSkip ){
204 fossil_print("ADDED %s\n", zPath);
205 return 1;
206 }else{
207 fossil_print("SKIP %s\n", zPath);
208 return 0;
@@ -204,11 +210,13 @@
210 }
211
212 /*
213 ** Add all files in the sfile temp table.
214 **
215 ** Automatically exclude the repository file and any other files
216 ** with reserved names. Also exclude files that are beneath an
217 ** existing symlink.
218 */
219 static int add_files_in_sfile(int vid){
220 const char *zRepo; /* Name of the repository database file */
221 int nAdd = 0; /* Number of files added */
222 int i; /* Loop counter */
@@ -226,18 +234,30 @@
234 if( filenames_are_case_sensitive() ){
235 xCmp = fossil_strcmp;
236 }else{
237 xCmp = fossil_stricmp;
238 }
239 db_prepare(&loop,
240 "SELECT pathname FROM sfile"
241 " WHERE pathname NOT IN ("
242 "SELECT sfile.pathname FROM vfile, sfile"
243 " WHERE vfile.islink"
244 " AND NOT vfile.deleted"
245 " AND sfile.pathname>(vfile.pathname||'/')"
246 " AND sfile.pathname<(vfile.pathname||'0'))"
247 " ORDER BY pathname");
248 while( db_step(&loop)==SQLITE_ROW ){
249 const char *zToAdd = db_column_text(&loop, 0);
250 if( fossil_strcmp(zToAdd, zRepo)==0 ) continue;
251 if( strchr(zToAdd,'/') ){
252 if( file_is_reserved_name(zToAdd, -1) ) continue;
253 }else{
254 for(i=0; (zReserved = fossil_reserved_name(i, 0))!=0; i++){
255 if( xCmp(zToAdd, zReserved)==0 ) break;
256 }
257 if( zReserved ) continue;
258 }
 
259 nAdd += add_one_file(zToAdd, vid);
260 }
261 db_finalize(&loop);
262 blob_reset(&repoName);
263 return nAdd;
264
--- src/checkin.c
+++ src/checkin.c
@@ -856,12 +856,14 @@
856856
857857
if( zIgnoreFlag==0 ){
858858
zIgnoreFlag = db_get("ignore-glob", 0);
859859
}
860860
pIgnore = glob_create(zIgnoreFlag);
861
+#ifdef FOSSIL_LEGACY_ALLOW_SYMLINKS
861862
/* Always consider symlinks. */
862863
g.allowSymlinks = db_allow_symlinks_by_default();
864
+#endif
863865
locate_unmanaged_files(g.argc-2, g.argv+2, scanFlags, pIgnore);
864866
glob_free(pIgnore);
865867
866868
blob_zero(&report);
867869
status_report(&report, flags);
@@ -1015,12 +1017,14 @@
10151017
verify_all_options();
10161018
pIgnore = glob_create(zIgnoreFlag);
10171019
pKeep = glob_create(zKeepFlag);
10181020
pClean = glob_create(zCleanFlag);
10191021
nRoot = (int)strlen(g.zLocalRoot);
1022
+#ifdef FOSSIL_LEGACY_ALLOW_SYMLINKS
10201023
/* Always consider symlinks. */
10211024
g.allowSymlinks = db_allow_symlinks_by_default();
1025
+#endif
10221026
if( !dirsOnlyFlag ){
10231027
Stmt q;
10241028
Blob repo;
10251029
if( !dryRunFlag && !disableUndo ) undo_begin();
10261030
locate_unmanaged_files(g.argc-2, g.argv+2, scanFlags, pIgnore);
10271031
--- src/checkin.c
+++ src/checkin.c
@@ -856,12 +856,14 @@
856
857 if( zIgnoreFlag==0 ){
858 zIgnoreFlag = db_get("ignore-glob", 0);
859 }
860 pIgnore = glob_create(zIgnoreFlag);
 
861 /* Always consider symlinks. */
862 g.allowSymlinks = db_allow_symlinks_by_default();
 
863 locate_unmanaged_files(g.argc-2, g.argv+2, scanFlags, pIgnore);
864 glob_free(pIgnore);
865
866 blob_zero(&report);
867 status_report(&report, flags);
@@ -1015,12 +1017,14 @@
1015 verify_all_options();
1016 pIgnore = glob_create(zIgnoreFlag);
1017 pKeep = glob_create(zKeepFlag);
1018 pClean = glob_create(zCleanFlag);
1019 nRoot = (int)strlen(g.zLocalRoot);
 
1020 /* Always consider symlinks. */
1021 g.allowSymlinks = db_allow_symlinks_by_default();
 
1022 if( !dirsOnlyFlag ){
1023 Stmt q;
1024 Blob repo;
1025 if( !dryRunFlag && !disableUndo ) undo_begin();
1026 locate_unmanaged_files(g.argc-2, g.argv+2, scanFlags, pIgnore);
1027
--- src/checkin.c
+++ src/checkin.c
@@ -856,12 +856,14 @@
856
857 if( zIgnoreFlag==0 ){
858 zIgnoreFlag = db_get("ignore-glob", 0);
859 }
860 pIgnore = glob_create(zIgnoreFlag);
861 #ifdef FOSSIL_LEGACY_ALLOW_SYMLINKS
862 /* Always consider symlinks. */
863 g.allowSymlinks = db_allow_symlinks_by_default();
864 #endif
865 locate_unmanaged_files(g.argc-2, g.argv+2, scanFlags, pIgnore);
866 glob_free(pIgnore);
867
868 blob_zero(&report);
869 status_report(&report, flags);
@@ -1015,12 +1017,14 @@
1017 verify_all_options();
1018 pIgnore = glob_create(zIgnoreFlag);
1019 pKeep = glob_create(zKeepFlag);
1020 pClean = glob_create(zCleanFlag);
1021 nRoot = (int)strlen(g.zLocalRoot);
1022 #ifdef FOSSIL_LEGACY_ALLOW_SYMLINKS
1023 /* Always consider symlinks. */
1024 g.allowSymlinks = db_allow_symlinks_by_default();
1025 #endif
1026 if( !dirsOnlyFlag ){
1027 Stmt q;
1028 Blob repo;
1029 if( !dryRunFlag && !disableUndo ) undo_begin();
1030 locate_unmanaged_files(g.argc-2, g.argv+2, scanFlags, pIgnore);
1031
--- src/checkin.c
+++ src/checkin.c
@@ -856,12 +856,14 @@
856856
857857
if( zIgnoreFlag==0 ){
858858
zIgnoreFlag = db_get("ignore-glob", 0);
859859
}
860860
pIgnore = glob_create(zIgnoreFlag);
861
+#ifdef FOSSIL_LEGACY_ALLOW_SYMLINKS
861862
/* Always consider symlinks. */
862863
g.allowSymlinks = db_allow_symlinks_by_default();
864
+#endif
863865
locate_unmanaged_files(g.argc-2, g.argv+2, scanFlags, pIgnore);
864866
glob_free(pIgnore);
865867
866868
blob_zero(&report);
867869
status_report(&report, flags);
@@ -1015,12 +1017,14 @@
10151017
verify_all_options();
10161018
pIgnore = glob_create(zIgnoreFlag);
10171019
pKeep = glob_create(zKeepFlag);
10181020
pClean = glob_create(zCleanFlag);
10191021
nRoot = (int)strlen(g.zLocalRoot);
1022
+#ifdef FOSSIL_LEGACY_ALLOW_SYMLINKS
10201023
/* Always consider symlinks. */
10211024
g.allowSymlinks = db_allow_symlinks_by_default();
1025
+#endif
10221026
if( !dirsOnlyFlag ){
10231027
Stmt q;
10241028
Blob repo;
10251029
if( !dryRunFlag && !disableUndo ) undo_begin();
10261030
locate_unmanaged_files(g.argc-2, g.argv+2, scanFlags, pIgnore);
10271031
--- src/checkin.c
+++ src/checkin.c
@@ -856,12 +856,14 @@
856
857 if( zIgnoreFlag==0 ){
858 zIgnoreFlag = db_get("ignore-glob", 0);
859 }
860 pIgnore = glob_create(zIgnoreFlag);
 
861 /* Always consider symlinks. */
862 g.allowSymlinks = db_allow_symlinks_by_default();
 
863 locate_unmanaged_files(g.argc-2, g.argv+2, scanFlags, pIgnore);
864 glob_free(pIgnore);
865
866 blob_zero(&report);
867 status_report(&report, flags);
@@ -1015,12 +1017,14 @@
1015 verify_all_options();
1016 pIgnore = glob_create(zIgnoreFlag);
1017 pKeep = glob_create(zKeepFlag);
1018 pClean = glob_create(zCleanFlag);
1019 nRoot = (int)strlen(g.zLocalRoot);
 
1020 /* Always consider symlinks. */
1021 g.allowSymlinks = db_allow_symlinks_by_default();
 
1022 if( !dirsOnlyFlag ){
1023 Stmt q;
1024 Blob repo;
1025 if( !dryRunFlag && !disableUndo ) undo_begin();
1026 locate_unmanaged_files(g.argc-2, g.argv+2, scanFlags, pIgnore);
1027
--- src/checkin.c
+++ src/checkin.c
@@ -856,12 +856,14 @@
856
857 if( zIgnoreFlag==0 ){
858 zIgnoreFlag = db_get("ignore-glob", 0);
859 }
860 pIgnore = glob_create(zIgnoreFlag);
861 #ifdef FOSSIL_LEGACY_ALLOW_SYMLINKS
862 /* Always consider symlinks. */
863 g.allowSymlinks = db_allow_symlinks_by_default();
864 #endif
865 locate_unmanaged_files(g.argc-2, g.argv+2, scanFlags, pIgnore);
866 glob_free(pIgnore);
867
868 blob_zero(&report);
869 status_report(&report, flags);
@@ -1015,12 +1017,14 @@
1017 verify_all_options();
1018 pIgnore = glob_create(zIgnoreFlag);
1019 pKeep = glob_create(zKeepFlag);
1020 pClean = glob_create(zCleanFlag);
1021 nRoot = (int)strlen(g.zLocalRoot);
1022 #ifdef FOSSIL_LEGACY_ALLOW_SYMLINKS
1023 /* Always consider symlinks. */
1024 g.allowSymlinks = db_allow_symlinks_by_default();
1025 #endif
1026 if( !dirsOnlyFlag ){
1027 Stmt q;
1028 Blob repo;
1029 if( !dryRunFlag && !disableUndo ) undo_begin();
1030 locate_unmanaged_files(g.argc-2, g.argv+2, scanFlags, pIgnore);
1031
--- src/configure.c
+++ src/configure.c
@@ -137,11 +137,13 @@
137137
{ "keep-glob", CONFIGSET_PROJ },
138138
{ "crlf-glob", CONFIGSET_PROJ },
139139
{ "crnl-glob", CONFIGSET_PROJ },
140140
{ "encoding-glob", CONFIGSET_PROJ },
141141
{ "empty-dirs", CONFIGSET_PROJ },
142
+#ifdef FOSSIL_LEGACY_ALLOW_SYMLINKS
142143
{ "allow-symlinks", CONFIGSET_PROJ },
144
+#endif
143145
{ "dotfiles", CONFIGSET_PROJ },
144146
{ "parent-project-code", CONFIGSET_PROJ },
145147
{ "parent-project-name", CONFIGSET_PROJ },
146148
{ "hash-policy", CONFIGSET_PROJ },
147149
{ "comment-format", CONFIGSET_PROJ },
148150
--- src/configure.c
+++ src/configure.c
@@ -137,11 +137,13 @@
137 { "keep-glob", CONFIGSET_PROJ },
138 { "crlf-glob", CONFIGSET_PROJ },
139 { "crnl-glob", CONFIGSET_PROJ },
140 { "encoding-glob", CONFIGSET_PROJ },
141 { "empty-dirs", CONFIGSET_PROJ },
 
142 { "allow-symlinks", CONFIGSET_PROJ },
 
143 { "dotfiles", CONFIGSET_PROJ },
144 { "parent-project-code", CONFIGSET_PROJ },
145 { "parent-project-name", CONFIGSET_PROJ },
146 { "hash-policy", CONFIGSET_PROJ },
147 { "comment-format", CONFIGSET_PROJ },
148
--- src/configure.c
+++ src/configure.c
@@ -137,11 +137,13 @@
137 { "keep-glob", CONFIGSET_PROJ },
138 { "crlf-glob", CONFIGSET_PROJ },
139 { "crnl-glob", CONFIGSET_PROJ },
140 { "encoding-glob", CONFIGSET_PROJ },
141 { "empty-dirs", CONFIGSET_PROJ },
142 #ifdef FOSSIL_LEGACY_ALLOW_SYMLINKS
143 { "allow-symlinks", CONFIGSET_PROJ },
144 #endif
145 { "dotfiles", CONFIGSET_PROJ },
146 { "parent-project-code", CONFIGSET_PROJ },
147 { "parent-project-name", CONFIGSET_PROJ },
148 { "hash-policy", CONFIGSET_PROJ },
149 { "comment-format", CONFIGSET_PROJ },
150
--- src/configure.c
+++ src/configure.c
@@ -137,11 +137,13 @@
137137
{ "keep-glob", CONFIGSET_PROJ },
138138
{ "crlf-glob", CONFIGSET_PROJ },
139139
{ "crnl-glob", CONFIGSET_PROJ },
140140
{ "encoding-glob", CONFIGSET_PROJ },
141141
{ "empty-dirs", CONFIGSET_PROJ },
142
+#ifdef FOSSIL_LEGACY_ALLOW_SYMLINKS
142143
{ "allow-symlinks", CONFIGSET_PROJ },
144
+#endif
143145
{ "dotfiles", CONFIGSET_PROJ },
144146
{ "parent-project-code", CONFIGSET_PROJ },
145147
{ "parent-project-name", CONFIGSET_PROJ },
146148
{ "hash-policy", CONFIGSET_PROJ },
147149
{ "comment-format", CONFIGSET_PROJ },
148150
--- src/configure.c
+++ src/configure.c
@@ -137,11 +137,13 @@
137 { "keep-glob", CONFIGSET_PROJ },
138 { "crlf-glob", CONFIGSET_PROJ },
139 { "crnl-glob", CONFIGSET_PROJ },
140 { "encoding-glob", CONFIGSET_PROJ },
141 { "empty-dirs", CONFIGSET_PROJ },
 
142 { "allow-symlinks", CONFIGSET_PROJ },
 
143 { "dotfiles", CONFIGSET_PROJ },
144 { "parent-project-code", CONFIGSET_PROJ },
145 { "parent-project-name", CONFIGSET_PROJ },
146 { "hash-policy", CONFIGSET_PROJ },
147 { "comment-format", CONFIGSET_PROJ },
148
--- src/configure.c
+++ src/configure.c
@@ -137,11 +137,13 @@
137 { "keep-glob", CONFIGSET_PROJ },
138 { "crlf-glob", CONFIGSET_PROJ },
139 { "crnl-glob", CONFIGSET_PROJ },
140 { "encoding-glob", CONFIGSET_PROJ },
141 { "empty-dirs", CONFIGSET_PROJ },
142 #ifdef FOSSIL_LEGACY_ALLOW_SYMLINKS
143 { "allow-symlinks", CONFIGSET_PROJ },
144 #endif
145 { "dotfiles", CONFIGSET_PROJ },
146 { "parent-project-code", CONFIGSET_PROJ },
147 { "parent-project-name", CONFIGSET_PROJ },
148 { "hash-policy", CONFIGSET_PROJ },
149 { "comment-format", CONFIGSET_PROJ },
150
+80 -17
--- src/db.c
+++ src/db.c
@@ -122,10 +122,13 @@
122122
char *azBeforeCommit[5]; /* Commands to run prior to COMMIT */
123123
int nBeforeCommit; /* Number of entries in azBeforeCommit */
124124
int nPriorChanges; /* sqlite3_total_changes() at transaction start */
125125
const char *zStartFile; /* File in which transaction was started */
126126
int iStartLine; /* Line of zStartFile where transaction started */
127
+ int (*xAuth)(void*,int,const char*,const char*,const char*,const char*);
128
+ void *pAuthArg; /* Argument to the authorizer */
129
+ const char *zAuthName; /* Name of the authorizer */
127130
} db = {0, 0, 0, 0, 0, 0, };
128131
129132
/*
130133
** Arrange for the given file to be deleted on a failure.
131134
*/
@@ -306,10 +309,36 @@
306309
}
307310
db.aHook[db.nCommitHook].sequence = sequence;
308311
db.aHook[db.nCommitHook].xHook = x;
309312
db.nCommitHook++;
310313
}
314
+
315
+/*
316
+** Set or unset the query authorizer callback function
317
+*/
318
+void db_set_authorizer(
319
+ int(*xAuth)(void*,int,const char*,const char*,const char*,const char*),
320
+ void *pArg,
321
+ const char *zName /* for tracing */
322
+){
323
+ if( db.xAuth ){
324
+ fossil_panic("multiple active db_set_authorizer() calls");
325
+ }
326
+ if( g.db ) sqlite3_set_authorizer(g.db, xAuth, pArg);
327
+ db.xAuth = xAuth;
328
+ db.pAuthArg = pArg;
329
+ db.zAuthName = zName;
330
+ if( g.fSqlTrace ) fossil_trace("-- set authorizer %s\n", zName);
331
+}
332
+void db_clear_authorizer(void){
333
+ if( db.zAuthName && g.fSqlTrace ){
334
+ fossil_trace("-- discontinue authorizer %s\n", db.zAuthName);
335
+ }
336
+ if( g.db ) sqlite3_set_authorizer(g.db, 0, 0);
337
+ db.xAuth = 0;
338
+ db.pAuthArg = 0;
339
+}
311340
312341
#if INTERFACE
313342
/*
314343
** Possible flags to db_vprepare
315344
*/
@@ -824,34 +853,37 @@
824853
void db_init_database(
825854
const char *zFileName, /* Name of database file to create */
826855
const char *zSchema, /* First part of schema */
827856
... /* Additional SQL to run. Terminate with NULL. */
828857
){
829
- sqlite3 *db;
858
+ sqlite3 *xdb;
830859
int rc;
831860
const char *zSql;
832861
va_list ap;
833862
834
- db = db_open(zFileName ? zFileName : ":memory:");
835
- sqlite3_exec(db, "BEGIN EXCLUSIVE", 0, 0, 0);
836
- rc = sqlite3_exec(db, zSchema, 0, 0, 0);
863
+ xdb = db_open(zFileName ? zFileName : ":memory:");
864
+ sqlite3_exec(xdb, "BEGIN EXCLUSIVE", 0, 0, 0);
865
+ if( db.xAuth ){
866
+ sqlite3_set_authorizer(xdb, db.xAuth, db.pAuthArg);
867
+ }
868
+ rc = sqlite3_exec(xdb, zSchema, 0, 0, 0);
837869
if( rc!=SQLITE_OK ){
838
- db_err("%s", sqlite3_errmsg(db));
870
+ db_err("%s", sqlite3_errmsg(xdb));
839871
}
840872
va_start(ap, zSchema);
841873
while( (zSql = va_arg(ap, const char*))!=0 ){
842
- rc = sqlite3_exec(db, zSql, 0, 0, 0);
874
+ rc = sqlite3_exec(xdb, zSql, 0, 0, 0);
843875
if( rc!=SQLITE_OK ){
844
- db_err("%s", sqlite3_errmsg(db));
876
+ db_err("%s", sqlite3_errmsg(xdb));
845877
}
846878
}
847879
va_end(ap);
848
- sqlite3_exec(db, "COMMIT", 0, 0, 0);
880
+ sqlite3_exec(xdb, "COMMIT", 0, 0, 0);
849881
if( zFileName || g.db!=0 ){
850
- sqlite3_close(db);
882
+ sqlite3_close(xdb);
851883
}else{
852
- g.db = db;
884
+ g.db = xdb;
853885
}
854886
}
855887
856888
/*
857889
** Function to return the number of seconds since 1970. This is
@@ -1639,11 +1671,11 @@
16391671
/*
16401672
** Returns non-zero if the default value for the "allow-symlinks" setting
16411673
** is "on". When on Windows, this always returns false.
16421674
*/
16431675
int db_allow_symlinks_by_default(void){
1644
-#if defined(_WIN32)
1676
+#if defined(_WIN32) || !defined(FOSSIL_LEGACY_ALLOW_SYMLINKS)
16451677
return 0;
16461678
#else
16471679
return 1;
16481680
#endif
16491681
}
@@ -1932,10 +1964,11 @@
19321964
** argument is true. Ignore unfinalized statements when false.
19331965
*/
19341966
void db_close(int reportErrors){
19351967
sqlite3_stmt *pStmt;
19361968
if( g.db==0 ) return;
1969
+ sqlite3_set_authorizer(g.db, 0, 0);
19371970
if( g.fSqlStats ){
19381971
int cur, hiwtr;
19391972
sqlite3_db_status(g.db, SQLITE_DBSTATUS_LOOKASIDE_USED, &cur, &hiwtr, 0);
19401973
fprintf(stderr, "-- LOOKASIDE_USED %10d %10d\n", cur, hiwtr);
19411974
sqlite3_db_status(g.db, SQLITE_DBSTATUS_LOOKASIDE_HIT, &cur, &hiwtr, 0);
@@ -1961,17 +1994,20 @@
19611994
fprintf(stderr, "-- prepared statements %10d\n", db.nPrepare);
19621995
}
19631996
while( db.pAllStmt ){
19641997
db_finalize(db.pAllStmt);
19651998
}
1966
- if( db.nBegin && reportErrors ){
1967
- fossil_warning("Transaction started at %s:%d never commits",
1968
- db.zStartFile, db.iStartLine);
1999
+ if( db.nBegin ){
2000
+ if( reportErrors ){
2001
+ fossil_warning("Transaction started at %s:%d never commits",
2002
+ db.zStartFile, db.iStartLine);
2003
+ }
19692004
db_end_transaction(1);
19702005
}
19712006
pStmt = 0;
1972
- g.dbIgnoreErrors++; /* Stop "database locked" warnings from PRAGMA optimize */
2007
+ sqlite3_busy_timeout(g.db, 0);
2008
+ g.dbIgnoreErrors++; /* Stop "database locked" warnings */
19732009
sqlite3_exec(g.db, "PRAGMA optimize", 0, 0, 0);
19742010
g.dbIgnoreErrors--;
19752011
db_close_config();
19762012
19772013
/* If the localdb has a lot of unused free space,
@@ -2011,10 +2047,11 @@
20112047
if( g.db ){
20122048
int rc;
20132049
sqlite3_wal_checkpoint(g.db, 0);
20142050
rc = sqlite3_close(g.db);
20152051
if( g.fSqlTrace ) fossil_trace("-- sqlite3_close(%d)\n", rc);
2052
+ db_clear_authorizer();
20162053
}
20172054
g.db = 0;
20182055
g.repositoryOpen = 0;
20192056
g.localOpen = 0;
20202057
}
@@ -2740,17 +2777,19 @@
27402777
dflt = 0;
27412778
}
27422779
fossil_free(zVal);
27432780
return dflt;
27442781
}
2782
+#ifdef FOSSIL_LEGACY_ALLOW_SYMLINKS
27452783
int db_get_versioned_boolean(const char *zName, int dflt){
27462784
char *zVal = db_get_versioned(zName, 0);
27472785
if( zVal==0 ) return dflt;
27482786
if( is_truth(zVal) ) return 1;
27492787
if( is_false(zVal) ) return 0;
27502788
return dflt;
27512789
}
2790
+#endif /* FOSSIL_LEGACY_ALLOW_SYMLINKS */
27522791
char *db_lget(const char *zName, const char *zDefault){
27532792
return db_text(zDefault,
27542793
"SELECT value FROM vvar WHERE name=%Q", zName);
27552794
}
27562795
void db_lset(const char *zName, const char *zValue){
@@ -2928,11 +2967,13 @@
29282967
void cmd_open(void){
29292968
int emptyFlag;
29302969
int keepFlag;
29312970
int forceMissingFlag;
29322971
int allowNested;
2972
+#ifdef FOSSIL_LEGACY_ALLOW_SYMLINKS
29332973
int allowSymlinks;
2974
+#endif
29342975
int setmtimeFlag; /* --setmtime. Set mtimes on files */
29352976
static char *azNewArgv[] = { 0, "checkout", "--prompt", 0, 0, 0, 0 };
29362977
29372978
url_proxy_options();
29382979
emptyFlag = find_option("empty",0,0)!=0;
@@ -2959,10 +3000,11 @@
29593000
}else if( db_exists("SELECT 1 FROM event WHERE type='ci'") ){
29603001
g.zOpenRevision = db_get("main-branch", 0);
29613002
}
29623003
}
29633004
3005
+#ifdef FOSSIL_LEGACY_ALLOW_SYMLINKS
29643006
if( g.zOpenRevision ){
29653007
/* Since the repository is open and we know the revision now,
29663008
** refresh the allow-symlinks flag. Since neither the local
29673009
** checkout nor the configuration database are open at this
29683010
** point, this should always return the versioned setting,
@@ -2972,10 +3014,11 @@
29723014
** repository or global configuration databases only. */
29733015
allowSymlinks = db_get_versioned_boolean("allow-symlinks", -1);
29743016
}else{
29753017
allowSymlinks = -1; /* Use non-versioned settings only. */
29763018
}
3019
+#endif
29773020
29783021
#if defined(_WIN32) || defined(__CYGWIN__)
29793022
# define LOCALDB_NAME "./_FOSSIL_"
29803023
#else
29813024
# define LOCALDB_NAME "./.fslckout"
@@ -2985,10 +3028,11 @@
29853028
"COMMIT; PRAGMA journal_mode=WAL; BEGIN;",
29863029
#endif
29873030
(char*)0);
29883031
db_delete_on_failure(LOCALDB_NAME);
29893032
db_open_local(0);
3033
+#ifdef FOSSIL_LEGACY_ALLOW_SYMLINKS
29903034
if( allowSymlinks>=0 ){
29913035
/* Use the value from the versioned setting, which was read
29923036
** prior to opening the local checkout (i.e. which is most
29933037
** likely empty and does not actually contain any versioned
29943038
** setting files yet). Normally, this value would be given
@@ -3001,10 +3045,11 @@
30013045
** point, this will probably be the setting value from the
30023046
** repository or global configuration databases. */
30033047
g.allowSymlinks = db_get_boolean("allow-symlinks",
30043048
db_allow_symlinks_by_default());
30053049
}
3050
+#endif /* FOSSIL_LEGACY_ALLOW_SYMLINKS */
30063051
db_lset("repository", g.argv[2]);
30073052
db_record_repository_filename(g.argv[2]);
30083053
db_set_checkout(0);
30093054
azNewArgv[0] = g.argv[0];
30103055
g.argv = azNewArgv;
@@ -3107,11 +3152,29 @@
31073152
** SETTING: admin-log boolean default=off
31083153
**
31093154
** When the admin-log setting is enabled, configuration changes are recorded
31103155
** in the "admin_log" table of the repository.
31113156
*/
3112
-#if defined(_WIN32)
3157
+#if !defined(FOSSIL_LEGACY_ALLOW_SYMLINKS)
3158
+/*
3159
+** SETTING: allow-symlinks boolean default=off
3160
+**
3161
+** When allow-symlinks is OFF (which is the default and recommended setting)
3162
+** symbolic links are treated like text files that contain a single line of
3163
+** content which is the name of their target. If allow-symlinks is ON,
3164
+** the symbolic links are actually followed.
3165
+**
3166
+** The use of symbolic links is dangerous. If you checkout a maliciously
3167
+** crafted checkin that contains symbolic links, it is possible that files
3168
+** outside of the working directory might be overwritten.
3169
+**
3170
+** Keep this setting OFF unless you have a very good reason to turn it
3171
+** on and you implicitly trust the integrity of the repositories you
3172
+** open.
3173
+*/
3174
+#endif
3175
+#if defined(_WIN32) && defined(FOSSIL_LEGACY_ALLOW_SYMLINKS)
31133176
/*
31143177
** SETTING: allow-symlinks boolean default=off versionable
31153178
**
31163179
** When allow-symlinks is OFF, symbolic links in the repository are followed
31173180
** and treated no differently from real files. When allow-symlinks is ON,
@@ -3118,11 +3181,11 @@
31183181
** the object to which the symbolic link points is ignored, and the content
31193182
** of the symbolic link that is stored in the repository is the name of the
31203183
** object to which the symbolic link points.
31213184
*/
31223185
#endif
3123
-#if !defined(_WIN32)
3186
+#if !defined(_WIN32) && defined(FOSSIL_LEGACY_ALLOW_SYMLINKS)
31243187
/*
31253188
** SETTING: allow-symlinks boolean default=on versionable
31263189
**
31273190
** When allow-symlinks is OFF, symbolic links in the repository are followed
31283191
** and treated no differently from real files. When allow-symlinks is ON,
31293192
--- src/db.c
+++ src/db.c
@@ -122,10 +122,13 @@
122 char *azBeforeCommit[5]; /* Commands to run prior to COMMIT */
123 int nBeforeCommit; /* Number of entries in azBeforeCommit */
124 int nPriorChanges; /* sqlite3_total_changes() at transaction start */
125 const char *zStartFile; /* File in which transaction was started */
126 int iStartLine; /* Line of zStartFile where transaction started */
 
 
 
127 } db = {0, 0, 0, 0, 0, 0, };
128
129 /*
130 ** Arrange for the given file to be deleted on a failure.
131 */
@@ -306,10 +309,36 @@
306 }
307 db.aHook[db.nCommitHook].sequence = sequence;
308 db.aHook[db.nCommitHook].xHook = x;
309 db.nCommitHook++;
310 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
311
312 #if INTERFACE
313 /*
314 ** Possible flags to db_vprepare
315 */
@@ -824,34 +853,37 @@
824 void db_init_database(
825 const char *zFileName, /* Name of database file to create */
826 const char *zSchema, /* First part of schema */
827 ... /* Additional SQL to run. Terminate with NULL. */
828 ){
829 sqlite3 *db;
830 int rc;
831 const char *zSql;
832 va_list ap;
833
834 db = db_open(zFileName ? zFileName : ":memory:");
835 sqlite3_exec(db, "BEGIN EXCLUSIVE", 0, 0, 0);
836 rc = sqlite3_exec(db, zSchema, 0, 0, 0);
 
 
 
837 if( rc!=SQLITE_OK ){
838 db_err("%s", sqlite3_errmsg(db));
839 }
840 va_start(ap, zSchema);
841 while( (zSql = va_arg(ap, const char*))!=0 ){
842 rc = sqlite3_exec(db, zSql, 0, 0, 0);
843 if( rc!=SQLITE_OK ){
844 db_err("%s", sqlite3_errmsg(db));
845 }
846 }
847 va_end(ap);
848 sqlite3_exec(db, "COMMIT", 0, 0, 0);
849 if( zFileName || g.db!=0 ){
850 sqlite3_close(db);
851 }else{
852 g.db = db;
853 }
854 }
855
856 /*
857 ** Function to return the number of seconds since 1970. This is
@@ -1639,11 +1671,11 @@
1639 /*
1640 ** Returns non-zero if the default value for the "allow-symlinks" setting
1641 ** is "on". When on Windows, this always returns false.
1642 */
1643 int db_allow_symlinks_by_default(void){
1644 #if defined(_WIN32)
1645 return 0;
1646 #else
1647 return 1;
1648 #endif
1649 }
@@ -1932,10 +1964,11 @@
1932 ** argument is true. Ignore unfinalized statements when false.
1933 */
1934 void db_close(int reportErrors){
1935 sqlite3_stmt *pStmt;
1936 if( g.db==0 ) return;
 
1937 if( g.fSqlStats ){
1938 int cur, hiwtr;
1939 sqlite3_db_status(g.db, SQLITE_DBSTATUS_LOOKASIDE_USED, &cur, &hiwtr, 0);
1940 fprintf(stderr, "-- LOOKASIDE_USED %10d %10d\n", cur, hiwtr);
1941 sqlite3_db_status(g.db, SQLITE_DBSTATUS_LOOKASIDE_HIT, &cur, &hiwtr, 0);
@@ -1961,17 +1994,20 @@
1961 fprintf(stderr, "-- prepared statements %10d\n", db.nPrepare);
1962 }
1963 while( db.pAllStmt ){
1964 db_finalize(db.pAllStmt);
1965 }
1966 if( db.nBegin && reportErrors ){
1967 fossil_warning("Transaction started at %s:%d never commits",
1968 db.zStartFile, db.iStartLine);
 
 
1969 db_end_transaction(1);
1970 }
1971 pStmt = 0;
1972 g.dbIgnoreErrors++; /* Stop "database locked" warnings from PRAGMA optimize */
 
1973 sqlite3_exec(g.db, "PRAGMA optimize", 0, 0, 0);
1974 g.dbIgnoreErrors--;
1975 db_close_config();
1976
1977 /* If the localdb has a lot of unused free space,
@@ -2011,10 +2047,11 @@
2011 if( g.db ){
2012 int rc;
2013 sqlite3_wal_checkpoint(g.db, 0);
2014 rc = sqlite3_close(g.db);
2015 if( g.fSqlTrace ) fossil_trace("-- sqlite3_close(%d)\n", rc);
 
2016 }
2017 g.db = 0;
2018 g.repositoryOpen = 0;
2019 g.localOpen = 0;
2020 }
@@ -2740,17 +2777,19 @@
2740 dflt = 0;
2741 }
2742 fossil_free(zVal);
2743 return dflt;
2744 }
 
2745 int db_get_versioned_boolean(const char *zName, int dflt){
2746 char *zVal = db_get_versioned(zName, 0);
2747 if( zVal==0 ) return dflt;
2748 if( is_truth(zVal) ) return 1;
2749 if( is_false(zVal) ) return 0;
2750 return dflt;
2751 }
 
2752 char *db_lget(const char *zName, const char *zDefault){
2753 return db_text(zDefault,
2754 "SELECT value FROM vvar WHERE name=%Q", zName);
2755 }
2756 void db_lset(const char *zName, const char *zValue){
@@ -2928,11 +2967,13 @@
2928 void cmd_open(void){
2929 int emptyFlag;
2930 int keepFlag;
2931 int forceMissingFlag;
2932 int allowNested;
 
2933 int allowSymlinks;
 
2934 int setmtimeFlag; /* --setmtime. Set mtimes on files */
2935 static char *azNewArgv[] = { 0, "checkout", "--prompt", 0, 0, 0, 0 };
2936
2937 url_proxy_options();
2938 emptyFlag = find_option("empty",0,0)!=0;
@@ -2959,10 +3000,11 @@
2959 }else if( db_exists("SELECT 1 FROM event WHERE type='ci'") ){
2960 g.zOpenRevision = db_get("main-branch", 0);
2961 }
2962 }
2963
 
2964 if( g.zOpenRevision ){
2965 /* Since the repository is open and we know the revision now,
2966 ** refresh the allow-symlinks flag. Since neither the local
2967 ** checkout nor the configuration database are open at this
2968 ** point, this should always return the versioned setting,
@@ -2972,10 +3014,11 @@
2972 ** repository or global configuration databases only. */
2973 allowSymlinks = db_get_versioned_boolean("allow-symlinks", -1);
2974 }else{
2975 allowSymlinks = -1; /* Use non-versioned settings only. */
2976 }
 
2977
2978 #if defined(_WIN32) || defined(__CYGWIN__)
2979 # define LOCALDB_NAME "./_FOSSIL_"
2980 #else
2981 # define LOCALDB_NAME "./.fslckout"
@@ -2985,10 +3028,11 @@
2985 "COMMIT; PRAGMA journal_mode=WAL; BEGIN;",
2986 #endif
2987 (char*)0);
2988 db_delete_on_failure(LOCALDB_NAME);
2989 db_open_local(0);
 
2990 if( allowSymlinks>=0 ){
2991 /* Use the value from the versioned setting, which was read
2992 ** prior to opening the local checkout (i.e. which is most
2993 ** likely empty and does not actually contain any versioned
2994 ** setting files yet). Normally, this value would be given
@@ -3001,10 +3045,11 @@
3001 ** point, this will probably be the setting value from the
3002 ** repository or global configuration databases. */
3003 g.allowSymlinks = db_get_boolean("allow-symlinks",
3004 db_allow_symlinks_by_default());
3005 }
 
3006 db_lset("repository", g.argv[2]);
3007 db_record_repository_filename(g.argv[2]);
3008 db_set_checkout(0);
3009 azNewArgv[0] = g.argv[0];
3010 g.argv = azNewArgv;
@@ -3107,11 +3152,29 @@
3107 ** SETTING: admin-log boolean default=off
3108 **
3109 ** When the admin-log setting is enabled, configuration changes are recorded
3110 ** in the "admin_log" table of the repository.
3111 */
3112 #if defined(_WIN32)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3113 /*
3114 ** SETTING: allow-symlinks boolean default=off versionable
3115 **
3116 ** When allow-symlinks is OFF, symbolic links in the repository are followed
3117 ** and treated no differently from real files. When allow-symlinks is ON,
@@ -3118,11 +3181,11 @@
3118 ** the object to which the symbolic link points is ignored, and the content
3119 ** of the symbolic link that is stored in the repository is the name of the
3120 ** object to which the symbolic link points.
3121 */
3122 #endif
3123 #if !defined(_WIN32)
3124 /*
3125 ** SETTING: allow-symlinks boolean default=on versionable
3126 **
3127 ** When allow-symlinks is OFF, symbolic links in the repository are followed
3128 ** and treated no differently from real files. When allow-symlinks is ON,
3129
--- src/db.c
+++ src/db.c
@@ -122,10 +122,13 @@
122 char *azBeforeCommit[5]; /* Commands to run prior to COMMIT */
123 int nBeforeCommit; /* Number of entries in azBeforeCommit */
124 int nPriorChanges; /* sqlite3_total_changes() at transaction start */
125 const char *zStartFile; /* File in which transaction was started */
126 int iStartLine; /* Line of zStartFile where transaction started */
127 int (*xAuth)(void*,int,const char*,const char*,const char*,const char*);
128 void *pAuthArg; /* Argument to the authorizer */
129 const char *zAuthName; /* Name of the authorizer */
130 } db = {0, 0, 0, 0, 0, 0, };
131
132 /*
133 ** Arrange for the given file to be deleted on a failure.
134 */
@@ -306,10 +309,36 @@
309 }
310 db.aHook[db.nCommitHook].sequence = sequence;
311 db.aHook[db.nCommitHook].xHook = x;
312 db.nCommitHook++;
313 }
314
315 /*
316 ** Set or unset the query authorizer callback function
317 */
318 void db_set_authorizer(
319 int(*xAuth)(void*,int,const char*,const char*,const char*,const char*),
320 void *pArg,
321 const char *zName /* for tracing */
322 ){
323 if( db.xAuth ){
324 fossil_panic("multiple active db_set_authorizer() calls");
325 }
326 if( g.db ) sqlite3_set_authorizer(g.db, xAuth, pArg);
327 db.xAuth = xAuth;
328 db.pAuthArg = pArg;
329 db.zAuthName = zName;
330 if( g.fSqlTrace ) fossil_trace("-- set authorizer %s\n", zName);
331 }
332 void db_clear_authorizer(void){
333 if( db.zAuthName && g.fSqlTrace ){
334 fossil_trace("-- discontinue authorizer %s\n", db.zAuthName);
335 }
336 if( g.db ) sqlite3_set_authorizer(g.db, 0, 0);
337 db.xAuth = 0;
338 db.pAuthArg = 0;
339 }
340
341 #if INTERFACE
342 /*
343 ** Possible flags to db_vprepare
344 */
@@ -824,34 +853,37 @@
853 void db_init_database(
854 const char *zFileName, /* Name of database file to create */
855 const char *zSchema, /* First part of schema */
856 ... /* Additional SQL to run. Terminate with NULL. */
857 ){
858 sqlite3 *xdb;
859 int rc;
860 const char *zSql;
861 va_list ap;
862
863 xdb = db_open(zFileName ? zFileName : ":memory:");
864 sqlite3_exec(xdb, "BEGIN EXCLUSIVE", 0, 0, 0);
865 if( db.xAuth ){
866 sqlite3_set_authorizer(xdb, db.xAuth, db.pAuthArg);
867 }
868 rc = sqlite3_exec(xdb, zSchema, 0, 0, 0);
869 if( rc!=SQLITE_OK ){
870 db_err("%s", sqlite3_errmsg(xdb));
871 }
872 va_start(ap, zSchema);
873 while( (zSql = va_arg(ap, const char*))!=0 ){
874 rc = sqlite3_exec(xdb, zSql, 0, 0, 0);
875 if( rc!=SQLITE_OK ){
876 db_err("%s", sqlite3_errmsg(xdb));
877 }
878 }
879 va_end(ap);
880 sqlite3_exec(xdb, "COMMIT", 0, 0, 0);
881 if( zFileName || g.db!=0 ){
882 sqlite3_close(xdb);
883 }else{
884 g.db = xdb;
885 }
886 }
887
888 /*
889 ** Function to return the number of seconds since 1970. This is
@@ -1639,11 +1671,11 @@
1671 /*
1672 ** Returns non-zero if the default value for the "allow-symlinks" setting
1673 ** is "on". When on Windows, this always returns false.
1674 */
1675 int db_allow_symlinks_by_default(void){
1676 #if defined(_WIN32) || !defined(FOSSIL_LEGACY_ALLOW_SYMLINKS)
1677 return 0;
1678 #else
1679 return 1;
1680 #endif
1681 }
@@ -1932,10 +1964,11 @@
1964 ** argument is true. Ignore unfinalized statements when false.
1965 */
1966 void db_close(int reportErrors){
1967 sqlite3_stmt *pStmt;
1968 if( g.db==0 ) return;
1969 sqlite3_set_authorizer(g.db, 0, 0);
1970 if( g.fSqlStats ){
1971 int cur, hiwtr;
1972 sqlite3_db_status(g.db, SQLITE_DBSTATUS_LOOKASIDE_USED, &cur, &hiwtr, 0);
1973 fprintf(stderr, "-- LOOKASIDE_USED %10d %10d\n", cur, hiwtr);
1974 sqlite3_db_status(g.db, SQLITE_DBSTATUS_LOOKASIDE_HIT, &cur, &hiwtr, 0);
@@ -1961,17 +1994,20 @@
1994 fprintf(stderr, "-- prepared statements %10d\n", db.nPrepare);
1995 }
1996 while( db.pAllStmt ){
1997 db_finalize(db.pAllStmt);
1998 }
1999 if( db.nBegin ){
2000 if( reportErrors ){
2001 fossil_warning("Transaction started at %s:%d never commits",
2002 db.zStartFile, db.iStartLine);
2003 }
2004 db_end_transaction(1);
2005 }
2006 pStmt = 0;
2007 sqlite3_busy_timeout(g.db, 0);
2008 g.dbIgnoreErrors++; /* Stop "database locked" warnings */
2009 sqlite3_exec(g.db, "PRAGMA optimize", 0, 0, 0);
2010 g.dbIgnoreErrors--;
2011 db_close_config();
2012
2013 /* If the localdb has a lot of unused free space,
@@ -2011,10 +2047,11 @@
2047 if( g.db ){
2048 int rc;
2049 sqlite3_wal_checkpoint(g.db, 0);
2050 rc = sqlite3_close(g.db);
2051 if( g.fSqlTrace ) fossil_trace("-- sqlite3_close(%d)\n", rc);
2052 db_clear_authorizer();
2053 }
2054 g.db = 0;
2055 g.repositoryOpen = 0;
2056 g.localOpen = 0;
2057 }
@@ -2740,17 +2777,19 @@
2777 dflt = 0;
2778 }
2779 fossil_free(zVal);
2780 return dflt;
2781 }
2782 #ifdef FOSSIL_LEGACY_ALLOW_SYMLINKS
2783 int db_get_versioned_boolean(const char *zName, int dflt){
2784 char *zVal = db_get_versioned(zName, 0);
2785 if( zVal==0 ) return dflt;
2786 if( is_truth(zVal) ) return 1;
2787 if( is_false(zVal) ) return 0;
2788 return dflt;
2789 }
2790 #endif /* FOSSIL_LEGACY_ALLOW_SYMLINKS */
2791 char *db_lget(const char *zName, const char *zDefault){
2792 return db_text(zDefault,
2793 "SELECT value FROM vvar WHERE name=%Q", zName);
2794 }
2795 void db_lset(const char *zName, const char *zValue){
@@ -2928,11 +2967,13 @@
2967 void cmd_open(void){
2968 int emptyFlag;
2969 int keepFlag;
2970 int forceMissingFlag;
2971 int allowNested;
2972 #ifdef FOSSIL_LEGACY_ALLOW_SYMLINKS
2973 int allowSymlinks;
2974 #endif
2975 int setmtimeFlag; /* --setmtime. Set mtimes on files */
2976 static char *azNewArgv[] = { 0, "checkout", "--prompt", 0, 0, 0, 0 };
2977
2978 url_proxy_options();
2979 emptyFlag = find_option("empty",0,0)!=0;
@@ -2959,10 +3000,11 @@
3000 }else if( db_exists("SELECT 1 FROM event WHERE type='ci'") ){
3001 g.zOpenRevision = db_get("main-branch", 0);
3002 }
3003 }
3004
3005 #ifdef FOSSIL_LEGACY_ALLOW_SYMLINKS
3006 if( g.zOpenRevision ){
3007 /* Since the repository is open and we know the revision now,
3008 ** refresh the allow-symlinks flag. Since neither the local
3009 ** checkout nor the configuration database are open at this
3010 ** point, this should always return the versioned setting,
@@ -2972,10 +3014,11 @@
3014 ** repository or global configuration databases only. */
3015 allowSymlinks = db_get_versioned_boolean("allow-symlinks", -1);
3016 }else{
3017 allowSymlinks = -1; /* Use non-versioned settings only. */
3018 }
3019 #endif
3020
3021 #if defined(_WIN32) || defined(__CYGWIN__)
3022 # define LOCALDB_NAME "./_FOSSIL_"
3023 #else
3024 # define LOCALDB_NAME "./.fslckout"
@@ -2985,10 +3028,11 @@
3028 "COMMIT; PRAGMA journal_mode=WAL; BEGIN;",
3029 #endif
3030 (char*)0);
3031 db_delete_on_failure(LOCALDB_NAME);
3032 db_open_local(0);
3033 #ifdef FOSSIL_LEGACY_ALLOW_SYMLINKS
3034 if( allowSymlinks>=0 ){
3035 /* Use the value from the versioned setting, which was read
3036 ** prior to opening the local checkout (i.e. which is most
3037 ** likely empty and does not actually contain any versioned
3038 ** setting files yet). Normally, this value would be given
@@ -3001,10 +3045,11 @@
3045 ** point, this will probably be the setting value from the
3046 ** repository or global configuration databases. */
3047 g.allowSymlinks = db_get_boolean("allow-symlinks",
3048 db_allow_symlinks_by_default());
3049 }
3050 #endif /* FOSSIL_LEGACY_ALLOW_SYMLINKS */
3051 db_lset("repository", g.argv[2]);
3052 db_record_repository_filename(g.argv[2]);
3053 db_set_checkout(0);
3054 azNewArgv[0] = g.argv[0];
3055 g.argv = azNewArgv;
@@ -3107,11 +3152,29 @@
3152 ** SETTING: admin-log boolean default=off
3153 **
3154 ** When the admin-log setting is enabled, configuration changes are recorded
3155 ** in the "admin_log" table of the repository.
3156 */
3157 #if !defined(FOSSIL_LEGACY_ALLOW_SYMLINKS)
3158 /*
3159 ** SETTING: allow-symlinks boolean default=off
3160 **
3161 ** When allow-symlinks is OFF (which is the default and recommended setting)
3162 ** symbolic links are treated like text files that contain a single line of
3163 ** content which is the name of their target. If allow-symlinks is ON,
3164 ** the symbolic links are actually followed.
3165 **
3166 ** The use of symbolic links is dangerous. If you checkout a maliciously
3167 ** crafted checkin that contains symbolic links, it is possible that files
3168 ** outside of the working directory might be overwritten.
3169 **
3170 ** Keep this setting OFF unless you have a very good reason to turn it
3171 ** on and you implicitly trust the integrity of the repositories you
3172 ** open.
3173 */
3174 #endif
3175 #if defined(_WIN32) && defined(FOSSIL_LEGACY_ALLOW_SYMLINKS)
3176 /*
3177 ** SETTING: allow-symlinks boolean default=off versionable
3178 **
3179 ** When allow-symlinks is OFF, symbolic links in the repository are followed
3180 ** and treated no differently from real files. When allow-symlinks is ON,
@@ -3118,11 +3181,11 @@
3181 ** the object to which the symbolic link points is ignored, and the content
3182 ** of the symbolic link that is stored in the repository is the name of the
3183 ** object to which the symbolic link points.
3184 */
3185 #endif
3186 #if !defined(_WIN32) && defined(FOSSIL_LEGACY_ALLOW_SYMLINKS)
3187 /*
3188 ** SETTING: allow-symlinks boolean default=on versionable
3189 **
3190 ** When allow-symlinks is OFF, symbolic links in the repository are followed
3191 ** and treated no differently from real files. When allow-symlinks is ON,
3192
+80 -17
--- src/db.c
+++ src/db.c
@@ -122,10 +122,13 @@
122122
char *azBeforeCommit[5]; /* Commands to run prior to COMMIT */
123123
int nBeforeCommit; /* Number of entries in azBeforeCommit */
124124
int nPriorChanges; /* sqlite3_total_changes() at transaction start */
125125
const char *zStartFile; /* File in which transaction was started */
126126
int iStartLine; /* Line of zStartFile where transaction started */
127
+ int (*xAuth)(void*,int,const char*,const char*,const char*,const char*);
128
+ void *pAuthArg; /* Argument to the authorizer */
129
+ const char *zAuthName; /* Name of the authorizer */
127130
} db = {0, 0, 0, 0, 0, 0, };
128131
129132
/*
130133
** Arrange for the given file to be deleted on a failure.
131134
*/
@@ -306,10 +309,36 @@
306309
}
307310
db.aHook[db.nCommitHook].sequence = sequence;
308311
db.aHook[db.nCommitHook].xHook = x;
309312
db.nCommitHook++;
310313
}
314
+
315
+/*
316
+** Set or unset the query authorizer callback function
317
+*/
318
+void db_set_authorizer(
319
+ int(*xAuth)(void*,int,const char*,const char*,const char*,const char*),
320
+ void *pArg,
321
+ const char *zName /* for tracing */
322
+){
323
+ if( db.xAuth ){
324
+ fossil_panic("multiple active db_set_authorizer() calls");
325
+ }
326
+ if( g.db ) sqlite3_set_authorizer(g.db, xAuth, pArg);
327
+ db.xAuth = xAuth;
328
+ db.pAuthArg = pArg;
329
+ db.zAuthName = zName;
330
+ if( g.fSqlTrace ) fossil_trace("-- set authorizer %s\n", zName);
331
+}
332
+void db_clear_authorizer(void){
333
+ if( db.zAuthName && g.fSqlTrace ){
334
+ fossil_trace("-- discontinue authorizer %s\n", db.zAuthName);
335
+ }
336
+ if( g.db ) sqlite3_set_authorizer(g.db, 0, 0);
337
+ db.xAuth = 0;
338
+ db.pAuthArg = 0;
339
+}
311340
312341
#if INTERFACE
313342
/*
314343
** Possible flags to db_vprepare
315344
*/
@@ -824,34 +853,37 @@
824853
void db_init_database(
825854
const char *zFileName, /* Name of database file to create */
826855
const char *zSchema, /* First part of schema */
827856
... /* Additional SQL to run. Terminate with NULL. */
828857
){
829
- sqlite3 *db;
858
+ sqlite3 *xdb;
830859
int rc;
831860
const char *zSql;
832861
va_list ap;
833862
834
- db = db_open(zFileName ? zFileName : ":memory:");
835
- sqlite3_exec(db, "BEGIN EXCLUSIVE", 0, 0, 0);
836
- rc = sqlite3_exec(db, zSchema, 0, 0, 0);
863
+ xdb = db_open(zFileName ? zFileName : ":memory:");
864
+ sqlite3_exec(xdb, "BEGIN EXCLUSIVE", 0, 0, 0);
865
+ if( db.xAuth ){
866
+ sqlite3_set_authorizer(xdb, db.xAuth, db.pAuthArg);
867
+ }
868
+ rc = sqlite3_exec(xdb, zSchema, 0, 0, 0);
837869
if( rc!=SQLITE_OK ){
838
- db_err("%s", sqlite3_errmsg(db));
870
+ db_err("%s", sqlite3_errmsg(xdb));
839871
}
840872
va_start(ap, zSchema);
841873
while( (zSql = va_arg(ap, const char*))!=0 ){
842
- rc = sqlite3_exec(db, zSql, 0, 0, 0);
874
+ rc = sqlite3_exec(xdb, zSql, 0, 0, 0);
843875
if( rc!=SQLITE_OK ){
844
- db_err("%s", sqlite3_errmsg(db));
876
+ db_err("%s", sqlite3_errmsg(xdb));
845877
}
846878
}
847879
va_end(ap);
848
- sqlite3_exec(db, "COMMIT", 0, 0, 0);
880
+ sqlite3_exec(xdb, "COMMIT", 0, 0, 0);
849881
if( zFileName || g.db!=0 ){
850
- sqlite3_close(db);
882
+ sqlite3_close(xdb);
851883
}else{
852
- g.db = db;
884
+ g.db = xdb;
853885
}
854886
}
855887
856888
/*
857889
** Function to return the number of seconds since 1970. This is
@@ -1639,11 +1671,11 @@
16391671
/*
16401672
** Returns non-zero if the default value for the "allow-symlinks" setting
16411673
** is "on". When on Windows, this always returns false.
16421674
*/
16431675
int db_allow_symlinks_by_default(void){
1644
-#if defined(_WIN32)
1676
+#if defined(_WIN32) || !defined(FOSSIL_LEGACY_ALLOW_SYMLINKS)
16451677
return 0;
16461678
#else
16471679
return 1;
16481680
#endif
16491681
}
@@ -1932,10 +1964,11 @@
19321964
** argument is true. Ignore unfinalized statements when false.
19331965
*/
19341966
void db_close(int reportErrors){
19351967
sqlite3_stmt *pStmt;
19361968
if( g.db==0 ) return;
1969
+ sqlite3_set_authorizer(g.db, 0, 0);
19371970
if( g.fSqlStats ){
19381971
int cur, hiwtr;
19391972
sqlite3_db_status(g.db, SQLITE_DBSTATUS_LOOKASIDE_USED, &cur, &hiwtr, 0);
19401973
fprintf(stderr, "-- LOOKASIDE_USED %10d %10d\n", cur, hiwtr);
19411974
sqlite3_db_status(g.db, SQLITE_DBSTATUS_LOOKASIDE_HIT, &cur, &hiwtr, 0);
@@ -1961,17 +1994,20 @@
19611994
fprintf(stderr, "-- prepared statements %10d\n", db.nPrepare);
19621995
}
19631996
while( db.pAllStmt ){
19641997
db_finalize(db.pAllStmt);
19651998
}
1966
- if( db.nBegin && reportErrors ){
1967
- fossil_warning("Transaction started at %s:%d never commits",
1968
- db.zStartFile, db.iStartLine);
1999
+ if( db.nBegin ){
2000
+ if( reportErrors ){
2001
+ fossil_warning("Transaction started at %s:%d never commits",
2002
+ db.zStartFile, db.iStartLine);
2003
+ }
19692004
db_end_transaction(1);
19702005
}
19712006
pStmt = 0;
1972
- g.dbIgnoreErrors++; /* Stop "database locked" warnings from PRAGMA optimize */
2007
+ sqlite3_busy_timeout(g.db, 0);
2008
+ g.dbIgnoreErrors++; /* Stop "database locked" warnings */
19732009
sqlite3_exec(g.db, "PRAGMA optimize", 0, 0, 0);
19742010
g.dbIgnoreErrors--;
19752011
db_close_config();
19762012
19772013
/* If the localdb has a lot of unused free space,
@@ -2011,10 +2047,11 @@
20112047
if( g.db ){
20122048
int rc;
20132049
sqlite3_wal_checkpoint(g.db, 0);
20142050
rc = sqlite3_close(g.db);
20152051
if( g.fSqlTrace ) fossil_trace("-- sqlite3_close(%d)\n", rc);
2052
+ db_clear_authorizer();
20162053
}
20172054
g.db = 0;
20182055
g.repositoryOpen = 0;
20192056
g.localOpen = 0;
20202057
}
@@ -2740,17 +2777,19 @@
27402777
dflt = 0;
27412778
}
27422779
fossil_free(zVal);
27432780
return dflt;
27442781
}
2782
+#ifdef FOSSIL_LEGACY_ALLOW_SYMLINKS
27452783
int db_get_versioned_boolean(const char *zName, int dflt){
27462784
char *zVal = db_get_versioned(zName, 0);
27472785
if( zVal==0 ) return dflt;
27482786
if( is_truth(zVal) ) return 1;
27492787
if( is_false(zVal) ) return 0;
27502788
return dflt;
27512789
}
2790
+#endif /* FOSSIL_LEGACY_ALLOW_SYMLINKS */
27522791
char *db_lget(const char *zName, const char *zDefault){
27532792
return db_text(zDefault,
27542793
"SELECT value FROM vvar WHERE name=%Q", zName);
27552794
}
27562795
void db_lset(const char *zName, const char *zValue){
@@ -2928,11 +2967,13 @@
29282967
void cmd_open(void){
29292968
int emptyFlag;
29302969
int keepFlag;
29312970
int forceMissingFlag;
29322971
int allowNested;
2972
+#ifdef FOSSIL_LEGACY_ALLOW_SYMLINKS
29332973
int allowSymlinks;
2974
+#endif
29342975
int setmtimeFlag; /* --setmtime. Set mtimes on files */
29352976
static char *azNewArgv[] = { 0, "checkout", "--prompt", 0, 0, 0, 0 };
29362977
29372978
url_proxy_options();
29382979
emptyFlag = find_option("empty",0,0)!=0;
@@ -2959,10 +3000,11 @@
29593000
}else if( db_exists("SELECT 1 FROM event WHERE type='ci'") ){
29603001
g.zOpenRevision = db_get("main-branch", 0);
29613002
}
29623003
}
29633004
3005
+#ifdef FOSSIL_LEGACY_ALLOW_SYMLINKS
29643006
if( g.zOpenRevision ){
29653007
/* Since the repository is open and we know the revision now,
29663008
** refresh the allow-symlinks flag. Since neither the local
29673009
** checkout nor the configuration database are open at this
29683010
** point, this should always return the versioned setting,
@@ -2972,10 +3014,11 @@
29723014
** repository or global configuration databases only. */
29733015
allowSymlinks = db_get_versioned_boolean("allow-symlinks", -1);
29743016
}else{
29753017
allowSymlinks = -1; /* Use non-versioned settings only. */
29763018
}
3019
+#endif
29773020
29783021
#if defined(_WIN32) || defined(__CYGWIN__)
29793022
# define LOCALDB_NAME "./_FOSSIL_"
29803023
#else
29813024
# define LOCALDB_NAME "./.fslckout"
@@ -2985,10 +3028,11 @@
29853028
"COMMIT; PRAGMA journal_mode=WAL; BEGIN;",
29863029
#endif
29873030
(char*)0);
29883031
db_delete_on_failure(LOCALDB_NAME);
29893032
db_open_local(0);
3033
+#ifdef FOSSIL_LEGACY_ALLOW_SYMLINKS
29903034
if( allowSymlinks>=0 ){
29913035
/* Use the value from the versioned setting, which was read
29923036
** prior to opening the local checkout (i.e. which is most
29933037
** likely empty and does not actually contain any versioned
29943038
** setting files yet). Normally, this value would be given
@@ -3001,10 +3045,11 @@
30013045
** point, this will probably be the setting value from the
30023046
** repository or global configuration databases. */
30033047
g.allowSymlinks = db_get_boolean("allow-symlinks",
30043048
db_allow_symlinks_by_default());
30053049
}
3050
+#endif /* FOSSIL_LEGACY_ALLOW_SYMLINKS */
30063051
db_lset("repository", g.argv[2]);
30073052
db_record_repository_filename(g.argv[2]);
30083053
db_set_checkout(0);
30093054
azNewArgv[0] = g.argv[0];
30103055
g.argv = azNewArgv;
@@ -3107,11 +3152,29 @@
31073152
** SETTING: admin-log boolean default=off
31083153
**
31093154
** When the admin-log setting is enabled, configuration changes are recorded
31103155
** in the "admin_log" table of the repository.
31113156
*/
3112
-#if defined(_WIN32)
3157
+#if !defined(FOSSIL_LEGACY_ALLOW_SYMLINKS)
3158
+/*
3159
+** SETTING: allow-symlinks boolean default=off
3160
+**
3161
+** When allow-symlinks is OFF (which is the default and recommended setting)
3162
+** symbolic links are treated like text files that contain a single line of
3163
+** content which is the name of their target. If allow-symlinks is ON,
3164
+** the symbolic links are actually followed.
3165
+**
3166
+** The use of symbolic links is dangerous. If you checkout a maliciously
3167
+** crafted checkin that contains symbolic links, it is possible that files
3168
+** outside of the working directory might be overwritten.
3169
+**
3170
+** Keep this setting OFF unless you have a very good reason to turn it
3171
+** on and you implicitly trust the integrity of the repositories you
3172
+** open.
3173
+*/
3174
+#endif
3175
+#if defined(_WIN32) && defined(FOSSIL_LEGACY_ALLOW_SYMLINKS)
31133176
/*
31143177
** SETTING: allow-symlinks boolean default=off versionable
31153178
**
31163179
** When allow-symlinks is OFF, symbolic links in the repository are followed
31173180
** and treated no differently from real files. When allow-symlinks is ON,
@@ -3118,11 +3181,11 @@
31183181
** the object to which the symbolic link points is ignored, and the content
31193182
** of the symbolic link that is stored in the repository is the name of the
31203183
** object to which the symbolic link points.
31213184
*/
31223185
#endif
3123
-#if !defined(_WIN32)
3186
+#if !defined(_WIN32) && defined(FOSSIL_LEGACY_ALLOW_SYMLINKS)
31243187
/*
31253188
** SETTING: allow-symlinks boolean default=on versionable
31263189
**
31273190
** When allow-symlinks is OFF, symbolic links in the repository are followed
31283191
** and treated no differently from real files. When allow-symlinks is ON,
31293192
--- src/db.c
+++ src/db.c
@@ -122,10 +122,13 @@
122 char *azBeforeCommit[5]; /* Commands to run prior to COMMIT */
123 int nBeforeCommit; /* Number of entries in azBeforeCommit */
124 int nPriorChanges; /* sqlite3_total_changes() at transaction start */
125 const char *zStartFile; /* File in which transaction was started */
126 int iStartLine; /* Line of zStartFile where transaction started */
 
 
 
127 } db = {0, 0, 0, 0, 0, 0, };
128
129 /*
130 ** Arrange for the given file to be deleted on a failure.
131 */
@@ -306,10 +309,36 @@
306 }
307 db.aHook[db.nCommitHook].sequence = sequence;
308 db.aHook[db.nCommitHook].xHook = x;
309 db.nCommitHook++;
310 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
311
312 #if INTERFACE
313 /*
314 ** Possible flags to db_vprepare
315 */
@@ -824,34 +853,37 @@
824 void db_init_database(
825 const char *zFileName, /* Name of database file to create */
826 const char *zSchema, /* First part of schema */
827 ... /* Additional SQL to run. Terminate with NULL. */
828 ){
829 sqlite3 *db;
830 int rc;
831 const char *zSql;
832 va_list ap;
833
834 db = db_open(zFileName ? zFileName : ":memory:");
835 sqlite3_exec(db, "BEGIN EXCLUSIVE", 0, 0, 0);
836 rc = sqlite3_exec(db, zSchema, 0, 0, 0);
 
 
 
837 if( rc!=SQLITE_OK ){
838 db_err("%s", sqlite3_errmsg(db));
839 }
840 va_start(ap, zSchema);
841 while( (zSql = va_arg(ap, const char*))!=0 ){
842 rc = sqlite3_exec(db, zSql, 0, 0, 0);
843 if( rc!=SQLITE_OK ){
844 db_err("%s", sqlite3_errmsg(db));
845 }
846 }
847 va_end(ap);
848 sqlite3_exec(db, "COMMIT", 0, 0, 0);
849 if( zFileName || g.db!=0 ){
850 sqlite3_close(db);
851 }else{
852 g.db = db;
853 }
854 }
855
856 /*
857 ** Function to return the number of seconds since 1970. This is
@@ -1639,11 +1671,11 @@
1639 /*
1640 ** Returns non-zero if the default value for the "allow-symlinks" setting
1641 ** is "on". When on Windows, this always returns false.
1642 */
1643 int db_allow_symlinks_by_default(void){
1644 #if defined(_WIN32)
1645 return 0;
1646 #else
1647 return 1;
1648 #endif
1649 }
@@ -1932,10 +1964,11 @@
1932 ** argument is true. Ignore unfinalized statements when false.
1933 */
1934 void db_close(int reportErrors){
1935 sqlite3_stmt *pStmt;
1936 if( g.db==0 ) return;
 
1937 if( g.fSqlStats ){
1938 int cur, hiwtr;
1939 sqlite3_db_status(g.db, SQLITE_DBSTATUS_LOOKASIDE_USED, &cur, &hiwtr, 0);
1940 fprintf(stderr, "-- LOOKASIDE_USED %10d %10d\n", cur, hiwtr);
1941 sqlite3_db_status(g.db, SQLITE_DBSTATUS_LOOKASIDE_HIT, &cur, &hiwtr, 0);
@@ -1961,17 +1994,20 @@
1961 fprintf(stderr, "-- prepared statements %10d\n", db.nPrepare);
1962 }
1963 while( db.pAllStmt ){
1964 db_finalize(db.pAllStmt);
1965 }
1966 if( db.nBegin && reportErrors ){
1967 fossil_warning("Transaction started at %s:%d never commits",
1968 db.zStartFile, db.iStartLine);
 
 
1969 db_end_transaction(1);
1970 }
1971 pStmt = 0;
1972 g.dbIgnoreErrors++; /* Stop "database locked" warnings from PRAGMA optimize */
 
1973 sqlite3_exec(g.db, "PRAGMA optimize", 0, 0, 0);
1974 g.dbIgnoreErrors--;
1975 db_close_config();
1976
1977 /* If the localdb has a lot of unused free space,
@@ -2011,10 +2047,11 @@
2011 if( g.db ){
2012 int rc;
2013 sqlite3_wal_checkpoint(g.db, 0);
2014 rc = sqlite3_close(g.db);
2015 if( g.fSqlTrace ) fossil_trace("-- sqlite3_close(%d)\n", rc);
 
2016 }
2017 g.db = 0;
2018 g.repositoryOpen = 0;
2019 g.localOpen = 0;
2020 }
@@ -2740,17 +2777,19 @@
2740 dflt = 0;
2741 }
2742 fossil_free(zVal);
2743 return dflt;
2744 }
 
2745 int db_get_versioned_boolean(const char *zName, int dflt){
2746 char *zVal = db_get_versioned(zName, 0);
2747 if( zVal==0 ) return dflt;
2748 if( is_truth(zVal) ) return 1;
2749 if( is_false(zVal) ) return 0;
2750 return dflt;
2751 }
 
2752 char *db_lget(const char *zName, const char *zDefault){
2753 return db_text(zDefault,
2754 "SELECT value FROM vvar WHERE name=%Q", zName);
2755 }
2756 void db_lset(const char *zName, const char *zValue){
@@ -2928,11 +2967,13 @@
2928 void cmd_open(void){
2929 int emptyFlag;
2930 int keepFlag;
2931 int forceMissingFlag;
2932 int allowNested;
 
2933 int allowSymlinks;
 
2934 int setmtimeFlag; /* --setmtime. Set mtimes on files */
2935 static char *azNewArgv[] = { 0, "checkout", "--prompt", 0, 0, 0, 0 };
2936
2937 url_proxy_options();
2938 emptyFlag = find_option("empty",0,0)!=0;
@@ -2959,10 +3000,11 @@
2959 }else if( db_exists("SELECT 1 FROM event WHERE type='ci'") ){
2960 g.zOpenRevision = db_get("main-branch", 0);
2961 }
2962 }
2963
 
2964 if( g.zOpenRevision ){
2965 /* Since the repository is open and we know the revision now,
2966 ** refresh the allow-symlinks flag. Since neither the local
2967 ** checkout nor the configuration database are open at this
2968 ** point, this should always return the versioned setting,
@@ -2972,10 +3014,11 @@
2972 ** repository or global configuration databases only. */
2973 allowSymlinks = db_get_versioned_boolean("allow-symlinks", -1);
2974 }else{
2975 allowSymlinks = -1; /* Use non-versioned settings only. */
2976 }
 
2977
2978 #if defined(_WIN32) || defined(__CYGWIN__)
2979 # define LOCALDB_NAME "./_FOSSIL_"
2980 #else
2981 # define LOCALDB_NAME "./.fslckout"
@@ -2985,10 +3028,11 @@
2985 "COMMIT; PRAGMA journal_mode=WAL; BEGIN;",
2986 #endif
2987 (char*)0);
2988 db_delete_on_failure(LOCALDB_NAME);
2989 db_open_local(0);
 
2990 if( allowSymlinks>=0 ){
2991 /* Use the value from the versioned setting, which was read
2992 ** prior to opening the local checkout (i.e. which is most
2993 ** likely empty and does not actually contain any versioned
2994 ** setting files yet). Normally, this value would be given
@@ -3001,10 +3045,11 @@
3001 ** point, this will probably be the setting value from the
3002 ** repository or global configuration databases. */
3003 g.allowSymlinks = db_get_boolean("allow-symlinks",
3004 db_allow_symlinks_by_default());
3005 }
 
3006 db_lset("repository", g.argv[2]);
3007 db_record_repository_filename(g.argv[2]);
3008 db_set_checkout(0);
3009 azNewArgv[0] = g.argv[0];
3010 g.argv = azNewArgv;
@@ -3107,11 +3152,29 @@
3107 ** SETTING: admin-log boolean default=off
3108 **
3109 ** When the admin-log setting is enabled, configuration changes are recorded
3110 ** in the "admin_log" table of the repository.
3111 */
3112 #if defined(_WIN32)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3113 /*
3114 ** SETTING: allow-symlinks boolean default=off versionable
3115 **
3116 ** When allow-symlinks is OFF, symbolic links in the repository are followed
3117 ** and treated no differently from real files. When allow-symlinks is ON,
@@ -3118,11 +3181,11 @@
3118 ** the object to which the symbolic link points is ignored, and the content
3119 ** of the symbolic link that is stored in the repository is the name of the
3120 ** object to which the symbolic link points.
3121 */
3122 #endif
3123 #if !defined(_WIN32)
3124 /*
3125 ** SETTING: allow-symlinks boolean default=on versionable
3126 **
3127 ** When allow-symlinks is OFF, symbolic links in the repository are followed
3128 ** and treated no differently from real files. When allow-symlinks is ON,
3129
--- src/db.c
+++ src/db.c
@@ -122,10 +122,13 @@
122 char *azBeforeCommit[5]; /* Commands to run prior to COMMIT */
123 int nBeforeCommit; /* Number of entries in azBeforeCommit */
124 int nPriorChanges; /* sqlite3_total_changes() at transaction start */
125 const char *zStartFile; /* File in which transaction was started */
126 int iStartLine; /* Line of zStartFile where transaction started */
127 int (*xAuth)(void*,int,const char*,const char*,const char*,const char*);
128 void *pAuthArg; /* Argument to the authorizer */
129 const char *zAuthName; /* Name of the authorizer */
130 } db = {0, 0, 0, 0, 0, 0, };
131
132 /*
133 ** Arrange for the given file to be deleted on a failure.
134 */
@@ -306,10 +309,36 @@
309 }
310 db.aHook[db.nCommitHook].sequence = sequence;
311 db.aHook[db.nCommitHook].xHook = x;
312 db.nCommitHook++;
313 }
314
315 /*
316 ** Set or unset the query authorizer callback function
317 */
318 void db_set_authorizer(
319 int(*xAuth)(void*,int,const char*,const char*,const char*,const char*),
320 void *pArg,
321 const char *zName /* for tracing */
322 ){
323 if( db.xAuth ){
324 fossil_panic("multiple active db_set_authorizer() calls");
325 }
326 if( g.db ) sqlite3_set_authorizer(g.db, xAuth, pArg);
327 db.xAuth = xAuth;
328 db.pAuthArg = pArg;
329 db.zAuthName = zName;
330 if( g.fSqlTrace ) fossil_trace("-- set authorizer %s\n", zName);
331 }
332 void db_clear_authorizer(void){
333 if( db.zAuthName && g.fSqlTrace ){
334 fossil_trace("-- discontinue authorizer %s\n", db.zAuthName);
335 }
336 if( g.db ) sqlite3_set_authorizer(g.db, 0, 0);
337 db.xAuth = 0;
338 db.pAuthArg = 0;
339 }
340
341 #if INTERFACE
342 /*
343 ** Possible flags to db_vprepare
344 */
@@ -824,34 +853,37 @@
853 void db_init_database(
854 const char *zFileName, /* Name of database file to create */
855 const char *zSchema, /* First part of schema */
856 ... /* Additional SQL to run. Terminate with NULL. */
857 ){
858 sqlite3 *xdb;
859 int rc;
860 const char *zSql;
861 va_list ap;
862
863 xdb = db_open(zFileName ? zFileName : ":memory:");
864 sqlite3_exec(xdb, "BEGIN EXCLUSIVE", 0, 0, 0);
865 if( db.xAuth ){
866 sqlite3_set_authorizer(xdb, db.xAuth, db.pAuthArg);
867 }
868 rc = sqlite3_exec(xdb, zSchema, 0, 0, 0);
869 if( rc!=SQLITE_OK ){
870 db_err("%s", sqlite3_errmsg(xdb));
871 }
872 va_start(ap, zSchema);
873 while( (zSql = va_arg(ap, const char*))!=0 ){
874 rc = sqlite3_exec(xdb, zSql, 0, 0, 0);
875 if( rc!=SQLITE_OK ){
876 db_err("%s", sqlite3_errmsg(xdb));
877 }
878 }
879 va_end(ap);
880 sqlite3_exec(xdb, "COMMIT", 0, 0, 0);
881 if( zFileName || g.db!=0 ){
882 sqlite3_close(xdb);
883 }else{
884 g.db = xdb;
885 }
886 }
887
888 /*
889 ** Function to return the number of seconds since 1970. This is
@@ -1639,11 +1671,11 @@
1671 /*
1672 ** Returns non-zero if the default value for the "allow-symlinks" setting
1673 ** is "on". When on Windows, this always returns false.
1674 */
1675 int db_allow_symlinks_by_default(void){
1676 #if defined(_WIN32) || !defined(FOSSIL_LEGACY_ALLOW_SYMLINKS)
1677 return 0;
1678 #else
1679 return 1;
1680 #endif
1681 }
@@ -1932,10 +1964,11 @@
1964 ** argument is true. Ignore unfinalized statements when false.
1965 */
1966 void db_close(int reportErrors){
1967 sqlite3_stmt *pStmt;
1968 if( g.db==0 ) return;
1969 sqlite3_set_authorizer(g.db, 0, 0);
1970 if( g.fSqlStats ){
1971 int cur, hiwtr;
1972 sqlite3_db_status(g.db, SQLITE_DBSTATUS_LOOKASIDE_USED, &cur, &hiwtr, 0);
1973 fprintf(stderr, "-- LOOKASIDE_USED %10d %10d\n", cur, hiwtr);
1974 sqlite3_db_status(g.db, SQLITE_DBSTATUS_LOOKASIDE_HIT, &cur, &hiwtr, 0);
@@ -1961,17 +1994,20 @@
1994 fprintf(stderr, "-- prepared statements %10d\n", db.nPrepare);
1995 }
1996 while( db.pAllStmt ){
1997 db_finalize(db.pAllStmt);
1998 }
1999 if( db.nBegin ){
2000 if( reportErrors ){
2001 fossil_warning("Transaction started at %s:%d never commits",
2002 db.zStartFile, db.iStartLine);
2003 }
2004 db_end_transaction(1);
2005 }
2006 pStmt = 0;
2007 sqlite3_busy_timeout(g.db, 0);
2008 g.dbIgnoreErrors++; /* Stop "database locked" warnings */
2009 sqlite3_exec(g.db, "PRAGMA optimize", 0, 0, 0);
2010 g.dbIgnoreErrors--;
2011 db_close_config();
2012
2013 /* If the localdb has a lot of unused free space,
@@ -2011,10 +2047,11 @@
2047 if( g.db ){
2048 int rc;
2049 sqlite3_wal_checkpoint(g.db, 0);
2050 rc = sqlite3_close(g.db);
2051 if( g.fSqlTrace ) fossil_trace("-- sqlite3_close(%d)\n", rc);
2052 db_clear_authorizer();
2053 }
2054 g.db = 0;
2055 g.repositoryOpen = 0;
2056 g.localOpen = 0;
2057 }
@@ -2740,17 +2777,19 @@
2777 dflt = 0;
2778 }
2779 fossil_free(zVal);
2780 return dflt;
2781 }
2782 #ifdef FOSSIL_LEGACY_ALLOW_SYMLINKS
2783 int db_get_versioned_boolean(const char *zName, int dflt){
2784 char *zVal = db_get_versioned(zName, 0);
2785 if( zVal==0 ) return dflt;
2786 if( is_truth(zVal) ) return 1;
2787 if( is_false(zVal) ) return 0;
2788 return dflt;
2789 }
2790 #endif /* FOSSIL_LEGACY_ALLOW_SYMLINKS */
2791 char *db_lget(const char *zName, const char *zDefault){
2792 return db_text(zDefault,
2793 "SELECT value FROM vvar WHERE name=%Q", zName);
2794 }
2795 void db_lset(const char *zName, const char *zValue){
@@ -2928,11 +2967,13 @@
2967 void cmd_open(void){
2968 int emptyFlag;
2969 int keepFlag;
2970 int forceMissingFlag;
2971 int allowNested;
2972 #ifdef FOSSIL_LEGACY_ALLOW_SYMLINKS
2973 int allowSymlinks;
2974 #endif
2975 int setmtimeFlag; /* --setmtime. Set mtimes on files */
2976 static char *azNewArgv[] = { 0, "checkout", "--prompt", 0, 0, 0, 0 };
2977
2978 url_proxy_options();
2979 emptyFlag = find_option("empty",0,0)!=0;
@@ -2959,10 +3000,11 @@
3000 }else if( db_exists("SELECT 1 FROM event WHERE type='ci'") ){
3001 g.zOpenRevision = db_get("main-branch", 0);
3002 }
3003 }
3004
3005 #ifdef FOSSIL_LEGACY_ALLOW_SYMLINKS
3006 if( g.zOpenRevision ){
3007 /* Since the repository is open and we know the revision now,
3008 ** refresh the allow-symlinks flag. Since neither the local
3009 ** checkout nor the configuration database are open at this
3010 ** point, this should always return the versioned setting,
@@ -2972,10 +3014,11 @@
3014 ** repository or global configuration databases only. */
3015 allowSymlinks = db_get_versioned_boolean("allow-symlinks", -1);
3016 }else{
3017 allowSymlinks = -1; /* Use non-versioned settings only. */
3018 }
3019 #endif
3020
3021 #if defined(_WIN32) || defined(__CYGWIN__)
3022 # define LOCALDB_NAME "./_FOSSIL_"
3023 #else
3024 # define LOCALDB_NAME "./.fslckout"
@@ -2985,10 +3028,11 @@
3028 "COMMIT; PRAGMA journal_mode=WAL; BEGIN;",
3029 #endif
3030 (char*)0);
3031 db_delete_on_failure(LOCALDB_NAME);
3032 db_open_local(0);
3033 #ifdef FOSSIL_LEGACY_ALLOW_SYMLINKS
3034 if( allowSymlinks>=0 ){
3035 /* Use the value from the versioned setting, which was read
3036 ** prior to opening the local checkout (i.e. which is most
3037 ** likely empty and does not actually contain any versioned
3038 ** setting files yet). Normally, this value would be given
@@ -3001,10 +3045,11 @@
3045 ** point, this will probably be the setting value from the
3046 ** repository or global configuration databases. */
3047 g.allowSymlinks = db_get_boolean("allow-symlinks",
3048 db_allow_symlinks_by_default());
3049 }
3050 #endif /* FOSSIL_LEGACY_ALLOW_SYMLINKS */
3051 db_lset("repository", g.argv[2]);
3052 db_record_repository_filename(g.argv[2]);
3053 db_set_checkout(0);
3054 azNewArgv[0] = g.argv[0];
3055 g.argv = azNewArgv;
@@ -3107,11 +3152,29 @@
3152 ** SETTING: admin-log boolean default=off
3153 **
3154 ** When the admin-log setting is enabled, configuration changes are recorded
3155 ** in the "admin_log" table of the repository.
3156 */
3157 #if !defined(FOSSIL_LEGACY_ALLOW_SYMLINKS)
3158 /*
3159 ** SETTING: allow-symlinks boolean default=off
3160 **
3161 ** When allow-symlinks is OFF (which is the default and recommended setting)
3162 ** symbolic links are treated like text files that contain a single line of
3163 ** content which is the name of their target. If allow-symlinks is ON,
3164 ** the symbolic links are actually followed.
3165 **
3166 ** The use of symbolic links is dangerous. If you checkout a maliciously
3167 ** crafted checkin that contains symbolic links, it is possible that files
3168 ** outside of the working directory might be overwritten.
3169 **
3170 ** Keep this setting OFF unless you have a very good reason to turn it
3171 ** on and you implicitly trust the integrity of the repositories you
3172 ** open.
3173 */
3174 #endif
3175 #if defined(_WIN32) && defined(FOSSIL_LEGACY_ALLOW_SYMLINKS)
3176 /*
3177 ** SETTING: allow-symlinks boolean default=off versionable
3178 **
3179 ** When allow-symlinks is OFF, symbolic links in the repository are followed
3180 ** and treated no differently from real files. When allow-symlinks is ON,
@@ -3118,11 +3181,11 @@
3181 ** the object to which the symbolic link points is ignored, and the content
3182 ** of the symbolic link that is stored in the repository is the name of the
3183 ** object to which the symbolic link points.
3184 */
3185 #endif
3186 #if !defined(_WIN32) && defined(FOSSIL_LEGACY_ALLOW_SYMLINKS)
3187 /*
3188 ** SETTING: allow-symlinks boolean default=on versionable
3189 **
3190 ** When allow-symlinks is OFF, symbolic links in the repository are followed
3191 ** and treated no differently from real files. When allow-symlinks is ON,
3192
+159 -1
--- src/file.c
+++ src/file.c
@@ -323,10 +323,82 @@
323323
** On Windows, always return False.
324324
*/
325325
int file_islink(const char *zFilename){
326326
return file_perm(zFilename, RepoFILE)==PERM_LNK;
327327
}
328
+
329
+/*
330
+** Check every sub-directory of zRoot along the path to zFile.
331
+** If any sub-directory is really an ordinary file or a symbolic link,
332
+** return an integer which is the length of the prefix of zFile which
333
+** is the name of that object. Return 0 if all no non-directory
334
+** objects are found along the path.
335
+**
336
+** Example: Given inputs
337
+**
338
+** zRoot = /home/alice/project1
339
+** zFile = /home/alice/project1/main/src/js/fileA.js
340
+**
341
+** Look for objects in the following order:
342
+**
343
+** /home/alice/project/main
344
+** /home/alice/project/main/src
345
+** /home/alice/project/main/src/js
346
+**
347
+** If any of those objects exist and are something other than a directory
348
+** then return the length of the name of the first non-directory object
349
+** seen.
350
+*/
351
+int file_nondir_objects_on_path(const char *zRoot, const char *zFile){
352
+ int i = (int)strlen(zRoot);
353
+ char *z = fossil_strdup(zFile);
354
+ assert( fossil_strnicmp(zRoot, z, i)==0 );
355
+ if( i && zRoot[i-1]=='/' ) i--;
356
+ while( z[i]=='/' ){
357
+ int j, rc;
358
+ for(j=i+1; z[j] && z[j]!='/'; j++){}
359
+ if( z[j]!='/' ) break;
360
+ z[j] = 0;
361
+ rc = file_isdir(z, SymFILE);
362
+ if( rc!=1 ){
363
+ if( rc==2 ){
364
+ fossil_free(z);
365
+ return j;
366
+ }
367
+ break;
368
+ }
369
+ z[j] = '/';
370
+ i = j;
371
+ }
372
+ fossil_free(z);
373
+ return 0;
374
+}
375
+
376
+/*
377
+** The file named zFile is suppose to be an in-tree file. Check to
378
+** ensure that it will be safe to write to this file by verifying that
379
+** there are no symlinks or other non-directory objects in between the
380
+** root of the checkout and zFile.
381
+**
382
+** If a problem is found, print a warning message (using fossil_warning())
383
+** and return non-zero. If everything is ok, return zero.
384
+*/
385
+int file_unsafe_in_tree_path(const char *zFile){
386
+ int n;
387
+ if( !file_is_absolute_path(zFile) ){
388
+ fossil_panic("%s is not an absolute pathname",zFile);
389
+ }
390
+ if( fossil_strnicmp(g.zLocalRoot, zFile, (int)strlen(g.zLocalRoot)) ){
391
+ fossil_panic("%s is not a prefix of %s", g.zLocalRoot, zFile);
392
+ }
393
+ n = file_nondir_objects_on_path(g.zLocalRoot, zFile);
394
+ if( n ){
395
+ fossil_warning("cannot write to %s because non-directory object %.*s"
396
+ " is in the way", zFile, n, zFile);
397
+ }
398
+ return n;
399
+}
328400
329401
/*
330402
** Return 1 if zFilename is a directory. Return 0 if zFilename
331403
** does not exist. Return 2 if zFilename exists but is something
332404
** other than a directory.
@@ -529,11 +601,14 @@
529601
*/
530602
int file_setexe(const char *zFilename, int onoff){
531603
int rc = 0;
532604
#if !defined(_WIN32)
533605
struct stat buf;
534
- if( fossil_stat(zFilename, &buf, RepoFILE)!=0 || S_ISLNK(buf.st_mode) ){
606
+ if( fossil_stat(zFilename, &buf, RepoFILE)!=0
607
+ || S_ISLNK(buf.st_mode)
608
+ || S_ISDIR(buf.st_mode)
609
+ ){
535610
return 0;
536611
}
537612
if( onoff ){
538613
int targetMode = (buf.st_mode & 0444)>>2;
539614
if( (buf.st_mode & 0100)==0 ){
@@ -2226,5 +2301,88 @@
22262301
changeCount);
22272302
}else{
22282303
fossil_print("Touched %d file(s)\n", changeCount);
22292304
}
22302305
}
2306
+
2307
+/*
2308
+** Returns non-zero if the specified file name ends with any reserved name,
2309
+** e.g.: _FOSSIL_ or .fslckout. Specifically, it returns 1 for exact match
2310
+** or 2 for a tail match on a longer file name.
2311
+**
2312
+** For the sake of efficiency, zFilename must be a canonical name, e.g. an
2313
+** absolute path using only forward slash ('/') as a directory separator.
2314
+**
2315
+** nFilename must be the length of zFilename. When negative, strlen() will
2316
+** be used to calculate it.
2317
+*/
2318
+int file_is_reserved_name(const char *zFilename, int nFilename){
2319
+ const char *zEnd; /* one-after-the-end of zFilename */
2320
+ int gotSuffix = 0; /* length of suffix (-wal, -shm, -journal) */
2321
+
2322
+ assert( zFilename && "API misuse" );
2323
+ if( nFilename<0 ) nFilename = (int)strlen(zFilename);
2324
+ if( nFilename<8 ) return 0; /* strlen("_FOSSIL_") */
2325
+ zEnd = zFilename + nFilename;
2326
+ if( nFilename>=12 ){ /* strlen("_FOSSIL_-(shm|wal)") */
2327
+ /* Check for (-wal, -shm, -journal) suffixes, with an eye towards
2328
+ ** runtime speed. */
2329
+ if( zEnd[-4]=='-' ){
2330
+ if( fossil_strnicmp("wal", &zEnd[-3], 3)
2331
+ && fossil_strnicmp("shm", &zEnd[-3], 3) ){
2332
+ return 0;
2333
+ }
2334
+ gotSuffix = 4;
2335
+ }else if( nFilename>=16 && zEnd[-8]=='-' ){ /*strlen(_FOSSIL_-journal) */
2336
+ if( fossil_strnicmp("journal", &zEnd[-7], 7) ) return 0;
2337
+ gotSuffix = 8;
2338
+ }
2339
+ if( gotSuffix ){
2340
+ assert( 4==gotSuffix || 8==gotSuffix );
2341
+ zEnd -= gotSuffix;
2342
+ nFilename -= gotSuffix;
2343
+ gotSuffix = 1;
2344
+ }
2345
+ assert( nFilename>=8 && "strlen(_FOSSIL_)" );
2346
+ assert( gotSuffix==0 || gotSuffix==1 );
2347
+ }
2348
+ switch( zEnd[-1] ){
2349
+ case '_':{
2350
+ if( fossil_strnicmp("_FOSSIL_", &zEnd[-8], 8) ) return 0;
2351
+ if( 8==nFilename ) return 1;
2352
+ return zEnd[-9]=='/' ? 2 : gotSuffix;
2353
+ }
2354
+ case 'T':
2355
+ case 't':{
2356
+ if( nFilename<9 || zEnd[-9]!='.'
2357
+ || fossil_strnicmp(".fslckout", &zEnd[-9], 9) ){
2358
+ return 0;
2359
+ }
2360
+ if( 9==nFilename ) return 1;
2361
+ return zEnd[-10]=='/' ? 2 : gotSuffix;
2362
+ }
2363
+ default:{
2364
+ return 0;
2365
+ }
2366
+ }
2367
+}
2368
+
2369
+/*
2370
+** COMMAND: test-is-reserved-name
2371
+**
2372
+** Usage: %fossil test-is-ckout-db FILENAMES...
2373
+**
2374
+** Passes each given name to file_is_reserved_name() and outputs one
2375
+** line per file: the result value of that function followed by the
2376
+** name.
2377
+*/
2378
+void test_is_reserved_name_cmd(void){
2379
+ int i;
2380
+
2381
+ if(g.argc<3){
2382
+ usage("FILENAME_1 [...FILENAME_N]");
2383
+ }
2384
+ for( i = 2; i < g.argc; ++i ){
2385
+ const int check = file_is_reserved_name(g.argv[i], -1);
2386
+ fossil_print("%d %s\n", check, g.argv[i]);
2387
+ }
2388
+}
22312389
--- src/file.c
+++ src/file.c
@@ -323,10 +323,82 @@
323 ** On Windows, always return False.
324 */
325 int file_islink(const char *zFilename){
326 return file_perm(zFilename, RepoFILE)==PERM_LNK;
327 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
328
329 /*
330 ** Return 1 if zFilename is a directory. Return 0 if zFilename
331 ** does not exist. Return 2 if zFilename exists but is something
332 ** other than a directory.
@@ -529,11 +601,14 @@
529 */
530 int file_setexe(const char *zFilename, int onoff){
531 int rc = 0;
532 #if !defined(_WIN32)
533 struct stat buf;
534 if( fossil_stat(zFilename, &buf, RepoFILE)!=0 || S_ISLNK(buf.st_mode) ){
 
 
 
535 return 0;
536 }
537 if( onoff ){
538 int targetMode = (buf.st_mode & 0444)>>2;
539 if( (buf.st_mode & 0100)==0 ){
@@ -2226,5 +2301,88 @@
2226 changeCount);
2227 }else{
2228 fossil_print("Touched %d file(s)\n", changeCount);
2229 }
2230 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2231
--- src/file.c
+++ src/file.c
@@ -323,10 +323,82 @@
323 ** On Windows, always return False.
324 */
325 int file_islink(const char *zFilename){
326 return file_perm(zFilename, RepoFILE)==PERM_LNK;
327 }
328
329 /*
330 ** Check every sub-directory of zRoot along the path to zFile.
331 ** If any sub-directory is really an ordinary file or a symbolic link,
332 ** return an integer which is the length of the prefix of zFile which
333 ** is the name of that object. Return 0 if all no non-directory
334 ** objects are found along the path.
335 **
336 ** Example: Given inputs
337 **
338 ** zRoot = /home/alice/project1
339 ** zFile = /home/alice/project1/main/src/js/fileA.js
340 **
341 ** Look for objects in the following order:
342 **
343 ** /home/alice/project/main
344 ** /home/alice/project/main/src
345 ** /home/alice/project/main/src/js
346 **
347 ** If any of those objects exist and are something other than a directory
348 ** then return the length of the name of the first non-directory object
349 ** seen.
350 */
351 int file_nondir_objects_on_path(const char *zRoot, const char *zFile){
352 int i = (int)strlen(zRoot);
353 char *z = fossil_strdup(zFile);
354 assert( fossil_strnicmp(zRoot, z, i)==0 );
355 if( i && zRoot[i-1]=='/' ) i--;
356 while( z[i]=='/' ){
357 int j, rc;
358 for(j=i+1; z[j] && z[j]!='/'; j++){}
359 if( z[j]!='/' ) break;
360 z[j] = 0;
361 rc = file_isdir(z, SymFILE);
362 if( rc!=1 ){
363 if( rc==2 ){
364 fossil_free(z);
365 return j;
366 }
367 break;
368 }
369 z[j] = '/';
370 i = j;
371 }
372 fossil_free(z);
373 return 0;
374 }
375
376 /*
377 ** The file named zFile is suppose to be an in-tree file. Check to
378 ** ensure that it will be safe to write to this file by verifying that
379 ** there are no symlinks or other non-directory objects in between the
380 ** root of the checkout and zFile.
381 **
382 ** If a problem is found, print a warning message (using fossil_warning())
383 ** and return non-zero. If everything is ok, return zero.
384 */
385 int file_unsafe_in_tree_path(const char *zFile){
386 int n;
387 if( !file_is_absolute_path(zFile) ){
388 fossil_panic("%s is not an absolute pathname",zFile);
389 }
390 if( fossil_strnicmp(g.zLocalRoot, zFile, (int)strlen(g.zLocalRoot)) ){
391 fossil_panic("%s is not a prefix of %s", g.zLocalRoot, zFile);
392 }
393 n = file_nondir_objects_on_path(g.zLocalRoot, zFile);
394 if( n ){
395 fossil_warning("cannot write to %s because non-directory object %.*s"
396 " is in the way", zFile, n, zFile);
397 }
398 return n;
399 }
400
401 /*
402 ** Return 1 if zFilename is a directory. Return 0 if zFilename
403 ** does not exist. Return 2 if zFilename exists but is something
404 ** other than a directory.
@@ -529,11 +601,14 @@
601 */
602 int file_setexe(const char *zFilename, int onoff){
603 int rc = 0;
604 #if !defined(_WIN32)
605 struct stat buf;
606 if( fossil_stat(zFilename, &buf, RepoFILE)!=0
607 || S_ISLNK(buf.st_mode)
608 || S_ISDIR(buf.st_mode)
609 ){
610 return 0;
611 }
612 if( onoff ){
613 int targetMode = (buf.st_mode & 0444)>>2;
614 if( (buf.st_mode & 0100)==0 ){
@@ -2226,5 +2301,88 @@
2301 changeCount);
2302 }else{
2303 fossil_print("Touched %d file(s)\n", changeCount);
2304 }
2305 }
2306
2307 /*
2308 ** Returns non-zero if the specified file name ends with any reserved name,
2309 ** e.g.: _FOSSIL_ or .fslckout. Specifically, it returns 1 for exact match
2310 ** or 2 for a tail match on a longer file name.
2311 **
2312 ** For the sake of efficiency, zFilename must be a canonical name, e.g. an
2313 ** absolute path using only forward slash ('/') as a directory separator.
2314 **
2315 ** nFilename must be the length of zFilename. When negative, strlen() will
2316 ** be used to calculate it.
2317 */
2318 int file_is_reserved_name(const char *zFilename, int nFilename){
2319 const char *zEnd; /* one-after-the-end of zFilename */
2320 int gotSuffix = 0; /* length of suffix (-wal, -shm, -journal) */
2321
2322 assert( zFilename && "API misuse" );
2323 if( nFilename<0 ) nFilename = (int)strlen(zFilename);
2324 if( nFilename<8 ) return 0; /* strlen("_FOSSIL_") */
2325 zEnd = zFilename + nFilename;
2326 if( nFilename>=12 ){ /* strlen("_FOSSIL_-(shm|wal)") */
2327 /* Check for (-wal, -shm, -journal) suffixes, with an eye towards
2328 ** runtime speed. */
2329 if( zEnd[-4]=='-' ){
2330 if( fossil_strnicmp("wal", &zEnd[-3], 3)
2331 && fossil_strnicmp("shm", &zEnd[-3], 3) ){
2332 return 0;
2333 }
2334 gotSuffix = 4;
2335 }else if( nFilename>=16 && zEnd[-8]=='-' ){ /*strlen(_FOSSIL_-journal) */
2336 if( fossil_strnicmp("journal", &zEnd[-7], 7) ) return 0;
2337 gotSuffix = 8;
2338 }
2339 if( gotSuffix ){
2340 assert( 4==gotSuffix || 8==gotSuffix );
2341 zEnd -= gotSuffix;
2342 nFilename -= gotSuffix;
2343 gotSuffix = 1;
2344 }
2345 assert( nFilename>=8 && "strlen(_FOSSIL_)" );
2346 assert( gotSuffix==0 || gotSuffix==1 );
2347 }
2348 switch( zEnd[-1] ){
2349 case '_':{
2350 if( fossil_strnicmp("_FOSSIL_", &zEnd[-8], 8) ) return 0;
2351 if( 8==nFilename ) return 1;
2352 return zEnd[-9]=='/' ? 2 : gotSuffix;
2353 }
2354 case 'T':
2355 case 't':{
2356 if( nFilename<9 || zEnd[-9]!='.'
2357 || fossil_strnicmp(".fslckout", &zEnd[-9], 9) ){
2358 return 0;
2359 }
2360 if( 9==nFilename ) return 1;
2361 return zEnd[-10]=='/' ? 2 : gotSuffix;
2362 }
2363 default:{
2364 return 0;
2365 }
2366 }
2367 }
2368
2369 /*
2370 ** COMMAND: test-is-reserved-name
2371 **
2372 ** Usage: %fossil test-is-ckout-db FILENAMES...
2373 **
2374 ** Passes each given name to file_is_reserved_name() and outputs one
2375 ** line per file: the result value of that function followed by the
2376 ** name.
2377 */
2378 void test_is_reserved_name_cmd(void){
2379 int i;
2380
2381 if(g.argc<3){
2382 usage("FILENAME_1 [...FILENAME_N]");
2383 }
2384 for( i = 2; i < g.argc; ++i ){
2385 const int check = file_is_reserved_name(g.argv[i], -1);
2386 fossil_print("%d %s\n", check, g.argv[i]);
2387 }
2388 }
2389
+159 -1
--- src/file.c
+++ src/file.c
@@ -323,10 +323,82 @@
323323
** On Windows, always return False.
324324
*/
325325
int file_islink(const char *zFilename){
326326
return file_perm(zFilename, RepoFILE)==PERM_LNK;
327327
}
328
+
329
+/*
330
+** Check every sub-directory of zRoot along the path to zFile.
331
+** If any sub-directory is really an ordinary file or a symbolic link,
332
+** return an integer which is the length of the prefix of zFile which
333
+** is the name of that object. Return 0 if all no non-directory
334
+** objects are found along the path.
335
+**
336
+** Example: Given inputs
337
+**
338
+** zRoot = /home/alice/project1
339
+** zFile = /home/alice/project1/main/src/js/fileA.js
340
+**
341
+** Look for objects in the following order:
342
+**
343
+** /home/alice/project/main
344
+** /home/alice/project/main/src
345
+** /home/alice/project/main/src/js
346
+**
347
+** If any of those objects exist and are something other than a directory
348
+** then return the length of the name of the first non-directory object
349
+** seen.
350
+*/
351
+int file_nondir_objects_on_path(const char *zRoot, const char *zFile){
352
+ int i = (int)strlen(zRoot);
353
+ char *z = fossil_strdup(zFile);
354
+ assert( fossil_strnicmp(zRoot, z, i)==0 );
355
+ if( i && zRoot[i-1]=='/' ) i--;
356
+ while( z[i]=='/' ){
357
+ int j, rc;
358
+ for(j=i+1; z[j] && z[j]!='/'; j++){}
359
+ if( z[j]!='/' ) break;
360
+ z[j] = 0;
361
+ rc = file_isdir(z, SymFILE);
362
+ if( rc!=1 ){
363
+ if( rc==2 ){
364
+ fossil_free(z);
365
+ return j;
366
+ }
367
+ break;
368
+ }
369
+ z[j] = '/';
370
+ i = j;
371
+ }
372
+ fossil_free(z);
373
+ return 0;
374
+}
375
+
376
+/*
377
+** The file named zFile is suppose to be an in-tree file. Check to
378
+** ensure that it will be safe to write to this file by verifying that
379
+** there are no symlinks or other non-directory objects in between the
380
+** root of the checkout and zFile.
381
+**
382
+** If a problem is found, print a warning message (using fossil_warning())
383
+** and return non-zero. If everything is ok, return zero.
384
+*/
385
+int file_unsafe_in_tree_path(const char *zFile){
386
+ int n;
387
+ if( !file_is_absolute_path(zFile) ){
388
+ fossil_panic("%s is not an absolute pathname",zFile);
389
+ }
390
+ if( fossil_strnicmp(g.zLocalRoot, zFile, (int)strlen(g.zLocalRoot)) ){
391
+ fossil_panic("%s is not a prefix of %s", g.zLocalRoot, zFile);
392
+ }
393
+ n = file_nondir_objects_on_path(g.zLocalRoot, zFile);
394
+ if( n ){
395
+ fossil_warning("cannot write to %s because non-directory object %.*s"
396
+ " is in the way", zFile, n, zFile);
397
+ }
398
+ return n;
399
+}
328400
329401
/*
330402
** Return 1 if zFilename is a directory. Return 0 if zFilename
331403
** does not exist. Return 2 if zFilename exists but is something
332404
** other than a directory.
@@ -529,11 +601,14 @@
529601
*/
530602
int file_setexe(const char *zFilename, int onoff){
531603
int rc = 0;
532604
#if !defined(_WIN32)
533605
struct stat buf;
534
- if( fossil_stat(zFilename, &buf, RepoFILE)!=0 || S_ISLNK(buf.st_mode) ){
606
+ if( fossil_stat(zFilename, &buf, RepoFILE)!=0
607
+ || S_ISLNK(buf.st_mode)
608
+ || S_ISDIR(buf.st_mode)
609
+ ){
535610
return 0;
536611
}
537612
if( onoff ){
538613
int targetMode = (buf.st_mode & 0444)>>2;
539614
if( (buf.st_mode & 0100)==0 ){
@@ -2226,5 +2301,88 @@
22262301
changeCount);
22272302
}else{
22282303
fossil_print("Touched %d file(s)\n", changeCount);
22292304
}
22302305
}
2306
+
2307
+/*
2308
+** Returns non-zero if the specified file name ends with any reserved name,
2309
+** e.g.: _FOSSIL_ or .fslckout. Specifically, it returns 1 for exact match
2310
+** or 2 for a tail match on a longer file name.
2311
+**
2312
+** For the sake of efficiency, zFilename must be a canonical name, e.g. an
2313
+** absolute path using only forward slash ('/') as a directory separator.
2314
+**
2315
+** nFilename must be the length of zFilename. When negative, strlen() will
2316
+** be used to calculate it.
2317
+*/
2318
+int file_is_reserved_name(const char *zFilename, int nFilename){
2319
+ const char *zEnd; /* one-after-the-end of zFilename */
2320
+ int gotSuffix = 0; /* length of suffix (-wal, -shm, -journal) */
2321
+
2322
+ assert( zFilename && "API misuse" );
2323
+ if( nFilename<0 ) nFilename = (int)strlen(zFilename);
2324
+ if( nFilename<8 ) return 0; /* strlen("_FOSSIL_") */
2325
+ zEnd = zFilename + nFilename;
2326
+ if( nFilename>=12 ){ /* strlen("_FOSSIL_-(shm|wal)") */
2327
+ /* Check for (-wal, -shm, -journal) suffixes, with an eye towards
2328
+ ** runtime speed. */
2329
+ if( zEnd[-4]=='-' ){
2330
+ if( fossil_strnicmp("wal", &zEnd[-3], 3)
2331
+ && fossil_strnicmp("shm", &zEnd[-3], 3) ){
2332
+ return 0;
2333
+ }
2334
+ gotSuffix = 4;
2335
+ }else if( nFilename>=16 && zEnd[-8]=='-' ){ /*strlen(_FOSSIL_-journal) */
2336
+ if( fossil_strnicmp("journal", &zEnd[-7], 7) ) return 0;
2337
+ gotSuffix = 8;
2338
+ }
2339
+ if( gotSuffix ){
2340
+ assert( 4==gotSuffix || 8==gotSuffix );
2341
+ zEnd -= gotSuffix;
2342
+ nFilename -= gotSuffix;
2343
+ gotSuffix = 1;
2344
+ }
2345
+ assert( nFilename>=8 && "strlen(_FOSSIL_)" );
2346
+ assert( gotSuffix==0 || gotSuffix==1 );
2347
+ }
2348
+ switch( zEnd[-1] ){
2349
+ case '_':{
2350
+ if( fossil_strnicmp("_FOSSIL_", &zEnd[-8], 8) ) return 0;
2351
+ if( 8==nFilename ) return 1;
2352
+ return zEnd[-9]=='/' ? 2 : gotSuffix;
2353
+ }
2354
+ case 'T':
2355
+ case 't':{
2356
+ if( nFilename<9 || zEnd[-9]!='.'
2357
+ || fossil_strnicmp(".fslckout", &zEnd[-9], 9) ){
2358
+ return 0;
2359
+ }
2360
+ if( 9==nFilename ) return 1;
2361
+ return zEnd[-10]=='/' ? 2 : gotSuffix;
2362
+ }
2363
+ default:{
2364
+ return 0;
2365
+ }
2366
+ }
2367
+}
2368
+
2369
+/*
2370
+** COMMAND: test-is-reserved-name
2371
+**
2372
+** Usage: %fossil test-is-ckout-db FILENAMES...
2373
+**
2374
+** Passes each given name to file_is_reserved_name() and outputs one
2375
+** line per file: the result value of that function followed by the
2376
+** name.
2377
+*/
2378
+void test_is_reserved_name_cmd(void){
2379
+ int i;
2380
+
2381
+ if(g.argc<3){
2382
+ usage("FILENAME_1 [...FILENAME_N]");
2383
+ }
2384
+ for( i = 2; i < g.argc; ++i ){
2385
+ const int check = file_is_reserved_name(g.argv[i], -1);
2386
+ fossil_print("%d %s\n", check, g.argv[i]);
2387
+ }
2388
+}
22312389
--- src/file.c
+++ src/file.c
@@ -323,10 +323,82 @@
323 ** On Windows, always return False.
324 */
325 int file_islink(const char *zFilename){
326 return file_perm(zFilename, RepoFILE)==PERM_LNK;
327 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
328
329 /*
330 ** Return 1 if zFilename is a directory. Return 0 if zFilename
331 ** does not exist. Return 2 if zFilename exists but is something
332 ** other than a directory.
@@ -529,11 +601,14 @@
529 */
530 int file_setexe(const char *zFilename, int onoff){
531 int rc = 0;
532 #if !defined(_WIN32)
533 struct stat buf;
534 if( fossil_stat(zFilename, &buf, RepoFILE)!=0 || S_ISLNK(buf.st_mode) ){
 
 
 
535 return 0;
536 }
537 if( onoff ){
538 int targetMode = (buf.st_mode & 0444)>>2;
539 if( (buf.st_mode & 0100)==0 ){
@@ -2226,5 +2301,88 @@
2226 changeCount);
2227 }else{
2228 fossil_print("Touched %d file(s)\n", changeCount);
2229 }
2230 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2231
--- src/file.c
+++ src/file.c
@@ -323,10 +323,82 @@
323 ** On Windows, always return False.
324 */
325 int file_islink(const char *zFilename){
326 return file_perm(zFilename, RepoFILE)==PERM_LNK;
327 }
328
329 /*
330 ** Check every sub-directory of zRoot along the path to zFile.
331 ** If any sub-directory is really an ordinary file or a symbolic link,
332 ** return an integer which is the length of the prefix of zFile which
333 ** is the name of that object. Return 0 if all no non-directory
334 ** objects are found along the path.
335 **
336 ** Example: Given inputs
337 **
338 ** zRoot = /home/alice/project1
339 ** zFile = /home/alice/project1/main/src/js/fileA.js
340 **
341 ** Look for objects in the following order:
342 **
343 ** /home/alice/project/main
344 ** /home/alice/project/main/src
345 ** /home/alice/project/main/src/js
346 **
347 ** If any of those objects exist and are something other than a directory
348 ** then return the length of the name of the first non-directory object
349 ** seen.
350 */
351 int file_nondir_objects_on_path(const char *zRoot, const char *zFile){
352 int i = (int)strlen(zRoot);
353 char *z = fossil_strdup(zFile);
354 assert( fossil_strnicmp(zRoot, z, i)==0 );
355 if( i && zRoot[i-1]=='/' ) i--;
356 while( z[i]=='/' ){
357 int j, rc;
358 for(j=i+1; z[j] && z[j]!='/'; j++){}
359 if( z[j]!='/' ) break;
360 z[j] = 0;
361 rc = file_isdir(z, SymFILE);
362 if( rc!=1 ){
363 if( rc==2 ){
364 fossil_free(z);
365 return j;
366 }
367 break;
368 }
369 z[j] = '/';
370 i = j;
371 }
372 fossil_free(z);
373 return 0;
374 }
375
376 /*
377 ** The file named zFile is suppose to be an in-tree file. Check to
378 ** ensure that it will be safe to write to this file by verifying that
379 ** there are no symlinks or other non-directory objects in between the
380 ** root of the checkout and zFile.
381 **
382 ** If a problem is found, print a warning message (using fossil_warning())
383 ** and return non-zero. If everything is ok, return zero.
384 */
385 int file_unsafe_in_tree_path(const char *zFile){
386 int n;
387 if( !file_is_absolute_path(zFile) ){
388 fossil_panic("%s is not an absolute pathname",zFile);
389 }
390 if( fossil_strnicmp(g.zLocalRoot, zFile, (int)strlen(g.zLocalRoot)) ){
391 fossil_panic("%s is not a prefix of %s", g.zLocalRoot, zFile);
392 }
393 n = file_nondir_objects_on_path(g.zLocalRoot, zFile);
394 if( n ){
395 fossil_warning("cannot write to %s because non-directory object %.*s"
396 " is in the way", zFile, n, zFile);
397 }
398 return n;
399 }
400
401 /*
402 ** Return 1 if zFilename is a directory. Return 0 if zFilename
403 ** does not exist. Return 2 if zFilename exists but is something
404 ** other than a directory.
@@ -529,11 +601,14 @@
601 */
602 int file_setexe(const char *zFilename, int onoff){
603 int rc = 0;
604 #if !defined(_WIN32)
605 struct stat buf;
606 if( fossil_stat(zFilename, &buf, RepoFILE)!=0
607 || S_ISLNK(buf.st_mode)
608 || S_ISDIR(buf.st_mode)
609 ){
610 return 0;
611 }
612 if( onoff ){
613 int targetMode = (buf.st_mode & 0444)>>2;
614 if( (buf.st_mode & 0100)==0 ){
@@ -2226,5 +2301,88 @@
2301 changeCount);
2302 }else{
2303 fossil_print("Touched %d file(s)\n", changeCount);
2304 }
2305 }
2306
2307 /*
2308 ** Returns non-zero if the specified file name ends with any reserved name,
2309 ** e.g.: _FOSSIL_ or .fslckout. Specifically, it returns 1 for exact match
2310 ** or 2 for a tail match on a longer file name.
2311 **
2312 ** For the sake of efficiency, zFilename must be a canonical name, e.g. an
2313 ** absolute path using only forward slash ('/') as a directory separator.
2314 **
2315 ** nFilename must be the length of zFilename. When negative, strlen() will
2316 ** be used to calculate it.
2317 */
2318 int file_is_reserved_name(const char *zFilename, int nFilename){
2319 const char *zEnd; /* one-after-the-end of zFilename */
2320 int gotSuffix = 0; /* length of suffix (-wal, -shm, -journal) */
2321
2322 assert( zFilename && "API misuse" );
2323 if( nFilename<0 ) nFilename = (int)strlen(zFilename);
2324 if( nFilename<8 ) return 0; /* strlen("_FOSSIL_") */
2325 zEnd = zFilename + nFilename;
2326 if( nFilename>=12 ){ /* strlen("_FOSSIL_-(shm|wal)") */
2327 /* Check for (-wal, -shm, -journal) suffixes, with an eye towards
2328 ** runtime speed. */
2329 if( zEnd[-4]=='-' ){
2330 if( fossil_strnicmp("wal", &zEnd[-3], 3)
2331 && fossil_strnicmp("shm", &zEnd[-3], 3) ){
2332 return 0;
2333 }
2334 gotSuffix = 4;
2335 }else if( nFilename>=16 && zEnd[-8]=='-' ){ /*strlen(_FOSSIL_-journal) */
2336 if( fossil_strnicmp("journal", &zEnd[-7], 7) ) return 0;
2337 gotSuffix = 8;
2338 }
2339 if( gotSuffix ){
2340 assert( 4==gotSuffix || 8==gotSuffix );
2341 zEnd -= gotSuffix;
2342 nFilename -= gotSuffix;
2343 gotSuffix = 1;
2344 }
2345 assert( nFilename>=8 && "strlen(_FOSSIL_)" );
2346 assert( gotSuffix==0 || gotSuffix==1 );
2347 }
2348 switch( zEnd[-1] ){
2349 case '_':{
2350 if( fossil_strnicmp("_FOSSIL_", &zEnd[-8], 8) ) return 0;
2351 if( 8==nFilename ) return 1;
2352 return zEnd[-9]=='/' ? 2 : gotSuffix;
2353 }
2354 case 'T':
2355 case 't':{
2356 if( nFilename<9 || zEnd[-9]!='.'
2357 || fossil_strnicmp(".fslckout", &zEnd[-9], 9) ){
2358 return 0;
2359 }
2360 if( 9==nFilename ) return 1;
2361 return zEnd[-10]=='/' ? 2 : gotSuffix;
2362 }
2363 default:{
2364 return 0;
2365 }
2366 }
2367 }
2368
2369 /*
2370 ** COMMAND: test-is-reserved-name
2371 **
2372 ** Usage: %fossil test-is-ckout-db FILENAMES...
2373 **
2374 ** Passes each given name to file_is_reserved_name() and outputs one
2375 ** line per file: the result value of that function followed by the
2376 ** name.
2377 */
2378 void test_is_reserved_name_cmd(void){
2379 int i;
2380
2381 if(g.argc<3){
2382 usage("FILENAME_1 [...FILENAME_N]");
2383 }
2384 for( i = 2; i < g.argc; ++i ){
2385 const int check = file_is_reserved_name(g.argv[i], -1);
2386 fossil_print("%d %s\n", check, g.argv[i]);
2387 }
2388 }
2389
+10 -1
--- src/http.c
+++ src/http.c
@@ -375,17 +375,26 @@
375375
j -= 4;
376376
zLine[j] = 0;
377377
}
378378
if( (mHttpFlags & HTTP_QUIET)==0 ){
379379
fossil_print("redirect with status %d to %s\n", rc, &zLine[i]);
380
+ }
381
+ if( g.url.isFile || g.url.isSsh ){
382
+ fossil_warning("cannot redirect from %s to %s", g.url.canonical,
383
+ &zLine[i]);
384
+ goto write_err;
380385
}
381386
wasHttps = g.url.isHttps;
382387
url_parse(&zLine[i], 0);
383388
if( wasHttps && !g.url.isHttps ){
384389
fossil_warning("cannot redirect from HTTPS to HTTP");
385390
goto write_err;
386
- }
391
+ }
392
+ if( g.url.isSsh || g.url.isFile ){
393
+ fossil_warning("cannot redirect to %s", &zLine[i]);
394
+ goto write_err;
395
+ }
387396
transport_close(&g.url);
388397
transport_global_shutdown(&g.url);
389398
fSeenHttpAuth = 0;
390399
if( g.zHttpAuth ) free(g.zHttpAuth);
391400
g.zHttpAuth = get_httpauth();
392401
--- src/http.c
+++ src/http.c
@@ -375,17 +375,26 @@
375 j -= 4;
376 zLine[j] = 0;
377 }
378 if( (mHttpFlags & HTTP_QUIET)==0 ){
379 fossil_print("redirect with status %d to %s\n", rc, &zLine[i]);
 
 
 
 
 
380 }
381 wasHttps = g.url.isHttps;
382 url_parse(&zLine[i], 0);
383 if( wasHttps && !g.url.isHttps ){
384 fossil_warning("cannot redirect from HTTPS to HTTP");
385 goto write_err;
386 }
 
 
 
 
387 transport_close(&g.url);
388 transport_global_shutdown(&g.url);
389 fSeenHttpAuth = 0;
390 if( g.zHttpAuth ) free(g.zHttpAuth);
391 g.zHttpAuth = get_httpauth();
392
--- src/http.c
+++ src/http.c
@@ -375,17 +375,26 @@
375 j -= 4;
376 zLine[j] = 0;
377 }
378 if( (mHttpFlags & HTTP_QUIET)==0 ){
379 fossil_print("redirect with status %d to %s\n", rc, &zLine[i]);
380 }
381 if( g.url.isFile || g.url.isSsh ){
382 fossil_warning("cannot redirect from %s to %s", g.url.canonical,
383 &zLine[i]);
384 goto write_err;
385 }
386 wasHttps = g.url.isHttps;
387 url_parse(&zLine[i], 0);
388 if( wasHttps && !g.url.isHttps ){
389 fossil_warning("cannot redirect from HTTPS to HTTP");
390 goto write_err;
391 }
392 if( g.url.isSsh || g.url.isFile ){
393 fossil_warning("cannot redirect to %s", &zLine[i]);
394 goto write_err;
395 }
396 transport_close(&g.url);
397 transport_global_shutdown(&g.url);
398 fSeenHttpAuth = 0;
399 if( g.zHttpAuth ) free(g.zHttpAuth);
400 g.zHttpAuth = get_httpauth();
401
+10 -1
--- src/http.c
+++ src/http.c
@@ -375,17 +375,26 @@
375375
j -= 4;
376376
zLine[j] = 0;
377377
}
378378
if( (mHttpFlags & HTTP_QUIET)==0 ){
379379
fossil_print("redirect with status %d to %s\n", rc, &zLine[i]);
380
+ }
381
+ if( g.url.isFile || g.url.isSsh ){
382
+ fossil_warning("cannot redirect from %s to %s", g.url.canonical,
383
+ &zLine[i]);
384
+ goto write_err;
380385
}
381386
wasHttps = g.url.isHttps;
382387
url_parse(&zLine[i], 0);
383388
if( wasHttps && !g.url.isHttps ){
384389
fossil_warning("cannot redirect from HTTPS to HTTP");
385390
goto write_err;
386
- }
391
+ }
392
+ if( g.url.isSsh || g.url.isFile ){
393
+ fossil_warning("cannot redirect to %s", &zLine[i]);
394
+ goto write_err;
395
+ }
387396
transport_close(&g.url);
388397
transport_global_shutdown(&g.url);
389398
fSeenHttpAuth = 0;
390399
if( g.zHttpAuth ) free(g.zHttpAuth);
391400
g.zHttpAuth = get_httpauth();
392401
--- src/http.c
+++ src/http.c
@@ -375,17 +375,26 @@
375 j -= 4;
376 zLine[j] = 0;
377 }
378 if( (mHttpFlags & HTTP_QUIET)==0 ){
379 fossil_print("redirect with status %d to %s\n", rc, &zLine[i]);
 
 
 
 
 
380 }
381 wasHttps = g.url.isHttps;
382 url_parse(&zLine[i], 0);
383 if( wasHttps && !g.url.isHttps ){
384 fossil_warning("cannot redirect from HTTPS to HTTP");
385 goto write_err;
386 }
 
 
 
 
387 transport_close(&g.url);
388 transport_global_shutdown(&g.url);
389 fSeenHttpAuth = 0;
390 if( g.zHttpAuth ) free(g.zHttpAuth);
391 g.zHttpAuth = get_httpauth();
392
--- src/http.c
+++ src/http.c
@@ -375,17 +375,26 @@
375 j -= 4;
376 zLine[j] = 0;
377 }
378 if( (mHttpFlags & HTTP_QUIET)==0 ){
379 fossil_print("redirect with status %d to %s\n", rc, &zLine[i]);
380 }
381 if( g.url.isFile || g.url.isSsh ){
382 fossil_warning("cannot redirect from %s to %s", g.url.canonical,
383 &zLine[i]);
384 goto write_err;
385 }
386 wasHttps = g.url.isHttps;
387 url_parse(&zLine[i], 0);
388 if( wasHttps && !g.url.isHttps ){
389 fossil_warning("cannot redirect from HTTPS to HTTP");
390 goto write_err;
391 }
392 if( g.url.isSsh || g.url.isFile ){
393 fossil_warning("cannot redirect to %s", &zLine[i]);
394 goto write_err;
395 }
396 transport_close(&g.url);
397 transport_global_shutdown(&g.url);
398 fSeenHttpAuth = 0;
399 if( g.zHttpAuth ) free(g.zHttpAuth);
400 g.zHttpAuth = get_httpauth();
401
--- src/json_config.c
+++ src/json_config.c
@@ -81,11 +81,13 @@
8181
{ "keep-glob", CONFIGSET_PROJ },
8282
{ "crlf-glob", CONFIGSET_PROJ },
8383
{ "crnl-glob", CONFIGSET_PROJ },
8484
{ "encoding-glob", CONFIGSET_PROJ },
8585
{ "empty-dirs", CONFIGSET_PROJ },
86
+#ifdef FOSSIL_LEGACY_ALLOW_SYMLINKS
8687
{ "allow-symlinks", CONFIGSET_PROJ },
88
+#endif
8789
{ "dotfiles", CONFIGSET_PROJ },
8890
8991
{ "ticket-table", CONFIGSET_TKT },
9092
{ "ticket-common", CONFIGSET_TKT },
9193
{ "ticket-change", CONFIGSET_TKT },
9294
--- src/json_config.c
+++ src/json_config.c
@@ -81,11 +81,13 @@
81 { "keep-glob", CONFIGSET_PROJ },
82 { "crlf-glob", CONFIGSET_PROJ },
83 { "crnl-glob", CONFIGSET_PROJ },
84 { "encoding-glob", CONFIGSET_PROJ },
85 { "empty-dirs", CONFIGSET_PROJ },
 
86 { "allow-symlinks", CONFIGSET_PROJ },
 
87 { "dotfiles", CONFIGSET_PROJ },
88
89 { "ticket-table", CONFIGSET_TKT },
90 { "ticket-common", CONFIGSET_TKT },
91 { "ticket-change", CONFIGSET_TKT },
92
--- src/json_config.c
+++ src/json_config.c
@@ -81,11 +81,13 @@
81 { "keep-glob", CONFIGSET_PROJ },
82 { "crlf-glob", CONFIGSET_PROJ },
83 { "crnl-glob", CONFIGSET_PROJ },
84 { "encoding-glob", CONFIGSET_PROJ },
85 { "empty-dirs", CONFIGSET_PROJ },
86 #ifdef FOSSIL_LEGACY_ALLOW_SYMLINKS
87 { "allow-symlinks", CONFIGSET_PROJ },
88 #endif
89 { "dotfiles", CONFIGSET_PROJ },
90
91 { "ticket-table", CONFIGSET_TKT },
92 { "ticket-common", CONFIGSET_TKT },
93 { "ticket-change", CONFIGSET_TKT },
94
--- src/json_config.c
+++ src/json_config.c
@@ -81,11 +81,13 @@
8181
{ "keep-glob", CONFIGSET_PROJ },
8282
{ "crlf-glob", CONFIGSET_PROJ },
8383
{ "crnl-glob", CONFIGSET_PROJ },
8484
{ "encoding-glob", CONFIGSET_PROJ },
8585
{ "empty-dirs", CONFIGSET_PROJ },
86
+#ifdef FOSSIL_LEGACY_ALLOW_SYMLINKS
8687
{ "allow-symlinks", CONFIGSET_PROJ },
88
+#endif
8789
{ "dotfiles", CONFIGSET_PROJ },
8890
8991
{ "ticket-table", CONFIGSET_TKT },
9092
{ "ticket-common", CONFIGSET_TKT },
9193
{ "ticket-change", CONFIGSET_TKT },
9294
--- src/json_config.c
+++ src/json_config.c
@@ -81,11 +81,13 @@
81 { "keep-glob", CONFIGSET_PROJ },
82 { "crlf-glob", CONFIGSET_PROJ },
83 { "crnl-glob", CONFIGSET_PROJ },
84 { "encoding-glob", CONFIGSET_PROJ },
85 { "empty-dirs", CONFIGSET_PROJ },
 
86 { "allow-symlinks", CONFIGSET_PROJ },
 
87 { "dotfiles", CONFIGSET_PROJ },
88
89 { "ticket-table", CONFIGSET_TKT },
90 { "ticket-common", CONFIGSET_TKT },
91 { "ticket-change", CONFIGSET_TKT },
92
--- src/json_config.c
+++ src/json_config.c
@@ -81,11 +81,13 @@
81 { "keep-glob", CONFIGSET_PROJ },
82 { "crlf-glob", CONFIGSET_PROJ },
83 { "crnl-glob", CONFIGSET_PROJ },
84 { "encoding-glob", CONFIGSET_PROJ },
85 { "empty-dirs", CONFIGSET_PROJ },
86 #ifdef FOSSIL_LEGACY_ALLOW_SYMLINKS
87 { "allow-symlinks", CONFIGSET_PROJ },
88 #endif
89 { "dotfiles", CONFIGSET_PROJ },
90
91 { "ticket-table", CONFIGSET_TKT },
92 { "ticket-common", CONFIGSET_TKT },
93 { "ticket-change", CONFIGSET_TKT },
94
+3
--- src/main.c
+++ src/main.c
@@ -1122,10 +1122,13 @@
11221122
#if defined(FOSSIL_DYNAMIC_BUILD)
11231123
blob_append(pOut, "FOSSIL_DYNAMIC_BUILD\n", -1);
11241124
#else
11251125
blob_append(pOut, "FOSSIL_STATIC_BUILD\n", -1);
11261126
#endif
1127
+#if defined(FOSSIL_LEGACY_ALLOW_SYMLINKS)
1128
+ blob_append(pOut, "FOSSIL_LEGACY_ALLOW_SYMLINKS\n", -1);
1129
+#endif
11271130
#if defined(HAVE_PLEDGE)
11281131
blob_append(pOut, "HAVE_PLEDGE\n", -1);
11291132
#endif
11301133
#if defined(USE_MMAN_H)
11311134
blob_append(pOut, "USE_MMAN_H\n", -1);
11321135
--- src/main.c
+++ src/main.c
@@ -1122,10 +1122,13 @@
1122 #if defined(FOSSIL_DYNAMIC_BUILD)
1123 blob_append(pOut, "FOSSIL_DYNAMIC_BUILD\n", -1);
1124 #else
1125 blob_append(pOut, "FOSSIL_STATIC_BUILD\n", -1);
1126 #endif
 
 
 
1127 #if defined(HAVE_PLEDGE)
1128 blob_append(pOut, "HAVE_PLEDGE\n", -1);
1129 #endif
1130 #if defined(USE_MMAN_H)
1131 blob_append(pOut, "USE_MMAN_H\n", -1);
1132
--- src/main.c
+++ src/main.c
@@ -1122,10 +1122,13 @@
1122 #if defined(FOSSIL_DYNAMIC_BUILD)
1123 blob_append(pOut, "FOSSIL_DYNAMIC_BUILD\n", -1);
1124 #else
1125 blob_append(pOut, "FOSSIL_STATIC_BUILD\n", -1);
1126 #endif
1127 #if defined(FOSSIL_LEGACY_ALLOW_SYMLINKS)
1128 blob_append(pOut, "FOSSIL_LEGACY_ALLOW_SYMLINKS\n", -1);
1129 #endif
1130 #if defined(HAVE_PLEDGE)
1131 blob_append(pOut, "HAVE_PLEDGE\n", -1);
1132 #endif
1133 #if defined(USE_MMAN_H)
1134 blob_append(pOut, "USE_MMAN_H\n", -1);
1135
+3
--- src/main.c
+++ src/main.c
@@ -1122,10 +1122,13 @@
11221122
#if defined(FOSSIL_DYNAMIC_BUILD)
11231123
blob_append(pOut, "FOSSIL_DYNAMIC_BUILD\n", -1);
11241124
#else
11251125
blob_append(pOut, "FOSSIL_STATIC_BUILD\n", -1);
11261126
#endif
1127
+#if defined(FOSSIL_LEGACY_ALLOW_SYMLINKS)
1128
+ blob_append(pOut, "FOSSIL_LEGACY_ALLOW_SYMLINKS\n", -1);
1129
+#endif
11271130
#if defined(HAVE_PLEDGE)
11281131
blob_append(pOut, "HAVE_PLEDGE\n", -1);
11291132
#endif
11301133
#if defined(USE_MMAN_H)
11311134
blob_append(pOut, "USE_MMAN_H\n", -1);
11321135
--- src/main.c
+++ src/main.c
@@ -1122,10 +1122,13 @@
1122 #if defined(FOSSIL_DYNAMIC_BUILD)
1123 blob_append(pOut, "FOSSIL_DYNAMIC_BUILD\n", -1);
1124 #else
1125 blob_append(pOut, "FOSSIL_STATIC_BUILD\n", -1);
1126 #endif
 
 
 
1127 #if defined(HAVE_PLEDGE)
1128 blob_append(pOut, "HAVE_PLEDGE\n", -1);
1129 #endif
1130 #if defined(USE_MMAN_H)
1131 blob_append(pOut, "USE_MMAN_H\n", -1);
1132
--- src/main.c
+++ src/main.c
@@ -1122,10 +1122,13 @@
1122 #if defined(FOSSIL_DYNAMIC_BUILD)
1123 blob_append(pOut, "FOSSIL_DYNAMIC_BUILD\n", -1);
1124 #else
1125 blob_append(pOut, "FOSSIL_STATIC_BUILD\n", -1);
1126 #endif
1127 #if defined(FOSSIL_LEGACY_ALLOW_SYMLINKS)
1128 blob_append(pOut, "FOSSIL_LEGACY_ALLOW_SYMLINKS\n", -1);
1129 #endif
1130 #if defined(HAVE_PLEDGE)
1131 blob_append(pOut, "HAVE_PLEDGE\n", -1);
1132 #endif
1133 #if defined(USE_MMAN_H)
1134 blob_append(pOut, "USE_MMAN_H\n", -1);
1135
+12 -3
--- src/manifest.c
+++ src/manifest.c
@@ -587,10 +587,11 @@
587587
case 'E': {
588588
if( p->rEventDate>0.0 ) SYNTAX("more than one E-card");
589589
p->rEventDate = db_double(0.0,"SELECT julianday(%Q)", next_token(&x,0));
590590
if( p->rEventDate<=0.0 ) SYNTAX("malformed date on E-card");
591591
p->zEventId = next_token(&x, &sz);
592
+ if( p->zEventId==0 ) SYNTAX("missing hash on E-card");
592593
if( !hname_validate(p->zEventId, sz) ){
593594
SYNTAX("malformed hash on E-card");
594595
}
595596
p->type = CFTYPE_EVENT;
596597
break;
@@ -611,10 +612,11 @@
611612
if( !file_is_simple_pathname_nonstrict(zName) ){
612613
SYNTAX("F-card filename is not a simple path");
613614
}
614615
zUuid = next_token(&x, &sz);
615616
if( p->zBaseline==0 || zUuid!=0 ){
617
+ if( zUuid==0 ) SYNTAX("missing hash on F-card");
616618
if( !hname_validate(zUuid,sz) ){
617619
SYNTAX("F-card hash invalid");
618620
}
619621
}
620622
zPerm = next_token(&x,0);
@@ -629,17 +631,24 @@
629631
p->nFileAlloc = p->nFileAlloc*2 + 10;
630632
p->aFile = fossil_realloc(p->aFile,
631633
p->nFileAlloc*sizeof(p->aFile[0]) );
632634
}
633635
i = p->nFile++;
636
+ if( i>0 && fossil_strcmp(p->aFile[i-1].zName, zName)>=0 ){
637
+ SYNTAX("incorrect F-card sort order");
638
+ }
639
+ if( file_is_reserved_name(zName,-1) ){
640
+ /* If reserved names leaked into historical manifests due to
641
+ ** slack oversight by older versions of Fossil, simply ignore
642
+ ** those files */
643
+ p->nFile--;
644
+ break;
645
+ }
634646
p->aFile[i].zName = zName;
635647
p->aFile[i].zUuid = zUuid;
636648
p->aFile[i].zPerm = zPerm;
637649
p->aFile[i].zPrior = zPriorName;
638
- if( i>0 && fossil_strcmp(p->aFile[i-1].zName, zName)>=0 ){
639
- SYNTAX("incorrect F-card sort order");
640
- }
641650
p->type = CFTYPE_MANIFEST;
642651
break;
643652
}
644653
645654
/*
646655
--- src/manifest.c
+++ src/manifest.c
@@ -587,10 +587,11 @@
587 case 'E': {
588 if( p->rEventDate>0.0 ) SYNTAX("more than one E-card");
589 p->rEventDate = db_double(0.0,"SELECT julianday(%Q)", next_token(&x,0));
590 if( p->rEventDate<=0.0 ) SYNTAX("malformed date on E-card");
591 p->zEventId = next_token(&x, &sz);
 
592 if( !hname_validate(p->zEventId, sz) ){
593 SYNTAX("malformed hash on E-card");
594 }
595 p->type = CFTYPE_EVENT;
596 break;
@@ -611,10 +612,11 @@
611 if( !file_is_simple_pathname_nonstrict(zName) ){
612 SYNTAX("F-card filename is not a simple path");
613 }
614 zUuid = next_token(&x, &sz);
615 if( p->zBaseline==0 || zUuid!=0 ){
 
616 if( !hname_validate(zUuid,sz) ){
617 SYNTAX("F-card hash invalid");
618 }
619 }
620 zPerm = next_token(&x,0);
@@ -629,17 +631,24 @@
629 p->nFileAlloc = p->nFileAlloc*2 + 10;
630 p->aFile = fossil_realloc(p->aFile,
631 p->nFileAlloc*sizeof(p->aFile[0]) );
632 }
633 i = p->nFile++;
 
 
 
 
 
 
 
 
 
 
634 p->aFile[i].zName = zName;
635 p->aFile[i].zUuid = zUuid;
636 p->aFile[i].zPerm = zPerm;
637 p->aFile[i].zPrior = zPriorName;
638 if( i>0 && fossil_strcmp(p->aFile[i-1].zName, zName)>=0 ){
639 SYNTAX("incorrect F-card sort order");
640 }
641 p->type = CFTYPE_MANIFEST;
642 break;
643 }
644
645 /*
646
--- src/manifest.c
+++ src/manifest.c
@@ -587,10 +587,11 @@
587 case 'E': {
588 if( p->rEventDate>0.0 ) SYNTAX("more than one E-card");
589 p->rEventDate = db_double(0.0,"SELECT julianday(%Q)", next_token(&x,0));
590 if( p->rEventDate<=0.0 ) SYNTAX("malformed date on E-card");
591 p->zEventId = next_token(&x, &sz);
592 if( p->zEventId==0 ) SYNTAX("missing hash on E-card");
593 if( !hname_validate(p->zEventId, sz) ){
594 SYNTAX("malformed hash on E-card");
595 }
596 p->type = CFTYPE_EVENT;
597 break;
@@ -611,10 +612,11 @@
612 if( !file_is_simple_pathname_nonstrict(zName) ){
613 SYNTAX("F-card filename is not a simple path");
614 }
615 zUuid = next_token(&x, &sz);
616 if( p->zBaseline==0 || zUuid!=0 ){
617 if( zUuid==0 ) SYNTAX("missing hash on F-card");
618 if( !hname_validate(zUuid,sz) ){
619 SYNTAX("F-card hash invalid");
620 }
621 }
622 zPerm = next_token(&x,0);
@@ -629,17 +631,24 @@
631 p->nFileAlloc = p->nFileAlloc*2 + 10;
632 p->aFile = fossil_realloc(p->aFile,
633 p->nFileAlloc*sizeof(p->aFile[0]) );
634 }
635 i = p->nFile++;
636 if( i>0 && fossil_strcmp(p->aFile[i-1].zName, zName)>=0 ){
637 SYNTAX("incorrect F-card sort order");
638 }
639 if( file_is_reserved_name(zName,-1) ){
640 /* If reserved names leaked into historical manifests due to
641 ** slack oversight by older versions of Fossil, simply ignore
642 ** those files */
643 p->nFile--;
644 break;
645 }
646 p->aFile[i].zName = zName;
647 p->aFile[i].zUuid = zUuid;
648 p->aFile[i].zPerm = zPerm;
649 p->aFile[i].zPrior = zPriorName;
 
 
 
650 p->type = CFTYPE_MANIFEST;
651 break;
652 }
653
654 /*
655
+12 -3
--- src/manifest.c
+++ src/manifest.c
@@ -587,10 +587,11 @@
587587
case 'E': {
588588
if( p->rEventDate>0.0 ) SYNTAX("more than one E-card");
589589
p->rEventDate = db_double(0.0,"SELECT julianday(%Q)", next_token(&x,0));
590590
if( p->rEventDate<=0.0 ) SYNTAX("malformed date on E-card");
591591
p->zEventId = next_token(&x, &sz);
592
+ if( p->zEventId==0 ) SYNTAX("missing hash on E-card");
592593
if( !hname_validate(p->zEventId, sz) ){
593594
SYNTAX("malformed hash on E-card");
594595
}
595596
p->type = CFTYPE_EVENT;
596597
break;
@@ -611,10 +612,11 @@
611612
if( !file_is_simple_pathname_nonstrict(zName) ){
612613
SYNTAX("F-card filename is not a simple path");
613614
}
614615
zUuid = next_token(&x, &sz);
615616
if( p->zBaseline==0 || zUuid!=0 ){
617
+ if( zUuid==0 ) SYNTAX("missing hash on F-card");
616618
if( !hname_validate(zUuid,sz) ){
617619
SYNTAX("F-card hash invalid");
618620
}
619621
}
620622
zPerm = next_token(&x,0);
@@ -629,17 +631,24 @@
629631
p->nFileAlloc = p->nFileAlloc*2 + 10;
630632
p->aFile = fossil_realloc(p->aFile,
631633
p->nFileAlloc*sizeof(p->aFile[0]) );
632634
}
633635
i = p->nFile++;
636
+ if( i>0 && fossil_strcmp(p->aFile[i-1].zName, zName)>=0 ){
637
+ SYNTAX("incorrect F-card sort order");
638
+ }
639
+ if( file_is_reserved_name(zName,-1) ){
640
+ /* If reserved names leaked into historical manifests due to
641
+ ** slack oversight by older versions of Fossil, simply ignore
642
+ ** those files */
643
+ p->nFile--;
644
+ break;
645
+ }
634646
p->aFile[i].zName = zName;
635647
p->aFile[i].zUuid = zUuid;
636648
p->aFile[i].zPerm = zPerm;
637649
p->aFile[i].zPrior = zPriorName;
638
- if( i>0 && fossil_strcmp(p->aFile[i-1].zName, zName)>=0 ){
639
- SYNTAX("incorrect F-card sort order");
640
- }
641650
p->type = CFTYPE_MANIFEST;
642651
break;
643652
}
644653
645654
/*
646655
--- src/manifest.c
+++ src/manifest.c
@@ -587,10 +587,11 @@
587 case 'E': {
588 if( p->rEventDate>0.0 ) SYNTAX("more than one E-card");
589 p->rEventDate = db_double(0.0,"SELECT julianday(%Q)", next_token(&x,0));
590 if( p->rEventDate<=0.0 ) SYNTAX("malformed date on E-card");
591 p->zEventId = next_token(&x, &sz);
 
592 if( !hname_validate(p->zEventId, sz) ){
593 SYNTAX("malformed hash on E-card");
594 }
595 p->type = CFTYPE_EVENT;
596 break;
@@ -611,10 +612,11 @@
611 if( !file_is_simple_pathname_nonstrict(zName) ){
612 SYNTAX("F-card filename is not a simple path");
613 }
614 zUuid = next_token(&x, &sz);
615 if( p->zBaseline==0 || zUuid!=0 ){
 
616 if( !hname_validate(zUuid,sz) ){
617 SYNTAX("F-card hash invalid");
618 }
619 }
620 zPerm = next_token(&x,0);
@@ -629,17 +631,24 @@
629 p->nFileAlloc = p->nFileAlloc*2 + 10;
630 p->aFile = fossil_realloc(p->aFile,
631 p->nFileAlloc*sizeof(p->aFile[0]) );
632 }
633 i = p->nFile++;
 
 
 
 
 
 
 
 
 
 
634 p->aFile[i].zName = zName;
635 p->aFile[i].zUuid = zUuid;
636 p->aFile[i].zPerm = zPerm;
637 p->aFile[i].zPrior = zPriorName;
638 if( i>0 && fossil_strcmp(p->aFile[i-1].zName, zName)>=0 ){
639 SYNTAX("incorrect F-card sort order");
640 }
641 p->type = CFTYPE_MANIFEST;
642 break;
643 }
644
645 /*
646
--- src/manifest.c
+++ src/manifest.c
@@ -587,10 +587,11 @@
587 case 'E': {
588 if( p->rEventDate>0.0 ) SYNTAX("more than one E-card");
589 p->rEventDate = db_double(0.0,"SELECT julianday(%Q)", next_token(&x,0));
590 if( p->rEventDate<=0.0 ) SYNTAX("malformed date on E-card");
591 p->zEventId = next_token(&x, &sz);
592 if( p->zEventId==0 ) SYNTAX("missing hash on E-card");
593 if( !hname_validate(p->zEventId, sz) ){
594 SYNTAX("malformed hash on E-card");
595 }
596 p->type = CFTYPE_EVENT;
597 break;
@@ -611,10 +612,11 @@
612 if( !file_is_simple_pathname_nonstrict(zName) ){
613 SYNTAX("F-card filename is not a simple path");
614 }
615 zUuid = next_token(&x, &sz);
616 if( p->zBaseline==0 || zUuid!=0 ){
617 if( zUuid==0 ) SYNTAX("missing hash on F-card");
618 if( !hname_validate(zUuid,sz) ){
619 SYNTAX("F-card hash invalid");
620 }
621 }
622 zPerm = next_token(&x,0);
@@ -629,17 +631,24 @@
631 p->nFileAlloc = p->nFileAlloc*2 + 10;
632 p->aFile = fossil_realloc(p->aFile,
633 p->nFileAlloc*sizeof(p->aFile[0]) );
634 }
635 i = p->nFile++;
636 if( i>0 && fossil_strcmp(p->aFile[i-1].zName, zName)>=0 ){
637 SYNTAX("incorrect F-card sort order");
638 }
639 if( file_is_reserved_name(zName,-1) ){
640 /* If reserved names leaked into historical manifests due to
641 ** slack oversight by older versions of Fossil, simply ignore
642 ** those files */
643 p->nFile--;
644 break;
645 }
646 p->aFile[i].zName = zName;
647 p->aFile[i].zUuid = zUuid;
648 p->aFile[i].zPerm = zPerm;
649 p->aFile[i].zPrior = zPriorName;
 
 
 
650 p->type = CFTYPE_MANIFEST;
651 break;
652 }
653
654 /*
655
+3 -3
--- src/report.c
+++ src/report.c
@@ -229,15 +229,15 @@
229229
230230
/*
231231
** Activate the query authorizer
232232
*/
233233
void report_restrict_sql(char **pzErr){
234
- sqlite3_set_authorizer(g.db, report_query_authorizer, (void*)pzErr);
234
+ db_set_authorizer(report_query_authorizer,(void*)pzErr,"Ticket-Report");
235235
sqlite3_limit(g.db, SQLITE_LIMIT_VDBE_OP, 10000);
236236
}
237237
void report_unrestrict_sql(void){
238
- sqlite3_set_authorizer(g.db, 0, 0);
238
+ db_clear_authorizer();
239239
}
240240
241241
242242
/*
243243
** Check the given SQL to see if is a valid query that does not
@@ -679,11 +679,11 @@
679679
*/
680680
if( pState->nCount==0 ){
681681
/* Turn off the authorizer. It is no longer doing anything since the
682682
** query has already been prepared.
683683
*/
684
- sqlite3_set_authorizer(g.db, 0, 0);
684
+ db_clear_authorizer();
685685
686686
/* Figure out the number of columns, the column that determines background
687687
** color, and whether or not this row of data is represented by multiple
688688
** rows in the table.
689689
*/
690690
--- src/report.c
+++ src/report.c
@@ -229,15 +229,15 @@
229
230 /*
231 ** Activate the query authorizer
232 */
233 void report_restrict_sql(char **pzErr){
234 sqlite3_set_authorizer(g.db, report_query_authorizer, (void*)pzErr);
235 sqlite3_limit(g.db, SQLITE_LIMIT_VDBE_OP, 10000);
236 }
237 void report_unrestrict_sql(void){
238 sqlite3_set_authorizer(g.db, 0, 0);
239 }
240
241
242 /*
243 ** Check the given SQL to see if is a valid query that does not
@@ -679,11 +679,11 @@
679 */
680 if( pState->nCount==0 ){
681 /* Turn off the authorizer. It is no longer doing anything since the
682 ** query has already been prepared.
683 */
684 sqlite3_set_authorizer(g.db, 0, 0);
685
686 /* Figure out the number of columns, the column that determines background
687 ** color, and whether or not this row of data is represented by multiple
688 ** rows in the table.
689 */
690
--- src/report.c
+++ src/report.c
@@ -229,15 +229,15 @@
229
230 /*
231 ** Activate the query authorizer
232 */
233 void report_restrict_sql(char **pzErr){
234 db_set_authorizer(report_query_authorizer,(void*)pzErr,"Ticket-Report");
235 sqlite3_limit(g.db, SQLITE_LIMIT_VDBE_OP, 10000);
236 }
237 void report_unrestrict_sql(void){
238 db_clear_authorizer();
239 }
240
241
242 /*
243 ** Check the given SQL to see if is a valid query that does not
@@ -679,11 +679,11 @@
679 */
680 if( pState->nCount==0 ){
681 /* Turn off the authorizer. It is no longer doing anything since the
682 ** query has already been prepared.
683 */
684 db_clear_authorizer();
685
686 /* Figure out the number of columns, the column that determines background
687 ** color, and whether or not this row of data is represented by multiple
688 ** rows in the table.
689 */
690
+3 -3
--- src/report.c
+++ src/report.c
@@ -229,15 +229,15 @@
229229
230230
/*
231231
** Activate the query authorizer
232232
*/
233233
void report_restrict_sql(char **pzErr){
234
- sqlite3_set_authorizer(g.db, report_query_authorizer, (void*)pzErr);
234
+ db_set_authorizer(report_query_authorizer,(void*)pzErr,"Ticket-Report");
235235
sqlite3_limit(g.db, SQLITE_LIMIT_VDBE_OP, 10000);
236236
}
237237
void report_unrestrict_sql(void){
238
- sqlite3_set_authorizer(g.db, 0, 0);
238
+ db_clear_authorizer();
239239
}
240240
241241
242242
/*
243243
** Check the given SQL to see if is a valid query that does not
@@ -679,11 +679,11 @@
679679
*/
680680
if( pState->nCount==0 ){
681681
/* Turn off the authorizer. It is no longer doing anything since the
682682
** query has already been prepared.
683683
*/
684
- sqlite3_set_authorizer(g.db, 0, 0);
684
+ db_clear_authorizer();
685685
686686
/* Figure out the number of columns, the column that determines background
687687
** color, and whether or not this row of data is represented by multiple
688688
** rows in the table.
689689
*/
690690
--- src/report.c
+++ src/report.c
@@ -229,15 +229,15 @@
229
230 /*
231 ** Activate the query authorizer
232 */
233 void report_restrict_sql(char **pzErr){
234 sqlite3_set_authorizer(g.db, report_query_authorizer, (void*)pzErr);
235 sqlite3_limit(g.db, SQLITE_LIMIT_VDBE_OP, 10000);
236 }
237 void report_unrestrict_sql(void){
238 sqlite3_set_authorizer(g.db, 0, 0);
239 }
240
241
242 /*
243 ** Check the given SQL to see if is a valid query that does not
@@ -679,11 +679,11 @@
679 */
680 if( pState->nCount==0 ){
681 /* Turn off the authorizer. It is no longer doing anything since the
682 ** query has already been prepared.
683 */
684 sqlite3_set_authorizer(g.db, 0, 0);
685
686 /* Figure out the number of columns, the column that determines background
687 ** color, and whether or not this row of data is represented by multiple
688 ** rows in the table.
689 */
690
--- src/report.c
+++ src/report.c
@@ -229,15 +229,15 @@
229
230 /*
231 ** Activate the query authorizer
232 */
233 void report_restrict_sql(char **pzErr){
234 db_set_authorizer(report_query_authorizer,(void*)pzErr,"Ticket-Report");
235 sqlite3_limit(g.db, SQLITE_LIMIT_VDBE_OP, 10000);
236 }
237 void report_unrestrict_sql(void){
238 db_clear_authorizer();
239 }
240
241
242 /*
243 ** Check the given SQL to see if is a valid query that does not
@@ -679,11 +679,11 @@
679 */
680 if( pState->nCount==0 ){
681 /* Turn off the authorizer. It is no longer doing anything since the
682 ** query has already been prepared.
683 */
684 db_clear_authorizer();
685
686 /* Figure out the number of columns, the column that determines background
687 ** color, and whether or not this row of data is represented by multiple
688 ** rows in the table.
689 */
690
--- src/stash.c
+++ src/stash.c
@@ -334,10 +334,12 @@
334334
blob_write_to_file(&delta, zNPath);
335335
file_setexe(zNPath, isExec);
336336
}else if( isRemoved ){
337337
fossil_print("DELETE %s\n", zOrig);
338338
file_delete(zOPath);
339
+ }else if( file_unsafe_in_tree_path(zNPath) ){
340
+ /* Ignore the unsafe path */
339341
}else{
340342
Blob a, b, out, disk;
341343
int isNewLink = file_islink(zOPath);
342344
db_ephemeral_blob(&q, 6, &delta);
343345
blob_read_from_file(&disk, zOPath, RepoFILE);
344346
--- src/stash.c
+++ src/stash.c
@@ -334,10 +334,12 @@
334 blob_write_to_file(&delta, zNPath);
335 file_setexe(zNPath, isExec);
336 }else if( isRemoved ){
337 fossil_print("DELETE %s\n", zOrig);
338 file_delete(zOPath);
 
 
339 }else{
340 Blob a, b, out, disk;
341 int isNewLink = file_islink(zOPath);
342 db_ephemeral_blob(&q, 6, &delta);
343 blob_read_from_file(&disk, zOPath, RepoFILE);
344
--- src/stash.c
+++ src/stash.c
@@ -334,10 +334,12 @@
334 blob_write_to_file(&delta, zNPath);
335 file_setexe(zNPath, isExec);
336 }else if( isRemoved ){
337 fossil_print("DELETE %s\n", zOrig);
338 file_delete(zOPath);
339 }else if( file_unsafe_in_tree_path(zNPath) ){
340 /* Ignore the unsafe path */
341 }else{
342 Blob a, b, out, disk;
343 int isNewLink = file_islink(zOPath);
344 db_ephemeral_blob(&q, 6, &delta);
345 blob_read_from_file(&disk, zOPath, RepoFILE);
346
--- src/stash.c
+++ src/stash.c
@@ -334,10 +334,12 @@
334334
blob_write_to_file(&delta, zNPath);
335335
file_setexe(zNPath, isExec);
336336
}else if( isRemoved ){
337337
fossil_print("DELETE %s\n", zOrig);
338338
file_delete(zOPath);
339
+ }else if( file_unsafe_in_tree_path(zNPath) ){
340
+ /* Ignore the unsafe path */
339341
}else{
340342
Blob a, b, out, disk;
341343
int isNewLink = file_islink(zOPath);
342344
db_ephemeral_blob(&q, 6, &delta);
343345
blob_read_from_file(&disk, zOPath, RepoFILE);
344346
--- src/stash.c
+++ src/stash.c
@@ -334,10 +334,12 @@
334 blob_write_to_file(&delta, zNPath);
335 file_setexe(zNPath, isExec);
336 }else if( isRemoved ){
337 fossil_print("DELETE %s\n", zOrig);
338 file_delete(zOPath);
 
 
339 }else{
340 Blob a, b, out, disk;
341 int isNewLink = file_islink(zOPath);
342 db_ephemeral_blob(&q, 6, &delta);
343 blob_read_from_file(&disk, zOPath, RepoFILE);
344
--- src/stash.c
+++ src/stash.c
@@ -334,10 +334,12 @@
334 blob_write_to_file(&delta, zNPath);
335 file_setexe(zNPath, isExec);
336 }else if( isRemoved ){
337 fossil_print("DELETE %s\n", zOrig);
338 file_delete(zOPath);
339 }else if( file_unsafe_in_tree_path(zNPath) ){
340 /* Ignore the unsafe path */
341 }else{
342 Blob a, b, out, disk;
343 int isNewLink = file_islink(zOPath);
344 db_ephemeral_blob(&q, 6, &delta);
345 blob_read_from_file(&disk, zOPath, RepoFILE);
346
+72
--- src/tkt.c
+++ src/tkt.c
@@ -359,10 +359,79 @@
359359
Th_FossilInit(TH_INIT_DEFAULT);
360360
Th_Store("uuid", zUuid);
361361
zConfig = ticket_change_code();
362362
return Th_Eval(g.interp, 0, zConfig, -1);
363363
}
364
+
365
+/*
366
+** An authorizer function for the SQL used to initialize the
367
+** schema for the ticketing system. Only allow CREATE TABLE and
368
+** CREATE INDEX for tables whose names begin with "ticket" and
369
+** changes to tables whose names begin with "ticket".
370
+*/
371
+static int ticket_schema_auth(
372
+ void *pNErr,
373
+ int eCode,
374
+ const char *z0,
375
+ const char *z1,
376
+ const char *z2,
377
+ const char *z3
378
+){
379
+ switch( eCode ){
380
+ case SQLITE_CREATE_TABLE: {
381
+ if( sqlite3_stricmp(z2,"main")!=0
382
+ && sqlite3_stricmp(z2,"repository")!=0
383
+ ){
384
+ goto ticket_schema_error;
385
+ }
386
+ if( sqlite3_strnicmp(z0,"ticket",6)!=0 ){
387
+ goto ticket_schema_error;
388
+ }
389
+ break;
390
+ }
391
+ case SQLITE_CREATE_INDEX: {
392
+ if( sqlite3_stricmp(z2,"main")!=0
393
+ && sqlite3_stricmp(z2,"repository")!=0
394
+ ){
395
+ goto ticket_schema_error;
396
+ }
397
+ if( sqlite3_strnicmp(z1,"ticket",6)!=0 ){
398
+ goto ticket_schema_error;
399
+ }
400
+ break;
401
+ }
402
+ case SQLITE_INSERT:
403
+ case SQLITE_UPDATE:
404
+ case SQLITE_DELETE: {
405
+ if( sqlite3_stricmp(z2,"main")!=0
406
+ && sqlite3_stricmp(z2,"repository")!=0
407
+ ){
408
+ goto ticket_schema_error;
409
+ }
410
+ if( sqlite3_strnicmp(z0,"ticket",6)!=0
411
+ && sqlite3_strnicmp(z0,"sqlite_",7)!=0
412
+ ){
413
+ goto ticket_schema_error;
414
+ }
415
+ break;
416
+ }
417
+ case SQLITE_REINDEX:
418
+ case SQLITE_TRANSACTION:
419
+ case SQLITE_READ: {
420
+ break;
421
+ }
422
+ default: {
423
+ goto ticket_schema_error;
424
+ }
425
+ }
426
+ return SQLITE_OK;
427
+
428
+ticket_schema_error:
429
+ if( pNErr ) *(int*)pNErr = 1;
430
+ return SQLITE_DENY;
431
+}
432
+
364433
365434
/*
366435
** Recreate the TICKET and TICKETCHNG tables.
367436
*/
368437
void ticket_create_table(int separateConnection){
@@ -373,14 +442,17 @@
373442
"DROP TABLE IF EXISTS ticketchng;"
374443
);
375444
zSql = ticket_table_schema();
376445
if( separateConnection ){
377446
if( db_transaction_nesting_depth() ) db_end_transaction(0);
447
+ db_set_authorizer(ticket_schema_auth,0,"Ticket-Schema");
378448
db_init_database(g.zRepositoryName, zSql, 0);
379449
}else{
450
+ db_set_authorizer(ticket_schema_auth,0,"Ticket-Schema");
380451
db_multi_exec("%s", zSql/*safe-for-%s*/);
381452
}
453
+ db_clear_authorizer();
382454
}
383455
384456
/*
385457
** Repopulate the TICKET and TICKETCHNG tables from scratch using all
386458
** available ticket artifacts.
387459
--- src/tkt.c
+++ src/tkt.c
@@ -359,10 +359,79 @@
359 Th_FossilInit(TH_INIT_DEFAULT);
360 Th_Store("uuid", zUuid);
361 zConfig = ticket_change_code();
362 return Th_Eval(g.interp, 0, zConfig, -1);
363 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
364
365 /*
366 ** Recreate the TICKET and TICKETCHNG tables.
367 */
368 void ticket_create_table(int separateConnection){
@@ -373,14 +442,17 @@
373 "DROP TABLE IF EXISTS ticketchng;"
374 );
375 zSql = ticket_table_schema();
376 if( separateConnection ){
377 if( db_transaction_nesting_depth() ) db_end_transaction(0);
 
378 db_init_database(g.zRepositoryName, zSql, 0);
379 }else{
 
380 db_multi_exec("%s", zSql/*safe-for-%s*/);
381 }
 
382 }
383
384 /*
385 ** Repopulate the TICKET and TICKETCHNG tables from scratch using all
386 ** available ticket artifacts.
387
--- src/tkt.c
+++ src/tkt.c
@@ -359,10 +359,79 @@
359 Th_FossilInit(TH_INIT_DEFAULT);
360 Th_Store("uuid", zUuid);
361 zConfig = ticket_change_code();
362 return Th_Eval(g.interp, 0, zConfig, -1);
363 }
364
365 /*
366 ** An authorizer function for the SQL used to initialize the
367 ** schema for the ticketing system. Only allow CREATE TABLE and
368 ** CREATE INDEX for tables whose names begin with "ticket" and
369 ** changes to tables whose names begin with "ticket".
370 */
371 static int ticket_schema_auth(
372 void *pNErr,
373 int eCode,
374 const char *z0,
375 const char *z1,
376 const char *z2,
377 const char *z3
378 ){
379 switch( eCode ){
380 case SQLITE_CREATE_TABLE: {
381 if( sqlite3_stricmp(z2,"main")!=0
382 && sqlite3_stricmp(z2,"repository")!=0
383 ){
384 goto ticket_schema_error;
385 }
386 if( sqlite3_strnicmp(z0,"ticket",6)!=0 ){
387 goto ticket_schema_error;
388 }
389 break;
390 }
391 case SQLITE_CREATE_INDEX: {
392 if( sqlite3_stricmp(z2,"main")!=0
393 && sqlite3_stricmp(z2,"repository")!=0
394 ){
395 goto ticket_schema_error;
396 }
397 if( sqlite3_strnicmp(z1,"ticket",6)!=0 ){
398 goto ticket_schema_error;
399 }
400 break;
401 }
402 case SQLITE_INSERT:
403 case SQLITE_UPDATE:
404 case SQLITE_DELETE: {
405 if( sqlite3_stricmp(z2,"main")!=0
406 && sqlite3_stricmp(z2,"repository")!=0
407 ){
408 goto ticket_schema_error;
409 }
410 if( sqlite3_strnicmp(z0,"ticket",6)!=0
411 && sqlite3_strnicmp(z0,"sqlite_",7)!=0
412 ){
413 goto ticket_schema_error;
414 }
415 break;
416 }
417 case SQLITE_REINDEX:
418 case SQLITE_TRANSACTION:
419 case SQLITE_READ: {
420 break;
421 }
422 default: {
423 goto ticket_schema_error;
424 }
425 }
426 return SQLITE_OK;
427
428 ticket_schema_error:
429 if( pNErr ) *(int*)pNErr = 1;
430 return SQLITE_DENY;
431 }
432
433
434 /*
435 ** Recreate the TICKET and TICKETCHNG tables.
436 */
437 void ticket_create_table(int separateConnection){
@@ -373,14 +442,17 @@
442 "DROP TABLE IF EXISTS ticketchng;"
443 );
444 zSql = ticket_table_schema();
445 if( separateConnection ){
446 if( db_transaction_nesting_depth() ) db_end_transaction(0);
447 db_set_authorizer(ticket_schema_auth,0,"Ticket-Schema");
448 db_init_database(g.zRepositoryName, zSql, 0);
449 }else{
450 db_set_authorizer(ticket_schema_auth,0,"Ticket-Schema");
451 db_multi_exec("%s", zSql/*safe-for-%s*/);
452 }
453 db_clear_authorizer();
454 }
455
456 /*
457 ** Repopulate the TICKET and TICKETCHNG tables from scratch using all
458 ** available ticket artifacts.
459
+72
--- src/tkt.c
+++ src/tkt.c
@@ -359,10 +359,79 @@
359359
Th_FossilInit(TH_INIT_DEFAULT);
360360
Th_Store("uuid", zUuid);
361361
zConfig = ticket_change_code();
362362
return Th_Eval(g.interp, 0, zConfig, -1);
363363
}
364
+
365
+/*
366
+** An authorizer function for the SQL used to initialize the
367
+** schema for the ticketing system. Only allow CREATE TABLE and
368
+** CREATE INDEX for tables whose names begin with "ticket" and
369
+** changes to tables whose names begin with "ticket".
370
+*/
371
+static int ticket_schema_auth(
372
+ void *pNErr,
373
+ int eCode,
374
+ const char *z0,
375
+ const char *z1,
376
+ const char *z2,
377
+ const char *z3
378
+){
379
+ switch( eCode ){
380
+ case SQLITE_CREATE_TABLE: {
381
+ if( sqlite3_stricmp(z2,"main")!=0
382
+ && sqlite3_stricmp(z2,"repository")!=0
383
+ ){
384
+ goto ticket_schema_error;
385
+ }
386
+ if( sqlite3_strnicmp(z0,"ticket",6)!=0 ){
387
+ goto ticket_schema_error;
388
+ }
389
+ break;
390
+ }
391
+ case SQLITE_CREATE_INDEX: {
392
+ if( sqlite3_stricmp(z2,"main")!=0
393
+ && sqlite3_stricmp(z2,"repository")!=0
394
+ ){
395
+ goto ticket_schema_error;
396
+ }
397
+ if( sqlite3_strnicmp(z1,"ticket",6)!=0 ){
398
+ goto ticket_schema_error;
399
+ }
400
+ break;
401
+ }
402
+ case SQLITE_INSERT:
403
+ case SQLITE_UPDATE:
404
+ case SQLITE_DELETE: {
405
+ if( sqlite3_stricmp(z2,"main")!=0
406
+ && sqlite3_stricmp(z2,"repository")!=0
407
+ ){
408
+ goto ticket_schema_error;
409
+ }
410
+ if( sqlite3_strnicmp(z0,"ticket",6)!=0
411
+ && sqlite3_strnicmp(z0,"sqlite_",7)!=0
412
+ ){
413
+ goto ticket_schema_error;
414
+ }
415
+ break;
416
+ }
417
+ case SQLITE_REINDEX:
418
+ case SQLITE_TRANSACTION:
419
+ case SQLITE_READ: {
420
+ break;
421
+ }
422
+ default: {
423
+ goto ticket_schema_error;
424
+ }
425
+ }
426
+ return SQLITE_OK;
427
+
428
+ticket_schema_error:
429
+ if( pNErr ) *(int*)pNErr = 1;
430
+ return SQLITE_DENY;
431
+}
432
+
364433
365434
/*
366435
** Recreate the TICKET and TICKETCHNG tables.
367436
*/
368437
void ticket_create_table(int separateConnection){
@@ -373,14 +442,17 @@
373442
"DROP TABLE IF EXISTS ticketchng;"
374443
);
375444
zSql = ticket_table_schema();
376445
if( separateConnection ){
377446
if( db_transaction_nesting_depth() ) db_end_transaction(0);
447
+ db_set_authorizer(ticket_schema_auth,0,"Ticket-Schema");
378448
db_init_database(g.zRepositoryName, zSql, 0);
379449
}else{
450
+ db_set_authorizer(ticket_schema_auth,0,"Ticket-Schema");
380451
db_multi_exec("%s", zSql/*safe-for-%s*/);
381452
}
453
+ db_clear_authorizer();
382454
}
383455
384456
/*
385457
** Repopulate the TICKET and TICKETCHNG tables from scratch using all
386458
** available ticket artifacts.
387459
--- src/tkt.c
+++ src/tkt.c
@@ -359,10 +359,79 @@
359 Th_FossilInit(TH_INIT_DEFAULT);
360 Th_Store("uuid", zUuid);
361 zConfig = ticket_change_code();
362 return Th_Eval(g.interp, 0, zConfig, -1);
363 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
364
365 /*
366 ** Recreate the TICKET and TICKETCHNG tables.
367 */
368 void ticket_create_table(int separateConnection){
@@ -373,14 +442,17 @@
373 "DROP TABLE IF EXISTS ticketchng;"
374 );
375 zSql = ticket_table_schema();
376 if( separateConnection ){
377 if( db_transaction_nesting_depth() ) db_end_transaction(0);
 
378 db_init_database(g.zRepositoryName, zSql, 0);
379 }else{
 
380 db_multi_exec("%s", zSql/*safe-for-%s*/);
381 }
 
382 }
383
384 /*
385 ** Repopulate the TICKET and TICKETCHNG tables from scratch using all
386 ** available ticket artifacts.
387
--- src/tkt.c
+++ src/tkt.c
@@ -359,10 +359,79 @@
359 Th_FossilInit(TH_INIT_DEFAULT);
360 Th_Store("uuid", zUuid);
361 zConfig = ticket_change_code();
362 return Th_Eval(g.interp, 0, zConfig, -1);
363 }
364
365 /*
366 ** An authorizer function for the SQL used to initialize the
367 ** schema for the ticketing system. Only allow CREATE TABLE and
368 ** CREATE INDEX for tables whose names begin with "ticket" and
369 ** changes to tables whose names begin with "ticket".
370 */
371 static int ticket_schema_auth(
372 void *pNErr,
373 int eCode,
374 const char *z0,
375 const char *z1,
376 const char *z2,
377 const char *z3
378 ){
379 switch( eCode ){
380 case SQLITE_CREATE_TABLE: {
381 if( sqlite3_stricmp(z2,"main")!=0
382 && sqlite3_stricmp(z2,"repository")!=0
383 ){
384 goto ticket_schema_error;
385 }
386 if( sqlite3_strnicmp(z0,"ticket",6)!=0 ){
387 goto ticket_schema_error;
388 }
389 break;
390 }
391 case SQLITE_CREATE_INDEX: {
392 if( sqlite3_stricmp(z2,"main")!=0
393 && sqlite3_stricmp(z2,"repository")!=0
394 ){
395 goto ticket_schema_error;
396 }
397 if( sqlite3_strnicmp(z1,"ticket",6)!=0 ){
398 goto ticket_schema_error;
399 }
400 break;
401 }
402 case SQLITE_INSERT:
403 case SQLITE_UPDATE:
404 case SQLITE_DELETE: {
405 if( sqlite3_stricmp(z2,"main")!=0
406 && sqlite3_stricmp(z2,"repository")!=0
407 ){
408 goto ticket_schema_error;
409 }
410 if( sqlite3_strnicmp(z0,"ticket",6)!=0
411 && sqlite3_strnicmp(z0,"sqlite_",7)!=0
412 ){
413 goto ticket_schema_error;
414 }
415 break;
416 }
417 case SQLITE_REINDEX:
418 case SQLITE_TRANSACTION:
419 case SQLITE_READ: {
420 break;
421 }
422 default: {
423 goto ticket_schema_error;
424 }
425 }
426 return SQLITE_OK;
427
428 ticket_schema_error:
429 if( pNErr ) *(int*)pNErr = 1;
430 return SQLITE_DENY;
431 }
432
433
434 /*
435 ** Recreate the TICKET and TICKETCHNG tables.
436 */
437 void ticket_create_table(int separateConnection){
@@ -373,14 +442,17 @@
442 "DROP TABLE IF EXISTS ticketchng;"
443 );
444 zSql = ticket_table_schema();
445 if( separateConnection ){
446 if( db_transaction_nesting_depth() ) db_end_transaction(0);
447 db_set_authorizer(ticket_schema_auth,0,"Ticket-Schema");
448 db_init_database(g.zRepositoryName, zSql, 0);
449 }else{
450 db_set_authorizer(ticket_schema_auth,0,"Ticket-Schema");
451 db_multi_exec("%s", zSql/*safe-for-%s*/);
452 }
453 db_clear_authorizer();
454 }
455
456 /*
457 ** Repopulate the TICKET and TICKETCHNG tables from scratch using all
458 ** available ticket artifacts.
459
+4 -2
--- src/undo.c
+++ src/undo.c
@@ -52,11 +52,11 @@
5252
int new_exe;
5353
int new_link;
5454
int old_link;
5555
Blob current;
5656
Blob new;
57
- zFullname = mprintf("%s/%s", g.zLocalRoot, zPathname);
57
+ zFullname = mprintf("%s%s", g.zLocalRoot, zPathname);
5858
old_link = db_column_int(&q, 3);
5959
new_exists = file_size(zFullname, RepoFILE)>=0;
6060
new_link = file_islink(0);
6161
if( new_exists ){
6262
blob_read_from_file(&current, zFullname, RepoFILE);
@@ -69,11 +69,13 @@
6969
old_exists = db_column_int(&q, 1);
7070
old_exe = db_column_int(&q, 2);
7171
if( old_exists ){
7272
db_ephemeral_blob(&q, 0, &new);
7373
}
74
- if( old_exists ){
74
+ if( file_unsafe_in_tree_path(zFullname) ){
75
+ /* do nothign with this unsafe file */
76
+ }else if( old_exists ){
7577
if( new_exists ){
7678
fossil_print("%s %s\n", redoFlag ? "REDO" : "UNDO", zPathname);
7779
}else{
7880
fossil_print("NEW %s\n", zPathname);
7981
}
8082
--- src/undo.c
+++ src/undo.c
@@ -52,11 +52,11 @@
52 int new_exe;
53 int new_link;
54 int old_link;
55 Blob current;
56 Blob new;
57 zFullname = mprintf("%s/%s", g.zLocalRoot, zPathname);
58 old_link = db_column_int(&q, 3);
59 new_exists = file_size(zFullname, RepoFILE)>=0;
60 new_link = file_islink(0);
61 if( new_exists ){
62 blob_read_from_file(&current, zFullname, RepoFILE);
@@ -69,11 +69,13 @@
69 old_exists = db_column_int(&q, 1);
70 old_exe = db_column_int(&q, 2);
71 if( old_exists ){
72 db_ephemeral_blob(&q, 0, &new);
73 }
74 if( old_exists ){
 
 
75 if( new_exists ){
76 fossil_print("%s %s\n", redoFlag ? "REDO" : "UNDO", zPathname);
77 }else{
78 fossil_print("NEW %s\n", zPathname);
79 }
80
--- src/undo.c
+++ src/undo.c
@@ -52,11 +52,11 @@
52 int new_exe;
53 int new_link;
54 int old_link;
55 Blob current;
56 Blob new;
57 zFullname = mprintf("%s%s", g.zLocalRoot, zPathname);
58 old_link = db_column_int(&q, 3);
59 new_exists = file_size(zFullname, RepoFILE)>=0;
60 new_link = file_islink(0);
61 if( new_exists ){
62 blob_read_from_file(&current, zFullname, RepoFILE);
@@ -69,11 +69,13 @@
69 old_exists = db_column_int(&q, 1);
70 old_exe = db_column_int(&q, 2);
71 if( old_exists ){
72 db_ephemeral_blob(&q, 0, &new);
73 }
74 if( file_unsafe_in_tree_path(zFullname) ){
75 /* do nothign with this unsafe file */
76 }else if( old_exists ){
77 if( new_exists ){
78 fossil_print("%s %s\n", redoFlag ? "REDO" : "UNDO", zPathname);
79 }else{
80 fossil_print("NEW %s\n", zPathname);
81 }
82
+4 -2
--- src/undo.c
+++ src/undo.c
@@ -52,11 +52,11 @@
5252
int new_exe;
5353
int new_link;
5454
int old_link;
5555
Blob current;
5656
Blob new;
57
- zFullname = mprintf("%s/%s", g.zLocalRoot, zPathname);
57
+ zFullname = mprintf("%s%s", g.zLocalRoot, zPathname);
5858
old_link = db_column_int(&q, 3);
5959
new_exists = file_size(zFullname, RepoFILE)>=0;
6060
new_link = file_islink(0);
6161
if( new_exists ){
6262
blob_read_from_file(&current, zFullname, RepoFILE);
@@ -69,11 +69,13 @@
6969
old_exists = db_column_int(&q, 1);
7070
old_exe = db_column_int(&q, 2);
7171
if( old_exists ){
7272
db_ephemeral_blob(&q, 0, &new);
7373
}
74
- if( old_exists ){
74
+ if( file_unsafe_in_tree_path(zFullname) ){
75
+ /* do nothign with this unsafe file */
76
+ }else if( old_exists ){
7577
if( new_exists ){
7678
fossil_print("%s %s\n", redoFlag ? "REDO" : "UNDO", zPathname);
7779
}else{
7880
fossil_print("NEW %s\n", zPathname);
7981
}
8082
--- src/undo.c
+++ src/undo.c
@@ -52,11 +52,11 @@
52 int new_exe;
53 int new_link;
54 int old_link;
55 Blob current;
56 Blob new;
57 zFullname = mprintf("%s/%s", g.zLocalRoot, zPathname);
58 old_link = db_column_int(&q, 3);
59 new_exists = file_size(zFullname, RepoFILE)>=0;
60 new_link = file_islink(0);
61 if( new_exists ){
62 blob_read_from_file(&current, zFullname, RepoFILE);
@@ -69,11 +69,13 @@
69 old_exists = db_column_int(&q, 1);
70 old_exe = db_column_int(&q, 2);
71 if( old_exists ){
72 db_ephemeral_blob(&q, 0, &new);
73 }
74 if( old_exists ){
 
 
75 if( new_exists ){
76 fossil_print("%s %s\n", redoFlag ? "REDO" : "UNDO", zPathname);
77 }else{
78 fossil_print("NEW %s\n", zPathname);
79 }
80
--- src/undo.c
+++ src/undo.c
@@ -52,11 +52,11 @@
52 int new_exe;
53 int new_link;
54 int old_link;
55 Blob current;
56 Blob new;
57 zFullname = mprintf("%s%s", g.zLocalRoot, zPathname);
58 old_link = db_column_int(&q, 3);
59 new_exists = file_size(zFullname, RepoFILE)>=0;
60 new_link = file_islink(0);
61 if( new_exists ){
62 blob_read_from_file(&current, zFullname, RepoFILE);
@@ -69,11 +69,13 @@
69 old_exists = db_column_int(&q, 1);
70 old_exe = db_column_int(&q, 2);
71 if( old_exists ){
72 db_ephemeral_blob(&q, 0, &new);
73 }
74 if( file_unsafe_in_tree_path(zFullname) ){
75 /* do nothign with this unsafe file */
76 }else if( old_exists ){
77 if( new_exists ){
78 fossil_print("%s %s\n", redoFlag ? "REDO" : "UNDO", zPathname);
79 }else{
80 fossil_print("NEW %s\n", zPathname);
81 }
82
--- src/update.c
+++ src/update.c
@@ -868,10 +868,12 @@
868868
" SET pathname=origname, origname=NULL"
869869
" WHERE pathname=%Q AND origname!=pathname;"
870870
"DELETE FROM vfile WHERE pathname=%Q",
871871
zFile, zFile
872872
);
873
+ }else if( file_unsafe_in_tree_path(zFull) ){
874
+ /* Ignore this file */
873875
}else{
874876
sqlite3_int64 mtime;
875877
int rvChnged = 0;
876878
int rvPerm = manifest_file_mperm(pRvFile);
877879
878880
--- src/update.c
+++ src/update.c
@@ -868,10 +868,12 @@
868 " SET pathname=origname, origname=NULL"
869 " WHERE pathname=%Q AND origname!=pathname;"
870 "DELETE FROM vfile WHERE pathname=%Q",
871 zFile, zFile
872 );
 
 
873 }else{
874 sqlite3_int64 mtime;
875 int rvChnged = 0;
876 int rvPerm = manifest_file_mperm(pRvFile);
877
878
--- src/update.c
+++ src/update.c
@@ -868,10 +868,12 @@
868 " SET pathname=origname, origname=NULL"
869 " WHERE pathname=%Q AND origname!=pathname;"
870 "DELETE FROM vfile WHERE pathname=%Q",
871 zFile, zFile
872 );
873 }else if( file_unsafe_in_tree_path(zFull) ){
874 /* Ignore this file */
875 }else{
876 sqlite3_int64 mtime;
877 int rvChnged = 0;
878 int rvPerm = manifest_file_mperm(pRvFile);
879
880
--- src/update.c
+++ src/update.c
@@ -868,10 +868,12 @@
868868
" SET pathname=origname, origname=NULL"
869869
" WHERE pathname=%Q AND origname!=pathname;"
870870
"DELETE FROM vfile WHERE pathname=%Q",
871871
zFile, zFile
872872
);
873
+ }else if( file_unsafe_in_tree_path(zFull) ){
874
+ /* Ignore this file */
873875
}else{
874876
sqlite3_int64 mtime;
875877
int rvChnged = 0;
876878
int rvPerm = manifest_file_mperm(pRvFile);
877879
878880
--- src/update.c
+++ src/update.c
@@ -868,10 +868,12 @@
868 " SET pathname=origname, origname=NULL"
869 " WHERE pathname=%Q AND origname!=pathname;"
870 "DELETE FROM vfile WHERE pathname=%Q",
871 zFile, zFile
872 );
 
 
873 }else{
874 sqlite3_int64 mtime;
875 int rvChnged = 0;
876 int rvPerm = manifest_file_mperm(pRvFile);
877
878
--- src/update.c
+++ src/update.c
@@ -868,10 +868,12 @@
868 " SET pathname=origname, origname=NULL"
869 " WHERE pathname=%Q AND origname!=pathname;"
870 "DELETE FROM vfile WHERE pathname=%Q",
871 zFile, zFile
872 );
873 }else if( file_unsafe_in_tree_path(zFull) ){
874 /* Ignore this file */
875 }else{
876 sqlite3_int64 mtime;
877 int rvChnged = 0;
878 int rvPerm = manifest_file_mperm(pRvFile);
879
880
--- src/vfile.c
+++ src/vfile.c
@@ -313,10 +313,13 @@
313313
id = db_column_int(&q, 0);
314314
zName = db_column_text(&q, 1);
315315
rid = db_column_int(&q, 2);
316316
isExe = db_column_int(&q, 3);
317317
isLink = db_column_int(&q, 4);
318
+ if( file_unsafe_in_tree_path(zName) ){
319
+ continue;
320
+ }
318321
content_get(rid, &content);
319322
if( file_is_the_same(&content, zName) ){
320323
blob_reset(&content);
321324
if( file_setexe(zName, isExe) ){
322325
db_multi_exec("UPDATE vfile SET mtime=%lld WHERE id=%d",
323326
--- src/vfile.c
+++ src/vfile.c
@@ -313,10 +313,13 @@
313 id = db_column_int(&q, 0);
314 zName = db_column_text(&q, 1);
315 rid = db_column_int(&q, 2);
316 isExe = db_column_int(&q, 3);
317 isLink = db_column_int(&q, 4);
 
 
 
318 content_get(rid, &content);
319 if( file_is_the_same(&content, zName) ){
320 blob_reset(&content);
321 if( file_setexe(zName, isExe) ){
322 db_multi_exec("UPDATE vfile SET mtime=%lld WHERE id=%d",
323
--- src/vfile.c
+++ src/vfile.c
@@ -313,10 +313,13 @@
313 id = db_column_int(&q, 0);
314 zName = db_column_text(&q, 1);
315 rid = db_column_int(&q, 2);
316 isExe = db_column_int(&q, 3);
317 isLink = db_column_int(&q, 4);
318 if( file_unsafe_in_tree_path(zName) ){
319 continue;
320 }
321 content_get(rid, &content);
322 if( file_is_the_same(&content, zName) ){
323 blob_reset(&content);
324 if( file_setexe(zName, isExe) ){
325 db_multi_exec("UPDATE vfile SET mtime=%lld WHERE id=%d",
326

Keyboard Shortcuts

Open search /
Next entry (timeline) j
Previous entry (timeline) k
Open focused entry Enter
Show this help ?
Toggle theme Top nav button