Fossil SCM

Cherrypick key fixes from the sec2020 branch in order to devise a minimal patch to get us to version 2.12.1.

drh 2020-08-19 01:07 branch-2.12
Commit fe1264d35df2fe16a7ac3c3fbc7d607718319ce148adb9961ff05e9df2a92158
+19 -5
--- src/add.c
+++ src/add.c
@@ -186,11 +186,13 @@
186186
}
187187
188188
/*
189189
** Add all files in the sfile temp table.
190190
**
191
-** Automatically exclude the repository file.
191
+** Automatically exclude the repository file and any other files
192
+** with reserved names. Also exclude files that are beneath an
193
+** existing symlink.
192194
*/
193195
static int add_files_in_sfile(int vid){
194196
const char *zRepo; /* Name of the repository database file */
195197
int nAdd = 0; /* Number of files added */
196198
int i; /* Loop counter */
@@ -208,18 +210,30 @@
208210
if( filenames_are_case_sensitive() ){
209211
xCmp = fossil_strcmp;
210212
}else{
211213
xCmp = fossil_stricmp;
212214
}
213
- db_prepare(&loop, "SELECT pathname FROM sfile ORDER BY pathname");
215
+ db_prepare(&loop,
216
+ "SELECT pathname FROM sfile"
217
+ " WHERE pathname NOT IN ("
218
+ "SELECT sfile.pathname FROM vfile, sfile"
219
+ " WHERE vfile.islink"
220
+ " AND NOT vfile.deleted"
221
+ " AND sfile.pathname>(vfile.pathname||'/')"
222
+ " AND sfile.pathname<(vfile.pathname||'0'))"
223
+ " ORDER BY pathname");
214224
while( db_step(&loop)==SQLITE_ROW ){
215225
const char *zToAdd = db_column_text(&loop, 0);
216226
if( fossil_strcmp(zToAdd, zRepo)==0 ) continue;
217
- for(i=0; (zReserved = fossil_reserved_name(i, 0))!=0; i++){
218
- if( xCmp(zToAdd, zReserved)==0 ) break;
227
+ if( strchr(zToAdd,'/') ){
228
+ if( file_is_reserved_name(zToAdd, -1) ) continue;
229
+ }else{
230
+ for(i=0; (zReserved = fossil_reserved_name(i, 0))!=0; i++){
231
+ if( xCmp(zToAdd, zReserved)==0 ) break;
232
+ }
233
+ if( zReserved ) continue;
219234
}
220
- if( zReserved ) continue;
221235
nAdd += add_one_file(zToAdd, vid);
222236
}
223237
db_finalize(&loop);
224238
blob_reset(&repoName);
225239
return nAdd;
226240
--- src/add.c
+++ src/add.c
@@ -186,11 +186,13 @@
186 }
187
188 /*
189 ** Add all files in the sfile temp table.
190 **
191 ** Automatically exclude the repository file.
 
 
192 */
193 static int add_files_in_sfile(int vid){
194 const char *zRepo; /* Name of the repository database file */
195 int nAdd = 0; /* Number of files added */
196 int i; /* Loop counter */
@@ -208,18 +210,30 @@
208 if( filenames_are_case_sensitive() ){
209 xCmp = fossil_strcmp;
210 }else{
211 xCmp = fossil_stricmp;
212 }
213 db_prepare(&loop, "SELECT pathname FROM sfile ORDER BY pathname");
 
 
 
 
 
 
 
 
214 while( db_step(&loop)==SQLITE_ROW ){
215 const char *zToAdd = db_column_text(&loop, 0);
216 if( fossil_strcmp(zToAdd, zRepo)==0 ) continue;
217 for(i=0; (zReserved = fossil_reserved_name(i, 0))!=0; i++){
218 if( xCmp(zToAdd, zReserved)==0 ) break;
 
 
 
 
 
219 }
220 if( zReserved ) continue;
221 nAdd += add_one_file(zToAdd, vid);
222 }
223 db_finalize(&loop);
224 blob_reset(&repoName);
225 return nAdd;
226
--- src/add.c
+++ src/add.c
@@ -186,11 +186,13 @@
186 }
187
188 /*
189 ** Add all files in the sfile temp table.
190 **
191 ** Automatically exclude the repository file and any other files
192 ** with reserved names. Also exclude files that are beneath an
193 ** existing symlink.
194 */
195 static int add_files_in_sfile(int vid){
196 const char *zRepo; /* Name of the repository database file */
197 int nAdd = 0; /* Number of files added */
198 int i; /* Loop counter */
@@ -208,18 +210,30 @@
210 if( filenames_are_case_sensitive() ){
211 xCmp = fossil_strcmp;
212 }else{
213 xCmp = fossil_stricmp;
214 }
215 db_prepare(&loop,
216 "SELECT pathname FROM sfile"
217 " WHERE pathname NOT IN ("
218 "SELECT sfile.pathname FROM vfile, sfile"
219 " WHERE vfile.islink"
220 " AND NOT vfile.deleted"
221 " AND sfile.pathname>(vfile.pathname||'/')"
222 " AND sfile.pathname<(vfile.pathname||'0'))"
223 " ORDER BY pathname");
224 while( db_step(&loop)==SQLITE_ROW ){
225 const char *zToAdd = db_column_text(&loop, 0);
226 if( fossil_strcmp(zToAdd, zRepo)==0 ) continue;
227 if( strchr(zToAdd,'/') ){
228 if( file_is_reserved_name(zToAdd, -1) ) continue;
229 }else{
230 for(i=0; (zReserved = fossil_reserved_name(i, 0))!=0; i++){
231 if( xCmp(zToAdd, zReserved)==0 ) break;
232 }
233 if( zReserved ) continue;
234 }
 
235 nAdd += add_one_file(zToAdd, vid);
236 }
237 db_finalize(&loop);
238 blob_reset(&repoName);
239 return nAdd;
240
+19 -5
--- src/add.c
+++ src/add.c
@@ -186,11 +186,13 @@
186186
}
187187
188188
/*
189189
** Add all files in the sfile temp table.
190190
**
191
-** Automatically exclude the repository file.
191
+** Automatically exclude the repository file and any other files
192
+** with reserved names. Also exclude files that are beneath an
193
+** existing symlink.
192194
*/
193195
static int add_files_in_sfile(int vid){
194196
const char *zRepo; /* Name of the repository database file */
195197
int nAdd = 0; /* Number of files added */
196198
int i; /* Loop counter */
@@ -208,18 +210,30 @@
208210
if( filenames_are_case_sensitive() ){
209211
xCmp = fossil_strcmp;
210212
}else{
211213
xCmp = fossil_stricmp;
212214
}
213
- db_prepare(&loop, "SELECT pathname FROM sfile ORDER BY pathname");
215
+ db_prepare(&loop,
216
+ "SELECT pathname FROM sfile"
217
+ " WHERE pathname NOT IN ("
218
+ "SELECT sfile.pathname FROM vfile, sfile"
219
+ " WHERE vfile.islink"
220
+ " AND NOT vfile.deleted"
221
+ " AND sfile.pathname>(vfile.pathname||'/')"
222
+ " AND sfile.pathname<(vfile.pathname||'0'))"
223
+ " ORDER BY pathname");
214224
while( db_step(&loop)==SQLITE_ROW ){
215225
const char *zToAdd = db_column_text(&loop, 0);
216226
if( fossil_strcmp(zToAdd, zRepo)==0 ) continue;
217
- for(i=0; (zReserved = fossil_reserved_name(i, 0))!=0; i++){
218
- if( xCmp(zToAdd, zReserved)==0 ) break;
227
+ if( strchr(zToAdd,'/') ){
228
+ if( file_is_reserved_name(zToAdd, -1) ) continue;
229
+ }else{
230
+ for(i=0; (zReserved = fossil_reserved_name(i, 0))!=0; i++){
231
+ if( xCmp(zToAdd, zReserved)==0 ) break;
232
+ }
233
+ if( zReserved ) continue;
219234
}
220
- if( zReserved ) continue;
221235
nAdd += add_one_file(zToAdd, vid);
222236
}
223237
db_finalize(&loop);
224238
blob_reset(&repoName);
225239
return nAdd;
226240
--- src/add.c
+++ src/add.c
@@ -186,11 +186,13 @@
186 }
187
188 /*
189 ** Add all files in the sfile temp table.
190 **
191 ** Automatically exclude the repository file.
 
 
192 */
193 static int add_files_in_sfile(int vid){
194 const char *zRepo; /* Name of the repository database file */
195 int nAdd = 0; /* Number of files added */
196 int i; /* Loop counter */
@@ -208,18 +210,30 @@
208 if( filenames_are_case_sensitive() ){
209 xCmp = fossil_strcmp;
210 }else{
211 xCmp = fossil_stricmp;
212 }
213 db_prepare(&loop, "SELECT pathname FROM sfile ORDER BY pathname");
 
 
 
 
 
 
 
 
214 while( db_step(&loop)==SQLITE_ROW ){
215 const char *zToAdd = db_column_text(&loop, 0);
216 if( fossil_strcmp(zToAdd, zRepo)==0 ) continue;
217 for(i=0; (zReserved = fossil_reserved_name(i, 0))!=0; i++){
218 if( xCmp(zToAdd, zReserved)==0 ) break;
 
 
 
 
 
219 }
220 if( zReserved ) continue;
221 nAdd += add_one_file(zToAdd, vid);
222 }
223 db_finalize(&loop);
224 blob_reset(&repoName);
225 return nAdd;
226
--- src/add.c
+++ src/add.c
@@ -186,11 +186,13 @@
186 }
187
188 /*
189 ** Add all files in the sfile temp table.
190 **
191 ** Automatically exclude the repository file and any other files
192 ** with reserved names. Also exclude files that are beneath an
193 ** existing symlink.
194 */
195 static int add_files_in_sfile(int vid){
196 const char *zRepo; /* Name of the repository database file */
197 int nAdd = 0; /* Number of files added */
198 int i; /* Loop counter */
@@ -208,18 +210,30 @@
210 if( filenames_are_case_sensitive() ){
211 xCmp = fossil_strcmp;
212 }else{
213 xCmp = fossil_stricmp;
214 }
215 db_prepare(&loop,
216 "SELECT pathname FROM sfile"
217 " WHERE pathname NOT IN ("
218 "SELECT sfile.pathname FROM vfile, sfile"
219 " WHERE vfile.islink"
220 " AND NOT vfile.deleted"
221 " AND sfile.pathname>(vfile.pathname||'/')"
222 " AND sfile.pathname<(vfile.pathname||'0'))"
223 " ORDER BY pathname");
224 while( db_step(&loop)==SQLITE_ROW ){
225 const char *zToAdd = db_column_text(&loop, 0);
226 if( fossil_strcmp(zToAdd, zRepo)==0 ) continue;
227 if( strchr(zToAdd,'/') ){
228 if( file_is_reserved_name(zToAdd, -1) ) continue;
229 }else{
230 for(i=0; (zReserved = fossil_reserved_name(i, 0))!=0; i++){
231 if( xCmp(zToAdd, zReserved)==0 ) break;
232 }
233 if( zReserved ) continue;
234 }
 
235 nAdd += add_one_file(zToAdd, vid);
236 }
237 db_finalize(&loop);
238 blob_reset(&repoName);
239 return nAdd;
240
+19 -5
--- src/add.c
+++ src/add.c
@@ -186,11 +186,13 @@
186186
}
187187
188188
/*
189189
** Add all files in the sfile temp table.
190190
**
191
-** Automatically exclude the repository file.
191
+** Automatically exclude the repository file and any other files
192
+** with reserved names. Also exclude files that are beneath an
193
+** existing symlink.
192194
*/
193195
static int add_files_in_sfile(int vid){
194196
const char *zRepo; /* Name of the repository database file */
195197
int nAdd = 0; /* Number of files added */
196198
int i; /* Loop counter */
@@ -208,18 +210,30 @@
208210
if( filenames_are_case_sensitive() ){
209211
xCmp = fossil_strcmp;
210212
}else{
211213
xCmp = fossil_stricmp;
212214
}
213
- db_prepare(&loop, "SELECT pathname FROM sfile ORDER BY pathname");
215
+ db_prepare(&loop,
216
+ "SELECT pathname FROM sfile"
217
+ " WHERE pathname NOT IN ("
218
+ "SELECT sfile.pathname FROM vfile, sfile"
219
+ " WHERE vfile.islink"
220
+ " AND NOT vfile.deleted"
221
+ " AND sfile.pathname>(vfile.pathname||'/')"
222
+ " AND sfile.pathname<(vfile.pathname||'0'))"
223
+ " ORDER BY pathname");
214224
while( db_step(&loop)==SQLITE_ROW ){
215225
const char *zToAdd = db_column_text(&loop, 0);
216226
if( fossil_strcmp(zToAdd, zRepo)==0 ) continue;
217
- for(i=0; (zReserved = fossil_reserved_name(i, 0))!=0; i++){
218
- if( xCmp(zToAdd, zReserved)==0 ) break;
227
+ if( strchr(zToAdd,'/') ){
228
+ if( file_is_reserved_name(zToAdd, -1) ) continue;
229
+ }else{
230
+ for(i=0; (zReserved = fossil_reserved_name(i, 0))!=0; i++){
231
+ if( xCmp(zToAdd, zReserved)==0 ) break;
232
+ }
233
+ if( zReserved ) continue;
219234
}
220
- if( zReserved ) continue;
221235
nAdd += add_one_file(zToAdd, vid);
222236
}
223237
db_finalize(&loop);
224238
blob_reset(&repoName);
225239
return nAdd;
226240
--- src/add.c
+++ src/add.c
@@ -186,11 +186,13 @@
186 }
187
188 /*
189 ** Add all files in the sfile temp table.
190 **
191 ** Automatically exclude the repository file.
 
 
192 */
193 static int add_files_in_sfile(int vid){
194 const char *zRepo; /* Name of the repository database file */
195 int nAdd = 0; /* Number of files added */
196 int i; /* Loop counter */
@@ -208,18 +210,30 @@
208 if( filenames_are_case_sensitive() ){
209 xCmp = fossil_strcmp;
210 }else{
211 xCmp = fossil_stricmp;
212 }
213 db_prepare(&loop, "SELECT pathname FROM sfile ORDER BY pathname");
 
 
 
 
 
 
 
 
214 while( db_step(&loop)==SQLITE_ROW ){
215 const char *zToAdd = db_column_text(&loop, 0);
216 if( fossil_strcmp(zToAdd, zRepo)==0 ) continue;
217 for(i=0; (zReserved = fossil_reserved_name(i, 0))!=0; i++){
218 if( xCmp(zToAdd, zReserved)==0 ) break;
 
 
 
 
 
219 }
220 if( zReserved ) continue;
221 nAdd += add_one_file(zToAdd, vid);
222 }
223 db_finalize(&loop);
224 blob_reset(&repoName);
225 return nAdd;
226
--- src/add.c
+++ src/add.c
@@ -186,11 +186,13 @@
186 }
187
188 /*
189 ** Add all files in the sfile temp table.
190 **
191 ** Automatically exclude the repository file and any other files
192 ** with reserved names. Also exclude files that are beneath an
193 ** existing symlink.
194 */
195 static int add_files_in_sfile(int vid){
196 const char *zRepo; /* Name of the repository database file */
197 int nAdd = 0; /* Number of files added */
198 int i; /* Loop counter */
@@ -208,18 +210,30 @@
210 if( filenames_are_case_sensitive() ){
211 xCmp = fossil_strcmp;
212 }else{
213 xCmp = fossil_stricmp;
214 }
215 db_prepare(&loop,
216 "SELECT pathname FROM sfile"
217 " WHERE pathname NOT IN ("
218 "SELECT sfile.pathname FROM vfile, sfile"
219 " WHERE vfile.islink"
220 " AND NOT vfile.deleted"
221 " AND sfile.pathname>(vfile.pathname||'/')"
222 " AND sfile.pathname<(vfile.pathname||'0'))"
223 " ORDER BY pathname");
224 while( db_step(&loop)==SQLITE_ROW ){
225 const char *zToAdd = db_column_text(&loop, 0);
226 if( fossil_strcmp(zToAdd, zRepo)==0 ) continue;
227 if( strchr(zToAdd,'/') ){
228 if( file_is_reserved_name(zToAdd, -1) ) continue;
229 }else{
230 for(i=0; (zReserved = fossil_reserved_name(i, 0))!=0; i++){
231 if( xCmp(zToAdd, zReserved)==0 ) break;
232 }
233 if( zReserved ) continue;
234 }
 
235 nAdd += add_one_file(zToAdd, vid);
236 }
237 db_finalize(&loop);
238 blob_reset(&repoName);
239 return nAdd;
240
+19 -5
--- src/add.c
+++ src/add.c
@@ -186,11 +186,13 @@
186186
}
187187
188188
/*
189189
** Add all files in the sfile temp table.
190190
**
191
-** Automatically exclude the repository file.
191
+** Automatically exclude the repository file and any other files
192
+** with reserved names. Also exclude files that are beneath an
193
+** existing symlink.
192194
*/
193195
static int add_files_in_sfile(int vid){
194196
const char *zRepo; /* Name of the repository database file */
195197
int nAdd = 0; /* Number of files added */
196198
int i; /* Loop counter */
@@ -208,18 +210,30 @@
208210
if( filenames_are_case_sensitive() ){
209211
xCmp = fossil_strcmp;
210212
}else{
211213
xCmp = fossil_stricmp;
212214
}
213
- db_prepare(&loop, "SELECT pathname FROM sfile ORDER BY pathname");
215
+ db_prepare(&loop,
216
+ "SELECT pathname FROM sfile"
217
+ " WHERE pathname NOT IN ("
218
+ "SELECT sfile.pathname FROM vfile, sfile"
219
+ " WHERE vfile.islink"
220
+ " AND NOT vfile.deleted"
221
+ " AND sfile.pathname>(vfile.pathname||'/')"
222
+ " AND sfile.pathname<(vfile.pathname||'0'))"
223
+ " ORDER BY pathname");
214224
while( db_step(&loop)==SQLITE_ROW ){
215225
const char *zToAdd = db_column_text(&loop, 0);
216226
if( fossil_strcmp(zToAdd, zRepo)==0 ) continue;
217
- for(i=0; (zReserved = fossil_reserved_name(i, 0))!=0; i++){
218
- if( xCmp(zToAdd, zReserved)==0 ) break;
227
+ if( strchr(zToAdd,'/') ){
228
+ if( file_is_reserved_name(zToAdd, -1) ) continue;
229
+ }else{
230
+ for(i=0; (zReserved = fossil_reserved_name(i, 0))!=0; i++){
231
+ if( xCmp(zToAdd, zReserved)==0 ) break;
232
+ }
233
+ if( zReserved ) continue;
219234
}
220
- if( zReserved ) continue;
221235
nAdd += add_one_file(zToAdd, vid);
222236
}
223237
db_finalize(&loop);
224238
blob_reset(&repoName);
225239
return nAdd;
226240
--- src/add.c
+++ src/add.c
@@ -186,11 +186,13 @@
186 }
187
188 /*
189 ** Add all files in the sfile temp table.
190 **
191 ** Automatically exclude the repository file.
 
 
192 */
193 static int add_files_in_sfile(int vid){
194 const char *zRepo; /* Name of the repository database file */
195 int nAdd = 0; /* Number of files added */
196 int i; /* Loop counter */
@@ -208,18 +210,30 @@
208 if( filenames_are_case_sensitive() ){
209 xCmp = fossil_strcmp;
210 }else{
211 xCmp = fossil_stricmp;
212 }
213 db_prepare(&loop, "SELECT pathname FROM sfile ORDER BY pathname");
 
 
 
 
 
 
 
 
214 while( db_step(&loop)==SQLITE_ROW ){
215 const char *zToAdd = db_column_text(&loop, 0);
216 if( fossil_strcmp(zToAdd, zRepo)==0 ) continue;
217 for(i=0; (zReserved = fossil_reserved_name(i, 0))!=0; i++){
218 if( xCmp(zToAdd, zReserved)==0 ) break;
 
 
 
 
 
219 }
220 if( zReserved ) continue;
221 nAdd += add_one_file(zToAdd, vid);
222 }
223 db_finalize(&loop);
224 blob_reset(&repoName);
225 return nAdd;
226
--- src/add.c
+++ src/add.c
@@ -186,11 +186,13 @@
186 }
187
188 /*
189 ** Add all files in the sfile temp table.
190 **
191 ** Automatically exclude the repository file and any other files
192 ** with reserved names. Also exclude files that are beneath an
193 ** existing symlink.
194 */
195 static int add_files_in_sfile(int vid){
196 const char *zRepo; /* Name of the repository database file */
197 int nAdd = 0; /* Number of files added */
198 int i; /* Loop counter */
@@ -208,18 +210,30 @@
210 if( filenames_are_case_sensitive() ){
211 xCmp = fossil_strcmp;
212 }else{
213 xCmp = fossil_stricmp;
214 }
215 db_prepare(&loop,
216 "SELECT pathname FROM sfile"
217 " WHERE pathname NOT IN ("
218 "SELECT sfile.pathname FROM vfile, sfile"
219 " WHERE vfile.islink"
220 " AND NOT vfile.deleted"
221 " AND sfile.pathname>(vfile.pathname||'/')"
222 " AND sfile.pathname<(vfile.pathname||'0'))"
223 " ORDER BY pathname");
224 while( db_step(&loop)==SQLITE_ROW ){
225 const char *zToAdd = db_column_text(&loop, 0);
226 if( fossil_strcmp(zToAdd, zRepo)==0 ) continue;
227 if( strchr(zToAdd,'/') ){
228 if( file_is_reserved_name(zToAdd, -1) ) continue;
229 }else{
230 for(i=0; (zReserved = fossil_reserved_name(i, 0))!=0; i++){
231 if( xCmp(zToAdd, zReserved)==0 ) break;
232 }
233 if( zReserved ) continue;
234 }
 
235 nAdd += add_one_file(zToAdd, vid);
236 }
237 db_finalize(&loop);
238 blob_reset(&repoName);
239 return nAdd;
240
+19 -5
--- src/add.c
+++ src/add.c
@@ -186,11 +186,13 @@
186186
}
187187
188188
/*
189189
** Add all files in the sfile temp table.
190190
**
191
-** Automatically exclude the repository file.
191
+** Automatically exclude the repository file and any other files
192
+** with reserved names. Also exclude files that are beneath an
193
+** existing symlink.
192194
*/
193195
static int add_files_in_sfile(int vid){
194196
const char *zRepo; /* Name of the repository database file */
195197
int nAdd = 0; /* Number of files added */
196198
int i; /* Loop counter */
@@ -208,18 +210,30 @@
208210
if( filenames_are_case_sensitive() ){
209211
xCmp = fossil_strcmp;
210212
}else{
211213
xCmp = fossil_stricmp;
212214
}
213
- db_prepare(&loop, "SELECT pathname FROM sfile ORDER BY pathname");
215
+ db_prepare(&loop,
216
+ "SELECT pathname FROM sfile"
217
+ " WHERE pathname NOT IN ("
218
+ "SELECT sfile.pathname FROM vfile, sfile"
219
+ " WHERE vfile.islink"
220
+ " AND NOT vfile.deleted"
221
+ " AND sfile.pathname>(vfile.pathname||'/')"
222
+ " AND sfile.pathname<(vfile.pathname||'0'))"
223
+ " ORDER BY pathname");
214224
while( db_step(&loop)==SQLITE_ROW ){
215225
const char *zToAdd = db_column_text(&loop, 0);
216226
if( fossil_strcmp(zToAdd, zRepo)==0 ) continue;
217
- for(i=0; (zReserved = fossil_reserved_name(i, 0))!=0; i++){
218
- if( xCmp(zToAdd, zReserved)==0 ) break;
227
+ if( strchr(zToAdd,'/') ){
228
+ if( file_is_reserved_name(zToAdd, -1) ) continue;
229
+ }else{
230
+ for(i=0; (zReserved = fossil_reserved_name(i, 0))!=0; i++){
231
+ if( xCmp(zToAdd, zReserved)==0 ) break;
232
+ }
233
+ if( zReserved ) continue;
219234
}
220
- if( zReserved ) continue;
221235
nAdd += add_one_file(zToAdd, vid);
222236
}
223237
db_finalize(&loop);
224238
blob_reset(&repoName);
225239
return nAdd;
226240
--- src/add.c
+++ src/add.c
@@ -186,11 +186,13 @@
186 }
187
188 /*
189 ** Add all files in the sfile temp table.
190 **
191 ** Automatically exclude the repository file.
 
 
192 */
193 static int add_files_in_sfile(int vid){
194 const char *zRepo; /* Name of the repository database file */
195 int nAdd = 0; /* Number of files added */
196 int i; /* Loop counter */
@@ -208,18 +210,30 @@
208 if( filenames_are_case_sensitive() ){
209 xCmp = fossil_strcmp;
210 }else{
211 xCmp = fossil_stricmp;
212 }
213 db_prepare(&loop, "SELECT pathname FROM sfile ORDER BY pathname");
 
 
 
 
 
 
 
 
214 while( db_step(&loop)==SQLITE_ROW ){
215 const char *zToAdd = db_column_text(&loop, 0);
216 if( fossil_strcmp(zToAdd, zRepo)==0 ) continue;
217 for(i=0; (zReserved = fossil_reserved_name(i, 0))!=0; i++){
218 if( xCmp(zToAdd, zReserved)==0 ) break;
 
 
 
 
 
219 }
220 if( zReserved ) continue;
221 nAdd += add_one_file(zToAdd, vid);
222 }
223 db_finalize(&loop);
224 blob_reset(&repoName);
225 return nAdd;
226
--- src/add.c
+++ src/add.c
@@ -186,11 +186,13 @@
186 }
187
188 /*
189 ** Add all files in the sfile temp table.
190 **
191 ** Automatically exclude the repository file and any other files
192 ** with reserved names. Also exclude files that are beneath an
193 ** existing symlink.
194 */
195 static int add_files_in_sfile(int vid){
196 const char *zRepo; /* Name of the repository database file */
197 int nAdd = 0; /* Number of files added */
198 int i; /* Loop counter */
@@ -208,18 +210,30 @@
210 if( filenames_are_case_sensitive() ){
211 xCmp = fossil_strcmp;
212 }else{
213 xCmp = fossil_stricmp;
214 }
215 db_prepare(&loop,
216 "SELECT pathname FROM sfile"
217 " WHERE pathname NOT IN ("
218 "SELECT sfile.pathname FROM vfile, sfile"
219 " WHERE vfile.islink"
220 " AND NOT vfile.deleted"
221 " AND sfile.pathname>(vfile.pathname||'/')"
222 " AND sfile.pathname<(vfile.pathname||'0'))"
223 " ORDER BY pathname");
224 while( db_step(&loop)==SQLITE_ROW ){
225 const char *zToAdd = db_column_text(&loop, 0);
226 if( fossil_strcmp(zToAdd, zRepo)==0 ) continue;
227 if( strchr(zToAdd,'/') ){
228 if( file_is_reserved_name(zToAdd, -1) ) continue;
229 }else{
230 for(i=0; (zReserved = fossil_reserved_name(i, 0))!=0; i++){
231 if( xCmp(zToAdd, zReserved)==0 ) break;
232 }
233 if( zReserved ) continue;
234 }
 
235 nAdd += add_one_file(zToAdd, vid);
236 }
237 db_finalize(&loop);
238 blob_reset(&repoName);
239 return nAdd;
240
+19 -5
--- src/add.c
+++ src/add.c
@@ -186,11 +186,13 @@
186186
}
187187
188188
/*
189189
** Add all files in the sfile temp table.
190190
**
191
-** Automatically exclude the repository file.
191
+** Automatically exclude the repository file and any other files
192
+** with reserved names. Also exclude files that are beneath an
193
+** existing symlink.
192194
*/
193195
static int add_files_in_sfile(int vid){
194196
const char *zRepo; /* Name of the repository database file */
195197
int nAdd = 0; /* Number of files added */
196198
int i; /* Loop counter */
@@ -208,18 +210,30 @@
208210
if( filenames_are_case_sensitive() ){
209211
xCmp = fossil_strcmp;
210212
}else{
211213
xCmp = fossil_stricmp;
212214
}
213
- db_prepare(&loop, "SELECT pathname FROM sfile ORDER BY pathname");
215
+ db_prepare(&loop,
216
+ "SELECT pathname FROM sfile"
217
+ " WHERE pathname NOT IN ("
218
+ "SELECT sfile.pathname FROM vfile, sfile"
219
+ " WHERE vfile.islink"
220
+ " AND NOT vfile.deleted"
221
+ " AND sfile.pathname>(vfile.pathname||'/')"
222
+ " AND sfile.pathname<(vfile.pathname||'0'))"
223
+ " ORDER BY pathname");
214224
while( db_step(&loop)==SQLITE_ROW ){
215225
const char *zToAdd = db_column_text(&loop, 0);
216226
if( fossil_strcmp(zToAdd, zRepo)==0 ) continue;
217
- for(i=0; (zReserved = fossil_reserved_name(i, 0))!=0; i++){
218
- if( xCmp(zToAdd, zReserved)==0 ) break;
227
+ if( strchr(zToAdd,'/') ){
228
+ if( file_is_reserved_name(zToAdd, -1) ) continue;
229
+ }else{
230
+ for(i=0; (zReserved = fossil_reserved_name(i, 0))!=0; i++){
231
+ if( xCmp(zToAdd, zReserved)==0 ) break;
232
+ }
233
+ if( zReserved ) continue;
219234
}
220
- if( zReserved ) continue;
221235
nAdd += add_one_file(zToAdd, vid);
222236
}
223237
db_finalize(&loop);
224238
blob_reset(&repoName);
225239
return nAdd;
226240
--- src/add.c
+++ src/add.c
@@ -186,11 +186,13 @@
186 }
187
188 /*
189 ** Add all files in the sfile temp table.
190 **
191 ** Automatically exclude the repository file.
 
 
192 */
193 static int add_files_in_sfile(int vid){
194 const char *zRepo; /* Name of the repository database file */
195 int nAdd = 0; /* Number of files added */
196 int i; /* Loop counter */
@@ -208,18 +210,30 @@
208 if( filenames_are_case_sensitive() ){
209 xCmp = fossil_strcmp;
210 }else{
211 xCmp = fossil_stricmp;
212 }
213 db_prepare(&loop, "SELECT pathname FROM sfile ORDER BY pathname");
 
 
 
 
 
 
 
 
214 while( db_step(&loop)==SQLITE_ROW ){
215 const char *zToAdd = db_column_text(&loop, 0);
216 if( fossil_strcmp(zToAdd, zRepo)==0 ) continue;
217 for(i=0; (zReserved = fossil_reserved_name(i, 0))!=0; i++){
218 if( xCmp(zToAdd, zReserved)==0 ) break;
 
 
 
 
 
219 }
220 if( zReserved ) continue;
221 nAdd += add_one_file(zToAdd, vid);
222 }
223 db_finalize(&loop);
224 blob_reset(&repoName);
225 return nAdd;
226
--- src/add.c
+++ src/add.c
@@ -186,11 +186,13 @@
186 }
187
188 /*
189 ** Add all files in the sfile temp table.
190 **
191 ** Automatically exclude the repository file and any other files
192 ** with reserved names. Also exclude files that are beneath an
193 ** existing symlink.
194 */
195 static int add_files_in_sfile(int vid){
196 const char *zRepo; /* Name of the repository database file */
197 int nAdd = 0; /* Number of files added */
198 int i; /* Loop counter */
@@ -208,18 +210,30 @@
210 if( filenames_are_case_sensitive() ){
211 xCmp = fossil_strcmp;
212 }else{
213 xCmp = fossil_stricmp;
214 }
215 db_prepare(&loop,
216 "SELECT pathname FROM sfile"
217 " WHERE pathname NOT IN ("
218 "SELECT sfile.pathname FROM vfile, sfile"
219 " WHERE vfile.islink"
220 " AND NOT vfile.deleted"
221 " AND sfile.pathname>(vfile.pathname||'/')"
222 " AND sfile.pathname<(vfile.pathname||'0'))"
223 " ORDER BY pathname");
224 while( db_step(&loop)==SQLITE_ROW ){
225 const char *zToAdd = db_column_text(&loop, 0);
226 if( fossil_strcmp(zToAdd, zRepo)==0 ) continue;
227 if( strchr(zToAdd,'/') ){
228 if( file_is_reserved_name(zToAdd, -1) ) continue;
229 }else{
230 for(i=0; (zReserved = fossil_reserved_name(i, 0))!=0; i++){
231 if( xCmp(zToAdd, zReserved)==0 ) break;
232 }
233 if( zReserved ) continue;
234 }
 
235 nAdd += add_one_file(zToAdd, vid);
236 }
237 db_finalize(&loop);
238 blob_reset(&repoName);
239 return nAdd;
240
+19 -5
--- src/add.c
+++ src/add.c
@@ -186,11 +186,13 @@
186186
}
187187
188188
/*
189189
** Add all files in the sfile temp table.
190190
**
191
-** Automatically exclude the repository file.
191
+** Automatically exclude the repository file and any other files
192
+** with reserved names. Also exclude files that are beneath an
193
+** existing symlink.
192194
*/
193195
static int add_files_in_sfile(int vid){
194196
const char *zRepo; /* Name of the repository database file */
195197
int nAdd = 0; /* Number of files added */
196198
int i; /* Loop counter */
@@ -208,18 +210,30 @@
208210
if( filenames_are_case_sensitive() ){
209211
xCmp = fossil_strcmp;
210212
}else{
211213
xCmp = fossil_stricmp;
212214
}
213
- db_prepare(&loop, "SELECT pathname FROM sfile ORDER BY pathname");
215
+ db_prepare(&loop,
216
+ "SELECT pathname FROM sfile"
217
+ " WHERE pathname NOT IN ("
218
+ "SELECT sfile.pathname FROM vfile, sfile"
219
+ " WHERE vfile.islink"
220
+ " AND NOT vfile.deleted"
221
+ " AND sfile.pathname>(vfile.pathname||'/')"
222
+ " AND sfile.pathname<(vfile.pathname||'0'))"
223
+ " ORDER BY pathname");
214224
while( db_step(&loop)==SQLITE_ROW ){
215225
const char *zToAdd = db_column_text(&loop, 0);
216226
if( fossil_strcmp(zToAdd, zRepo)==0 ) continue;
217
- for(i=0; (zReserved = fossil_reserved_name(i, 0))!=0; i++){
218
- if( xCmp(zToAdd, zReserved)==0 ) break;
227
+ if( strchr(zToAdd,'/') ){
228
+ if( file_is_reserved_name(zToAdd, -1) ) continue;
229
+ }else{
230
+ for(i=0; (zReserved = fossil_reserved_name(i, 0))!=0; i++){
231
+ if( xCmp(zToAdd, zReserved)==0 ) break;
232
+ }
233
+ if( zReserved ) continue;
219234
}
220
- if( zReserved ) continue;
221235
nAdd += add_one_file(zToAdd, vid);
222236
}
223237
db_finalize(&loop);
224238
blob_reset(&repoName);
225239
return nAdd;
226240
--- src/add.c
+++ src/add.c
@@ -186,11 +186,13 @@
186 }
187
188 /*
189 ** Add all files in the sfile temp table.
190 **
191 ** Automatically exclude the repository file.
 
 
192 */
193 static int add_files_in_sfile(int vid){
194 const char *zRepo; /* Name of the repository database file */
195 int nAdd = 0; /* Number of files added */
196 int i; /* Loop counter */
@@ -208,18 +210,30 @@
208 if( filenames_are_case_sensitive() ){
209 xCmp = fossil_strcmp;
210 }else{
211 xCmp = fossil_stricmp;
212 }
213 db_prepare(&loop, "SELECT pathname FROM sfile ORDER BY pathname");
 
 
 
 
 
 
 
 
214 while( db_step(&loop)==SQLITE_ROW ){
215 const char *zToAdd = db_column_text(&loop, 0);
216 if( fossil_strcmp(zToAdd, zRepo)==0 ) continue;
217 for(i=0; (zReserved = fossil_reserved_name(i, 0))!=0; i++){
218 if( xCmp(zToAdd, zReserved)==0 ) break;
 
 
 
 
 
219 }
220 if( zReserved ) continue;
221 nAdd += add_one_file(zToAdd, vid);
222 }
223 db_finalize(&loop);
224 blob_reset(&repoName);
225 return nAdd;
226
--- src/add.c
+++ src/add.c
@@ -186,11 +186,13 @@
186 }
187
188 /*
189 ** Add all files in the sfile temp table.
190 **
191 ** Automatically exclude the repository file and any other files
192 ** with reserved names. Also exclude files that are beneath an
193 ** existing symlink.
194 */
195 static int add_files_in_sfile(int vid){
196 const char *zRepo; /* Name of the repository database file */
197 int nAdd = 0; /* Number of files added */
198 int i; /* Loop counter */
@@ -208,18 +210,30 @@
210 if( filenames_are_case_sensitive() ){
211 xCmp = fossil_strcmp;
212 }else{
213 xCmp = fossil_stricmp;
214 }
215 db_prepare(&loop,
216 "SELECT pathname FROM sfile"
217 " WHERE pathname NOT IN ("
218 "SELECT sfile.pathname FROM vfile, sfile"
219 " WHERE vfile.islink"
220 " AND NOT vfile.deleted"
221 " AND sfile.pathname>(vfile.pathname||'/')"
222 " AND sfile.pathname<(vfile.pathname||'0'))"
223 " ORDER BY pathname");
224 while( db_step(&loop)==SQLITE_ROW ){
225 const char *zToAdd = db_column_text(&loop, 0);
226 if( fossil_strcmp(zToAdd, zRepo)==0 ) continue;
227 if( strchr(zToAdd,'/') ){
228 if( file_is_reserved_name(zToAdd, -1) ) continue;
229 }else{
230 for(i=0; (zReserved = fossil_reserved_name(i, 0))!=0; i++){
231 if( xCmp(zToAdd, zReserved)==0 ) break;
232 }
233 if( zReserved ) continue;
234 }
 
235 nAdd += add_one_file(zToAdd, vid);
236 }
237 db_finalize(&loop);
238 blob_reset(&repoName);
239 return nAdd;
240
+19 -5
--- src/add.c
+++ src/add.c
@@ -186,11 +186,13 @@
186186
}
187187
188188
/*
189189
** Add all files in the sfile temp table.
190190
**
191
-** Automatically exclude the repository file.
191
+** Automatically exclude the repository file and any other files
192
+** with reserved names. Also exclude files that are beneath an
193
+** existing symlink.
192194
*/
193195
static int add_files_in_sfile(int vid){
194196
const char *zRepo; /* Name of the repository database file */
195197
int nAdd = 0; /* Number of files added */
196198
int i; /* Loop counter */
@@ -208,18 +210,30 @@
208210
if( filenames_are_case_sensitive() ){
209211
xCmp = fossil_strcmp;
210212
}else{
211213
xCmp = fossil_stricmp;
212214
}
213
- db_prepare(&loop, "SELECT pathname FROM sfile ORDER BY pathname");
215
+ db_prepare(&loop,
216
+ "SELECT pathname FROM sfile"
217
+ " WHERE pathname NOT IN ("
218
+ "SELECT sfile.pathname FROM vfile, sfile"
219
+ " WHERE vfile.islink"
220
+ " AND NOT vfile.deleted"
221
+ " AND sfile.pathname>(vfile.pathname||'/')"
222
+ " AND sfile.pathname<(vfile.pathname||'0'))"
223
+ " ORDER BY pathname");
214224
while( db_step(&loop)==SQLITE_ROW ){
215225
const char *zToAdd = db_column_text(&loop, 0);
216226
if( fossil_strcmp(zToAdd, zRepo)==0 ) continue;
217
- for(i=0; (zReserved = fossil_reserved_name(i, 0))!=0; i++){
218
- if( xCmp(zToAdd, zReserved)==0 ) break;
227
+ if( strchr(zToAdd,'/') ){
228
+ if( file_is_reserved_name(zToAdd, -1) ) continue;
229
+ }else{
230
+ for(i=0; (zReserved = fossil_reserved_name(i, 0))!=0; i++){
231
+ if( xCmp(zToAdd, zReserved)==0 ) break;
232
+ }
233
+ if( zReserved ) continue;
219234
}
220
- if( zReserved ) continue;
221235
nAdd += add_one_file(zToAdd, vid);
222236
}
223237
db_finalize(&loop);
224238
blob_reset(&repoName);
225239
return nAdd;
226240
--- src/add.c
+++ src/add.c
@@ -186,11 +186,13 @@
186 }
187
188 /*
189 ** Add all files in the sfile temp table.
190 **
191 ** Automatically exclude the repository file.
 
 
192 */
193 static int add_files_in_sfile(int vid){
194 const char *zRepo; /* Name of the repository database file */
195 int nAdd = 0; /* Number of files added */
196 int i; /* Loop counter */
@@ -208,18 +210,30 @@
208 if( filenames_are_case_sensitive() ){
209 xCmp = fossil_strcmp;
210 }else{
211 xCmp = fossil_stricmp;
212 }
213 db_prepare(&loop, "SELECT pathname FROM sfile ORDER BY pathname");
 
 
 
 
 
 
 
 
214 while( db_step(&loop)==SQLITE_ROW ){
215 const char *zToAdd = db_column_text(&loop, 0);
216 if( fossil_strcmp(zToAdd, zRepo)==0 ) continue;
217 for(i=0; (zReserved = fossil_reserved_name(i, 0))!=0; i++){
218 if( xCmp(zToAdd, zReserved)==0 ) break;
 
 
 
 
 
219 }
220 if( zReserved ) continue;
221 nAdd += add_one_file(zToAdd, vid);
222 }
223 db_finalize(&loop);
224 blob_reset(&repoName);
225 return nAdd;
226
--- src/add.c
+++ src/add.c
@@ -186,11 +186,13 @@
186 }
187
188 /*
189 ** Add all files in the sfile temp table.
190 **
191 ** Automatically exclude the repository file and any other files
192 ** with reserved names. Also exclude files that are beneath an
193 ** existing symlink.
194 */
195 static int add_files_in_sfile(int vid){
196 const char *zRepo; /* Name of the repository database file */
197 int nAdd = 0; /* Number of files added */
198 int i; /* Loop counter */
@@ -208,18 +210,30 @@
210 if( filenames_are_case_sensitive() ){
211 xCmp = fossil_strcmp;
212 }else{
213 xCmp = fossil_stricmp;
214 }
215 db_prepare(&loop,
216 "SELECT pathname FROM sfile"
217 " WHERE pathname NOT IN ("
218 "SELECT sfile.pathname FROM vfile, sfile"
219 " WHERE vfile.islink"
220 " AND NOT vfile.deleted"
221 " AND sfile.pathname>(vfile.pathname||'/')"
222 " AND sfile.pathname<(vfile.pathname||'0'))"
223 " ORDER BY pathname");
224 while( db_step(&loop)==SQLITE_ROW ){
225 const char *zToAdd = db_column_text(&loop, 0);
226 if( fossil_strcmp(zToAdd, zRepo)==0 ) continue;
227 if( strchr(zToAdd,'/') ){
228 if( file_is_reserved_name(zToAdd, -1) ) continue;
229 }else{
230 for(i=0; (zReserved = fossil_reserved_name(i, 0))!=0; i++){
231 if( xCmp(zToAdd, zReserved)==0 ) break;
232 }
233 if( zReserved ) continue;
234 }
 
235 nAdd += add_one_file(zToAdd, vid);
236 }
237 db_finalize(&loop);
238 blob_reset(&repoName);
239 return nAdd;
240
+19 -5
--- src/add.c
+++ src/add.c
@@ -186,11 +186,13 @@
186186
}
187187
188188
/*
189189
** Add all files in the sfile temp table.
190190
**
191
-** Automatically exclude the repository file.
191
+** Automatically exclude the repository file and any other files
192
+** with reserved names. Also exclude files that are beneath an
193
+** existing symlink.
192194
*/
193195
static int add_files_in_sfile(int vid){
194196
const char *zRepo; /* Name of the repository database file */
195197
int nAdd = 0; /* Number of files added */
196198
int i; /* Loop counter */
@@ -208,18 +210,30 @@
208210
if( filenames_are_case_sensitive() ){
209211
xCmp = fossil_strcmp;
210212
}else{
211213
xCmp = fossil_stricmp;
212214
}
213
- db_prepare(&loop, "SELECT pathname FROM sfile ORDER BY pathname");
215
+ db_prepare(&loop,
216
+ "SELECT pathname FROM sfile"
217
+ " WHERE pathname NOT IN ("
218
+ "SELECT sfile.pathname FROM vfile, sfile"
219
+ " WHERE vfile.islink"
220
+ " AND NOT vfile.deleted"
221
+ " AND sfile.pathname>(vfile.pathname||'/')"
222
+ " AND sfile.pathname<(vfile.pathname||'0'))"
223
+ " ORDER BY pathname");
214224
while( db_step(&loop)==SQLITE_ROW ){
215225
const char *zToAdd = db_column_text(&loop, 0);
216226
if( fossil_strcmp(zToAdd, zRepo)==0 ) continue;
217
- for(i=0; (zReserved = fossil_reserved_name(i, 0))!=0; i++){
218
- if( xCmp(zToAdd, zReserved)==0 ) break;
227
+ if( strchr(zToAdd,'/') ){
228
+ if( file_is_reserved_name(zToAdd, -1) ) continue;
229
+ }else{
230
+ for(i=0; (zReserved = fossil_reserved_name(i, 0))!=0; i++){
231
+ if( xCmp(zToAdd, zReserved)==0 ) break;
232
+ }
233
+ if( zReserved ) continue;
219234
}
220
- if( zReserved ) continue;
221235
nAdd += add_one_file(zToAdd, vid);
222236
}
223237
db_finalize(&loop);
224238
blob_reset(&repoName);
225239
return nAdd;
226240
--- src/add.c
+++ src/add.c
@@ -186,11 +186,13 @@
186 }
187
188 /*
189 ** Add all files in the sfile temp table.
190 **
191 ** Automatically exclude the repository file.
 
 
192 */
193 static int add_files_in_sfile(int vid){
194 const char *zRepo; /* Name of the repository database file */
195 int nAdd = 0; /* Number of files added */
196 int i; /* Loop counter */
@@ -208,18 +210,30 @@
208 if( filenames_are_case_sensitive() ){
209 xCmp = fossil_strcmp;
210 }else{
211 xCmp = fossil_stricmp;
212 }
213 db_prepare(&loop, "SELECT pathname FROM sfile ORDER BY pathname");
 
 
 
 
 
 
 
 
214 while( db_step(&loop)==SQLITE_ROW ){
215 const char *zToAdd = db_column_text(&loop, 0);
216 if( fossil_strcmp(zToAdd, zRepo)==0 ) continue;
217 for(i=0; (zReserved = fossil_reserved_name(i, 0))!=0; i++){
218 if( xCmp(zToAdd, zReserved)==0 ) break;
 
 
 
 
 
219 }
220 if( zReserved ) continue;
221 nAdd += add_one_file(zToAdd, vid);
222 }
223 db_finalize(&loop);
224 blob_reset(&repoName);
225 return nAdd;
226
--- src/add.c
+++ src/add.c
@@ -186,11 +186,13 @@
186 }
187
188 /*
189 ** Add all files in the sfile temp table.
190 **
191 ** Automatically exclude the repository file and any other files
192 ** with reserved names. Also exclude files that are beneath an
193 ** existing symlink.
194 */
195 static int add_files_in_sfile(int vid){
196 const char *zRepo; /* Name of the repository database file */
197 int nAdd = 0; /* Number of files added */
198 int i; /* Loop counter */
@@ -208,18 +210,30 @@
210 if( filenames_are_case_sensitive() ){
211 xCmp = fossil_strcmp;
212 }else{
213 xCmp = fossil_stricmp;
214 }
215 db_prepare(&loop,
216 "SELECT pathname FROM sfile"
217 " WHERE pathname NOT IN ("
218 "SELECT sfile.pathname FROM vfile, sfile"
219 " WHERE vfile.islink"
220 " AND NOT vfile.deleted"
221 " AND sfile.pathname>(vfile.pathname||'/')"
222 " AND sfile.pathname<(vfile.pathname||'0'))"
223 " ORDER BY pathname");
224 while( db_step(&loop)==SQLITE_ROW ){
225 const char *zToAdd = db_column_text(&loop, 0);
226 if( fossil_strcmp(zToAdd, zRepo)==0 ) continue;
227 if( strchr(zToAdd,'/') ){
228 if( file_is_reserved_name(zToAdd, -1) ) continue;
229 }else{
230 for(i=0; (zReserved = fossil_reserved_name(i, 0))!=0; i++){
231 if( xCmp(zToAdd, zReserved)==0 ) break;
232 }
233 if( zReserved ) continue;
234 }
 
235 nAdd += add_one_file(zToAdd, vid);
236 }
237 db_finalize(&loop);
238 blob_reset(&repoName);
239 return nAdd;
240
+51 -14
--- src/db.c
+++ src/db.c
@@ -130,10 +130,13 @@
130130
char *azBeforeCommit[5]; /* Commands to run prior to COMMIT */
131131
int nBeforeCommit; /* Number of entries in azBeforeCommit */
132132
int nPriorChanges; /* sqlite3_total_changes() at transaction start */
133133
const char *zStartFile; /* File in which transaction was started */
134134
int iStartLine; /* Line of zStartFile where transaction started */
135
+ int (*xAuth)(void*,int,const char*,const char*,const char*,const char*);
136
+ void *pAuthArg; /* Argument to the authorizer */
137
+ const char *zAuthName; /* Name of the authorizer */
135138
} db = {0, 0, 0, 0, 0, 0, };
136139
137140
/*
138141
** Arrange for the given file to be deleted on a failure.
139142
*/
@@ -316,10 +319,36 @@
316319
}
317320
db.aHook[db.nCommitHook].sequence = sequence;
318321
db.aHook[db.nCommitHook].xHook = x;
319322
db.nCommitHook++;
320323
}
324
+
325
+/*
326
+** Set or unset the query authorizer callback function
327
+*/
328
+void db_set_authorizer(
329
+ int(*xAuth)(void*,int,const char*,const char*,const char*,const char*),
330
+ void *pArg,
331
+ const char *zName /* for tracing */
332
+){
333
+ if( db.xAuth ){
334
+ fossil_panic("multiple active db_set_authorizer() calls");
335
+ }
336
+ if( g.db ) sqlite3_set_authorizer(g.db, xAuth, pArg);
337
+ db.xAuth = xAuth;
338
+ db.pAuthArg = pArg;
339
+ db.zAuthName = zName;
340
+ if( g.fSqlTrace ) fossil_trace("-- set authorizer %s\n", zName);
341
+}
342
+void db_clear_authorizer(void){
343
+ if( db.zAuthName && g.fSqlTrace ){
344
+ fossil_trace("-- discontinue authorizer %s\n", db.zAuthName);
345
+ }
346
+ if( g.db ) sqlite3_set_authorizer(g.db, 0, 0);
347
+ db.xAuth = 0;
348
+ db.pAuthArg = 0;
349
+}
321350
322351
#if INTERFACE
323352
/*
324353
** Possible flags to db_vprepare
325354
*/
@@ -844,34 +873,37 @@
844873
void db_init_database(
845874
const char *zFileName, /* Name of database file to create */
846875
const char *zSchema, /* First part of schema */
847876
... /* Additional SQL to run. Terminate with NULL. */
848877
){
849
- sqlite3 *db;
878
+ sqlite3 *xdb;
850879
int rc;
851880
const char *zSql;
852881
va_list ap;
853882
854
- db = db_open(zFileName ? zFileName : ":memory:");
855
- sqlite3_exec(db, "BEGIN EXCLUSIVE", 0, 0, 0);
856
- rc = sqlite3_exec(db, zSchema, 0, 0, 0);
883
+ xdb = db_open(zFileName ? zFileName : ":memory:");
884
+ sqlite3_exec(xdb, "BEGIN EXCLUSIVE", 0, 0, 0);
885
+ if( db.xAuth ){
886
+ sqlite3_set_authorizer(xdb, db.xAuth, db.pAuthArg);
887
+ }
888
+ rc = sqlite3_exec(xdb, zSchema, 0, 0, 0);
857889
if( rc!=SQLITE_OK ){
858
- db_err("%s", sqlite3_errmsg(db));
890
+ db_err("%s", sqlite3_errmsg(xdb));
859891
}
860892
va_start(ap, zSchema);
861893
while( (zSql = va_arg(ap, const char*))!=0 ){
862
- rc = sqlite3_exec(db, zSql, 0, 0, 0);
894
+ rc = sqlite3_exec(xdb, zSql, 0, 0, 0);
863895
if( rc!=SQLITE_OK ){
864
- db_err("%s", sqlite3_errmsg(db));
896
+ db_err("%s", sqlite3_errmsg(xdb));
865897
}
866898
}
867899
va_end(ap);
868
- sqlite3_exec(db, "COMMIT", 0, 0, 0);
900
+ sqlite3_exec(xdb, "COMMIT", 0, 0, 0);
869901
if( zFileName || g.db!=0 ){
870
- sqlite3_close(db);
902
+ sqlite3_close(xdb);
871903
}else{
872
- g.db = db;
904
+ g.db = xdb;
873905
}
874906
}
875907
876908
/*
877909
** Function to return the number of seconds since 1970. This is
@@ -2086,10 +2118,11 @@
20862118
** argument is true. Ignore unfinalized statements when false.
20872119
*/
20882120
void db_close(int reportErrors){
20892121
sqlite3_stmt *pStmt;
20902122
if( g.db==0 ) return;
2123
+ sqlite3_set_authorizer(g.db, 0, 0);
20912124
if( g.fSqlStats ){
20922125
int cur, hiwtr;
20932126
sqlite3_db_status(g.db, SQLITE_DBSTATUS_LOOKASIDE_USED, &cur, &hiwtr, 0);
20942127
fprintf(stderr, "-- LOOKASIDE_USED %10d %10d\n", cur, hiwtr);
20952128
sqlite3_db_status(g.db, SQLITE_DBSTATUS_LOOKASIDE_HIT, &cur, &hiwtr, 0);
@@ -2115,17 +2148,20 @@
21152148
fprintf(stderr, "-- prepared statements %10d\n", db.nPrepare);
21162149
}
21172150
while( db.pAllStmt ){
21182151
db_finalize(db.pAllStmt);
21192152
}
2120
- if( db.nBegin && reportErrors ){
2121
- fossil_warning("Transaction started at %s:%d never commits",
2122
- db.zStartFile, db.iStartLine);
2153
+ if( db.nBegin ){
2154
+ if( reportErrors ){
2155
+ fossil_warning("Transaction started at %s:%d never commits",
2156
+ db.zStartFile, db.iStartLine);
2157
+ }
21232158
db_end_transaction(1);
21242159
}
21252160
pStmt = 0;
2126
- g.dbIgnoreErrors++; /* Stop "database locked" warnings from PRAGMA optimize */
2161
+ sqlite3_busy_timeout(g.db, 0);
2162
+ g.dbIgnoreErrors++; /* Stop "database locked" warnings */
21272163
sqlite3_exec(g.db, "PRAGMA optimize", 0, 0, 0);
21282164
g.dbIgnoreErrors--;
21292165
db_close_config();
21302166
21312167
/* If the localdb has a lot of unused free space,
@@ -2165,10 +2201,11 @@
21652201
if( g.db ){
21662202
int rc;
21672203
sqlite3_wal_checkpoint(g.db, 0);
21682204
rc = sqlite3_close(g.db);
21692205
if( g.fSqlTrace ) fossil_trace("-- sqlite3_close(%d)\n", rc);
2206
+ db_clear_authorizer();
21702207
}
21712208
g.db = 0;
21722209
g.repositoryOpen = 0;
21732210
g.localOpen = 0;
21742211
}
21752212
--- src/db.c
+++ src/db.c
@@ -130,10 +130,13 @@
130 char *azBeforeCommit[5]; /* Commands to run prior to COMMIT */
131 int nBeforeCommit; /* Number of entries in azBeforeCommit */
132 int nPriorChanges; /* sqlite3_total_changes() at transaction start */
133 const char *zStartFile; /* File in which transaction was started */
134 int iStartLine; /* Line of zStartFile where transaction started */
 
 
 
135 } db = {0, 0, 0, 0, 0, 0, };
136
137 /*
138 ** Arrange for the given file to be deleted on a failure.
139 */
@@ -316,10 +319,36 @@
316 }
317 db.aHook[db.nCommitHook].sequence = sequence;
318 db.aHook[db.nCommitHook].xHook = x;
319 db.nCommitHook++;
320 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
321
322 #if INTERFACE
323 /*
324 ** Possible flags to db_vprepare
325 */
@@ -844,34 +873,37 @@
844 void db_init_database(
845 const char *zFileName, /* Name of database file to create */
846 const char *zSchema, /* First part of schema */
847 ... /* Additional SQL to run. Terminate with NULL. */
848 ){
849 sqlite3 *db;
850 int rc;
851 const char *zSql;
852 va_list ap;
853
854 db = db_open(zFileName ? zFileName : ":memory:");
855 sqlite3_exec(db, "BEGIN EXCLUSIVE", 0, 0, 0);
856 rc = sqlite3_exec(db, zSchema, 0, 0, 0);
 
 
 
857 if( rc!=SQLITE_OK ){
858 db_err("%s", sqlite3_errmsg(db));
859 }
860 va_start(ap, zSchema);
861 while( (zSql = va_arg(ap, const char*))!=0 ){
862 rc = sqlite3_exec(db, zSql, 0, 0, 0);
863 if( rc!=SQLITE_OK ){
864 db_err("%s", sqlite3_errmsg(db));
865 }
866 }
867 va_end(ap);
868 sqlite3_exec(db, "COMMIT", 0, 0, 0);
869 if( zFileName || g.db!=0 ){
870 sqlite3_close(db);
871 }else{
872 g.db = db;
873 }
874 }
875
876 /*
877 ** Function to return the number of seconds since 1970. This is
@@ -2086,10 +2118,11 @@
2086 ** argument is true. Ignore unfinalized statements when false.
2087 */
2088 void db_close(int reportErrors){
2089 sqlite3_stmt *pStmt;
2090 if( g.db==0 ) return;
 
2091 if( g.fSqlStats ){
2092 int cur, hiwtr;
2093 sqlite3_db_status(g.db, SQLITE_DBSTATUS_LOOKASIDE_USED, &cur, &hiwtr, 0);
2094 fprintf(stderr, "-- LOOKASIDE_USED %10d %10d\n", cur, hiwtr);
2095 sqlite3_db_status(g.db, SQLITE_DBSTATUS_LOOKASIDE_HIT, &cur, &hiwtr, 0);
@@ -2115,17 +2148,20 @@
2115 fprintf(stderr, "-- prepared statements %10d\n", db.nPrepare);
2116 }
2117 while( db.pAllStmt ){
2118 db_finalize(db.pAllStmt);
2119 }
2120 if( db.nBegin && reportErrors ){
2121 fossil_warning("Transaction started at %s:%d never commits",
2122 db.zStartFile, db.iStartLine);
 
 
2123 db_end_transaction(1);
2124 }
2125 pStmt = 0;
2126 g.dbIgnoreErrors++; /* Stop "database locked" warnings from PRAGMA optimize */
 
2127 sqlite3_exec(g.db, "PRAGMA optimize", 0, 0, 0);
2128 g.dbIgnoreErrors--;
2129 db_close_config();
2130
2131 /* If the localdb has a lot of unused free space,
@@ -2165,10 +2201,11 @@
2165 if( g.db ){
2166 int rc;
2167 sqlite3_wal_checkpoint(g.db, 0);
2168 rc = sqlite3_close(g.db);
2169 if( g.fSqlTrace ) fossil_trace("-- sqlite3_close(%d)\n", rc);
 
2170 }
2171 g.db = 0;
2172 g.repositoryOpen = 0;
2173 g.localOpen = 0;
2174 }
2175
--- src/db.c
+++ src/db.c
@@ -130,10 +130,13 @@
130 char *azBeforeCommit[5]; /* Commands to run prior to COMMIT */
131 int nBeforeCommit; /* Number of entries in azBeforeCommit */
132 int nPriorChanges; /* sqlite3_total_changes() at transaction start */
133 const char *zStartFile; /* File in which transaction was started */
134 int iStartLine; /* Line of zStartFile where transaction started */
135 int (*xAuth)(void*,int,const char*,const char*,const char*,const char*);
136 void *pAuthArg; /* Argument to the authorizer */
137 const char *zAuthName; /* Name of the authorizer */
138 } db = {0, 0, 0, 0, 0, 0, };
139
140 /*
141 ** Arrange for the given file to be deleted on a failure.
142 */
@@ -316,10 +319,36 @@
319 }
320 db.aHook[db.nCommitHook].sequence = sequence;
321 db.aHook[db.nCommitHook].xHook = x;
322 db.nCommitHook++;
323 }
324
325 /*
326 ** Set or unset the query authorizer callback function
327 */
328 void db_set_authorizer(
329 int(*xAuth)(void*,int,const char*,const char*,const char*,const char*),
330 void *pArg,
331 const char *zName /* for tracing */
332 ){
333 if( db.xAuth ){
334 fossil_panic("multiple active db_set_authorizer() calls");
335 }
336 if( g.db ) sqlite3_set_authorizer(g.db, xAuth, pArg);
337 db.xAuth = xAuth;
338 db.pAuthArg = pArg;
339 db.zAuthName = zName;
340 if( g.fSqlTrace ) fossil_trace("-- set authorizer %s\n", zName);
341 }
342 void db_clear_authorizer(void){
343 if( db.zAuthName && g.fSqlTrace ){
344 fossil_trace("-- discontinue authorizer %s\n", db.zAuthName);
345 }
346 if( g.db ) sqlite3_set_authorizer(g.db, 0, 0);
347 db.xAuth = 0;
348 db.pAuthArg = 0;
349 }
350
351 #if INTERFACE
352 /*
353 ** Possible flags to db_vprepare
354 */
@@ -844,34 +873,37 @@
873 void db_init_database(
874 const char *zFileName, /* Name of database file to create */
875 const char *zSchema, /* First part of schema */
876 ... /* Additional SQL to run. Terminate with NULL. */
877 ){
878 sqlite3 *xdb;
879 int rc;
880 const char *zSql;
881 va_list ap;
882
883 xdb = db_open(zFileName ? zFileName : ":memory:");
884 sqlite3_exec(xdb, "BEGIN EXCLUSIVE", 0, 0, 0);
885 if( db.xAuth ){
886 sqlite3_set_authorizer(xdb, db.xAuth, db.pAuthArg);
887 }
888 rc = sqlite3_exec(xdb, zSchema, 0, 0, 0);
889 if( rc!=SQLITE_OK ){
890 db_err("%s", sqlite3_errmsg(xdb));
891 }
892 va_start(ap, zSchema);
893 while( (zSql = va_arg(ap, const char*))!=0 ){
894 rc = sqlite3_exec(xdb, zSql, 0, 0, 0);
895 if( rc!=SQLITE_OK ){
896 db_err("%s", sqlite3_errmsg(xdb));
897 }
898 }
899 va_end(ap);
900 sqlite3_exec(xdb, "COMMIT", 0, 0, 0);
901 if( zFileName || g.db!=0 ){
902 sqlite3_close(xdb);
903 }else{
904 g.db = xdb;
905 }
906 }
907
908 /*
909 ** Function to return the number of seconds since 1970. This is
@@ -2086,10 +2118,11 @@
2118 ** argument is true. Ignore unfinalized statements when false.
2119 */
2120 void db_close(int reportErrors){
2121 sqlite3_stmt *pStmt;
2122 if( g.db==0 ) return;
2123 sqlite3_set_authorizer(g.db, 0, 0);
2124 if( g.fSqlStats ){
2125 int cur, hiwtr;
2126 sqlite3_db_status(g.db, SQLITE_DBSTATUS_LOOKASIDE_USED, &cur, &hiwtr, 0);
2127 fprintf(stderr, "-- LOOKASIDE_USED %10d %10d\n", cur, hiwtr);
2128 sqlite3_db_status(g.db, SQLITE_DBSTATUS_LOOKASIDE_HIT, &cur, &hiwtr, 0);
@@ -2115,17 +2148,20 @@
2148 fprintf(stderr, "-- prepared statements %10d\n", db.nPrepare);
2149 }
2150 while( db.pAllStmt ){
2151 db_finalize(db.pAllStmt);
2152 }
2153 if( db.nBegin ){
2154 if( reportErrors ){
2155 fossil_warning("Transaction started at %s:%d never commits",
2156 db.zStartFile, db.iStartLine);
2157 }
2158 db_end_transaction(1);
2159 }
2160 pStmt = 0;
2161 sqlite3_busy_timeout(g.db, 0);
2162 g.dbIgnoreErrors++; /* Stop "database locked" warnings */
2163 sqlite3_exec(g.db, "PRAGMA optimize", 0, 0, 0);
2164 g.dbIgnoreErrors--;
2165 db_close_config();
2166
2167 /* If the localdb has a lot of unused free space,
@@ -2165,10 +2201,11 @@
2201 if( g.db ){
2202 int rc;
2203 sqlite3_wal_checkpoint(g.db, 0);
2204 rc = sqlite3_close(g.db);
2205 if( g.fSqlTrace ) fossil_trace("-- sqlite3_close(%d)\n", rc);
2206 db_clear_authorizer();
2207 }
2208 g.db = 0;
2209 g.repositoryOpen = 0;
2210 g.localOpen = 0;
2211 }
2212
+51 -14
--- src/db.c
+++ src/db.c
@@ -130,10 +130,13 @@
130130
char *azBeforeCommit[5]; /* Commands to run prior to COMMIT */
131131
int nBeforeCommit; /* Number of entries in azBeforeCommit */
132132
int nPriorChanges; /* sqlite3_total_changes() at transaction start */
133133
const char *zStartFile; /* File in which transaction was started */
134134
int iStartLine; /* Line of zStartFile where transaction started */
135
+ int (*xAuth)(void*,int,const char*,const char*,const char*,const char*);
136
+ void *pAuthArg; /* Argument to the authorizer */
137
+ const char *zAuthName; /* Name of the authorizer */
135138
} db = {0, 0, 0, 0, 0, 0, };
136139
137140
/*
138141
** Arrange for the given file to be deleted on a failure.
139142
*/
@@ -316,10 +319,36 @@
316319
}
317320
db.aHook[db.nCommitHook].sequence = sequence;
318321
db.aHook[db.nCommitHook].xHook = x;
319322
db.nCommitHook++;
320323
}
324
+
325
+/*
326
+** Set or unset the query authorizer callback function
327
+*/
328
+void db_set_authorizer(
329
+ int(*xAuth)(void*,int,const char*,const char*,const char*,const char*),
330
+ void *pArg,
331
+ const char *zName /* for tracing */
332
+){
333
+ if( db.xAuth ){
334
+ fossil_panic("multiple active db_set_authorizer() calls");
335
+ }
336
+ if( g.db ) sqlite3_set_authorizer(g.db, xAuth, pArg);
337
+ db.xAuth = xAuth;
338
+ db.pAuthArg = pArg;
339
+ db.zAuthName = zName;
340
+ if( g.fSqlTrace ) fossil_trace("-- set authorizer %s\n", zName);
341
+}
342
+void db_clear_authorizer(void){
343
+ if( db.zAuthName && g.fSqlTrace ){
344
+ fossil_trace("-- discontinue authorizer %s\n", db.zAuthName);
345
+ }
346
+ if( g.db ) sqlite3_set_authorizer(g.db, 0, 0);
347
+ db.xAuth = 0;
348
+ db.pAuthArg = 0;
349
+}
321350
322351
#if INTERFACE
323352
/*
324353
** Possible flags to db_vprepare
325354
*/
@@ -844,34 +873,37 @@
844873
void db_init_database(
845874
const char *zFileName, /* Name of database file to create */
846875
const char *zSchema, /* First part of schema */
847876
... /* Additional SQL to run. Terminate with NULL. */
848877
){
849
- sqlite3 *db;
878
+ sqlite3 *xdb;
850879
int rc;
851880
const char *zSql;
852881
va_list ap;
853882
854
- db = db_open(zFileName ? zFileName : ":memory:");
855
- sqlite3_exec(db, "BEGIN EXCLUSIVE", 0, 0, 0);
856
- rc = sqlite3_exec(db, zSchema, 0, 0, 0);
883
+ xdb = db_open(zFileName ? zFileName : ":memory:");
884
+ sqlite3_exec(xdb, "BEGIN EXCLUSIVE", 0, 0, 0);
885
+ if( db.xAuth ){
886
+ sqlite3_set_authorizer(xdb, db.xAuth, db.pAuthArg);
887
+ }
888
+ rc = sqlite3_exec(xdb, zSchema, 0, 0, 0);
857889
if( rc!=SQLITE_OK ){
858
- db_err("%s", sqlite3_errmsg(db));
890
+ db_err("%s", sqlite3_errmsg(xdb));
859891
}
860892
va_start(ap, zSchema);
861893
while( (zSql = va_arg(ap, const char*))!=0 ){
862
- rc = sqlite3_exec(db, zSql, 0, 0, 0);
894
+ rc = sqlite3_exec(xdb, zSql, 0, 0, 0);
863895
if( rc!=SQLITE_OK ){
864
- db_err("%s", sqlite3_errmsg(db));
896
+ db_err("%s", sqlite3_errmsg(xdb));
865897
}
866898
}
867899
va_end(ap);
868
- sqlite3_exec(db, "COMMIT", 0, 0, 0);
900
+ sqlite3_exec(xdb, "COMMIT", 0, 0, 0);
869901
if( zFileName || g.db!=0 ){
870
- sqlite3_close(db);
902
+ sqlite3_close(xdb);
871903
}else{
872
- g.db = db;
904
+ g.db = xdb;
873905
}
874906
}
875907
876908
/*
877909
** Function to return the number of seconds since 1970. This is
@@ -2086,10 +2118,11 @@
20862118
** argument is true. Ignore unfinalized statements when false.
20872119
*/
20882120
void db_close(int reportErrors){
20892121
sqlite3_stmt *pStmt;
20902122
if( g.db==0 ) return;
2123
+ sqlite3_set_authorizer(g.db, 0, 0);
20912124
if( g.fSqlStats ){
20922125
int cur, hiwtr;
20932126
sqlite3_db_status(g.db, SQLITE_DBSTATUS_LOOKASIDE_USED, &cur, &hiwtr, 0);
20942127
fprintf(stderr, "-- LOOKASIDE_USED %10d %10d\n", cur, hiwtr);
20952128
sqlite3_db_status(g.db, SQLITE_DBSTATUS_LOOKASIDE_HIT, &cur, &hiwtr, 0);
@@ -2115,17 +2148,20 @@
21152148
fprintf(stderr, "-- prepared statements %10d\n", db.nPrepare);
21162149
}
21172150
while( db.pAllStmt ){
21182151
db_finalize(db.pAllStmt);
21192152
}
2120
- if( db.nBegin && reportErrors ){
2121
- fossil_warning("Transaction started at %s:%d never commits",
2122
- db.zStartFile, db.iStartLine);
2153
+ if( db.nBegin ){
2154
+ if( reportErrors ){
2155
+ fossil_warning("Transaction started at %s:%d never commits",
2156
+ db.zStartFile, db.iStartLine);
2157
+ }
21232158
db_end_transaction(1);
21242159
}
21252160
pStmt = 0;
2126
- g.dbIgnoreErrors++; /* Stop "database locked" warnings from PRAGMA optimize */
2161
+ sqlite3_busy_timeout(g.db, 0);
2162
+ g.dbIgnoreErrors++; /* Stop "database locked" warnings */
21272163
sqlite3_exec(g.db, "PRAGMA optimize", 0, 0, 0);
21282164
g.dbIgnoreErrors--;
21292165
db_close_config();
21302166
21312167
/* If the localdb has a lot of unused free space,
@@ -2165,10 +2201,11 @@
21652201
if( g.db ){
21662202
int rc;
21672203
sqlite3_wal_checkpoint(g.db, 0);
21682204
rc = sqlite3_close(g.db);
21692205
if( g.fSqlTrace ) fossil_trace("-- sqlite3_close(%d)\n", rc);
2206
+ db_clear_authorizer();
21702207
}
21712208
g.db = 0;
21722209
g.repositoryOpen = 0;
21732210
g.localOpen = 0;
21742211
}
21752212
--- src/db.c
+++ src/db.c
@@ -130,10 +130,13 @@
130 char *azBeforeCommit[5]; /* Commands to run prior to COMMIT */
131 int nBeforeCommit; /* Number of entries in azBeforeCommit */
132 int nPriorChanges; /* sqlite3_total_changes() at transaction start */
133 const char *zStartFile; /* File in which transaction was started */
134 int iStartLine; /* Line of zStartFile where transaction started */
 
 
 
135 } db = {0, 0, 0, 0, 0, 0, };
136
137 /*
138 ** Arrange for the given file to be deleted on a failure.
139 */
@@ -316,10 +319,36 @@
316 }
317 db.aHook[db.nCommitHook].sequence = sequence;
318 db.aHook[db.nCommitHook].xHook = x;
319 db.nCommitHook++;
320 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
321
322 #if INTERFACE
323 /*
324 ** Possible flags to db_vprepare
325 */
@@ -844,34 +873,37 @@
844 void db_init_database(
845 const char *zFileName, /* Name of database file to create */
846 const char *zSchema, /* First part of schema */
847 ... /* Additional SQL to run. Terminate with NULL. */
848 ){
849 sqlite3 *db;
850 int rc;
851 const char *zSql;
852 va_list ap;
853
854 db = db_open(zFileName ? zFileName : ":memory:");
855 sqlite3_exec(db, "BEGIN EXCLUSIVE", 0, 0, 0);
856 rc = sqlite3_exec(db, zSchema, 0, 0, 0);
 
 
 
857 if( rc!=SQLITE_OK ){
858 db_err("%s", sqlite3_errmsg(db));
859 }
860 va_start(ap, zSchema);
861 while( (zSql = va_arg(ap, const char*))!=0 ){
862 rc = sqlite3_exec(db, zSql, 0, 0, 0);
863 if( rc!=SQLITE_OK ){
864 db_err("%s", sqlite3_errmsg(db));
865 }
866 }
867 va_end(ap);
868 sqlite3_exec(db, "COMMIT", 0, 0, 0);
869 if( zFileName || g.db!=0 ){
870 sqlite3_close(db);
871 }else{
872 g.db = db;
873 }
874 }
875
876 /*
877 ** Function to return the number of seconds since 1970. This is
@@ -2086,10 +2118,11 @@
2086 ** argument is true. Ignore unfinalized statements when false.
2087 */
2088 void db_close(int reportErrors){
2089 sqlite3_stmt *pStmt;
2090 if( g.db==0 ) return;
 
2091 if( g.fSqlStats ){
2092 int cur, hiwtr;
2093 sqlite3_db_status(g.db, SQLITE_DBSTATUS_LOOKASIDE_USED, &cur, &hiwtr, 0);
2094 fprintf(stderr, "-- LOOKASIDE_USED %10d %10d\n", cur, hiwtr);
2095 sqlite3_db_status(g.db, SQLITE_DBSTATUS_LOOKASIDE_HIT, &cur, &hiwtr, 0);
@@ -2115,17 +2148,20 @@
2115 fprintf(stderr, "-- prepared statements %10d\n", db.nPrepare);
2116 }
2117 while( db.pAllStmt ){
2118 db_finalize(db.pAllStmt);
2119 }
2120 if( db.nBegin && reportErrors ){
2121 fossil_warning("Transaction started at %s:%d never commits",
2122 db.zStartFile, db.iStartLine);
 
 
2123 db_end_transaction(1);
2124 }
2125 pStmt = 0;
2126 g.dbIgnoreErrors++; /* Stop "database locked" warnings from PRAGMA optimize */
 
2127 sqlite3_exec(g.db, "PRAGMA optimize", 0, 0, 0);
2128 g.dbIgnoreErrors--;
2129 db_close_config();
2130
2131 /* If the localdb has a lot of unused free space,
@@ -2165,10 +2201,11 @@
2165 if( g.db ){
2166 int rc;
2167 sqlite3_wal_checkpoint(g.db, 0);
2168 rc = sqlite3_close(g.db);
2169 if( g.fSqlTrace ) fossil_trace("-- sqlite3_close(%d)\n", rc);
 
2170 }
2171 g.db = 0;
2172 g.repositoryOpen = 0;
2173 g.localOpen = 0;
2174 }
2175
--- src/db.c
+++ src/db.c
@@ -130,10 +130,13 @@
130 char *azBeforeCommit[5]; /* Commands to run prior to COMMIT */
131 int nBeforeCommit; /* Number of entries in azBeforeCommit */
132 int nPriorChanges; /* sqlite3_total_changes() at transaction start */
133 const char *zStartFile; /* File in which transaction was started */
134 int iStartLine; /* Line of zStartFile where transaction started */
135 int (*xAuth)(void*,int,const char*,const char*,const char*,const char*);
136 void *pAuthArg; /* Argument to the authorizer */
137 const char *zAuthName; /* Name of the authorizer */
138 } db = {0, 0, 0, 0, 0, 0, };
139
140 /*
141 ** Arrange for the given file to be deleted on a failure.
142 */
@@ -316,10 +319,36 @@
319 }
320 db.aHook[db.nCommitHook].sequence = sequence;
321 db.aHook[db.nCommitHook].xHook = x;
322 db.nCommitHook++;
323 }
324
325 /*
326 ** Set or unset the query authorizer callback function
327 */
328 void db_set_authorizer(
329 int(*xAuth)(void*,int,const char*,const char*,const char*,const char*),
330 void *pArg,
331 const char *zName /* for tracing */
332 ){
333 if( db.xAuth ){
334 fossil_panic("multiple active db_set_authorizer() calls");
335 }
336 if( g.db ) sqlite3_set_authorizer(g.db, xAuth, pArg);
337 db.xAuth = xAuth;
338 db.pAuthArg = pArg;
339 db.zAuthName = zName;
340 if( g.fSqlTrace ) fossil_trace("-- set authorizer %s\n", zName);
341 }
342 void db_clear_authorizer(void){
343 if( db.zAuthName && g.fSqlTrace ){
344 fossil_trace("-- discontinue authorizer %s\n", db.zAuthName);
345 }
346 if( g.db ) sqlite3_set_authorizer(g.db, 0, 0);
347 db.xAuth = 0;
348 db.pAuthArg = 0;
349 }
350
351 #if INTERFACE
352 /*
353 ** Possible flags to db_vprepare
354 */
@@ -844,34 +873,37 @@
873 void db_init_database(
874 const char *zFileName, /* Name of database file to create */
875 const char *zSchema, /* First part of schema */
876 ... /* Additional SQL to run. Terminate with NULL. */
877 ){
878 sqlite3 *xdb;
879 int rc;
880 const char *zSql;
881 va_list ap;
882
883 xdb = db_open(zFileName ? zFileName : ":memory:");
884 sqlite3_exec(xdb, "BEGIN EXCLUSIVE", 0, 0, 0);
885 if( db.xAuth ){
886 sqlite3_set_authorizer(xdb, db.xAuth, db.pAuthArg);
887 }
888 rc = sqlite3_exec(xdb, zSchema, 0, 0, 0);
889 if( rc!=SQLITE_OK ){
890 db_err("%s", sqlite3_errmsg(xdb));
891 }
892 va_start(ap, zSchema);
893 while( (zSql = va_arg(ap, const char*))!=0 ){
894 rc = sqlite3_exec(xdb, zSql, 0, 0, 0);
895 if( rc!=SQLITE_OK ){
896 db_err("%s", sqlite3_errmsg(xdb));
897 }
898 }
899 va_end(ap);
900 sqlite3_exec(xdb, "COMMIT", 0, 0, 0);
901 if( zFileName || g.db!=0 ){
902 sqlite3_close(xdb);
903 }else{
904 g.db = xdb;
905 }
906 }
907
908 /*
909 ** Function to return the number of seconds since 1970. This is
@@ -2086,10 +2118,11 @@
2118 ** argument is true. Ignore unfinalized statements when false.
2119 */
2120 void db_close(int reportErrors){
2121 sqlite3_stmt *pStmt;
2122 if( g.db==0 ) return;
2123 sqlite3_set_authorizer(g.db, 0, 0);
2124 if( g.fSqlStats ){
2125 int cur, hiwtr;
2126 sqlite3_db_status(g.db, SQLITE_DBSTATUS_LOOKASIDE_USED, &cur, &hiwtr, 0);
2127 fprintf(stderr, "-- LOOKASIDE_USED %10d %10d\n", cur, hiwtr);
2128 sqlite3_db_status(g.db, SQLITE_DBSTATUS_LOOKASIDE_HIT, &cur, &hiwtr, 0);
@@ -2115,17 +2148,20 @@
2148 fprintf(stderr, "-- prepared statements %10d\n", db.nPrepare);
2149 }
2150 while( db.pAllStmt ){
2151 db_finalize(db.pAllStmt);
2152 }
2153 if( db.nBegin ){
2154 if( reportErrors ){
2155 fossil_warning("Transaction started at %s:%d never commits",
2156 db.zStartFile, db.iStartLine);
2157 }
2158 db_end_transaction(1);
2159 }
2160 pStmt = 0;
2161 sqlite3_busy_timeout(g.db, 0);
2162 g.dbIgnoreErrors++; /* Stop "database locked" warnings */
2163 sqlite3_exec(g.db, "PRAGMA optimize", 0, 0, 0);
2164 g.dbIgnoreErrors--;
2165 db_close_config();
2166
2167 /* If the localdb has a lot of unused free space,
@@ -2165,10 +2201,11 @@
2201 if( g.db ){
2202 int rc;
2203 sqlite3_wal_checkpoint(g.db, 0);
2204 rc = sqlite3_close(g.db);
2205 if( g.fSqlTrace ) fossil_trace("-- sqlite3_close(%d)\n", rc);
2206 db_clear_authorizer();
2207 }
2208 g.db = 0;
2209 g.repositoryOpen = 0;
2210 g.localOpen = 0;
2211 }
2212
+51 -14
--- src/db.c
+++ src/db.c
@@ -130,10 +130,13 @@
130130
char *azBeforeCommit[5]; /* Commands to run prior to COMMIT */
131131
int nBeforeCommit; /* Number of entries in azBeforeCommit */
132132
int nPriorChanges; /* sqlite3_total_changes() at transaction start */
133133
const char *zStartFile; /* File in which transaction was started */
134134
int iStartLine; /* Line of zStartFile where transaction started */
135
+ int (*xAuth)(void*,int,const char*,const char*,const char*,const char*);
136
+ void *pAuthArg; /* Argument to the authorizer */
137
+ const char *zAuthName; /* Name of the authorizer */
135138
} db = {0, 0, 0, 0, 0, 0, };
136139
137140
/*
138141
** Arrange for the given file to be deleted on a failure.
139142
*/
@@ -316,10 +319,36 @@
316319
}
317320
db.aHook[db.nCommitHook].sequence = sequence;
318321
db.aHook[db.nCommitHook].xHook = x;
319322
db.nCommitHook++;
320323
}
324
+
325
+/*
326
+** Set or unset the query authorizer callback function
327
+*/
328
+void db_set_authorizer(
329
+ int(*xAuth)(void*,int,const char*,const char*,const char*,const char*),
330
+ void *pArg,
331
+ const char *zName /* for tracing */
332
+){
333
+ if( db.xAuth ){
334
+ fossil_panic("multiple active db_set_authorizer() calls");
335
+ }
336
+ if( g.db ) sqlite3_set_authorizer(g.db, xAuth, pArg);
337
+ db.xAuth = xAuth;
338
+ db.pAuthArg = pArg;
339
+ db.zAuthName = zName;
340
+ if( g.fSqlTrace ) fossil_trace("-- set authorizer %s\n", zName);
341
+}
342
+void db_clear_authorizer(void){
343
+ if( db.zAuthName && g.fSqlTrace ){
344
+ fossil_trace("-- discontinue authorizer %s\n", db.zAuthName);
345
+ }
346
+ if( g.db ) sqlite3_set_authorizer(g.db, 0, 0);
347
+ db.xAuth = 0;
348
+ db.pAuthArg = 0;
349
+}
321350
322351
#if INTERFACE
323352
/*
324353
** Possible flags to db_vprepare
325354
*/
@@ -844,34 +873,37 @@
844873
void db_init_database(
845874
const char *zFileName, /* Name of database file to create */
846875
const char *zSchema, /* First part of schema */
847876
... /* Additional SQL to run. Terminate with NULL. */
848877
){
849
- sqlite3 *db;
878
+ sqlite3 *xdb;
850879
int rc;
851880
const char *zSql;
852881
va_list ap;
853882
854
- db = db_open(zFileName ? zFileName : ":memory:");
855
- sqlite3_exec(db, "BEGIN EXCLUSIVE", 0, 0, 0);
856
- rc = sqlite3_exec(db, zSchema, 0, 0, 0);
883
+ xdb = db_open(zFileName ? zFileName : ":memory:");
884
+ sqlite3_exec(xdb, "BEGIN EXCLUSIVE", 0, 0, 0);
885
+ if( db.xAuth ){
886
+ sqlite3_set_authorizer(xdb, db.xAuth, db.pAuthArg);
887
+ }
888
+ rc = sqlite3_exec(xdb, zSchema, 0, 0, 0);
857889
if( rc!=SQLITE_OK ){
858
- db_err("%s", sqlite3_errmsg(db));
890
+ db_err("%s", sqlite3_errmsg(xdb));
859891
}
860892
va_start(ap, zSchema);
861893
while( (zSql = va_arg(ap, const char*))!=0 ){
862
- rc = sqlite3_exec(db, zSql, 0, 0, 0);
894
+ rc = sqlite3_exec(xdb, zSql, 0, 0, 0);
863895
if( rc!=SQLITE_OK ){
864
- db_err("%s", sqlite3_errmsg(db));
896
+ db_err("%s", sqlite3_errmsg(xdb));
865897
}
866898
}
867899
va_end(ap);
868
- sqlite3_exec(db, "COMMIT", 0, 0, 0);
900
+ sqlite3_exec(xdb, "COMMIT", 0, 0, 0);
869901
if( zFileName || g.db!=0 ){
870
- sqlite3_close(db);
902
+ sqlite3_close(xdb);
871903
}else{
872
- g.db = db;
904
+ g.db = xdb;
873905
}
874906
}
875907
876908
/*
877909
** Function to return the number of seconds since 1970. This is
@@ -2086,10 +2118,11 @@
20862118
** argument is true. Ignore unfinalized statements when false.
20872119
*/
20882120
void db_close(int reportErrors){
20892121
sqlite3_stmt *pStmt;
20902122
if( g.db==0 ) return;
2123
+ sqlite3_set_authorizer(g.db, 0, 0);
20912124
if( g.fSqlStats ){
20922125
int cur, hiwtr;
20932126
sqlite3_db_status(g.db, SQLITE_DBSTATUS_LOOKASIDE_USED, &cur, &hiwtr, 0);
20942127
fprintf(stderr, "-- LOOKASIDE_USED %10d %10d\n", cur, hiwtr);
20952128
sqlite3_db_status(g.db, SQLITE_DBSTATUS_LOOKASIDE_HIT, &cur, &hiwtr, 0);
@@ -2115,17 +2148,20 @@
21152148
fprintf(stderr, "-- prepared statements %10d\n", db.nPrepare);
21162149
}
21172150
while( db.pAllStmt ){
21182151
db_finalize(db.pAllStmt);
21192152
}
2120
- if( db.nBegin && reportErrors ){
2121
- fossil_warning("Transaction started at %s:%d never commits",
2122
- db.zStartFile, db.iStartLine);
2153
+ if( db.nBegin ){
2154
+ if( reportErrors ){
2155
+ fossil_warning("Transaction started at %s:%d never commits",
2156
+ db.zStartFile, db.iStartLine);
2157
+ }
21232158
db_end_transaction(1);
21242159
}
21252160
pStmt = 0;
2126
- g.dbIgnoreErrors++; /* Stop "database locked" warnings from PRAGMA optimize */
2161
+ sqlite3_busy_timeout(g.db, 0);
2162
+ g.dbIgnoreErrors++; /* Stop "database locked" warnings */
21272163
sqlite3_exec(g.db, "PRAGMA optimize", 0, 0, 0);
21282164
g.dbIgnoreErrors--;
21292165
db_close_config();
21302166
21312167
/* If the localdb has a lot of unused free space,
@@ -2165,10 +2201,11 @@
21652201
if( g.db ){
21662202
int rc;
21672203
sqlite3_wal_checkpoint(g.db, 0);
21682204
rc = sqlite3_close(g.db);
21692205
if( g.fSqlTrace ) fossil_trace("-- sqlite3_close(%d)\n", rc);
2206
+ db_clear_authorizer();
21702207
}
21712208
g.db = 0;
21722209
g.repositoryOpen = 0;
21732210
g.localOpen = 0;
21742211
}
21752212
--- src/db.c
+++ src/db.c
@@ -130,10 +130,13 @@
130 char *azBeforeCommit[5]; /* Commands to run prior to COMMIT */
131 int nBeforeCommit; /* Number of entries in azBeforeCommit */
132 int nPriorChanges; /* sqlite3_total_changes() at transaction start */
133 const char *zStartFile; /* File in which transaction was started */
134 int iStartLine; /* Line of zStartFile where transaction started */
 
 
 
135 } db = {0, 0, 0, 0, 0, 0, };
136
137 /*
138 ** Arrange for the given file to be deleted on a failure.
139 */
@@ -316,10 +319,36 @@
316 }
317 db.aHook[db.nCommitHook].sequence = sequence;
318 db.aHook[db.nCommitHook].xHook = x;
319 db.nCommitHook++;
320 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
321
322 #if INTERFACE
323 /*
324 ** Possible flags to db_vprepare
325 */
@@ -844,34 +873,37 @@
844 void db_init_database(
845 const char *zFileName, /* Name of database file to create */
846 const char *zSchema, /* First part of schema */
847 ... /* Additional SQL to run. Terminate with NULL. */
848 ){
849 sqlite3 *db;
850 int rc;
851 const char *zSql;
852 va_list ap;
853
854 db = db_open(zFileName ? zFileName : ":memory:");
855 sqlite3_exec(db, "BEGIN EXCLUSIVE", 0, 0, 0);
856 rc = sqlite3_exec(db, zSchema, 0, 0, 0);
 
 
 
857 if( rc!=SQLITE_OK ){
858 db_err("%s", sqlite3_errmsg(db));
859 }
860 va_start(ap, zSchema);
861 while( (zSql = va_arg(ap, const char*))!=0 ){
862 rc = sqlite3_exec(db, zSql, 0, 0, 0);
863 if( rc!=SQLITE_OK ){
864 db_err("%s", sqlite3_errmsg(db));
865 }
866 }
867 va_end(ap);
868 sqlite3_exec(db, "COMMIT", 0, 0, 0);
869 if( zFileName || g.db!=0 ){
870 sqlite3_close(db);
871 }else{
872 g.db = db;
873 }
874 }
875
876 /*
877 ** Function to return the number of seconds since 1970. This is
@@ -2086,10 +2118,11 @@
2086 ** argument is true. Ignore unfinalized statements when false.
2087 */
2088 void db_close(int reportErrors){
2089 sqlite3_stmt *pStmt;
2090 if( g.db==0 ) return;
 
2091 if( g.fSqlStats ){
2092 int cur, hiwtr;
2093 sqlite3_db_status(g.db, SQLITE_DBSTATUS_LOOKASIDE_USED, &cur, &hiwtr, 0);
2094 fprintf(stderr, "-- LOOKASIDE_USED %10d %10d\n", cur, hiwtr);
2095 sqlite3_db_status(g.db, SQLITE_DBSTATUS_LOOKASIDE_HIT, &cur, &hiwtr, 0);
@@ -2115,17 +2148,20 @@
2115 fprintf(stderr, "-- prepared statements %10d\n", db.nPrepare);
2116 }
2117 while( db.pAllStmt ){
2118 db_finalize(db.pAllStmt);
2119 }
2120 if( db.nBegin && reportErrors ){
2121 fossil_warning("Transaction started at %s:%d never commits",
2122 db.zStartFile, db.iStartLine);
 
 
2123 db_end_transaction(1);
2124 }
2125 pStmt = 0;
2126 g.dbIgnoreErrors++; /* Stop "database locked" warnings from PRAGMA optimize */
 
2127 sqlite3_exec(g.db, "PRAGMA optimize", 0, 0, 0);
2128 g.dbIgnoreErrors--;
2129 db_close_config();
2130
2131 /* If the localdb has a lot of unused free space,
@@ -2165,10 +2201,11 @@
2165 if( g.db ){
2166 int rc;
2167 sqlite3_wal_checkpoint(g.db, 0);
2168 rc = sqlite3_close(g.db);
2169 if( g.fSqlTrace ) fossil_trace("-- sqlite3_close(%d)\n", rc);
 
2170 }
2171 g.db = 0;
2172 g.repositoryOpen = 0;
2173 g.localOpen = 0;
2174 }
2175
--- src/db.c
+++ src/db.c
@@ -130,10 +130,13 @@
130 char *azBeforeCommit[5]; /* Commands to run prior to COMMIT */
131 int nBeforeCommit; /* Number of entries in azBeforeCommit */
132 int nPriorChanges; /* sqlite3_total_changes() at transaction start */
133 const char *zStartFile; /* File in which transaction was started */
134 int iStartLine; /* Line of zStartFile where transaction started */
135 int (*xAuth)(void*,int,const char*,const char*,const char*,const char*);
136 void *pAuthArg; /* Argument to the authorizer */
137 const char *zAuthName; /* Name of the authorizer */
138 } db = {0, 0, 0, 0, 0, 0, };
139
140 /*
141 ** Arrange for the given file to be deleted on a failure.
142 */
@@ -316,10 +319,36 @@
319 }
320 db.aHook[db.nCommitHook].sequence = sequence;
321 db.aHook[db.nCommitHook].xHook = x;
322 db.nCommitHook++;
323 }
324
325 /*
326 ** Set or unset the query authorizer callback function
327 */
328 void db_set_authorizer(
329 int(*xAuth)(void*,int,const char*,const char*,const char*,const char*),
330 void *pArg,
331 const char *zName /* for tracing */
332 ){
333 if( db.xAuth ){
334 fossil_panic("multiple active db_set_authorizer() calls");
335 }
336 if( g.db ) sqlite3_set_authorizer(g.db, xAuth, pArg);
337 db.xAuth = xAuth;
338 db.pAuthArg = pArg;
339 db.zAuthName = zName;
340 if( g.fSqlTrace ) fossil_trace("-- set authorizer %s\n", zName);
341 }
342 void db_clear_authorizer(void){
343 if( db.zAuthName && g.fSqlTrace ){
344 fossil_trace("-- discontinue authorizer %s\n", db.zAuthName);
345 }
346 if( g.db ) sqlite3_set_authorizer(g.db, 0, 0);
347 db.xAuth = 0;
348 db.pAuthArg = 0;
349 }
350
351 #if INTERFACE
352 /*
353 ** Possible flags to db_vprepare
354 */
@@ -844,34 +873,37 @@
873 void db_init_database(
874 const char *zFileName, /* Name of database file to create */
875 const char *zSchema, /* First part of schema */
876 ... /* Additional SQL to run. Terminate with NULL. */
877 ){
878 sqlite3 *xdb;
879 int rc;
880 const char *zSql;
881 va_list ap;
882
883 xdb = db_open(zFileName ? zFileName : ":memory:");
884 sqlite3_exec(xdb, "BEGIN EXCLUSIVE", 0, 0, 0);
885 if( db.xAuth ){
886 sqlite3_set_authorizer(xdb, db.xAuth, db.pAuthArg);
887 }
888 rc = sqlite3_exec(xdb, zSchema, 0, 0, 0);
889 if( rc!=SQLITE_OK ){
890 db_err("%s", sqlite3_errmsg(xdb));
891 }
892 va_start(ap, zSchema);
893 while( (zSql = va_arg(ap, const char*))!=0 ){
894 rc = sqlite3_exec(xdb, zSql, 0, 0, 0);
895 if( rc!=SQLITE_OK ){
896 db_err("%s", sqlite3_errmsg(xdb));
897 }
898 }
899 va_end(ap);
900 sqlite3_exec(xdb, "COMMIT", 0, 0, 0);
901 if( zFileName || g.db!=0 ){
902 sqlite3_close(xdb);
903 }else{
904 g.db = xdb;
905 }
906 }
907
908 /*
909 ** Function to return the number of seconds since 1970. This is
@@ -2086,10 +2118,11 @@
2118 ** argument is true. Ignore unfinalized statements when false.
2119 */
2120 void db_close(int reportErrors){
2121 sqlite3_stmt *pStmt;
2122 if( g.db==0 ) return;
2123 sqlite3_set_authorizer(g.db, 0, 0);
2124 if( g.fSqlStats ){
2125 int cur, hiwtr;
2126 sqlite3_db_status(g.db, SQLITE_DBSTATUS_LOOKASIDE_USED, &cur, &hiwtr, 0);
2127 fprintf(stderr, "-- LOOKASIDE_USED %10d %10d\n", cur, hiwtr);
2128 sqlite3_db_status(g.db, SQLITE_DBSTATUS_LOOKASIDE_HIT, &cur, &hiwtr, 0);
@@ -2115,17 +2148,20 @@
2148 fprintf(stderr, "-- prepared statements %10d\n", db.nPrepare);
2149 }
2150 while( db.pAllStmt ){
2151 db_finalize(db.pAllStmt);
2152 }
2153 if( db.nBegin ){
2154 if( reportErrors ){
2155 fossil_warning("Transaction started at %s:%d never commits",
2156 db.zStartFile, db.iStartLine);
2157 }
2158 db_end_transaction(1);
2159 }
2160 pStmt = 0;
2161 sqlite3_busy_timeout(g.db, 0);
2162 g.dbIgnoreErrors++; /* Stop "database locked" warnings */
2163 sqlite3_exec(g.db, "PRAGMA optimize", 0, 0, 0);
2164 g.dbIgnoreErrors--;
2165 db_close_config();
2166
2167 /* If the localdb has a lot of unused free space,
@@ -2165,10 +2201,11 @@
2201 if( g.db ){
2202 int rc;
2203 sqlite3_wal_checkpoint(g.db, 0);
2204 rc = sqlite3_close(g.db);
2205 if( g.fSqlTrace ) fossil_trace("-- sqlite3_close(%d)\n", rc);
2206 db_clear_authorizer();
2207 }
2208 g.db = 0;
2209 g.repositoryOpen = 0;
2210 g.localOpen = 0;
2211 }
2212
+51 -14
--- src/db.c
+++ src/db.c
@@ -130,10 +130,13 @@
130130
char *azBeforeCommit[5]; /* Commands to run prior to COMMIT */
131131
int nBeforeCommit; /* Number of entries in azBeforeCommit */
132132
int nPriorChanges; /* sqlite3_total_changes() at transaction start */
133133
const char *zStartFile; /* File in which transaction was started */
134134
int iStartLine; /* Line of zStartFile where transaction started */
135
+ int (*xAuth)(void*,int,const char*,const char*,const char*,const char*);
136
+ void *pAuthArg; /* Argument to the authorizer */
137
+ const char *zAuthName; /* Name of the authorizer */
135138
} db = {0, 0, 0, 0, 0, 0, };
136139
137140
/*
138141
** Arrange for the given file to be deleted on a failure.
139142
*/
@@ -316,10 +319,36 @@
316319
}
317320
db.aHook[db.nCommitHook].sequence = sequence;
318321
db.aHook[db.nCommitHook].xHook = x;
319322
db.nCommitHook++;
320323
}
324
+
325
+/*
326
+** Set or unset the query authorizer callback function
327
+*/
328
+void db_set_authorizer(
329
+ int(*xAuth)(void*,int,const char*,const char*,const char*,const char*),
330
+ void *pArg,
331
+ const char *zName /* for tracing */
332
+){
333
+ if( db.xAuth ){
334
+ fossil_panic("multiple active db_set_authorizer() calls");
335
+ }
336
+ if( g.db ) sqlite3_set_authorizer(g.db, xAuth, pArg);
337
+ db.xAuth = xAuth;
338
+ db.pAuthArg = pArg;
339
+ db.zAuthName = zName;
340
+ if( g.fSqlTrace ) fossil_trace("-- set authorizer %s\n", zName);
341
+}
342
+void db_clear_authorizer(void){
343
+ if( db.zAuthName && g.fSqlTrace ){
344
+ fossil_trace("-- discontinue authorizer %s\n", db.zAuthName);
345
+ }
346
+ if( g.db ) sqlite3_set_authorizer(g.db, 0, 0);
347
+ db.xAuth = 0;
348
+ db.pAuthArg = 0;
349
+}
321350
322351
#if INTERFACE
323352
/*
324353
** Possible flags to db_vprepare
325354
*/
@@ -844,34 +873,37 @@
844873
void db_init_database(
845874
const char *zFileName, /* Name of database file to create */
846875
const char *zSchema, /* First part of schema */
847876
... /* Additional SQL to run. Terminate with NULL. */
848877
){
849
- sqlite3 *db;
878
+ sqlite3 *xdb;
850879
int rc;
851880
const char *zSql;
852881
va_list ap;
853882
854
- db = db_open(zFileName ? zFileName : ":memory:");
855
- sqlite3_exec(db, "BEGIN EXCLUSIVE", 0, 0, 0);
856
- rc = sqlite3_exec(db, zSchema, 0, 0, 0);
883
+ xdb = db_open(zFileName ? zFileName : ":memory:");
884
+ sqlite3_exec(xdb, "BEGIN EXCLUSIVE", 0, 0, 0);
885
+ if( db.xAuth ){
886
+ sqlite3_set_authorizer(xdb, db.xAuth, db.pAuthArg);
887
+ }
888
+ rc = sqlite3_exec(xdb, zSchema, 0, 0, 0);
857889
if( rc!=SQLITE_OK ){
858
- db_err("%s", sqlite3_errmsg(db));
890
+ db_err("%s", sqlite3_errmsg(xdb));
859891
}
860892
va_start(ap, zSchema);
861893
while( (zSql = va_arg(ap, const char*))!=0 ){
862
- rc = sqlite3_exec(db, zSql, 0, 0, 0);
894
+ rc = sqlite3_exec(xdb, zSql, 0, 0, 0);
863895
if( rc!=SQLITE_OK ){
864
- db_err("%s", sqlite3_errmsg(db));
896
+ db_err("%s", sqlite3_errmsg(xdb));
865897
}
866898
}
867899
va_end(ap);
868
- sqlite3_exec(db, "COMMIT", 0, 0, 0);
900
+ sqlite3_exec(xdb, "COMMIT", 0, 0, 0);
869901
if( zFileName || g.db!=0 ){
870
- sqlite3_close(db);
902
+ sqlite3_close(xdb);
871903
}else{
872
- g.db = db;
904
+ g.db = xdb;
873905
}
874906
}
875907
876908
/*
877909
** Function to return the number of seconds since 1970. This is
@@ -2086,10 +2118,11 @@
20862118
** argument is true. Ignore unfinalized statements when false.
20872119
*/
20882120
void db_close(int reportErrors){
20892121
sqlite3_stmt *pStmt;
20902122
if( g.db==0 ) return;
2123
+ sqlite3_set_authorizer(g.db, 0, 0);
20912124
if( g.fSqlStats ){
20922125
int cur, hiwtr;
20932126
sqlite3_db_status(g.db, SQLITE_DBSTATUS_LOOKASIDE_USED, &cur, &hiwtr, 0);
20942127
fprintf(stderr, "-- LOOKASIDE_USED %10d %10d\n", cur, hiwtr);
20952128
sqlite3_db_status(g.db, SQLITE_DBSTATUS_LOOKASIDE_HIT, &cur, &hiwtr, 0);
@@ -2115,17 +2148,20 @@
21152148
fprintf(stderr, "-- prepared statements %10d\n", db.nPrepare);
21162149
}
21172150
while( db.pAllStmt ){
21182151
db_finalize(db.pAllStmt);
21192152
}
2120
- if( db.nBegin && reportErrors ){
2121
- fossil_warning("Transaction started at %s:%d never commits",
2122
- db.zStartFile, db.iStartLine);
2153
+ if( db.nBegin ){
2154
+ if( reportErrors ){
2155
+ fossil_warning("Transaction started at %s:%d never commits",
2156
+ db.zStartFile, db.iStartLine);
2157
+ }
21232158
db_end_transaction(1);
21242159
}
21252160
pStmt = 0;
2126
- g.dbIgnoreErrors++; /* Stop "database locked" warnings from PRAGMA optimize */
2161
+ sqlite3_busy_timeout(g.db, 0);
2162
+ g.dbIgnoreErrors++; /* Stop "database locked" warnings */
21272163
sqlite3_exec(g.db, "PRAGMA optimize", 0, 0, 0);
21282164
g.dbIgnoreErrors--;
21292165
db_close_config();
21302166
21312167
/* If the localdb has a lot of unused free space,
@@ -2165,10 +2201,11 @@
21652201
if( g.db ){
21662202
int rc;
21672203
sqlite3_wal_checkpoint(g.db, 0);
21682204
rc = sqlite3_close(g.db);
21692205
if( g.fSqlTrace ) fossil_trace("-- sqlite3_close(%d)\n", rc);
2206
+ db_clear_authorizer();
21702207
}
21712208
g.db = 0;
21722209
g.repositoryOpen = 0;
21732210
g.localOpen = 0;
21742211
}
21752212
--- src/db.c
+++ src/db.c
@@ -130,10 +130,13 @@
130 char *azBeforeCommit[5]; /* Commands to run prior to COMMIT */
131 int nBeforeCommit; /* Number of entries in azBeforeCommit */
132 int nPriorChanges; /* sqlite3_total_changes() at transaction start */
133 const char *zStartFile; /* File in which transaction was started */
134 int iStartLine; /* Line of zStartFile where transaction started */
 
 
 
135 } db = {0, 0, 0, 0, 0, 0, };
136
137 /*
138 ** Arrange for the given file to be deleted on a failure.
139 */
@@ -316,10 +319,36 @@
316 }
317 db.aHook[db.nCommitHook].sequence = sequence;
318 db.aHook[db.nCommitHook].xHook = x;
319 db.nCommitHook++;
320 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
321
322 #if INTERFACE
323 /*
324 ** Possible flags to db_vprepare
325 */
@@ -844,34 +873,37 @@
844 void db_init_database(
845 const char *zFileName, /* Name of database file to create */
846 const char *zSchema, /* First part of schema */
847 ... /* Additional SQL to run. Terminate with NULL. */
848 ){
849 sqlite3 *db;
850 int rc;
851 const char *zSql;
852 va_list ap;
853
854 db = db_open(zFileName ? zFileName : ":memory:");
855 sqlite3_exec(db, "BEGIN EXCLUSIVE", 0, 0, 0);
856 rc = sqlite3_exec(db, zSchema, 0, 0, 0);
 
 
 
857 if( rc!=SQLITE_OK ){
858 db_err("%s", sqlite3_errmsg(db));
859 }
860 va_start(ap, zSchema);
861 while( (zSql = va_arg(ap, const char*))!=0 ){
862 rc = sqlite3_exec(db, zSql, 0, 0, 0);
863 if( rc!=SQLITE_OK ){
864 db_err("%s", sqlite3_errmsg(db));
865 }
866 }
867 va_end(ap);
868 sqlite3_exec(db, "COMMIT", 0, 0, 0);
869 if( zFileName || g.db!=0 ){
870 sqlite3_close(db);
871 }else{
872 g.db = db;
873 }
874 }
875
876 /*
877 ** Function to return the number of seconds since 1970. This is
@@ -2086,10 +2118,11 @@
2086 ** argument is true. Ignore unfinalized statements when false.
2087 */
2088 void db_close(int reportErrors){
2089 sqlite3_stmt *pStmt;
2090 if( g.db==0 ) return;
 
2091 if( g.fSqlStats ){
2092 int cur, hiwtr;
2093 sqlite3_db_status(g.db, SQLITE_DBSTATUS_LOOKASIDE_USED, &cur, &hiwtr, 0);
2094 fprintf(stderr, "-- LOOKASIDE_USED %10d %10d\n", cur, hiwtr);
2095 sqlite3_db_status(g.db, SQLITE_DBSTATUS_LOOKASIDE_HIT, &cur, &hiwtr, 0);
@@ -2115,17 +2148,20 @@
2115 fprintf(stderr, "-- prepared statements %10d\n", db.nPrepare);
2116 }
2117 while( db.pAllStmt ){
2118 db_finalize(db.pAllStmt);
2119 }
2120 if( db.nBegin && reportErrors ){
2121 fossil_warning("Transaction started at %s:%d never commits",
2122 db.zStartFile, db.iStartLine);
 
 
2123 db_end_transaction(1);
2124 }
2125 pStmt = 0;
2126 g.dbIgnoreErrors++; /* Stop "database locked" warnings from PRAGMA optimize */
 
2127 sqlite3_exec(g.db, "PRAGMA optimize", 0, 0, 0);
2128 g.dbIgnoreErrors--;
2129 db_close_config();
2130
2131 /* If the localdb has a lot of unused free space,
@@ -2165,10 +2201,11 @@
2165 if( g.db ){
2166 int rc;
2167 sqlite3_wal_checkpoint(g.db, 0);
2168 rc = sqlite3_close(g.db);
2169 if( g.fSqlTrace ) fossil_trace("-- sqlite3_close(%d)\n", rc);
 
2170 }
2171 g.db = 0;
2172 g.repositoryOpen = 0;
2173 g.localOpen = 0;
2174 }
2175
--- src/db.c
+++ src/db.c
@@ -130,10 +130,13 @@
130 char *azBeforeCommit[5]; /* Commands to run prior to COMMIT */
131 int nBeforeCommit; /* Number of entries in azBeforeCommit */
132 int nPriorChanges; /* sqlite3_total_changes() at transaction start */
133 const char *zStartFile; /* File in which transaction was started */
134 int iStartLine; /* Line of zStartFile where transaction started */
135 int (*xAuth)(void*,int,const char*,const char*,const char*,const char*);
136 void *pAuthArg; /* Argument to the authorizer */
137 const char *zAuthName; /* Name of the authorizer */
138 } db = {0, 0, 0, 0, 0, 0, };
139
140 /*
141 ** Arrange for the given file to be deleted on a failure.
142 */
@@ -316,10 +319,36 @@
319 }
320 db.aHook[db.nCommitHook].sequence = sequence;
321 db.aHook[db.nCommitHook].xHook = x;
322 db.nCommitHook++;
323 }
324
325 /*
326 ** Set or unset the query authorizer callback function
327 */
328 void db_set_authorizer(
329 int(*xAuth)(void*,int,const char*,const char*,const char*,const char*),
330 void *pArg,
331 const char *zName /* for tracing */
332 ){
333 if( db.xAuth ){
334 fossil_panic("multiple active db_set_authorizer() calls");
335 }
336 if( g.db ) sqlite3_set_authorizer(g.db, xAuth, pArg);
337 db.xAuth = xAuth;
338 db.pAuthArg = pArg;
339 db.zAuthName = zName;
340 if( g.fSqlTrace ) fossil_trace("-- set authorizer %s\n", zName);
341 }
342 void db_clear_authorizer(void){
343 if( db.zAuthName && g.fSqlTrace ){
344 fossil_trace("-- discontinue authorizer %s\n", db.zAuthName);
345 }
346 if( g.db ) sqlite3_set_authorizer(g.db, 0, 0);
347 db.xAuth = 0;
348 db.pAuthArg = 0;
349 }
350
351 #if INTERFACE
352 /*
353 ** Possible flags to db_vprepare
354 */
@@ -844,34 +873,37 @@
873 void db_init_database(
874 const char *zFileName, /* Name of database file to create */
875 const char *zSchema, /* First part of schema */
876 ... /* Additional SQL to run. Terminate with NULL. */
877 ){
878 sqlite3 *xdb;
879 int rc;
880 const char *zSql;
881 va_list ap;
882
883 xdb = db_open(zFileName ? zFileName : ":memory:");
884 sqlite3_exec(xdb, "BEGIN EXCLUSIVE", 0, 0, 0);
885 if( db.xAuth ){
886 sqlite3_set_authorizer(xdb, db.xAuth, db.pAuthArg);
887 }
888 rc = sqlite3_exec(xdb, zSchema, 0, 0, 0);
889 if( rc!=SQLITE_OK ){
890 db_err("%s", sqlite3_errmsg(xdb));
891 }
892 va_start(ap, zSchema);
893 while( (zSql = va_arg(ap, const char*))!=0 ){
894 rc = sqlite3_exec(xdb, zSql, 0, 0, 0);
895 if( rc!=SQLITE_OK ){
896 db_err("%s", sqlite3_errmsg(xdb));
897 }
898 }
899 va_end(ap);
900 sqlite3_exec(xdb, "COMMIT", 0, 0, 0);
901 if( zFileName || g.db!=0 ){
902 sqlite3_close(xdb);
903 }else{
904 g.db = xdb;
905 }
906 }
907
908 /*
909 ** Function to return the number of seconds since 1970. This is
@@ -2086,10 +2118,11 @@
2118 ** argument is true. Ignore unfinalized statements when false.
2119 */
2120 void db_close(int reportErrors){
2121 sqlite3_stmt *pStmt;
2122 if( g.db==0 ) return;
2123 sqlite3_set_authorizer(g.db, 0, 0);
2124 if( g.fSqlStats ){
2125 int cur, hiwtr;
2126 sqlite3_db_status(g.db, SQLITE_DBSTATUS_LOOKASIDE_USED, &cur, &hiwtr, 0);
2127 fprintf(stderr, "-- LOOKASIDE_USED %10d %10d\n", cur, hiwtr);
2128 sqlite3_db_status(g.db, SQLITE_DBSTATUS_LOOKASIDE_HIT, &cur, &hiwtr, 0);
@@ -2115,17 +2148,20 @@
2148 fprintf(stderr, "-- prepared statements %10d\n", db.nPrepare);
2149 }
2150 while( db.pAllStmt ){
2151 db_finalize(db.pAllStmt);
2152 }
2153 if( db.nBegin ){
2154 if( reportErrors ){
2155 fossil_warning("Transaction started at %s:%d never commits",
2156 db.zStartFile, db.iStartLine);
2157 }
2158 db_end_transaction(1);
2159 }
2160 pStmt = 0;
2161 sqlite3_busy_timeout(g.db, 0);
2162 g.dbIgnoreErrors++; /* Stop "database locked" warnings */
2163 sqlite3_exec(g.db, "PRAGMA optimize", 0, 0, 0);
2164 g.dbIgnoreErrors--;
2165 db_close_config();
2166
2167 /* If the localdb has a lot of unused free space,
@@ -2165,10 +2201,11 @@
2201 if( g.db ){
2202 int rc;
2203 sqlite3_wal_checkpoint(g.db, 0);
2204 rc = sqlite3_close(g.db);
2205 if( g.fSqlTrace ) fossil_trace("-- sqlite3_close(%d)\n", rc);
2206 db_clear_authorizer();
2207 }
2208 g.db = 0;
2209 g.repositoryOpen = 0;
2210 g.localOpen = 0;
2211 }
2212
+51 -14
--- src/db.c
+++ src/db.c
@@ -130,10 +130,13 @@
130130
char *azBeforeCommit[5]; /* Commands to run prior to COMMIT */
131131
int nBeforeCommit; /* Number of entries in azBeforeCommit */
132132
int nPriorChanges; /* sqlite3_total_changes() at transaction start */
133133
const char *zStartFile; /* File in which transaction was started */
134134
int iStartLine; /* Line of zStartFile where transaction started */
135
+ int (*xAuth)(void*,int,const char*,const char*,const char*,const char*);
136
+ void *pAuthArg; /* Argument to the authorizer */
137
+ const char *zAuthName; /* Name of the authorizer */
135138
} db = {0, 0, 0, 0, 0, 0, };
136139
137140
/*
138141
** Arrange for the given file to be deleted on a failure.
139142
*/
@@ -316,10 +319,36 @@
316319
}
317320
db.aHook[db.nCommitHook].sequence = sequence;
318321
db.aHook[db.nCommitHook].xHook = x;
319322
db.nCommitHook++;
320323
}
324
+
325
+/*
326
+** Set or unset the query authorizer callback function
327
+*/
328
+void db_set_authorizer(
329
+ int(*xAuth)(void*,int,const char*,const char*,const char*,const char*),
330
+ void *pArg,
331
+ const char *zName /* for tracing */
332
+){
333
+ if( db.xAuth ){
334
+ fossil_panic("multiple active db_set_authorizer() calls");
335
+ }
336
+ if( g.db ) sqlite3_set_authorizer(g.db, xAuth, pArg);
337
+ db.xAuth = xAuth;
338
+ db.pAuthArg = pArg;
339
+ db.zAuthName = zName;
340
+ if( g.fSqlTrace ) fossil_trace("-- set authorizer %s\n", zName);
341
+}
342
+void db_clear_authorizer(void){
343
+ if( db.zAuthName && g.fSqlTrace ){
344
+ fossil_trace("-- discontinue authorizer %s\n", db.zAuthName);
345
+ }
346
+ if( g.db ) sqlite3_set_authorizer(g.db, 0, 0);
347
+ db.xAuth = 0;
348
+ db.pAuthArg = 0;
349
+}
321350
322351
#if INTERFACE
323352
/*
324353
** Possible flags to db_vprepare
325354
*/
@@ -844,34 +873,37 @@
844873
void db_init_database(
845874
const char *zFileName, /* Name of database file to create */
846875
const char *zSchema, /* First part of schema */
847876
... /* Additional SQL to run. Terminate with NULL. */
848877
){
849
- sqlite3 *db;
878
+ sqlite3 *xdb;
850879
int rc;
851880
const char *zSql;
852881
va_list ap;
853882
854
- db = db_open(zFileName ? zFileName : ":memory:");
855
- sqlite3_exec(db, "BEGIN EXCLUSIVE", 0, 0, 0);
856
- rc = sqlite3_exec(db, zSchema, 0, 0, 0);
883
+ xdb = db_open(zFileName ? zFileName : ":memory:");
884
+ sqlite3_exec(xdb, "BEGIN EXCLUSIVE", 0, 0, 0);
885
+ if( db.xAuth ){
886
+ sqlite3_set_authorizer(xdb, db.xAuth, db.pAuthArg);
887
+ }
888
+ rc = sqlite3_exec(xdb, zSchema, 0, 0, 0);
857889
if( rc!=SQLITE_OK ){
858
- db_err("%s", sqlite3_errmsg(db));
890
+ db_err("%s", sqlite3_errmsg(xdb));
859891
}
860892
va_start(ap, zSchema);
861893
while( (zSql = va_arg(ap, const char*))!=0 ){
862
- rc = sqlite3_exec(db, zSql, 0, 0, 0);
894
+ rc = sqlite3_exec(xdb, zSql, 0, 0, 0);
863895
if( rc!=SQLITE_OK ){
864
- db_err("%s", sqlite3_errmsg(db));
896
+ db_err("%s", sqlite3_errmsg(xdb));
865897
}
866898
}
867899
va_end(ap);
868
- sqlite3_exec(db, "COMMIT", 0, 0, 0);
900
+ sqlite3_exec(xdb, "COMMIT", 0, 0, 0);
869901
if( zFileName || g.db!=0 ){
870
- sqlite3_close(db);
902
+ sqlite3_close(xdb);
871903
}else{
872
- g.db = db;
904
+ g.db = xdb;
873905
}
874906
}
875907
876908
/*
877909
** Function to return the number of seconds since 1970. This is
@@ -2086,10 +2118,11 @@
20862118
** argument is true. Ignore unfinalized statements when false.
20872119
*/
20882120
void db_close(int reportErrors){
20892121
sqlite3_stmt *pStmt;
20902122
if( g.db==0 ) return;
2123
+ sqlite3_set_authorizer(g.db, 0, 0);
20912124
if( g.fSqlStats ){
20922125
int cur, hiwtr;
20932126
sqlite3_db_status(g.db, SQLITE_DBSTATUS_LOOKASIDE_USED, &cur, &hiwtr, 0);
20942127
fprintf(stderr, "-- LOOKASIDE_USED %10d %10d\n", cur, hiwtr);
20952128
sqlite3_db_status(g.db, SQLITE_DBSTATUS_LOOKASIDE_HIT, &cur, &hiwtr, 0);
@@ -2115,17 +2148,20 @@
21152148
fprintf(stderr, "-- prepared statements %10d\n", db.nPrepare);
21162149
}
21172150
while( db.pAllStmt ){
21182151
db_finalize(db.pAllStmt);
21192152
}
2120
- if( db.nBegin && reportErrors ){
2121
- fossil_warning("Transaction started at %s:%d never commits",
2122
- db.zStartFile, db.iStartLine);
2153
+ if( db.nBegin ){
2154
+ if( reportErrors ){
2155
+ fossil_warning("Transaction started at %s:%d never commits",
2156
+ db.zStartFile, db.iStartLine);
2157
+ }
21232158
db_end_transaction(1);
21242159
}
21252160
pStmt = 0;
2126
- g.dbIgnoreErrors++; /* Stop "database locked" warnings from PRAGMA optimize */
2161
+ sqlite3_busy_timeout(g.db, 0);
2162
+ g.dbIgnoreErrors++; /* Stop "database locked" warnings */
21272163
sqlite3_exec(g.db, "PRAGMA optimize", 0, 0, 0);
21282164
g.dbIgnoreErrors--;
21292165
db_close_config();
21302166
21312167
/* If the localdb has a lot of unused free space,
@@ -2165,10 +2201,11 @@
21652201
if( g.db ){
21662202
int rc;
21672203
sqlite3_wal_checkpoint(g.db, 0);
21682204
rc = sqlite3_close(g.db);
21692205
if( g.fSqlTrace ) fossil_trace("-- sqlite3_close(%d)\n", rc);
2206
+ db_clear_authorizer();
21702207
}
21712208
g.db = 0;
21722209
g.repositoryOpen = 0;
21732210
g.localOpen = 0;
21742211
}
21752212
--- src/db.c
+++ src/db.c
@@ -130,10 +130,13 @@
130 char *azBeforeCommit[5]; /* Commands to run prior to COMMIT */
131 int nBeforeCommit; /* Number of entries in azBeforeCommit */
132 int nPriorChanges; /* sqlite3_total_changes() at transaction start */
133 const char *zStartFile; /* File in which transaction was started */
134 int iStartLine; /* Line of zStartFile where transaction started */
 
 
 
135 } db = {0, 0, 0, 0, 0, 0, };
136
137 /*
138 ** Arrange for the given file to be deleted on a failure.
139 */
@@ -316,10 +319,36 @@
316 }
317 db.aHook[db.nCommitHook].sequence = sequence;
318 db.aHook[db.nCommitHook].xHook = x;
319 db.nCommitHook++;
320 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
321
322 #if INTERFACE
323 /*
324 ** Possible flags to db_vprepare
325 */
@@ -844,34 +873,37 @@
844 void db_init_database(
845 const char *zFileName, /* Name of database file to create */
846 const char *zSchema, /* First part of schema */
847 ... /* Additional SQL to run. Terminate with NULL. */
848 ){
849 sqlite3 *db;
850 int rc;
851 const char *zSql;
852 va_list ap;
853
854 db = db_open(zFileName ? zFileName : ":memory:");
855 sqlite3_exec(db, "BEGIN EXCLUSIVE", 0, 0, 0);
856 rc = sqlite3_exec(db, zSchema, 0, 0, 0);
 
 
 
857 if( rc!=SQLITE_OK ){
858 db_err("%s", sqlite3_errmsg(db));
859 }
860 va_start(ap, zSchema);
861 while( (zSql = va_arg(ap, const char*))!=0 ){
862 rc = sqlite3_exec(db, zSql, 0, 0, 0);
863 if( rc!=SQLITE_OK ){
864 db_err("%s", sqlite3_errmsg(db));
865 }
866 }
867 va_end(ap);
868 sqlite3_exec(db, "COMMIT", 0, 0, 0);
869 if( zFileName || g.db!=0 ){
870 sqlite3_close(db);
871 }else{
872 g.db = db;
873 }
874 }
875
876 /*
877 ** Function to return the number of seconds since 1970. This is
@@ -2086,10 +2118,11 @@
2086 ** argument is true. Ignore unfinalized statements when false.
2087 */
2088 void db_close(int reportErrors){
2089 sqlite3_stmt *pStmt;
2090 if( g.db==0 ) return;
 
2091 if( g.fSqlStats ){
2092 int cur, hiwtr;
2093 sqlite3_db_status(g.db, SQLITE_DBSTATUS_LOOKASIDE_USED, &cur, &hiwtr, 0);
2094 fprintf(stderr, "-- LOOKASIDE_USED %10d %10d\n", cur, hiwtr);
2095 sqlite3_db_status(g.db, SQLITE_DBSTATUS_LOOKASIDE_HIT, &cur, &hiwtr, 0);
@@ -2115,17 +2148,20 @@
2115 fprintf(stderr, "-- prepared statements %10d\n", db.nPrepare);
2116 }
2117 while( db.pAllStmt ){
2118 db_finalize(db.pAllStmt);
2119 }
2120 if( db.nBegin && reportErrors ){
2121 fossil_warning("Transaction started at %s:%d never commits",
2122 db.zStartFile, db.iStartLine);
 
 
2123 db_end_transaction(1);
2124 }
2125 pStmt = 0;
2126 g.dbIgnoreErrors++; /* Stop "database locked" warnings from PRAGMA optimize */
 
2127 sqlite3_exec(g.db, "PRAGMA optimize", 0, 0, 0);
2128 g.dbIgnoreErrors--;
2129 db_close_config();
2130
2131 /* If the localdb has a lot of unused free space,
@@ -2165,10 +2201,11 @@
2165 if( g.db ){
2166 int rc;
2167 sqlite3_wal_checkpoint(g.db, 0);
2168 rc = sqlite3_close(g.db);
2169 if( g.fSqlTrace ) fossil_trace("-- sqlite3_close(%d)\n", rc);
 
2170 }
2171 g.db = 0;
2172 g.repositoryOpen = 0;
2173 g.localOpen = 0;
2174 }
2175
--- src/db.c
+++ src/db.c
@@ -130,10 +130,13 @@
130 char *azBeforeCommit[5]; /* Commands to run prior to COMMIT */
131 int nBeforeCommit; /* Number of entries in azBeforeCommit */
132 int nPriorChanges; /* sqlite3_total_changes() at transaction start */
133 const char *zStartFile; /* File in which transaction was started */
134 int iStartLine; /* Line of zStartFile where transaction started */
135 int (*xAuth)(void*,int,const char*,const char*,const char*,const char*);
136 void *pAuthArg; /* Argument to the authorizer */
137 const char *zAuthName; /* Name of the authorizer */
138 } db = {0, 0, 0, 0, 0, 0, };
139
140 /*
141 ** Arrange for the given file to be deleted on a failure.
142 */
@@ -316,10 +319,36 @@
319 }
320 db.aHook[db.nCommitHook].sequence = sequence;
321 db.aHook[db.nCommitHook].xHook = x;
322 db.nCommitHook++;
323 }
324
325 /*
326 ** Set or unset the query authorizer callback function
327 */
328 void db_set_authorizer(
329 int(*xAuth)(void*,int,const char*,const char*,const char*,const char*),
330 void *pArg,
331 const char *zName /* for tracing */
332 ){
333 if( db.xAuth ){
334 fossil_panic("multiple active db_set_authorizer() calls");
335 }
336 if( g.db ) sqlite3_set_authorizer(g.db, xAuth, pArg);
337 db.xAuth = xAuth;
338 db.pAuthArg = pArg;
339 db.zAuthName = zName;
340 if( g.fSqlTrace ) fossil_trace("-- set authorizer %s\n", zName);
341 }
342 void db_clear_authorizer(void){
343 if( db.zAuthName && g.fSqlTrace ){
344 fossil_trace("-- discontinue authorizer %s\n", db.zAuthName);
345 }
346 if( g.db ) sqlite3_set_authorizer(g.db, 0, 0);
347 db.xAuth = 0;
348 db.pAuthArg = 0;
349 }
350
351 #if INTERFACE
352 /*
353 ** Possible flags to db_vprepare
354 */
@@ -844,34 +873,37 @@
873 void db_init_database(
874 const char *zFileName, /* Name of database file to create */
875 const char *zSchema, /* First part of schema */
876 ... /* Additional SQL to run. Terminate with NULL. */
877 ){
878 sqlite3 *xdb;
879 int rc;
880 const char *zSql;
881 va_list ap;
882
883 xdb = db_open(zFileName ? zFileName : ":memory:");
884 sqlite3_exec(xdb, "BEGIN EXCLUSIVE", 0, 0, 0);
885 if( db.xAuth ){
886 sqlite3_set_authorizer(xdb, db.xAuth, db.pAuthArg);
887 }
888 rc = sqlite3_exec(xdb, zSchema, 0, 0, 0);
889 if( rc!=SQLITE_OK ){
890 db_err("%s", sqlite3_errmsg(xdb));
891 }
892 va_start(ap, zSchema);
893 while( (zSql = va_arg(ap, const char*))!=0 ){
894 rc = sqlite3_exec(xdb, zSql, 0, 0, 0);
895 if( rc!=SQLITE_OK ){
896 db_err("%s", sqlite3_errmsg(xdb));
897 }
898 }
899 va_end(ap);
900 sqlite3_exec(xdb, "COMMIT", 0, 0, 0);
901 if( zFileName || g.db!=0 ){
902 sqlite3_close(xdb);
903 }else{
904 g.db = xdb;
905 }
906 }
907
908 /*
909 ** Function to return the number of seconds since 1970. This is
@@ -2086,10 +2118,11 @@
2118 ** argument is true. Ignore unfinalized statements when false.
2119 */
2120 void db_close(int reportErrors){
2121 sqlite3_stmt *pStmt;
2122 if( g.db==0 ) return;
2123 sqlite3_set_authorizer(g.db, 0, 0);
2124 if( g.fSqlStats ){
2125 int cur, hiwtr;
2126 sqlite3_db_status(g.db, SQLITE_DBSTATUS_LOOKASIDE_USED, &cur, &hiwtr, 0);
2127 fprintf(stderr, "-- LOOKASIDE_USED %10d %10d\n", cur, hiwtr);
2128 sqlite3_db_status(g.db, SQLITE_DBSTATUS_LOOKASIDE_HIT, &cur, &hiwtr, 0);
@@ -2115,17 +2148,20 @@
2148 fprintf(stderr, "-- prepared statements %10d\n", db.nPrepare);
2149 }
2150 while( db.pAllStmt ){
2151 db_finalize(db.pAllStmt);
2152 }
2153 if( db.nBegin ){
2154 if( reportErrors ){
2155 fossil_warning("Transaction started at %s:%d never commits",
2156 db.zStartFile, db.iStartLine);
2157 }
2158 db_end_transaction(1);
2159 }
2160 pStmt = 0;
2161 sqlite3_busy_timeout(g.db, 0);
2162 g.dbIgnoreErrors++; /* Stop "database locked" warnings */
2163 sqlite3_exec(g.db, "PRAGMA optimize", 0, 0, 0);
2164 g.dbIgnoreErrors--;
2165 db_close_config();
2166
2167 /* If the localdb has a lot of unused free space,
@@ -2165,10 +2201,11 @@
2201 if( g.db ){
2202 int rc;
2203 sqlite3_wal_checkpoint(g.db, 0);
2204 rc = sqlite3_close(g.db);
2205 if( g.fSqlTrace ) fossil_trace("-- sqlite3_close(%d)\n", rc);
2206 db_clear_authorizer();
2207 }
2208 g.db = 0;
2209 g.repositoryOpen = 0;
2210 g.localOpen = 0;
2211 }
2212
+51 -14
--- src/db.c
+++ src/db.c
@@ -130,10 +130,13 @@
130130
char *azBeforeCommit[5]; /* Commands to run prior to COMMIT */
131131
int nBeforeCommit; /* Number of entries in azBeforeCommit */
132132
int nPriorChanges; /* sqlite3_total_changes() at transaction start */
133133
const char *zStartFile; /* File in which transaction was started */
134134
int iStartLine; /* Line of zStartFile where transaction started */
135
+ int (*xAuth)(void*,int,const char*,const char*,const char*,const char*);
136
+ void *pAuthArg; /* Argument to the authorizer */
137
+ const char *zAuthName; /* Name of the authorizer */
135138
} db = {0, 0, 0, 0, 0, 0, };
136139
137140
/*
138141
** Arrange for the given file to be deleted on a failure.
139142
*/
@@ -316,10 +319,36 @@
316319
}
317320
db.aHook[db.nCommitHook].sequence = sequence;
318321
db.aHook[db.nCommitHook].xHook = x;
319322
db.nCommitHook++;
320323
}
324
+
325
+/*
326
+** Set or unset the query authorizer callback function
327
+*/
328
+void db_set_authorizer(
329
+ int(*xAuth)(void*,int,const char*,const char*,const char*,const char*),
330
+ void *pArg,
331
+ const char *zName /* for tracing */
332
+){
333
+ if( db.xAuth ){
334
+ fossil_panic("multiple active db_set_authorizer() calls");
335
+ }
336
+ if( g.db ) sqlite3_set_authorizer(g.db, xAuth, pArg);
337
+ db.xAuth = xAuth;
338
+ db.pAuthArg = pArg;
339
+ db.zAuthName = zName;
340
+ if( g.fSqlTrace ) fossil_trace("-- set authorizer %s\n", zName);
341
+}
342
+void db_clear_authorizer(void){
343
+ if( db.zAuthName && g.fSqlTrace ){
344
+ fossil_trace("-- discontinue authorizer %s\n", db.zAuthName);
345
+ }
346
+ if( g.db ) sqlite3_set_authorizer(g.db, 0, 0);
347
+ db.xAuth = 0;
348
+ db.pAuthArg = 0;
349
+}
321350
322351
#if INTERFACE
323352
/*
324353
** Possible flags to db_vprepare
325354
*/
@@ -844,34 +873,37 @@
844873
void db_init_database(
845874
const char *zFileName, /* Name of database file to create */
846875
const char *zSchema, /* First part of schema */
847876
... /* Additional SQL to run. Terminate with NULL. */
848877
){
849
- sqlite3 *db;
878
+ sqlite3 *xdb;
850879
int rc;
851880
const char *zSql;
852881
va_list ap;
853882
854
- db = db_open(zFileName ? zFileName : ":memory:");
855
- sqlite3_exec(db, "BEGIN EXCLUSIVE", 0, 0, 0);
856
- rc = sqlite3_exec(db, zSchema, 0, 0, 0);
883
+ xdb = db_open(zFileName ? zFileName : ":memory:");
884
+ sqlite3_exec(xdb, "BEGIN EXCLUSIVE", 0, 0, 0);
885
+ if( db.xAuth ){
886
+ sqlite3_set_authorizer(xdb, db.xAuth, db.pAuthArg);
887
+ }
888
+ rc = sqlite3_exec(xdb, zSchema, 0, 0, 0);
857889
if( rc!=SQLITE_OK ){
858
- db_err("%s", sqlite3_errmsg(db));
890
+ db_err("%s", sqlite3_errmsg(xdb));
859891
}
860892
va_start(ap, zSchema);
861893
while( (zSql = va_arg(ap, const char*))!=0 ){
862
- rc = sqlite3_exec(db, zSql, 0, 0, 0);
894
+ rc = sqlite3_exec(xdb, zSql, 0, 0, 0);
863895
if( rc!=SQLITE_OK ){
864
- db_err("%s", sqlite3_errmsg(db));
896
+ db_err("%s", sqlite3_errmsg(xdb));
865897
}
866898
}
867899
va_end(ap);
868
- sqlite3_exec(db, "COMMIT", 0, 0, 0);
900
+ sqlite3_exec(xdb, "COMMIT", 0, 0, 0);
869901
if( zFileName || g.db!=0 ){
870
- sqlite3_close(db);
902
+ sqlite3_close(xdb);
871903
}else{
872
- g.db = db;
904
+ g.db = xdb;
873905
}
874906
}
875907
876908
/*
877909
** Function to return the number of seconds since 1970. This is
@@ -2086,10 +2118,11 @@
20862118
** argument is true. Ignore unfinalized statements when false.
20872119
*/
20882120
void db_close(int reportErrors){
20892121
sqlite3_stmt *pStmt;
20902122
if( g.db==0 ) return;
2123
+ sqlite3_set_authorizer(g.db, 0, 0);
20912124
if( g.fSqlStats ){
20922125
int cur, hiwtr;
20932126
sqlite3_db_status(g.db, SQLITE_DBSTATUS_LOOKASIDE_USED, &cur, &hiwtr, 0);
20942127
fprintf(stderr, "-- LOOKASIDE_USED %10d %10d\n", cur, hiwtr);
20952128
sqlite3_db_status(g.db, SQLITE_DBSTATUS_LOOKASIDE_HIT, &cur, &hiwtr, 0);
@@ -2115,17 +2148,20 @@
21152148
fprintf(stderr, "-- prepared statements %10d\n", db.nPrepare);
21162149
}
21172150
while( db.pAllStmt ){
21182151
db_finalize(db.pAllStmt);
21192152
}
2120
- if( db.nBegin && reportErrors ){
2121
- fossil_warning("Transaction started at %s:%d never commits",
2122
- db.zStartFile, db.iStartLine);
2153
+ if( db.nBegin ){
2154
+ if( reportErrors ){
2155
+ fossil_warning("Transaction started at %s:%d never commits",
2156
+ db.zStartFile, db.iStartLine);
2157
+ }
21232158
db_end_transaction(1);
21242159
}
21252160
pStmt = 0;
2126
- g.dbIgnoreErrors++; /* Stop "database locked" warnings from PRAGMA optimize */
2161
+ sqlite3_busy_timeout(g.db, 0);
2162
+ g.dbIgnoreErrors++; /* Stop "database locked" warnings */
21272163
sqlite3_exec(g.db, "PRAGMA optimize", 0, 0, 0);
21282164
g.dbIgnoreErrors--;
21292165
db_close_config();
21302166
21312167
/* If the localdb has a lot of unused free space,
@@ -2165,10 +2201,11 @@
21652201
if( g.db ){
21662202
int rc;
21672203
sqlite3_wal_checkpoint(g.db, 0);
21682204
rc = sqlite3_close(g.db);
21692205
if( g.fSqlTrace ) fossil_trace("-- sqlite3_close(%d)\n", rc);
2206
+ db_clear_authorizer();
21702207
}
21712208
g.db = 0;
21722209
g.repositoryOpen = 0;
21732210
g.localOpen = 0;
21742211
}
21752212
--- src/db.c
+++ src/db.c
@@ -130,10 +130,13 @@
130 char *azBeforeCommit[5]; /* Commands to run prior to COMMIT */
131 int nBeforeCommit; /* Number of entries in azBeforeCommit */
132 int nPriorChanges; /* sqlite3_total_changes() at transaction start */
133 const char *zStartFile; /* File in which transaction was started */
134 int iStartLine; /* Line of zStartFile where transaction started */
 
 
 
135 } db = {0, 0, 0, 0, 0, 0, };
136
137 /*
138 ** Arrange for the given file to be deleted on a failure.
139 */
@@ -316,10 +319,36 @@
316 }
317 db.aHook[db.nCommitHook].sequence = sequence;
318 db.aHook[db.nCommitHook].xHook = x;
319 db.nCommitHook++;
320 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
321
322 #if INTERFACE
323 /*
324 ** Possible flags to db_vprepare
325 */
@@ -844,34 +873,37 @@
844 void db_init_database(
845 const char *zFileName, /* Name of database file to create */
846 const char *zSchema, /* First part of schema */
847 ... /* Additional SQL to run. Terminate with NULL. */
848 ){
849 sqlite3 *db;
850 int rc;
851 const char *zSql;
852 va_list ap;
853
854 db = db_open(zFileName ? zFileName : ":memory:");
855 sqlite3_exec(db, "BEGIN EXCLUSIVE", 0, 0, 0);
856 rc = sqlite3_exec(db, zSchema, 0, 0, 0);
 
 
 
857 if( rc!=SQLITE_OK ){
858 db_err("%s", sqlite3_errmsg(db));
859 }
860 va_start(ap, zSchema);
861 while( (zSql = va_arg(ap, const char*))!=0 ){
862 rc = sqlite3_exec(db, zSql, 0, 0, 0);
863 if( rc!=SQLITE_OK ){
864 db_err("%s", sqlite3_errmsg(db));
865 }
866 }
867 va_end(ap);
868 sqlite3_exec(db, "COMMIT", 0, 0, 0);
869 if( zFileName || g.db!=0 ){
870 sqlite3_close(db);
871 }else{
872 g.db = db;
873 }
874 }
875
876 /*
877 ** Function to return the number of seconds since 1970. This is
@@ -2086,10 +2118,11 @@
2086 ** argument is true. Ignore unfinalized statements when false.
2087 */
2088 void db_close(int reportErrors){
2089 sqlite3_stmt *pStmt;
2090 if( g.db==0 ) return;
 
2091 if( g.fSqlStats ){
2092 int cur, hiwtr;
2093 sqlite3_db_status(g.db, SQLITE_DBSTATUS_LOOKASIDE_USED, &cur, &hiwtr, 0);
2094 fprintf(stderr, "-- LOOKASIDE_USED %10d %10d\n", cur, hiwtr);
2095 sqlite3_db_status(g.db, SQLITE_DBSTATUS_LOOKASIDE_HIT, &cur, &hiwtr, 0);
@@ -2115,17 +2148,20 @@
2115 fprintf(stderr, "-- prepared statements %10d\n", db.nPrepare);
2116 }
2117 while( db.pAllStmt ){
2118 db_finalize(db.pAllStmt);
2119 }
2120 if( db.nBegin && reportErrors ){
2121 fossil_warning("Transaction started at %s:%d never commits",
2122 db.zStartFile, db.iStartLine);
 
 
2123 db_end_transaction(1);
2124 }
2125 pStmt = 0;
2126 g.dbIgnoreErrors++; /* Stop "database locked" warnings from PRAGMA optimize */
 
2127 sqlite3_exec(g.db, "PRAGMA optimize", 0, 0, 0);
2128 g.dbIgnoreErrors--;
2129 db_close_config();
2130
2131 /* If the localdb has a lot of unused free space,
@@ -2165,10 +2201,11 @@
2165 if( g.db ){
2166 int rc;
2167 sqlite3_wal_checkpoint(g.db, 0);
2168 rc = sqlite3_close(g.db);
2169 if( g.fSqlTrace ) fossil_trace("-- sqlite3_close(%d)\n", rc);
 
2170 }
2171 g.db = 0;
2172 g.repositoryOpen = 0;
2173 g.localOpen = 0;
2174 }
2175
--- src/db.c
+++ src/db.c
@@ -130,10 +130,13 @@
130 char *azBeforeCommit[5]; /* Commands to run prior to COMMIT */
131 int nBeforeCommit; /* Number of entries in azBeforeCommit */
132 int nPriorChanges; /* sqlite3_total_changes() at transaction start */
133 const char *zStartFile; /* File in which transaction was started */
134 int iStartLine; /* Line of zStartFile where transaction started */
135 int (*xAuth)(void*,int,const char*,const char*,const char*,const char*);
136 void *pAuthArg; /* Argument to the authorizer */
137 const char *zAuthName; /* Name of the authorizer */
138 } db = {0, 0, 0, 0, 0, 0, };
139
140 /*
141 ** Arrange for the given file to be deleted on a failure.
142 */
@@ -316,10 +319,36 @@
319 }
320 db.aHook[db.nCommitHook].sequence = sequence;
321 db.aHook[db.nCommitHook].xHook = x;
322 db.nCommitHook++;
323 }
324
325 /*
326 ** Set or unset the query authorizer callback function
327 */
328 void db_set_authorizer(
329 int(*xAuth)(void*,int,const char*,const char*,const char*,const char*),
330 void *pArg,
331 const char *zName /* for tracing */
332 ){
333 if( db.xAuth ){
334 fossil_panic("multiple active db_set_authorizer() calls");
335 }
336 if( g.db ) sqlite3_set_authorizer(g.db, xAuth, pArg);
337 db.xAuth = xAuth;
338 db.pAuthArg = pArg;
339 db.zAuthName = zName;
340 if( g.fSqlTrace ) fossil_trace("-- set authorizer %s\n", zName);
341 }
342 void db_clear_authorizer(void){
343 if( db.zAuthName && g.fSqlTrace ){
344 fossil_trace("-- discontinue authorizer %s\n", db.zAuthName);
345 }
346 if( g.db ) sqlite3_set_authorizer(g.db, 0, 0);
347 db.xAuth = 0;
348 db.pAuthArg = 0;
349 }
350
351 #if INTERFACE
352 /*
353 ** Possible flags to db_vprepare
354 */
@@ -844,34 +873,37 @@
873 void db_init_database(
874 const char *zFileName, /* Name of database file to create */
875 const char *zSchema, /* First part of schema */
876 ... /* Additional SQL to run. Terminate with NULL. */
877 ){
878 sqlite3 *xdb;
879 int rc;
880 const char *zSql;
881 va_list ap;
882
883 xdb = db_open(zFileName ? zFileName : ":memory:");
884 sqlite3_exec(xdb, "BEGIN EXCLUSIVE", 0, 0, 0);
885 if( db.xAuth ){
886 sqlite3_set_authorizer(xdb, db.xAuth, db.pAuthArg);
887 }
888 rc = sqlite3_exec(xdb, zSchema, 0, 0, 0);
889 if( rc!=SQLITE_OK ){
890 db_err("%s", sqlite3_errmsg(xdb));
891 }
892 va_start(ap, zSchema);
893 while( (zSql = va_arg(ap, const char*))!=0 ){
894 rc = sqlite3_exec(xdb, zSql, 0, 0, 0);
895 if( rc!=SQLITE_OK ){
896 db_err("%s", sqlite3_errmsg(xdb));
897 }
898 }
899 va_end(ap);
900 sqlite3_exec(xdb, "COMMIT", 0, 0, 0);
901 if( zFileName || g.db!=0 ){
902 sqlite3_close(xdb);
903 }else{
904 g.db = xdb;
905 }
906 }
907
908 /*
909 ** Function to return the number of seconds since 1970. This is
@@ -2086,10 +2118,11 @@
2118 ** argument is true. Ignore unfinalized statements when false.
2119 */
2120 void db_close(int reportErrors){
2121 sqlite3_stmt *pStmt;
2122 if( g.db==0 ) return;
2123 sqlite3_set_authorizer(g.db, 0, 0);
2124 if( g.fSqlStats ){
2125 int cur, hiwtr;
2126 sqlite3_db_status(g.db, SQLITE_DBSTATUS_LOOKASIDE_USED, &cur, &hiwtr, 0);
2127 fprintf(stderr, "-- LOOKASIDE_USED %10d %10d\n", cur, hiwtr);
2128 sqlite3_db_status(g.db, SQLITE_DBSTATUS_LOOKASIDE_HIT, &cur, &hiwtr, 0);
@@ -2115,17 +2148,20 @@
2148 fprintf(stderr, "-- prepared statements %10d\n", db.nPrepare);
2149 }
2150 while( db.pAllStmt ){
2151 db_finalize(db.pAllStmt);
2152 }
2153 if( db.nBegin ){
2154 if( reportErrors ){
2155 fossil_warning("Transaction started at %s:%d never commits",
2156 db.zStartFile, db.iStartLine);
2157 }
2158 db_end_transaction(1);
2159 }
2160 pStmt = 0;
2161 sqlite3_busy_timeout(g.db, 0);
2162 g.dbIgnoreErrors++; /* Stop "database locked" warnings */
2163 sqlite3_exec(g.db, "PRAGMA optimize", 0, 0, 0);
2164 g.dbIgnoreErrors--;
2165 db_close_config();
2166
2167 /* If the localdb has a lot of unused free space,
@@ -2165,10 +2201,11 @@
2201 if( g.db ){
2202 int rc;
2203 sqlite3_wal_checkpoint(g.db, 0);
2204 rc = sqlite3_close(g.db);
2205 if( g.fSqlTrace ) fossil_trace("-- sqlite3_close(%d)\n", rc);
2206 db_clear_authorizer();
2207 }
2208 g.db = 0;
2209 g.repositoryOpen = 0;
2210 g.localOpen = 0;
2211 }
2212
+51 -14
--- src/db.c
+++ src/db.c
@@ -130,10 +130,13 @@
130130
char *azBeforeCommit[5]; /* Commands to run prior to COMMIT */
131131
int nBeforeCommit; /* Number of entries in azBeforeCommit */
132132
int nPriorChanges; /* sqlite3_total_changes() at transaction start */
133133
const char *zStartFile; /* File in which transaction was started */
134134
int iStartLine; /* Line of zStartFile where transaction started */
135
+ int (*xAuth)(void*,int,const char*,const char*,const char*,const char*);
136
+ void *pAuthArg; /* Argument to the authorizer */
137
+ const char *zAuthName; /* Name of the authorizer */
135138
} db = {0, 0, 0, 0, 0, 0, };
136139
137140
/*
138141
** Arrange for the given file to be deleted on a failure.
139142
*/
@@ -316,10 +319,36 @@
316319
}
317320
db.aHook[db.nCommitHook].sequence = sequence;
318321
db.aHook[db.nCommitHook].xHook = x;
319322
db.nCommitHook++;
320323
}
324
+
325
+/*
326
+** Set or unset the query authorizer callback function
327
+*/
328
+void db_set_authorizer(
329
+ int(*xAuth)(void*,int,const char*,const char*,const char*,const char*),
330
+ void *pArg,
331
+ const char *zName /* for tracing */
332
+){
333
+ if( db.xAuth ){
334
+ fossil_panic("multiple active db_set_authorizer() calls");
335
+ }
336
+ if( g.db ) sqlite3_set_authorizer(g.db, xAuth, pArg);
337
+ db.xAuth = xAuth;
338
+ db.pAuthArg = pArg;
339
+ db.zAuthName = zName;
340
+ if( g.fSqlTrace ) fossil_trace("-- set authorizer %s\n", zName);
341
+}
342
+void db_clear_authorizer(void){
343
+ if( db.zAuthName && g.fSqlTrace ){
344
+ fossil_trace("-- discontinue authorizer %s\n", db.zAuthName);
345
+ }
346
+ if( g.db ) sqlite3_set_authorizer(g.db, 0, 0);
347
+ db.xAuth = 0;
348
+ db.pAuthArg = 0;
349
+}
321350
322351
#if INTERFACE
323352
/*
324353
** Possible flags to db_vprepare
325354
*/
@@ -844,34 +873,37 @@
844873
void db_init_database(
845874
const char *zFileName, /* Name of database file to create */
846875
const char *zSchema, /* First part of schema */
847876
... /* Additional SQL to run. Terminate with NULL. */
848877
){
849
- sqlite3 *db;
878
+ sqlite3 *xdb;
850879
int rc;
851880
const char *zSql;
852881
va_list ap;
853882
854
- db = db_open(zFileName ? zFileName : ":memory:");
855
- sqlite3_exec(db, "BEGIN EXCLUSIVE", 0, 0, 0);
856
- rc = sqlite3_exec(db, zSchema, 0, 0, 0);
883
+ xdb = db_open(zFileName ? zFileName : ":memory:");
884
+ sqlite3_exec(xdb, "BEGIN EXCLUSIVE", 0, 0, 0);
885
+ if( db.xAuth ){
886
+ sqlite3_set_authorizer(xdb, db.xAuth, db.pAuthArg);
887
+ }
888
+ rc = sqlite3_exec(xdb, zSchema, 0, 0, 0);
857889
if( rc!=SQLITE_OK ){
858
- db_err("%s", sqlite3_errmsg(db));
890
+ db_err("%s", sqlite3_errmsg(xdb));
859891
}
860892
va_start(ap, zSchema);
861893
while( (zSql = va_arg(ap, const char*))!=0 ){
862
- rc = sqlite3_exec(db, zSql, 0, 0, 0);
894
+ rc = sqlite3_exec(xdb, zSql, 0, 0, 0);
863895
if( rc!=SQLITE_OK ){
864
- db_err("%s", sqlite3_errmsg(db));
896
+ db_err("%s", sqlite3_errmsg(xdb));
865897
}
866898
}
867899
va_end(ap);
868
- sqlite3_exec(db, "COMMIT", 0, 0, 0);
900
+ sqlite3_exec(xdb, "COMMIT", 0, 0, 0);
869901
if( zFileName || g.db!=0 ){
870
- sqlite3_close(db);
902
+ sqlite3_close(xdb);
871903
}else{
872
- g.db = db;
904
+ g.db = xdb;
873905
}
874906
}
875907
876908
/*
877909
** Function to return the number of seconds since 1970. This is
@@ -2086,10 +2118,11 @@
20862118
** argument is true. Ignore unfinalized statements when false.
20872119
*/
20882120
void db_close(int reportErrors){
20892121
sqlite3_stmt *pStmt;
20902122
if( g.db==0 ) return;
2123
+ sqlite3_set_authorizer(g.db, 0, 0);
20912124
if( g.fSqlStats ){
20922125
int cur, hiwtr;
20932126
sqlite3_db_status(g.db, SQLITE_DBSTATUS_LOOKASIDE_USED, &cur, &hiwtr, 0);
20942127
fprintf(stderr, "-- LOOKASIDE_USED %10d %10d\n", cur, hiwtr);
20952128
sqlite3_db_status(g.db, SQLITE_DBSTATUS_LOOKASIDE_HIT, &cur, &hiwtr, 0);
@@ -2115,17 +2148,20 @@
21152148
fprintf(stderr, "-- prepared statements %10d\n", db.nPrepare);
21162149
}
21172150
while( db.pAllStmt ){
21182151
db_finalize(db.pAllStmt);
21192152
}
2120
- if( db.nBegin && reportErrors ){
2121
- fossil_warning("Transaction started at %s:%d never commits",
2122
- db.zStartFile, db.iStartLine);
2153
+ if( db.nBegin ){
2154
+ if( reportErrors ){
2155
+ fossil_warning("Transaction started at %s:%d never commits",
2156
+ db.zStartFile, db.iStartLine);
2157
+ }
21232158
db_end_transaction(1);
21242159
}
21252160
pStmt = 0;
2126
- g.dbIgnoreErrors++; /* Stop "database locked" warnings from PRAGMA optimize */
2161
+ sqlite3_busy_timeout(g.db, 0);
2162
+ g.dbIgnoreErrors++; /* Stop "database locked" warnings */
21272163
sqlite3_exec(g.db, "PRAGMA optimize", 0, 0, 0);
21282164
g.dbIgnoreErrors--;
21292165
db_close_config();
21302166
21312167
/* If the localdb has a lot of unused free space,
@@ -2165,10 +2201,11 @@
21652201
if( g.db ){
21662202
int rc;
21672203
sqlite3_wal_checkpoint(g.db, 0);
21682204
rc = sqlite3_close(g.db);
21692205
if( g.fSqlTrace ) fossil_trace("-- sqlite3_close(%d)\n", rc);
2206
+ db_clear_authorizer();
21702207
}
21712208
g.db = 0;
21722209
g.repositoryOpen = 0;
21732210
g.localOpen = 0;
21742211
}
21752212
--- src/db.c
+++ src/db.c
@@ -130,10 +130,13 @@
130 char *azBeforeCommit[5]; /* Commands to run prior to COMMIT */
131 int nBeforeCommit; /* Number of entries in azBeforeCommit */
132 int nPriorChanges; /* sqlite3_total_changes() at transaction start */
133 const char *zStartFile; /* File in which transaction was started */
134 int iStartLine; /* Line of zStartFile where transaction started */
 
 
 
135 } db = {0, 0, 0, 0, 0, 0, };
136
137 /*
138 ** Arrange for the given file to be deleted on a failure.
139 */
@@ -316,10 +319,36 @@
316 }
317 db.aHook[db.nCommitHook].sequence = sequence;
318 db.aHook[db.nCommitHook].xHook = x;
319 db.nCommitHook++;
320 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
321
322 #if INTERFACE
323 /*
324 ** Possible flags to db_vprepare
325 */
@@ -844,34 +873,37 @@
844 void db_init_database(
845 const char *zFileName, /* Name of database file to create */
846 const char *zSchema, /* First part of schema */
847 ... /* Additional SQL to run. Terminate with NULL. */
848 ){
849 sqlite3 *db;
850 int rc;
851 const char *zSql;
852 va_list ap;
853
854 db = db_open(zFileName ? zFileName : ":memory:");
855 sqlite3_exec(db, "BEGIN EXCLUSIVE", 0, 0, 0);
856 rc = sqlite3_exec(db, zSchema, 0, 0, 0);
 
 
 
857 if( rc!=SQLITE_OK ){
858 db_err("%s", sqlite3_errmsg(db));
859 }
860 va_start(ap, zSchema);
861 while( (zSql = va_arg(ap, const char*))!=0 ){
862 rc = sqlite3_exec(db, zSql, 0, 0, 0);
863 if( rc!=SQLITE_OK ){
864 db_err("%s", sqlite3_errmsg(db));
865 }
866 }
867 va_end(ap);
868 sqlite3_exec(db, "COMMIT", 0, 0, 0);
869 if( zFileName || g.db!=0 ){
870 sqlite3_close(db);
871 }else{
872 g.db = db;
873 }
874 }
875
876 /*
877 ** Function to return the number of seconds since 1970. This is
@@ -2086,10 +2118,11 @@
2086 ** argument is true. Ignore unfinalized statements when false.
2087 */
2088 void db_close(int reportErrors){
2089 sqlite3_stmt *pStmt;
2090 if( g.db==0 ) return;
 
2091 if( g.fSqlStats ){
2092 int cur, hiwtr;
2093 sqlite3_db_status(g.db, SQLITE_DBSTATUS_LOOKASIDE_USED, &cur, &hiwtr, 0);
2094 fprintf(stderr, "-- LOOKASIDE_USED %10d %10d\n", cur, hiwtr);
2095 sqlite3_db_status(g.db, SQLITE_DBSTATUS_LOOKASIDE_HIT, &cur, &hiwtr, 0);
@@ -2115,17 +2148,20 @@
2115 fprintf(stderr, "-- prepared statements %10d\n", db.nPrepare);
2116 }
2117 while( db.pAllStmt ){
2118 db_finalize(db.pAllStmt);
2119 }
2120 if( db.nBegin && reportErrors ){
2121 fossil_warning("Transaction started at %s:%d never commits",
2122 db.zStartFile, db.iStartLine);
 
 
2123 db_end_transaction(1);
2124 }
2125 pStmt = 0;
2126 g.dbIgnoreErrors++; /* Stop "database locked" warnings from PRAGMA optimize */
 
2127 sqlite3_exec(g.db, "PRAGMA optimize", 0, 0, 0);
2128 g.dbIgnoreErrors--;
2129 db_close_config();
2130
2131 /* If the localdb has a lot of unused free space,
@@ -2165,10 +2201,11 @@
2165 if( g.db ){
2166 int rc;
2167 sqlite3_wal_checkpoint(g.db, 0);
2168 rc = sqlite3_close(g.db);
2169 if( g.fSqlTrace ) fossil_trace("-- sqlite3_close(%d)\n", rc);
 
2170 }
2171 g.db = 0;
2172 g.repositoryOpen = 0;
2173 g.localOpen = 0;
2174 }
2175
--- src/db.c
+++ src/db.c
@@ -130,10 +130,13 @@
130 char *azBeforeCommit[5]; /* Commands to run prior to COMMIT */
131 int nBeforeCommit; /* Number of entries in azBeforeCommit */
132 int nPriorChanges; /* sqlite3_total_changes() at transaction start */
133 const char *zStartFile; /* File in which transaction was started */
134 int iStartLine; /* Line of zStartFile where transaction started */
135 int (*xAuth)(void*,int,const char*,const char*,const char*,const char*);
136 void *pAuthArg; /* Argument to the authorizer */
137 const char *zAuthName; /* Name of the authorizer */
138 } db = {0, 0, 0, 0, 0, 0, };
139
140 /*
141 ** Arrange for the given file to be deleted on a failure.
142 */
@@ -316,10 +319,36 @@
319 }
320 db.aHook[db.nCommitHook].sequence = sequence;
321 db.aHook[db.nCommitHook].xHook = x;
322 db.nCommitHook++;
323 }
324
325 /*
326 ** Set or unset the query authorizer callback function
327 */
328 void db_set_authorizer(
329 int(*xAuth)(void*,int,const char*,const char*,const char*,const char*),
330 void *pArg,
331 const char *zName /* for tracing */
332 ){
333 if( db.xAuth ){
334 fossil_panic("multiple active db_set_authorizer() calls");
335 }
336 if( g.db ) sqlite3_set_authorizer(g.db, xAuth, pArg);
337 db.xAuth = xAuth;
338 db.pAuthArg = pArg;
339 db.zAuthName = zName;
340 if( g.fSqlTrace ) fossil_trace("-- set authorizer %s\n", zName);
341 }
342 void db_clear_authorizer(void){
343 if( db.zAuthName && g.fSqlTrace ){
344 fossil_trace("-- discontinue authorizer %s\n", db.zAuthName);
345 }
346 if( g.db ) sqlite3_set_authorizer(g.db, 0, 0);
347 db.xAuth = 0;
348 db.pAuthArg = 0;
349 }
350
351 #if INTERFACE
352 /*
353 ** Possible flags to db_vprepare
354 */
@@ -844,34 +873,37 @@
873 void db_init_database(
874 const char *zFileName, /* Name of database file to create */
875 const char *zSchema, /* First part of schema */
876 ... /* Additional SQL to run. Terminate with NULL. */
877 ){
878 sqlite3 *xdb;
879 int rc;
880 const char *zSql;
881 va_list ap;
882
883 xdb = db_open(zFileName ? zFileName : ":memory:");
884 sqlite3_exec(xdb, "BEGIN EXCLUSIVE", 0, 0, 0);
885 if( db.xAuth ){
886 sqlite3_set_authorizer(xdb, db.xAuth, db.pAuthArg);
887 }
888 rc = sqlite3_exec(xdb, zSchema, 0, 0, 0);
889 if( rc!=SQLITE_OK ){
890 db_err("%s", sqlite3_errmsg(xdb));
891 }
892 va_start(ap, zSchema);
893 while( (zSql = va_arg(ap, const char*))!=0 ){
894 rc = sqlite3_exec(xdb, zSql, 0, 0, 0);
895 if( rc!=SQLITE_OK ){
896 db_err("%s", sqlite3_errmsg(xdb));
897 }
898 }
899 va_end(ap);
900 sqlite3_exec(xdb, "COMMIT", 0, 0, 0);
901 if( zFileName || g.db!=0 ){
902 sqlite3_close(xdb);
903 }else{
904 g.db = xdb;
905 }
906 }
907
908 /*
909 ** Function to return the number of seconds since 1970. This is
@@ -2086,10 +2118,11 @@
2118 ** argument is true. Ignore unfinalized statements when false.
2119 */
2120 void db_close(int reportErrors){
2121 sqlite3_stmt *pStmt;
2122 if( g.db==0 ) return;
2123 sqlite3_set_authorizer(g.db, 0, 0);
2124 if( g.fSqlStats ){
2125 int cur, hiwtr;
2126 sqlite3_db_status(g.db, SQLITE_DBSTATUS_LOOKASIDE_USED, &cur, &hiwtr, 0);
2127 fprintf(stderr, "-- LOOKASIDE_USED %10d %10d\n", cur, hiwtr);
2128 sqlite3_db_status(g.db, SQLITE_DBSTATUS_LOOKASIDE_HIT, &cur, &hiwtr, 0);
@@ -2115,17 +2148,20 @@
2148 fprintf(stderr, "-- prepared statements %10d\n", db.nPrepare);
2149 }
2150 while( db.pAllStmt ){
2151 db_finalize(db.pAllStmt);
2152 }
2153 if( db.nBegin ){
2154 if( reportErrors ){
2155 fossil_warning("Transaction started at %s:%d never commits",
2156 db.zStartFile, db.iStartLine);
2157 }
2158 db_end_transaction(1);
2159 }
2160 pStmt = 0;
2161 sqlite3_busy_timeout(g.db, 0);
2162 g.dbIgnoreErrors++; /* Stop "database locked" warnings */
2163 sqlite3_exec(g.db, "PRAGMA optimize", 0, 0, 0);
2164 g.dbIgnoreErrors--;
2165 db_close_config();
2166
2167 /* If the localdb has a lot of unused free space,
@@ -2165,10 +2201,11 @@
2201 if( g.db ){
2202 int rc;
2203 sqlite3_wal_checkpoint(g.db, 0);
2204 rc = sqlite3_close(g.db);
2205 if( g.fSqlTrace ) fossil_trace("-- sqlite3_close(%d)\n", rc);
2206 db_clear_authorizer();
2207 }
2208 g.db = 0;
2209 g.repositoryOpen = 0;
2210 g.localOpen = 0;
2211 }
2212
+51 -14
--- src/db.c
+++ src/db.c
@@ -130,10 +130,13 @@
130130
char *azBeforeCommit[5]; /* Commands to run prior to COMMIT */
131131
int nBeforeCommit; /* Number of entries in azBeforeCommit */
132132
int nPriorChanges; /* sqlite3_total_changes() at transaction start */
133133
const char *zStartFile; /* File in which transaction was started */
134134
int iStartLine; /* Line of zStartFile where transaction started */
135
+ int (*xAuth)(void*,int,const char*,const char*,const char*,const char*);
136
+ void *pAuthArg; /* Argument to the authorizer */
137
+ const char *zAuthName; /* Name of the authorizer */
135138
} db = {0, 0, 0, 0, 0, 0, };
136139
137140
/*
138141
** Arrange for the given file to be deleted on a failure.
139142
*/
@@ -316,10 +319,36 @@
316319
}
317320
db.aHook[db.nCommitHook].sequence = sequence;
318321
db.aHook[db.nCommitHook].xHook = x;
319322
db.nCommitHook++;
320323
}
324
+
325
+/*
326
+** Set or unset the query authorizer callback function
327
+*/
328
+void db_set_authorizer(
329
+ int(*xAuth)(void*,int,const char*,const char*,const char*,const char*),
330
+ void *pArg,
331
+ const char *zName /* for tracing */
332
+){
333
+ if( db.xAuth ){
334
+ fossil_panic("multiple active db_set_authorizer() calls");
335
+ }
336
+ if( g.db ) sqlite3_set_authorizer(g.db, xAuth, pArg);
337
+ db.xAuth = xAuth;
338
+ db.pAuthArg = pArg;
339
+ db.zAuthName = zName;
340
+ if( g.fSqlTrace ) fossil_trace("-- set authorizer %s\n", zName);
341
+}
342
+void db_clear_authorizer(void){
343
+ if( db.zAuthName && g.fSqlTrace ){
344
+ fossil_trace("-- discontinue authorizer %s\n", db.zAuthName);
345
+ }
346
+ if( g.db ) sqlite3_set_authorizer(g.db, 0, 0);
347
+ db.xAuth = 0;
348
+ db.pAuthArg = 0;
349
+}
321350
322351
#if INTERFACE
323352
/*
324353
** Possible flags to db_vprepare
325354
*/
@@ -844,34 +873,37 @@
844873
void db_init_database(
845874
const char *zFileName, /* Name of database file to create */
846875
const char *zSchema, /* First part of schema */
847876
... /* Additional SQL to run. Terminate with NULL. */
848877
){
849
- sqlite3 *db;
878
+ sqlite3 *xdb;
850879
int rc;
851880
const char *zSql;
852881
va_list ap;
853882
854
- db = db_open(zFileName ? zFileName : ":memory:");
855
- sqlite3_exec(db, "BEGIN EXCLUSIVE", 0, 0, 0);
856
- rc = sqlite3_exec(db, zSchema, 0, 0, 0);
883
+ xdb = db_open(zFileName ? zFileName : ":memory:");
884
+ sqlite3_exec(xdb, "BEGIN EXCLUSIVE", 0, 0, 0);
885
+ if( db.xAuth ){
886
+ sqlite3_set_authorizer(xdb, db.xAuth, db.pAuthArg);
887
+ }
888
+ rc = sqlite3_exec(xdb, zSchema, 0, 0, 0);
857889
if( rc!=SQLITE_OK ){
858
- db_err("%s", sqlite3_errmsg(db));
890
+ db_err("%s", sqlite3_errmsg(xdb));
859891
}
860892
va_start(ap, zSchema);
861893
while( (zSql = va_arg(ap, const char*))!=0 ){
862
- rc = sqlite3_exec(db, zSql, 0, 0, 0);
894
+ rc = sqlite3_exec(xdb, zSql, 0, 0, 0);
863895
if( rc!=SQLITE_OK ){
864
- db_err("%s", sqlite3_errmsg(db));
896
+ db_err("%s", sqlite3_errmsg(xdb));
865897
}
866898
}
867899
va_end(ap);
868
- sqlite3_exec(db, "COMMIT", 0, 0, 0);
900
+ sqlite3_exec(xdb, "COMMIT", 0, 0, 0);
869901
if( zFileName || g.db!=0 ){
870
- sqlite3_close(db);
902
+ sqlite3_close(xdb);
871903
}else{
872
- g.db = db;
904
+ g.db = xdb;
873905
}
874906
}
875907
876908
/*
877909
** Function to return the number of seconds since 1970. This is
@@ -2086,10 +2118,11 @@
20862118
** argument is true. Ignore unfinalized statements when false.
20872119
*/
20882120
void db_close(int reportErrors){
20892121
sqlite3_stmt *pStmt;
20902122
if( g.db==0 ) return;
2123
+ sqlite3_set_authorizer(g.db, 0, 0);
20912124
if( g.fSqlStats ){
20922125
int cur, hiwtr;
20932126
sqlite3_db_status(g.db, SQLITE_DBSTATUS_LOOKASIDE_USED, &cur, &hiwtr, 0);
20942127
fprintf(stderr, "-- LOOKASIDE_USED %10d %10d\n", cur, hiwtr);
20952128
sqlite3_db_status(g.db, SQLITE_DBSTATUS_LOOKASIDE_HIT, &cur, &hiwtr, 0);
@@ -2115,17 +2148,20 @@
21152148
fprintf(stderr, "-- prepared statements %10d\n", db.nPrepare);
21162149
}
21172150
while( db.pAllStmt ){
21182151
db_finalize(db.pAllStmt);
21192152
}
2120
- if( db.nBegin && reportErrors ){
2121
- fossil_warning("Transaction started at %s:%d never commits",
2122
- db.zStartFile, db.iStartLine);
2153
+ if( db.nBegin ){
2154
+ if( reportErrors ){
2155
+ fossil_warning("Transaction started at %s:%d never commits",
2156
+ db.zStartFile, db.iStartLine);
2157
+ }
21232158
db_end_transaction(1);
21242159
}
21252160
pStmt = 0;
2126
- g.dbIgnoreErrors++; /* Stop "database locked" warnings from PRAGMA optimize */
2161
+ sqlite3_busy_timeout(g.db, 0);
2162
+ g.dbIgnoreErrors++; /* Stop "database locked" warnings */
21272163
sqlite3_exec(g.db, "PRAGMA optimize", 0, 0, 0);
21282164
g.dbIgnoreErrors--;
21292165
db_close_config();
21302166
21312167
/* If the localdb has a lot of unused free space,
@@ -2165,10 +2201,11 @@
21652201
if( g.db ){
21662202
int rc;
21672203
sqlite3_wal_checkpoint(g.db, 0);
21682204
rc = sqlite3_close(g.db);
21692205
if( g.fSqlTrace ) fossil_trace("-- sqlite3_close(%d)\n", rc);
2206
+ db_clear_authorizer();
21702207
}
21712208
g.db = 0;
21722209
g.repositoryOpen = 0;
21732210
g.localOpen = 0;
21742211
}
21752212
--- src/db.c
+++ src/db.c
@@ -130,10 +130,13 @@
130 char *azBeforeCommit[5]; /* Commands to run prior to COMMIT */
131 int nBeforeCommit; /* Number of entries in azBeforeCommit */
132 int nPriorChanges; /* sqlite3_total_changes() at transaction start */
133 const char *zStartFile; /* File in which transaction was started */
134 int iStartLine; /* Line of zStartFile where transaction started */
 
 
 
135 } db = {0, 0, 0, 0, 0, 0, };
136
137 /*
138 ** Arrange for the given file to be deleted on a failure.
139 */
@@ -316,10 +319,36 @@
316 }
317 db.aHook[db.nCommitHook].sequence = sequence;
318 db.aHook[db.nCommitHook].xHook = x;
319 db.nCommitHook++;
320 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
321
322 #if INTERFACE
323 /*
324 ** Possible flags to db_vprepare
325 */
@@ -844,34 +873,37 @@
844 void db_init_database(
845 const char *zFileName, /* Name of database file to create */
846 const char *zSchema, /* First part of schema */
847 ... /* Additional SQL to run. Terminate with NULL. */
848 ){
849 sqlite3 *db;
850 int rc;
851 const char *zSql;
852 va_list ap;
853
854 db = db_open(zFileName ? zFileName : ":memory:");
855 sqlite3_exec(db, "BEGIN EXCLUSIVE", 0, 0, 0);
856 rc = sqlite3_exec(db, zSchema, 0, 0, 0);
 
 
 
857 if( rc!=SQLITE_OK ){
858 db_err("%s", sqlite3_errmsg(db));
859 }
860 va_start(ap, zSchema);
861 while( (zSql = va_arg(ap, const char*))!=0 ){
862 rc = sqlite3_exec(db, zSql, 0, 0, 0);
863 if( rc!=SQLITE_OK ){
864 db_err("%s", sqlite3_errmsg(db));
865 }
866 }
867 va_end(ap);
868 sqlite3_exec(db, "COMMIT", 0, 0, 0);
869 if( zFileName || g.db!=0 ){
870 sqlite3_close(db);
871 }else{
872 g.db = db;
873 }
874 }
875
876 /*
877 ** Function to return the number of seconds since 1970. This is
@@ -2086,10 +2118,11 @@
2086 ** argument is true. Ignore unfinalized statements when false.
2087 */
2088 void db_close(int reportErrors){
2089 sqlite3_stmt *pStmt;
2090 if( g.db==0 ) return;
 
2091 if( g.fSqlStats ){
2092 int cur, hiwtr;
2093 sqlite3_db_status(g.db, SQLITE_DBSTATUS_LOOKASIDE_USED, &cur, &hiwtr, 0);
2094 fprintf(stderr, "-- LOOKASIDE_USED %10d %10d\n", cur, hiwtr);
2095 sqlite3_db_status(g.db, SQLITE_DBSTATUS_LOOKASIDE_HIT, &cur, &hiwtr, 0);
@@ -2115,17 +2148,20 @@
2115 fprintf(stderr, "-- prepared statements %10d\n", db.nPrepare);
2116 }
2117 while( db.pAllStmt ){
2118 db_finalize(db.pAllStmt);
2119 }
2120 if( db.nBegin && reportErrors ){
2121 fossil_warning("Transaction started at %s:%d never commits",
2122 db.zStartFile, db.iStartLine);
 
 
2123 db_end_transaction(1);
2124 }
2125 pStmt = 0;
2126 g.dbIgnoreErrors++; /* Stop "database locked" warnings from PRAGMA optimize */
 
2127 sqlite3_exec(g.db, "PRAGMA optimize", 0, 0, 0);
2128 g.dbIgnoreErrors--;
2129 db_close_config();
2130
2131 /* If the localdb has a lot of unused free space,
@@ -2165,10 +2201,11 @@
2165 if( g.db ){
2166 int rc;
2167 sqlite3_wal_checkpoint(g.db, 0);
2168 rc = sqlite3_close(g.db);
2169 if( g.fSqlTrace ) fossil_trace("-- sqlite3_close(%d)\n", rc);
 
2170 }
2171 g.db = 0;
2172 g.repositoryOpen = 0;
2173 g.localOpen = 0;
2174 }
2175
--- src/db.c
+++ src/db.c
@@ -130,10 +130,13 @@
130 char *azBeforeCommit[5]; /* Commands to run prior to COMMIT */
131 int nBeforeCommit; /* Number of entries in azBeforeCommit */
132 int nPriorChanges; /* sqlite3_total_changes() at transaction start */
133 const char *zStartFile; /* File in which transaction was started */
134 int iStartLine; /* Line of zStartFile where transaction started */
135 int (*xAuth)(void*,int,const char*,const char*,const char*,const char*);
136 void *pAuthArg; /* Argument to the authorizer */
137 const char *zAuthName; /* Name of the authorizer */
138 } db = {0, 0, 0, 0, 0, 0, };
139
140 /*
141 ** Arrange for the given file to be deleted on a failure.
142 */
@@ -316,10 +319,36 @@
319 }
320 db.aHook[db.nCommitHook].sequence = sequence;
321 db.aHook[db.nCommitHook].xHook = x;
322 db.nCommitHook++;
323 }
324
325 /*
326 ** Set or unset the query authorizer callback function
327 */
328 void db_set_authorizer(
329 int(*xAuth)(void*,int,const char*,const char*,const char*,const char*),
330 void *pArg,
331 const char *zName /* for tracing */
332 ){
333 if( db.xAuth ){
334 fossil_panic("multiple active db_set_authorizer() calls");
335 }
336 if( g.db ) sqlite3_set_authorizer(g.db, xAuth, pArg);
337 db.xAuth = xAuth;
338 db.pAuthArg = pArg;
339 db.zAuthName = zName;
340 if( g.fSqlTrace ) fossil_trace("-- set authorizer %s\n", zName);
341 }
342 void db_clear_authorizer(void){
343 if( db.zAuthName && g.fSqlTrace ){
344 fossil_trace("-- discontinue authorizer %s\n", db.zAuthName);
345 }
346 if( g.db ) sqlite3_set_authorizer(g.db, 0, 0);
347 db.xAuth = 0;
348 db.pAuthArg = 0;
349 }
350
351 #if INTERFACE
352 /*
353 ** Possible flags to db_vprepare
354 */
@@ -844,34 +873,37 @@
873 void db_init_database(
874 const char *zFileName, /* Name of database file to create */
875 const char *zSchema, /* First part of schema */
876 ... /* Additional SQL to run. Terminate with NULL. */
877 ){
878 sqlite3 *xdb;
879 int rc;
880 const char *zSql;
881 va_list ap;
882
883 xdb = db_open(zFileName ? zFileName : ":memory:");
884 sqlite3_exec(xdb, "BEGIN EXCLUSIVE", 0, 0, 0);
885 if( db.xAuth ){
886 sqlite3_set_authorizer(xdb, db.xAuth, db.pAuthArg);
887 }
888 rc = sqlite3_exec(xdb, zSchema, 0, 0, 0);
889 if( rc!=SQLITE_OK ){
890 db_err("%s", sqlite3_errmsg(xdb));
891 }
892 va_start(ap, zSchema);
893 while( (zSql = va_arg(ap, const char*))!=0 ){
894 rc = sqlite3_exec(xdb, zSql, 0, 0, 0);
895 if( rc!=SQLITE_OK ){
896 db_err("%s", sqlite3_errmsg(xdb));
897 }
898 }
899 va_end(ap);
900 sqlite3_exec(xdb, "COMMIT", 0, 0, 0);
901 if( zFileName || g.db!=0 ){
902 sqlite3_close(xdb);
903 }else{
904 g.db = xdb;
905 }
906 }
907
908 /*
909 ** Function to return the number of seconds since 1970. This is
@@ -2086,10 +2118,11 @@
2118 ** argument is true. Ignore unfinalized statements when false.
2119 */
2120 void db_close(int reportErrors){
2121 sqlite3_stmt *pStmt;
2122 if( g.db==0 ) return;
2123 sqlite3_set_authorizer(g.db, 0, 0);
2124 if( g.fSqlStats ){
2125 int cur, hiwtr;
2126 sqlite3_db_status(g.db, SQLITE_DBSTATUS_LOOKASIDE_USED, &cur, &hiwtr, 0);
2127 fprintf(stderr, "-- LOOKASIDE_USED %10d %10d\n", cur, hiwtr);
2128 sqlite3_db_status(g.db, SQLITE_DBSTATUS_LOOKASIDE_HIT, &cur, &hiwtr, 0);
@@ -2115,17 +2148,20 @@
2148 fprintf(stderr, "-- prepared statements %10d\n", db.nPrepare);
2149 }
2150 while( db.pAllStmt ){
2151 db_finalize(db.pAllStmt);
2152 }
2153 if( db.nBegin ){
2154 if( reportErrors ){
2155 fossil_warning("Transaction started at %s:%d never commits",
2156 db.zStartFile, db.iStartLine);
2157 }
2158 db_end_transaction(1);
2159 }
2160 pStmt = 0;
2161 sqlite3_busy_timeout(g.db, 0);
2162 g.dbIgnoreErrors++; /* Stop "database locked" warnings */
2163 sqlite3_exec(g.db, "PRAGMA optimize", 0, 0, 0);
2164 g.dbIgnoreErrors--;
2165 db_close_config();
2166
2167 /* If the localdb has a lot of unused free space,
@@ -2165,10 +2201,11 @@
2201 if( g.db ){
2202 int rc;
2203 sqlite3_wal_checkpoint(g.db, 0);
2204 rc = sqlite3_close(g.db);
2205 if( g.fSqlTrace ) fossil_trace("-- sqlite3_close(%d)\n", rc);
2206 db_clear_authorizer();
2207 }
2208 g.db = 0;
2209 g.repositoryOpen = 0;
2210 g.localOpen = 0;
2211 }
2212
+51 -14
--- src/db.c
+++ src/db.c
@@ -130,10 +130,13 @@
130130
char *azBeforeCommit[5]; /* Commands to run prior to COMMIT */
131131
int nBeforeCommit; /* Number of entries in azBeforeCommit */
132132
int nPriorChanges; /* sqlite3_total_changes() at transaction start */
133133
const char *zStartFile; /* File in which transaction was started */
134134
int iStartLine; /* Line of zStartFile where transaction started */
135
+ int (*xAuth)(void*,int,const char*,const char*,const char*,const char*);
136
+ void *pAuthArg; /* Argument to the authorizer */
137
+ const char *zAuthName; /* Name of the authorizer */
135138
} db = {0, 0, 0, 0, 0, 0, };
136139
137140
/*
138141
** Arrange for the given file to be deleted on a failure.
139142
*/
@@ -316,10 +319,36 @@
316319
}
317320
db.aHook[db.nCommitHook].sequence = sequence;
318321
db.aHook[db.nCommitHook].xHook = x;
319322
db.nCommitHook++;
320323
}
324
+
325
+/*
326
+** Set or unset the query authorizer callback function
327
+*/
328
+void db_set_authorizer(
329
+ int(*xAuth)(void*,int,const char*,const char*,const char*,const char*),
330
+ void *pArg,
331
+ const char *zName /* for tracing */
332
+){
333
+ if( db.xAuth ){
334
+ fossil_panic("multiple active db_set_authorizer() calls");
335
+ }
336
+ if( g.db ) sqlite3_set_authorizer(g.db, xAuth, pArg);
337
+ db.xAuth = xAuth;
338
+ db.pAuthArg = pArg;
339
+ db.zAuthName = zName;
340
+ if( g.fSqlTrace ) fossil_trace("-- set authorizer %s\n", zName);
341
+}
342
+void db_clear_authorizer(void){
343
+ if( db.zAuthName && g.fSqlTrace ){
344
+ fossil_trace("-- discontinue authorizer %s\n", db.zAuthName);
345
+ }
346
+ if( g.db ) sqlite3_set_authorizer(g.db, 0, 0);
347
+ db.xAuth = 0;
348
+ db.pAuthArg = 0;
349
+}
321350
322351
#if INTERFACE
323352
/*
324353
** Possible flags to db_vprepare
325354
*/
@@ -844,34 +873,37 @@
844873
void db_init_database(
845874
const char *zFileName, /* Name of database file to create */
846875
const char *zSchema, /* First part of schema */
847876
... /* Additional SQL to run. Terminate with NULL. */
848877
){
849
- sqlite3 *db;
878
+ sqlite3 *xdb;
850879
int rc;
851880
const char *zSql;
852881
va_list ap;
853882
854
- db = db_open(zFileName ? zFileName : ":memory:");
855
- sqlite3_exec(db, "BEGIN EXCLUSIVE", 0, 0, 0);
856
- rc = sqlite3_exec(db, zSchema, 0, 0, 0);
883
+ xdb = db_open(zFileName ? zFileName : ":memory:");
884
+ sqlite3_exec(xdb, "BEGIN EXCLUSIVE", 0, 0, 0);
885
+ if( db.xAuth ){
886
+ sqlite3_set_authorizer(xdb, db.xAuth, db.pAuthArg);
887
+ }
888
+ rc = sqlite3_exec(xdb, zSchema, 0, 0, 0);
857889
if( rc!=SQLITE_OK ){
858
- db_err("%s", sqlite3_errmsg(db));
890
+ db_err("%s", sqlite3_errmsg(xdb));
859891
}
860892
va_start(ap, zSchema);
861893
while( (zSql = va_arg(ap, const char*))!=0 ){
862
- rc = sqlite3_exec(db, zSql, 0, 0, 0);
894
+ rc = sqlite3_exec(xdb, zSql, 0, 0, 0);
863895
if( rc!=SQLITE_OK ){
864
- db_err("%s", sqlite3_errmsg(db));
896
+ db_err("%s", sqlite3_errmsg(xdb));
865897
}
866898
}
867899
va_end(ap);
868
- sqlite3_exec(db, "COMMIT", 0, 0, 0);
900
+ sqlite3_exec(xdb, "COMMIT", 0, 0, 0);
869901
if( zFileName || g.db!=0 ){
870
- sqlite3_close(db);
902
+ sqlite3_close(xdb);
871903
}else{
872
- g.db = db;
904
+ g.db = xdb;
873905
}
874906
}
875907
876908
/*
877909
** Function to return the number of seconds since 1970. This is
@@ -2086,10 +2118,11 @@
20862118
** argument is true. Ignore unfinalized statements when false.
20872119
*/
20882120
void db_close(int reportErrors){
20892121
sqlite3_stmt *pStmt;
20902122
if( g.db==0 ) return;
2123
+ sqlite3_set_authorizer(g.db, 0, 0);
20912124
if( g.fSqlStats ){
20922125
int cur, hiwtr;
20932126
sqlite3_db_status(g.db, SQLITE_DBSTATUS_LOOKASIDE_USED, &cur, &hiwtr, 0);
20942127
fprintf(stderr, "-- LOOKASIDE_USED %10d %10d\n", cur, hiwtr);
20952128
sqlite3_db_status(g.db, SQLITE_DBSTATUS_LOOKASIDE_HIT, &cur, &hiwtr, 0);
@@ -2115,17 +2148,20 @@
21152148
fprintf(stderr, "-- prepared statements %10d\n", db.nPrepare);
21162149
}
21172150
while( db.pAllStmt ){
21182151
db_finalize(db.pAllStmt);
21192152
}
2120
- if( db.nBegin && reportErrors ){
2121
- fossil_warning("Transaction started at %s:%d never commits",
2122
- db.zStartFile, db.iStartLine);
2153
+ if( db.nBegin ){
2154
+ if( reportErrors ){
2155
+ fossil_warning("Transaction started at %s:%d never commits",
2156
+ db.zStartFile, db.iStartLine);
2157
+ }
21232158
db_end_transaction(1);
21242159
}
21252160
pStmt = 0;
2126
- g.dbIgnoreErrors++; /* Stop "database locked" warnings from PRAGMA optimize */
2161
+ sqlite3_busy_timeout(g.db, 0);
2162
+ g.dbIgnoreErrors++; /* Stop "database locked" warnings */
21272163
sqlite3_exec(g.db, "PRAGMA optimize", 0, 0, 0);
21282164
g.dbIgnoreErrors--;
21292165
db_close_config();
21302166
21312167
/* If the localdb has a lot of unused free space,
@@ -2165,10 +2201,11 @@
21652201
if( g.db ){
21662202
int rc;
21672203
sqlite3_wal_checkpoint(g.db, 0);
21682204
rc = sqlite3_close(g.db);
21692205
if( g.fSqlTrace ) fossil_trace("-- sqlite3_close(%d)\n", rc);
2206
+ db_clear_authorizer();
21702207
}
21712208
g.db = 0;
21722209
g.repositoryOpen = 0;
21732210
g.localOpen = 0;
21742211
}
21752212
--- src/db.c
+++ src/db.c
@@ -130,10 +130,13 @@
130 char *azBeforeCommit[5]; /* Commands to run prior to COMMIT */
131 int nBeforeCommit; /* Number of entries in azBeforeCommit */
132 int nPriorChanges; /* sqlite3_total_changes() at transaction start */
133 const char *zStartFile; /* File in which transaction was started */
134 int iStartLine; /* Line of zStartFile where transaction started */
 
 
 
135 } db = {0, 0, 0, 0, 0, 0, };
136
137 /*
138 ** Arrange for the given file to be deleted on a failure.
139 */
@@ -316,10 +319,36 @@
316 }
317 db.aHook[db.nCommitHook].sequence = sequence;
318 db.aHook[db.nCommitHook].xHook = x;
319 db.nCommitHook++;
320 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
321
322 #if INTERFACE
323 /*
324 ** Possible flags to db_vprepare
325 */
@@ -844,34 +873,37 @@
844 void db_init_database(
845 const char *zFileName, /* Name of database file to create */
846 const char *zSchema, /* First part of schema */
847 ... /* Additional SQL to run. Terminate with NULL. */
848 ){
849 sqlite3 *db;
850 int rc;
851 const char *zSql;
852 va_list ap;
853
854 db = db_open(zFileName ? zFileName : ":memory:");
855 sqlite3_exec(db, "BEGIN EXCLUSIVE", 0, 0, 0);
856 rc = sqlite3_exec(db, zSchema, 0, 0, 0);
 
 
 
857 if( rc!=SQLITE_OK ){
858 db_err("%s", sqlite3_errmsg(db));
859 }
860 va_start(ap, zSchema);
861 while( (zSql = va_arg(ap, const char*))!=0 ){
862 rc = sqlite3_exec(db, zSql, 0, 0, 0);
863 if( rc!=SQLITE_OK ){
864 db_err("%s", sqlite3_errmsg(db));
865 }
866 }
867 va_end(ap);
868 sqlite3_exec(db, "COMMIT", 0, 0, 0);
869 if( zFileName || g.db!=0 ){
870 sqlite3_close(db);
871 }else{
872 g.db = db;
873 }
874 }
875
876 /*
877 ** Function to return the number of seconds since 1970. This is
@@ -2086,10 +2118,11 @@
2086 ** argument is true. Ignore unfinalized statements when false.
2087 */
2088 void db_close(int reportErrors){
2089 sqlite3_stmt *pStmt;
2090 if( g.db==0 ) return;
 
2091 if( g.fSqlStats ){
2092 int cur, hiwtr;
2093 sqlite3_db_status(g.db, SQLITE_DBSTATUS_LOOKASIDE_USED, &cur, &hiwtr, 0);
2094 fprintf(stderr, "-- LOOKASIDE_USED %10d %10d\n", cur, hiwtr);
2095 sqlite3_db_status(g.db, SQLITE_DBSTATUS_LOOKASIDE_HIT, &cur, &hiwtr, 0);
@@ -2115,17 +2148,20 @@
2115 fprintf(stderr, "-- prepared statements %10d\n", db.nPrepare);
2116 }
2117 while( db.pAllStmt ){
2118 db_finalize(db.pAllStmt);
2119 }
2120 if( db.nBegin && reportErrors ){
2121 fossil_warning("Transaction started at %s:%d never commits",
2122 db.zStartFile, db.iStartLine);
 
 
2123 db_end_transaction(1);
2124 }
2125 pStmt = 0;
2126 g.dbIgnoreErrors++; /* Stop "database locked" warnings from PRAGMA optimize */
 
2127 sqlite3_exec(g.db, "PRAGMA optimize", 0, 0, 0);
2128 g.dbIgnoreErrors--;
2129 db_close_config();
2130
2131 /* If the localdb has a lot of unused free space,
@@ -2165,10 +2201,11 @@
2165 if( g.db ){
2166 int rc;
2167 sqlite3_wal_checkpoint(g.db, 0);
2168 rc = sqlite3_close(g.db);
2169 if( g.fSqlTrace ) fossil_trace("-- sqlite3_close(%d)\n", rc);
 
2170 }
2171 g.db = 0;
2172 g.repositoryOpen = 0;
2173 g.localOpen = 0;
2174 }
2175
--- src/db.c
+++ src/db.c
@@ -130,10 +130,13 @@
130 char *azBeforeCommit[5]; /* Commands to run prior to COMMIT */
131 int nBeforeCommit; /* Number of entries in azBeforeCommit */
132 int nPriorChanges; /* sqlite3_total_changes() at transaction start */
133 const char *zStartFile; /* File in which transaction was started */
134 int iStartLine; /* Line of zStartFile where transaction started */
135 int (*xAuth)(void*,int,const char*,const char*,const char*,const char*);
136 void *pAuthArg; /* Argument to the authorizer */
137 const char *zAuthName; /* Name of the authorizer */
138 } db = {0, 0, 0, 0, 0, 0, };
139
140 /*
141 ** Arrange for the given file to be deleted on a failure.
142 */
@@ -316,10 +319,36 @@
319 }
320 db.aHook[db.nCommitHook].sequence = sequence;
321 db.aHook[db.nCommitHook].xHook = x;
322 db.nCommitHook++;
323 }
324
325 /*
326 ** Set or unset the query authorizer callback function
327 */
328 void db_set_authorizer(
329 int(*xAuth)(void*,int,const char*,const char*,const char*,const char*),
330 void *pArg,
331 const char *zName /* for tracing */
332 ){
333 if( db.xAuth ){
334 fossil_panic("multiple active db_set_authorizer() calls");
335 }
336 if( g.db ) sqlite3_set_authorizer(g.db, xAuth, pArg);
337 db.xAuth = xAuth;
338 db.pAuthArg = pArg;
339 db.zAuthName = zName;
340 if( g.fSqlTrace ) fossil_trace("-- set authorizer %s\n", zName);
341 }
342 void db_clear_authorizer(void){
343 if( db.zAuthName && g.fSqlTrace ){
344 fossil_trace("-- discontinue authorizer %s\n", db.zAuthName);
345 }
346 if( g.db ) sqlite3_set_authorizer(g.db, 0, 0);
347 db.xAuth = 0;
348 db.pAuthArg = 0;
349 }
350
351 #if INTERFACE
352 /*
353 ** Possible flags to db_vprepare
354 */
@@ -844,34 +873,37 @@
873 void db_init_database(
874 const char *zFileName, /* Name of database file to create */
875 const char *zSchema, /* First part of schema */
876 ... /* Additional SQL to run. Terminate with NULL. */
877 ){
878 sqlite3 *xdb;
879 int rc;
880 const char *zSql;
881 va_list ap;
882
883 xdb = db_open(zFileName ? zFileName : ":memory:");
884 sqlite3_exec(xdb, "BEGIN EXCLUSIVE", 0, 0, 0);
885 if( db.xAuth ){
886 sqlite3_set_authorizer(xdb, db.xAuth, db.pAuthArg);
887 }
888 rc = sqlite3_exec(xdb, zSchema, 0, 0, 0);
889 if( rc!=SQLITE_OK ){
890 db_err("%s", sqlite3_errmsg(xdb));
891 }
892 va_start(ap, zSchema);
893 while( (zSql = va_arg(ap, const char*))!=0 ){
894 rc = sqlite3_exec(xdb, zSql, 0, 0, 0);
895 if( rc!=SQLITE_OK ){
896 db_err("%s", sqlite3_errmsg(xdb));
897 }
898 }
899 va_end(ap);
900 sqlite3_exec(xdb, "COMMIT", 0, 0, 0);
901 if( zFileName || g.db!=0 ){
902 sqlite3_close(xdb);
903 }else{
904 g.db = xdb;
905 }
906 }
907
908 /*
909 ** Function to return the number of seconds since 1970. This is
@@ -2086,10 +2118,11 @@
2118 ** argument is true. Ignore unfinalized statements when false.
2119 */
2120 void db_close(int reportErrors){
2121 sqlite3_stmt *pStmt;
2122 if( g.db==0 ) return;
2123 sqlite3_set_authorizer(g.db, 0, 0);
2124 if( g.fSqlStats ){
2125 int cur, hiwtr;
2126 sqlite3_db_status(g.db, SQLITE_DBSTATUS_LOOKASIDE_USED, &cur, &hiwtr, 0);
2127 fprintf(stderr, "-- LOOKASIDE_USED %10d %10d\n", cur, hiwtr);
2128 sqlite3_db_status(g.db, SQLITE_DBSTATUS_LOOKASIDE_HIT, &cur, &hiwtr, 0);
@@ -2115,17 +2148,20 @@
2148 fprintf(stderr, "-- prepared statements %10d\n", db.nPrepare);
2149 }
2150 while( db.pAllStmt ){
2151 db_finalize(db.pAllStmt);
2152 }
2153 if( db.nBegin ){
2154 if( reportErrors ){
2155 fossil_warning("Transaction started at %s:%d never commits",
2156 db.zStartFile, db.iStartLine);
2157 }
2158 db_end_transaction(1);
2159 }
2160 pStmt = 0;
2161 sqlite3_busy_timeout(g.db, 0);
2162 g.dbIgnoreErrors++; /* Stop "database locked" warnings */
2163 sqlite3_exec(g.db, "PRAGMA optimize", 0, 0, 0);
2164 g.dbIgnoreErrors--;
2165 db_close_config();
2166
2167 /* If the localdb has a lot of unused free space,
@@ -2165,10 +2201,11 @@
2201 if( g.db ){
2202 int rc;
2203 sqlite3_wal_checkpoint(g.db, 0);
2204 rc = sqlite3_close(g.db);
2205 if( g.fSqlTrace ) fossil_trace("-- sqlite3_close(%d)\n", rc);
2206 db_clear_authorizer();
2207 }
2208 g.db = 0;
2209 g.repositoryOpen = 0;
2210 g.localOpen = 0;
2211 }
2212
+51 -14
--- src/db.c
+++ src/db.c
@@ -130,10 +130,13 @@
130130
char *azBeforeCommit[5]; /* Commands to run prior to COMMIT */
131131
int nBeforeCommit; /* Number of entries in azBeforeCommit */
132132
int nPriorChanges; /* sqlite3_total_changes() at transaction start */
133133
const char *zStartFile; /* File in which transaction was started */
134134
int iStartLine; /* Line of zStartFile where transaction started */
135
+ int (*xAuth)(void*,int,const char*,const char*,const char*,const char*);
136
+ void *pAuthArg; /* Argument to the authorizer */
137
+ const char *zAuthName; /* Name of the authorizer */
135138
} db = {0, 0, 0, 0, 0, 0, };
136139
137140
/*
138141
** Arrange for the given file to be deleted on a failure.
139142
*/
@@ -316,10 +319,36 @@
316319
}
317320
db.aHook[db.nCommitHook].sequence = sequence;
318321
db.aHook[db.nCommitHook].xHook = x;
319322
db.nCommitHook++;
320323
}
324
+
325
+/*
326
+** Set or unset the query authorizer callback function
327
+*/
328
+void db_set_authorizer(
329
+ int(*xAuth)(void*,int,const char*,const char*,const char*,const char*),
330
+ void *pArg,
331
+ const char *zName /* for tracing */
332
+){
333
+ if( db.xAuth ){
334
+ fossil_panic("multiple active db_set_authorizer() calls");
335
+ }
336
+ if( g.db ) sqlite3_set_authorizer(g.db, xAuth, pArg);
337
+ db.xAuth = xAuth;
338
+ db.pAuthArg = pArg;
339
+ db.zAuthName = zName;
340
+ if( g.fSqlTrace ) fossil_trace("-- set authorizer %s\n", zName);
341
+}
342
+void db_clear_authorizer(void){
343
+ if( db.zAuthName && g.fSqlTrace ){
344
+ fossil_trace("-- discontinue authorizer %s\n", db.zAuthName);
345
+ }
346
+ if( g.db ) sqlite3_set_authorizer(g.db, 0, 0);
347
+ db.xAuth = 0;
348
+ db.pAuthArg = 0;
349
+}
321350
322351
#if INTERFACE
323352
/*
324353
** Possible flags to db_vprepare
325354
*/
@@ -844,34 +873,37 @@
844873
void db_init_database(
845874
const char *zFileName, /* Name of database file to create */
846875
const char *zSchema, /* First part of schema */
847876
... /* Additional SQL to run. Terminate with NULL. */
848877
){
849
- sqlite3 *db;
878
+ sqlite3 *xdb;
850879
int rc;
851880
const char *zSql;
852881
va_list ap;
853882
854
- db = db_open(zFileName ? zFileName : ":memory:");
855
- sqlite3_exec(db, "BEGIN EXCLUSIVE", 0, 0, 0);
856
- rc = sqlite3_exec(db, zSchema, 0, 0, 0);
883
+ xdb = db_open(zFileName ? zFileName : ":memory:");
884
+ sqlite3_exec(xdb, "BEGIN EXCLUSIVE", 0, 0, 0);
885
+ if( db.xAuth ){
886
+ sqlite3_set_authorizer(xdb, db.xAuth, db.pAuthArg);
887
+ }
888
+ rc = sqlite3_exec(xdb, zSchema, 0, 0, 0);
857889
if( rc!=SQLITE_OK ){
858
- db_err("%s", sqlite3_errmsg(db));
890
+ db_err("%s", sqlite3_errmsg(xdb));
859891
}
860892
va_start(ap, zSchema);
861893
while( (zSql = va_arg(ap, const char*))!=0 ){
862
- rc = sqlite3_exec(db, zSql, 0, 0, 0);
894
+ rc = sqlite3_exec(xdb, zSql, 0, 0, 0);
863895
if( rc!=SQLITE_OK ){
864
- db_err("%s", sqlite3_errmsg(db));
896
+ db_err("%s", sqlite3_errmsg(xdb));
865897
}
866898
}
867899
va_end(ap);
868
- sqlite3_exec(db, "COMMIT", 0, 0, 0);
900
+ sqlite3_exec(xdb, "COMMIT", 0, 0, 0);
869901
if( zFileName || g.db!=0 ){
870
- sqlite3_close(db);
902
+ sqlite3_close(xdb);
871903
}else{
872
- g.db = db;
904
+ g.db = xdb;
873905
}
874906
}
875907
876908
/*
877909
** Function to return the number of seconds since 1970. This is
@@ -2086,10 +2118,11 @@
20862118
** argument is true. Ignore unfinalized statements when false.
20872119
*/
20882120
void db_close(int reportErrors){
20892121
sqlite3_stmt *pStmt;
20902122
if( g.db==0 ) return;
2123
+ sqlite3_set_authorizer(g.db, 0, 0);
20912124
if( g.fSqlStats ){
20922125
int cur, hiwtr;
20932126
sqlite3_db_status(g.db, SQLITE_DBSTATUS_LOOKASIDE_USED, &cur, &hiwtr, 0);
20942127
fprintf(stderr, "-- LOOKASIDE_USED %10d %10d\n", cur, hiwtr);
20952128
sqlite3_db_status(g.db, SQLITE_DBSTATUS_LOOKASIDE_HIT, &cur, &hiwtr, 0);
@@ -2115,17 +2148,20 @@
21152148
fprintf(stderr, "-- prepared statements %10d\n", db.nPrepare);
21162149
}
21172150
while( db.pAllStmt ){
21182151
db_finalize(db.pAllStmt);
21192152
}
2120
- if( db.nBegin && reportErrors ){
2121
- fossil_warning("Transaction started at %s:%d never commits",
2122
- db.zStartFile, db.iStartLine);
2153
+ if( db.nBegin ){
2154
+ if( reportErrors ){
2155
+ fossil_warning("Transaction started at %s:%d never commits",
2156
+ db.zStartFile, db.iStartLine);
2157
+ }
21232158
db_end_transaction(1);
21242159
}
21252160
pStmt = 0;
2126
- g.dbIgnoreErrors++; /* Stop "database locked" warnings from PRAGMA optimize */
2161
+ sqlite3_busy_timeout(g.db, 0);
2162
+ g.dbIgnoreErrors++; /* Stop "database locked" warnings */
21272163
sqlite3_exec(g.db, "PRAGMA optimize", 0, 0, 0);
21282164
g.dbIgnoreErrors--;
21292165
db_close_config();
21302166
21312167
/* If the localdb has a lot of unused free space,
@@ -2165,10 +2201,11 @@
21652201
if( g.db ){
21662202
int rc;
21672203
sqlite3_wal_checkpoint(g.db, 0);
21682204
rc = sqlite3_close(g.db);
21692205
if( g.fSqlTrace ) fossil_trace("-- sqlite3_close(%d)\n", rc);
2206
+ db_clear_authorizer();
21702207
}
21712208
g.db = 0;
21722209
g.repositoryOpen = 0;
21732210
g.localOpen = 0;
21742211
}
21752212
--- src/db.c
+++ src/db.c
@@ -130,10 +130,13 @@
130 char *azBeforeCommit[5]; /* Commands to run prior to COMMIT */
131 int nBeforeCommit; /* Number of entries in azBeforeCommit */
132 int nPriorChanges; /* sqlite3_total_changes() at transaction start */
133 const char *zStartFile; /* File in which transaction was started */
134 int iStartLine; /* Line of zStartFile where transaction started */
 
 
 
135 } db = {0, 0, 0, 0, 0, 0, };
136
137 /*
138 ** Arrange for the given file to be deleted on a failure.
139 */
@@ -316,10 +319,36 @@
316 }
317 db.aHook[db.nCommitHook].sequence = sequence;
318 db.aHook[db.nCommitHook].xHook = x;
319 db.nCommitHook++;
320 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
321
322 #if INTERFACE
323 /*
324 ** Possible flags to db_vprepare
325 */
@@ -844,34 +873,37 @@
844 void db_init_database(
845 const char *zFileName, /* Name of database file to create */
846 const char *zSchema, /* First part of schema */
847 ... /* Additional SQL to run. Terminate with NULL. */
848 ){
849 sqlite3 *db;
850 int rc;
851 const char *zSql;
852 va_list ap;
853
854 db = db_open(zFileName ? zFileName : ":memory:");
855 sqlite3_exec(db, "BEGIN EXCLUSIVE", 0, 0, 0);
856 rc = sqlite3_exec(db, zSchema, 0, 0, 0);
 
 
 
857 if( rc!=SQLITE_OK ){
858 db_err("%s", sqlite3_errmsg(db));
859 }
860 va_start(ap, zSchema);
861 while( (zSql = va_arg(ap, const char*))!=0 ){
862 rc = sqlite3_exec(db, zSql, 0, 0, 0);
863 if( rc!=SQLITE_OK ){
864 db_err("%s", sqlite3_errmsg(db));
865 }
866 }
867 va_end(ap);
868 sqlite3_exec(db, "COMMIT", 0, 0, 0);
869 if( zFileName || g.db!=0 ){
870 sqlite3_close(db);
871 }else{
872 g.db = db;
873 }
874 }
875
876 /*
877 ** Function to return the number of seconds since 1970. This is
@@ -2086,10 +2118,11 @@
2086 ** argument is true. Ignore unfinalized statements when false.
2087 */
2088 void db_close(int reportErrors){
2089 sqlite3_stmt *pStmt;
2090 if( g.db==0 ) return;
 
2091 if( g.fSqlStats ){
2092 int cur, hiwtr;
2093 sqlite3_db_status(g.db, SQLITE_DBSTATUS_LOOKASIDE_USED, &cur, &hiwtr, 0);
2094 fprintf(stderr, "-- LOOKASIDE_USED %10d %10d\n", cur, hiwtr);
2095 sqlite3_db_status(g.db, SQLITE_DBSTATUS_LOOKASIDE_HIT, &cur, &hiwtr, 0);
@@ -2115,17 +2148,20 @@
2115 fprintf(stderr, "-- prepared statements %10d\n", db.nPrepare);
2116 }
2117 while( db.pAllStmt ){
2118 db_finalize(db.pAllStmt);
2119 }
2120 if( db.nBegin && reportErrors ){
2121 fossil_warning("Transaction started at %s:%d never commits",
2122 db.zStartFile, db.iStartLine);
 
 
2123 db_end_transaction(1);
2124 }
2125 pStmt = 0;
2126 g.dbIgnoreErrors++; /* Stop "database locked" warnings from PRAGMA optimize */
 
2127 sqlite3_exec(g.db, "PRAGMA optimize", 0, 0, 0);
2128 g.dbIgnoreErrors--;
2129 db_close_config();
2130
2131 /* If the localdb has a lot of unused free space,
@@ -2165,10 +2201,11 @@
2165 if( g.db ){
2166 int rc;
2167 sqlite3_wal_checkpoint(g.db, 0);
2168 rc = sqlite3_close(g.db);
2169 if( g.fSqlTrace ) fossil_trace("-- sqlite3_close(%d)\n", rc);
 
2170 }
2171 g.db = 0;
2172 g.repositoryOpen = 0;
2173 g.localOpen = 0;
2174 }
2175
--- src/db.c
+++ src/db.c
@@ -130,10 +130,13 @@
130 char *azBeforeCommit[5]; /* Commands to run prior to COMMIT */
131 int nBeforeCommit; /* Number of entries in azBeforeCommit */
132 int nPriorChanges; /* sqlite3_total_changes() at transaction start */
133 const char *zStartFile; /* File in which transaction was started */
134 int iStartLine; /* Line of zStartFile where transaction started */
135 int (*xAuth)(void*,int,const char*,const char*,const char*,const char*);
136 void *pAuthArg; /* Argument to the authorizer */
137 const char *zAuthName; /* Name of the authorizer */
138 } db = {0, 0, 0, 0, 0, 0, };
139
140 /*
141 ** Arrange for the given file to be deleted on a failure.
142 */
@@ -316,10 +319,36 @@
319 }
320 db.aHook[db.nCommitHook].sequence = sequence;
321 db.aHook[db.nCommitHook].xHook = x;
322 db.nCommitHook++;
323 }
324
325 /*
326 ** Set or unset the query authorizer callback function
327 */
328 void db_set_authorizer(
329 int(*xAuth)(void*,int,const char*,const char*,const char*,const char*),
330 void *pArg,
331 const char *zName /* for tracing */
332 ){
333 if( db.xAuth ){
334 fossil_panic("multiple active db_set_authorizer() calls");
335 }
336 if( g.db ) sqlite3_set_authorizer(g.db, xAuth, pArg);
337 db.xAuth = xAuth;
338 db.pAuthArg = pArg;
339 db.zAuthName = zName;
340 if( g.fSqlTrace ) fossil_trace("-- set authorizer %s\n", zName);
341 }
342 void db_clear_authorizer(void){
343 if( db.zAuthName && g.fSqlTrace ){
344 fossil_trace("-- discontinue authorizer %s\n", db.zAuthName);
345 }
346 if( g.db ) sqlite3_set_authorizer(g.db, 0, 0);
347 db.xAuth = 0;
348 db.pAuthArg = 0;
349 }
350
351 #if INTERFACE
352 /*
353 ** Possible flags to db_vprepare
354 */
@@ -844,34 +873,37 @@
873 void db_init_database(
874 const char *zFileName, /* Name of database file to create */
875 const char *zSchema, /* First part of schema */
876 ... /* Additional SQL to run. Terminate with NULL. */
877 ){
878 sqlite3 *xdb;
879 int rc;
880 const char *zSql;
881 va_list ap;
882
883 xdb = db_open(zFileName ? zFileName : ":memory:");
884 sqlite3_exec(xdb, "BEGIN EXCLUSIVE", 0, 0, 0);
885 if( db.xAuth ){
886 sqlite3_set_authorizer(xdb, db.xAuth, db.pAuthArg);
887 }
888 rc = sqlite3_exec(xdb, zSchema, 0, 0, 0);
889 if( rc!=SQLITE_OK ){
890 db_err("%s", sqlite3_errmsg(xdb));
891 }
892 va_start(ap, zSchema);
893 while( (zSql = va_arg(ap, const char*))!=0 ){
894 rc = sqlite3_exec(xdb, zSql, 0, 0, 0);
895 if( rc!=SQLITE_OK ){
896 db_err("%s", sqlite3_errmsg(xdb));
897 }
898 }
899 va_end(ap);
900 sqlite3_exec(xdb, "COMMIT", 0, 0, 0);
901 if( zFileName || g.db!=0 ){
902 sqlite3_close(xdb);
903 }else{
904 g.db = xdb;
905 }
906 }
907
908 /*
909 ** Function to return the number of seconds since 1970. This is
@@ -2086,10 +2118,11 @@
2118 ** argument is true. Ignore unfinalized statements when false.
2119 */
2120 void db_close(int reportErrors){
2121 sqlite3_stmt *pStmt;
2122 if( g.db==0 ) return;
2123 sqlite3_set_authorizer(g.db, 0, 0);
2124 if( g.fSqlStats ){
2125 int cur, hiwtr;
2126 sqlite3_db_status(g.db, SQLITE_DBSTATUS_LOOKASIDE_USED, &cur, &hiwtr, 0);
2127 fprintf(stderr, "-- LOOKASIDE_USED %10d %10d\n", cur, hiwtr);
2128 sqlite3_db_status(g.db, SQLITE_DBSTATUS_LOOKASIDE_HIT, &cur, &hiwtr, 0);
@@ -2115,17 +2148,20 @@
2148 fprintf(stderr, "-- prepared statements %10d\n", db.nPrepare);
2149 }
2150 while( db.pAllStmt ){
2151 db_finalize(db.pAllStmt);
2152 }
2153 if( db.nBegin ){
2154 if( reportErrors ){
2155 fossil_warning("Transaction started at %s:%d never commits",
2156 db.zStartFile, db.iStartLine);
2157 }
2158 db_end_transaction(1);
2159 }
2160 pStmt = 0;
2161 sqlite3_busy_timeout(g.db, 0);
2162 g.dbIgnoreErrors++; /* Stop "database locked" warnings */
2163 sqlite3_exec(g.db, "PRAGMA optimize", 0, 0, 0);
2164 g.dbIgnoreErrors--;
2165 db_close_config();
2166
2167 /* If the localdb has a lot of unused free space,
@@ -2165,10 +2201,11 @@
2201 if( g.db ){
2202 int rc;
2203 sqlite3_wal_checkpoint(g.db, 0);
2204 rc = sqlite3_close(g.db);
2205 if( g.fSqlTrace ) fossil_trace("-- sqlite3_close(%d)\n", rc);
2206 db_clear_authorizer();
2207 }
2208 g.db = 0;
2209 g.repositoryOpen = 0;
2210 g.localOpen = 0;
2211 }
2212
+134 -1
--- src/file.c
+++ src/file.c
@@ -323,10 +323,57 @@
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
+}
328375
329376
/*
330377
** Return 1 if zFilename is a directory. Return 0 if zFilename
331378
** does not exist. Return 2 if zFilename exists but is something
332379
** other than a directory.
@@ -570,11 +617,14 @@
570617
*/
571618
int file_setexe(const char *zFilename, int onoff){
572619
int rc = 0;
573620
#if !defined(_WIN32)
574621
struct stat buf;
575
- if( fossil_stat(zFilename, &buf, RepoFILE)!=0 || S_ISLNK(buf.st_mode) ){
622
+ if( fossil_stat(zFilename, &buf, RepoFILE)!=0
623
+ || S_ISLNK(buf.st_mode)
624
+ || S_ISDIR(buf.st_mode)
625
+ ){
576626
return 0;
577627
}
578628
if( onoff ){
579629
int targetMode = (buf.st_mode & 0444)>>2;
580630
if( (buf.st_mode & 0100)==0 ){
@@ -2397,5 +2447,88 @@
23972447
changeCount);
23982448
}else{
23992449
fossil_print("Touched %d file(s)\n", changeCount);
24002450
}
24012451
}
2452
+
2453
+/*
2454
+** Returns non-zero if the specified file name ends with any reserved name,
2455
+** e.g.: _FOSSIL_ or .fslckout. Specifically, it returns 1 for exact match
2456
+** or 2 for a tail match on a longer file name.
2457
+**
2458
+** For the sake of efficiency, zFilename must be a canonical name, e.g. an
2459
+** absolute path using only forward slash ('/') as a directory separator.
2460
+**
2461
+** nFilename must be the length of zFilename. When negative, strlen() will
2462
+** be used to calculate it.
2463
+*/
2464
+int file_is_reserved_name(const char *zFilename, int nFilename){
2465
+ const char *zEnd; /* one-after-the-end of zFilename */
2466
+ int gotSuffix = 0; /* length of suffix (-wal, -shm, -journal) */
2467
+
2468
+ assert( zFilename && "API misuse" );
2469
+ if( nFilename<0 ) nFilename = (int)strlen(zFilename);
2470
+ if( nFilename<8 ) return 0; /* strlen("_FOSSIL_") */
2471
+ zEnd = zFilename + nFilename;
2472
+ if( nFilename>=12 ){ /* strlen("_FOSSIL_-(shm|wal)") */
2473
+ /* Check for (-wal, -shm, -journal) suffixes, with an eye towards
2474
+ ** runtime speed. */
2475
+ if( zEnd[-4]=='-' ){
2476
+ if( fossil_strnicmp("wal", &zEnd[-3], 3)
2477
+ && fossil_strnicmp("shm", &zEnd[-3], 3) ){
2478
+ return 0;
2479
+ }
2480
+ gotSuffix = 4;
2481
+ }else if( nFilename>=16 && zEnd[-8]=='-' ){ /*strlen(_FOSSIL_-journal) */
2482
+ if( fossil_strnicmp("journal", &zEnd[-7], 7) ) return 0;
2483
+ gotSuffix = 8;
2484
+ }
2485
+ if( gotSuffix ){
2486
+ assert( 4==gotSuffix || 8==gotSuffix );
2487
+ zEnd -= gotSuffix;
2488
+ nFilename -= gotSuffix;
2489
+ gotSuffix = 1;
2490
+ }
2491
+ assert( nFilename>=8 && "strlen(_FOSSIL_)" );
2492
+ assert( gotSuffix==0 || gotSuffix==1 );
2493
+ }
2494
+ switch( zEnd[-1] ){
2495
+ case '_':{
2496
+ if( fossil_strnicmp("_FOSSIL_", &zEnd[-8], 8) ) return 0;
2497
+ if( 8==nFilename ) return 1;
2498
+ return zEnd[-9]=='/' ? 2 : gotSuffix;
2499
+ }
2500
+ case 'T':
2501
+ case 't':{
2502
+ if( nFilename<9 || zEnd[-9]!='.'
2503
+ || fossil_strnicmp(".fslckout", &zEnd[-9], 9) ){
2504
+ return 0;
2505
+ }
2506
+ if( 9==nFilename ) return 1;
2507
+ return zEnd[-10]=='/' ? 2 : gotSuffix;
2508
+ }
2509
+ default:{
2510
+ return 0;
2511
+ }
2512
+ }
2513
+}
2514
+
2515
+/*
2516
+** COMMAND: test-is-reserved-name
2517
+**
2518
+** Usage: %fossil test-is-ckout-db FILENAMES...
2519
+**
2520
+** Passes each given name to file_is_reserved_name() and outputs one
2521
+** line per file: the result value of that function followed by the
2522
+** name.
2523
+*/
2524
+void test_is_reserved_name_cmd(void){
2525
+ int i;
2526
+
2527
+ if(g.argc<3){
2528
+ usage("FILENAME_1 [...FILENAME_N]");
2529
+ }
2530
+ for( i = 2; i < g.argc; ++i ){
2531
+ const int check = file_is_reserved_name(g.argv[i], -1);
2532
+ fossil_print("%d %s\n", check, g.argv[i]);
2533
+ }
2534
+}
24022535
--- src/file.c
+++ src/file.c
@@ -323,10 +323,57 @@
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.
@@ -570,11 +617,14 @@
570 */
571 int file_setexe(const char *zFilename, int onoff){
572 int rc = 0;
573 #if !defined(_WIN32)
574 struct stat buf;
575 if( fossil_stat(zFilename, &buf, RepoFILE)!=0 || S_ISLNK(buf.st_mode) ){
 
 
 
576 return 0;
577 }
578 if( onoff ){
579 int targetMode = (buf.st_mode & 0444)>>2;
580 if( (buf.st_mode & 0100)==0 ){
@@ -2397,5 +2447,88 @@
2397 changeCount);
2398 }else{
2399 fossil_print("Touched %d file(s)\n", changeCount);
2400 }
2401 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2402
--- src/file.c
+++ src/file.c
@@ -323,10 +323,57 @@
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 ** Return 1 if zFilename is a directory. Return 0 if zFilename
378 ** does not exist. Return 2 if zFilename exists but is something
379 ** other than a directory.
@@ -570,11 +617,14 @@
617 */
618 int file_setexe(const char *zFilename, int onoff){
619 int rc = 0;
620 #if !defined(_WIN32)
621 struct stat buf;
622 if( fossil_stat(zFilename, &buf, RepoFILE)!=0
623 || S_ISLNK(buf.st_mode)
624 || S_ISDIR(buf.st_mode)
625 ){
626 return 0;
627 }
628 if( onoff ){
629 int targetMode = (buf.st_mode & 0444)>>2;
630 if( (buf.st_mode & 0100)==0 ){
@@ -2397,5 +2447,88 @@
2447 changeCount);
2448 }else{
2449 fossil_print("Touched %d file(s)\n", changeCount);
2450 }
2451 }
2452
2453 /*
2454 ** Returns non-zero if the specified file name ends with any reserved name,
2455 ** e.g.: _FOSSIL_ or .fslckout. Specifically, it returns 1 for exact match
2456 ** or 2 for a tail match on a longer file name.
2457 **
2458 ** For the sake of efficiency, zFilename must be a canonical name, e.g. an
2459 ** absolute path using only forward slash ('/') as a directory separator.
2460 **
2461 ** nFilename must be the length of zFilename. When negative, strlen() will
2462 ** be used to calculate it.
2463 */
2464 int file_is_reserved_name(const char *zFilename, int nFilename){
2465 const char *zEnd; /* one-after-the-end of zFilename */
2466 int gotSuffix = 0; /* length of suffix (-wal, -shm, -journal) */
2467
2468 assert( zFilename && "API misuse" );
2469 if( nFilename<0 ) nFilename = (int)strlen(zFilename);
2470 if( nFilename<8 ) return 0; /* strlen("_FOSSIL_") */
2471 zEnd = zFilename + nFilename;
2472 if( nFilename>=12 ){ /* strlen("_FOSSIL_-(shm|wal)") */
2473 /* Check for (-wal, -shm, -journal) suffixes, with an eye towards
2474 ** runtime speed. */
2475 if( zEnd[-4]=='-' ){
2476 if( fossil_strnicmp("wal", &zEnd[-3], 3)
2477 && fossil_strnicmp("shm", &zEnd[-3], 3) ){
2478 return 0;
2479 }
2480 gotSuffix = 4;
2481 }else if( nFilename>=16 && zEnd[-8]=='-' ){ /*strlen(_FOSSIL_-journal) */
2482 if( fossil_strnicmp("journal", &zEnd[-7], 7) ) return 0;
2483 gotSuffix = 8;
2484 }
2485 if( gotSuffix ){
2486 assert( 4==gotSuffix || 8==gotSuffix );
2487 zEnd -= gotSuffix;
2488 nFilename -= gotSuffix;
2489 gotSuffix = 1;
2490 }
2491 assert( nFilename>=8 && "strlen(_FOSSIL_)" );
2492 assert( gotSuffix==0 || gotSuffix==1 );
2493 }
2494 switch( zEnd[-1] ){
2495 case '_':{
2496 if( fossil_strnicmp("_FOSSIL_", &zEnd[-8], 8) ) return 0;
2497 if( 8==nFilename ) return 1;
2498 return zEnd[-9]=='/' ? 2 : gotSuffix;
2499 }
2500 case 'T':
2501 case 't':{
2502 if( nFilename<9 || zEnd[-9]!='.'
2503 || fossil_strnicmp(".fslckout", &zEnd[-9], 9) ){
2504 return 0;
2505 }
2506 if( 9==nFilename ) return 1;
2507 return zEnd[-10]=='/' ? 2 : gotSuffix;
2508 }
2509 default:{
2510 return 0;
2511 }
2512 }
2513 }
2514
2515 /*
2516 ** COMMAND: test-is-reserved-name
2517 **
2518 ** Usage: %fossil test-is-ckout-db FILENAMES...
2519 **
2520 ** Passes each given name to file_is_reserved_name() and outputs one
2521 ** line per file: the result value of that function followed by the
2522 ** name.
2523 */
2524 void test_is_reserved_name_cmd(void){
2525 int i;
2526
2527 if(g.argc<3){
2528 usage("FILENAME_1 [...FILENAME_N]");
2529 }
2530 for( i = 2; i < g.argc; ++i ){
2531 const int check = file_is_reserved_name(g.argv[i], -1);
2532 fossil_print("%d %s\n", check, g.argv[i]);
2533 }
2534 }
2535
+134 -1
--- src/file.c
+++ src/file.c
@@ -323,10 +323,57 @@
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
+}
328375
329376
/*
330377
** Return 1 if zFilename is a directory. Return 0 if zFilename
331378
** does not exist. Return 2 if zFilename exists but is something
332379
** other than a directory.
@@ -570,11 +617,14 @@
570617
*/
571618
int file_setexe(const char *zFilename, int onoff){
572619
int rc = 0;
573620
#if !defined(_WIN32)
574621
struct stat buf;
575
- if( fossil_stat(zFilename, &buf, RepoFILE)!=0 || S_ISLNK(buf.st_mode) ){
622
+ if( fossil_stat(zFilename, &buf, RepoFILE)!=0
623
+ || S_ISLNK(buf.st_mode)
624
+ || S_ISDIR(buf.st_mode)
625
+ ){
576626
return 0;
577627
}
578628
if( onoff ){
579629
int targetMode = (buf.st_mode & 0444)>>2;
580630
if( (buf.st_mode & 0100)==0 ){
@@ -2397,5 +2447,88 @@
23972447
changeCount);
23982448
}else{
23992449
fossil_print("Touched %d file(s)\n", changeCount);
24002450
}
24012451
}
2452
+
2453
+/*
2454
+** Returns non-zero if the specified file name ends with any reserved name,
2455
+** e.g.: _FOSSIL_ or .fslckout. Specifically, it returns 1 for exact match
2456
+** or 2 for a tail match on a longer file name.
2457
+**
2458
+** For the sake of efficiency, zFilename must be a canonical name, e.g. an
2459
+** absolute path using only forward slash ('/') as a directory separator.
2460
+**
2461
+** nFilename must be the length of zFilename. When negative, strlen() will
2462
+** be used to calculate it.
2463
+*/
2464
+int file_is_reserved_name(const char *zFilename, int nFilename){
2465
+ const char *zEnd; /* one-after-the-end of zFilename */
2466
+ int gotSuffix = 0; /* length of suffix (-wal, -shm, -journal) */
2467
+
2468
+ assert( zFilename && "API misuse" );
2469
+ if( nFilename<0 ) nFilename = (int)strlen(zFilename);
2470
+ if( nFilename<8 ) return 0; /* strlen("_FOSSIL_") */
2471
+ zEnd = zFilename + nFilename;
2472
+ if( nFilename>=12 ){ /* strlen("_FOSSIL_-(shm|wal)") */
2473
+ /* Check for (-wal, -shm, -journal) suffixes, with an eye towards
2474
+ ** runtime speed. */
2475
+ if( zEnd[-4]=='-' ){
2476
+ if( fossil_strnicmp("wal", &zEnd[-3], 3)
2477
+ && fossil_strnicmp("shm", &zEnd[-3], 3) ){
2478
+ return 0;
2479
+ }
2480
+ gotSuffix = 4;
2481
+ }else if( nFilename>=16 && zEnd[-8]=='-' ){ /*strlen(_FOSSIL_-journal) */
2482
+ if( fossil_strnicmp("journal", &zEnd[-7], 7) ) return 0;
2483
+ gotSuffix = 8;
2484
+ }
2485
+ if( gotSuffix ){
2486
+ assert( 4==gotSuffix || 8==gotSuffix );
2487
+ zEnd -= gotSuffix;
2488
+ nFilename -= gotSuffix;
2489
+ gotSuffix = 1;
2490
+ }
2491
+ assert( nFilename>=8 && "strlen(_FOSSIL_)" );
2492
+ assert( gotSuffix==0 || gotSuffix==1 );
2493
+ }
2494
+ switch( zEnd[-1] ){
2495
+ case '_':{
2496
+ if( fossil_strnicmp("_FOSSIL_", &zEnd[-8], 8) ) return 0;
2497
+ if( 8==nFilename ) return 1;
2498
+ return zEnd[-9]=='/' ? 2 : gotSuffix;
2499
+ }
2500
+ case 'T':
2501
+ case 't':{
2502
+ if( nFilename<9 || zEnd[-9]!='.'
2503
+ || fossil_strnicmp(".fslckout", &zEnd[-9], 9) ){
2504
+ return 0;
2505
+ }
2506
+ if( 9==nFilename ) return 1;
2507
+ return zEnd[-10]=='/' ? 2 : gotSuffix;
2508
+ }
2509
+ default:{
2510
+ return 0;
2511
+ }
2512
+ }
2513
+}
2514
+
2515
+/*
2516
+** COMMAND: test-is-reserved-name
2517
+**
2518
+** Usage: %fossil test-is-ckout-db FILENAMES...
2519
+**
2520
+** Passes each given name to file_is_reserved_name() and outputs one
2521
+** line per file: the result value of that function followed by the
2522
+** name.
2523
+*/
2524
+void test_is_reserved_name_cmd(void){
2525
+ int i;
2526
+
2527
+ if(g.argc<3){
2528
+ usage("FILENAME_1 [...FILENAME_N]");
2529
+ }
2530
+ for( i = 2; i < g.argc; ++i ){
2531
+ const int check = file_is_reserved_name(g.argv[i], -1);
2532
+ fossil_print("%d %s\n", check, g.argv[i]);
2533
+ }
2534
+}
24022535
--- src/file.c
+++ src/file.c
@@ -323,10 +323,57 @@
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.
@@ -570,11 +617,14 @@
570 */
571 int file_setexe(const char *zFilename, int onoff){
572 int rc = 0;
573 #if !defined(_WIN32)
574 struct stat buf;
575 if( fossil_stat(zFilename, &buf, RepoFILE)!=0 || S_ISLNK(buf.st_mode) ){
 
 
 
576 return 0;
577 }
578 if( onoff ){
579 int targetMode = (buf.st_mode & 0444)>>2;
580 if( (buf.st_mode & 0100)==0 ){
@@ -2397,5 +2447,88 @@
2397 changeCount);
2398 }else{
2399 fossil_print("Touched %d file(s)\n", changeCount);
2400 }
2401 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2402
--- src/file.c
+++ src/file.c
@@ -323,10 +323,57 @@
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 ** Return 1 if zFilename is a directory. Return 0 if zFilename
378 ** does not exist. Return 2 if zFilename exists but is something
379 ** other than a directory.
@@ -570,11 +617,14 @@
617 */
618 int file_setexe(const char *zFilename, int onoff){
619 int rc = 0;
620 #if !defined(_WIN32)
621 struct stat buf;
622 if( fossil_stat(zFilename, &buf, RepoFILE)!=0
623 || S_ISLNK(buf.st_mode)
624 || S_ISDIR(buf.st_mode)
625 ){
626 return 0;
627 }
628 if( onoff ){
629 int targetMode = (buf.st_mode & 0444)>>2;
630 if( (buf.st_mode & 0100)==0 ){
@@ -2397,5 +2447,88 @@
2447 changeCount);
2448 }else{
2449 fossil_print("Touched %d file(s)\n", changeCount);
2450 }
2451 }
2452
2453 /*
2454 ** Returns non-zero if the specified file name ends with any reserved name,
2455 ** e.g.: _FOSSIL_ or .fslckout. Specifically, it returns 1 for exact match
2456 ** or 2 for a tail match on a longer file name.
2457 **
2458 ** For the sake of efficiency, zFilename must be a canonical name, e.g. an
2459 ** absolute path using only forward slash ('/') as a directory separator.
2460 **
2461 ** nFilename must be the length of zFilename. When negative, strlen() will
2462 ** be used to calculate it.
2463 */
2464 int file_is_reserved_name(const char *zFilename, int nFilename){
2465 const char *zEnd; /* one-after-the-end of zFilename */
2466 int gotSuffix = 0; /* length of suffix (-wal, -shm, -journal) */
2467
2468 assert( zFilename && "API misuse" );
2469 if( nFilename<0 ) nFilename = (int)strlen(zFilename);
2470 if( nFilename<8 ) return 0; /* strlen("_FOSSIL_") */
2471 zEnd = zFilename + nFilename;
2472 if( nFilename>=12 ){ /* strlen("_FOSSIL_-(shm|wal)") */
2473 /* Check for (-wal, -shm, -journal) suffixes, with an eye towards
2474 ** runtime speed. */
2475 if( zEnd[-4]=='-' ){
2476 if( fossil_strnicmp("wal", &zEnd[-3], 3)
2477 && fossil_strnicmp("shm", &zEnd[-3], 3) ){
2478 return 0;
2479 }
2480 gotSuffix = 4;
2481 }else if( nFilename>=16 && zEnd[-8]=='-' ){ /*strlen(_FOSSIL_-journal) */
2482 if( fossil_strnicmp("journal", &zEnd[-7], 7) ) return 0;
2483 gotSuffix = 8;
2484 }
2485 if( gotSuffix ){
2486 assert( 4==gotSuffix || 8==gotSuffix );
2487 zEnd -= gotSuffix;
2488 nFilename -= gotSuffix;
2489 gotSuffix = 1;
2490 }
2491 assert( nFilename>=8 && "strlen(_FOSSIL_)" );
2492 assert( gotSuffix==0 || gotSuffix==1 );
2493 }
2494 switch( zEnd[-1] ){
2495 case '_':{
2496 if( fossil_strnicmp("_FOSSIL_", &zEnd[-8], 8) ) return 0;
2497 if( 8==nFilename ) return 1;
2498 return zEnd[-9]=='/' ? 2 : gotSuffix;
2499 }
2500 case 'T':
2501 case 't':{
2502 if( nFilename<9 || zEnd[-9]!='.'
2503 || fossil_strnicmp(".fslckout", &zEnd[-9], 9) ){
2504 return 0;
2505 }
2506 if( 9==nFilename ) return 1;
2507 return zEnd[-10]=='/' ? 2 : gotSuffix;
2508 }
2509 default:{
2510 return 0;
2511 }
2512 }
2513 }
2514
2515 /*
2516 ** COMMAND: test-is-reserved-name
2517 **
2518 ** Usage: %fossil test-is-ckout-db FILENAMES...
2519 **
2520 ** Passes each given name to file_is_reserved_name() and outputs one
2521 ** line per file: the result value of that function followed by the
2522 ** name.
2523 */
2524 void test_is_reserved_name_cmd(void){
2525 int i;
2526
2527 if(g.argc<3){
2528 usage("FILENAME_1 [...FILENAME_N]");
2529 }
2530 for( i = 2; i < g.argc; ++i ){
2531 const int check = file_is_reserved_name(g.argv[i], -1);
2532 fossil_print("%d %s\n", check, g.argv[i]);
2533 }
2534 }
2535
+134 -1
--- src/file.c
+++ src/file.c
@@ -323,10 +323,57 @@
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
+}
328375
329376
/*
330377
** Return 1 if zFilename is a directory. Return 0 if zFilename
331378
** does not exist. Return 2 if zFilename exists but is something
332379
** other than a directory.
@@ -570,11 +617,14 @@
570617
*/
571618
int file_setexe(const char *zFilename, int onoff){
572619
int rc = 0;
573620
#if !defined(_WIN32)
574621
struct stat buf;
575
- if( fossil_stat(zFilename, &buf, RepoFILE)!=0 || S_ISLNK(buf.st_mode) ){
622
+ if( fossil_stat(zFilename, &buf, RepoFILE)!=0
623
+ || S_ISLNK(buf.st_mode)
624
+ || S_ISDIR(buf.st_mode)
625
+ ){
576626
return 0;
577627
}
578628
if( onoff ){
579629
int targetMode = (buf.st_mode & 0444)>>2;
580630
if( (buf.st_mode & 0100)==0 ){
@@ -2397,5 +2447,88 @@
23972447
changeCount);
23982448
}else{
23992449
fossil_print("Touched %d file(s)\n", changeCount);
24002450
}
24012451
}
2452
+
2453
+/*
2454
+** Returns non-zero if the specified file name ends with any reserved name,
2455
+** e.g.: _FOSSIL_ or .fslckout. Specifically, it returns 1 for exact match
2456
+** or 2 for a tail match on a longer file name.
2457
+**
2458
+** For the sake of efficiency, zFilename must be a canonical name, e.g. an
2459
+** absolute path using only forward slash ('/') as a directory separator.
2460
+**
2461
+** nFilename must be the length of zFilename. When negative, strlen() will
2462
+** be used to calculate it.
2463
+*/
2464
+int file_is_reserved_name(const char *zFilename, int nFilename){
2465
+ const char *zEnd; /* one-after-the-end of zFilename */
2466
+ int gotSuffix = 0; /* length of suffix (-wal, -shm, -journal) */
2467
+
2468
+ assert( zFilename && "API misuse" );
2469
+ if( nFilename<0 ) nFilename = (int)strlen(zFilename);
2470
+ if( nFilename<8 ) return 0; /* strlen("_FOSSIL_") */
2471
+ zEnd = zFilename + nFilename;
2472
+ if( nFilename>=12 ){ /* strlen("_FOSSIL_-(shm|wal)") */
2473
+ /* Check for (-wal, -shm, -journal) suffixes, with an eye towards
2474
+ ** runtime speed. */
2475
+ if( zEnd[-4]=='-' ){
2476
+ if( fossil_strnicmp("wal", &zEnd[-3], 3)
2477
+ && fossil_strnicmp("shm", &zEnd[-3], 3) ){
2478
+ return 0;
2479
+ }
2480
+ gotSuffix = 4;
2481
+ }else if( nFilename>=16 && zEnd[-8]=='-' ){ /*strlen(_FOSSIL_-journal) */
2482
+ if( fossil_strnicmp("journal", &zEnd[-7], 7) ) return 0;
2483
+ gotSuffix = 8;
2484
+ }
2485
+ if( gotSuffix ){
2486
+ assert( 4==gotSuffix || 8==gotSuffix );
2487
+ zEnd -= gotSuffix;
2488
+ nFilename -= gotSuffix;
2489
+ gotSuffix = 1;
2490
+ }
2491
+ assert( nFilename>=8 && "strlen(_FOSSIL_)" );
2492
+ assert( gotSuffix==0 || gotSuffix==1 );
2493
+ }
2494
+ switch( zEnd[-1] ){
2495
+ case '_':{
2496
+ if( fossil_strnicmp("_FOSSIL_", &zEnd[-8], 8) ) return 0;
2497
+ if( 8==nFilename ) return 1;
2498
+ return zEnd[-9]=='/' ? 2 : gotSuffix;
2499
+ }
2500
+ case 'T':
2501
+ case 't':{
2502
+ if( nFilename<9 || zEnd[-9]!='.'
2503
+ || fossil_strnicmp(".fslckout", &zEnd[-9], 9) ){
2504
+ return 0;
2505
+ }
2506
+ if( 9==nFilename ) return 1;
2507
+ return zEnd[-10]=='/' ? 2 : gotSuffix;
2508
+ }
2509
+ default:{
2510
+ return 0;
2511
+ }
2512
+ }
2513
+}
2514
+
2515
+/*
2516
+** COMMAND: test-is-reserved-name
2517
+**
2518
+** Usage: %fossil test-is-ckout-db FILENAMES...
2519
+**
2520
+** Passes each given name to file_is_reserved_name() and outputs one
2521
+** line per file: the result value of that function followed by the
2522
+** name.
2523
+*/
2524
+void test_is_reserved_name_cmd(void){
2525
+ int i;
2526
+
2527
+ if(g.argc<3){
2528
+ usage("FILENAME_1 [...FILENAME_N]");
2529
+ }
2530
+ for( i = 2; i < g.argc; ++i ){
2531
+ const int check = file_is_reserved_name(g.argv[i], -1);
2532
+ fossil_print("%d %s\n", check, g.argv[i]);
2533
+ }
2534
+}
24022535
--- src/file.c
+++ src/file.c
@@ -323,10 +323,57 @@
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.
@@ -570,11 +617,14 @@
570 */
571 int file_setexe(const char *zFilename, int onoff){
572 int rc = 0;
573 #if !defined(_WIN32)
574 struct stat buf;
575 if( fossil_stat(zFilename, &buf, RepoFILE)!=0 || S_ISLNK(buf.st_mode) ){
 
 
 
576 return 0;
577 }
578 if( onoff ){
579 int targetMode = (buf.st_mode & 0444)>>2;
580 if( (buf.st_mode & 0100)==0 ){
@@ -2397,5 +2447,88 @@
2397 changeCount);
2398 }else{
2399 fossil_print("Touched %d file(s)\n", changeCount);
2400 }
2401 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2402
--- src/file.c
+++ src/file.c
@@ -323,10 +323,57 @@
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 ** Return 1 if zFilename is a directory. Return 0 if zFilename
378 ** does not exist. Return 2 if zFilename exists but is something
379 ** other than a directory.
@@ -570,11 +617,14 @@
617 */
618 int file_setexe(const char *zFilename, int onoff){
619 int rc = 0;
620 #if !defined(_WIN32)
621 struct stat buf;
622 if( fossil_stat(zFilename, &buf, RepoFILE)!=0
623 || S_ISLNK(buf.st_mode)
624 || S_ISDIR(buf.st_mode)
625 ){
626 return 0;
627 }
628 if( onoff ){
629 int targetMode = (buf.st_mode & 0444)>>2;
630 if( (buf.st_mode & 0100)==0 ){
@@ -2397,5 +2447,88 @@
2447 changeCount);
2448 }else{
2449 fossil_print("Touched %d file(s)\n", changeCount);
2450 }
2451 }
2452
2453 /*
2454 ** Returns non-zero if the specified file name ends with any reserved name,
2455 ** e.g.: _FOSSIL_ or .fslckout. Specifically, it returns 1 for exact match
2456 ** or 2 for a tail match on a longer file name.
2457 **
2458 ** For the sake of efficiency, zFilename must be a canonical name, e.g. an
2459 ** absolute path using only forward slash ('/') as a directory separator.
2460 **
2461 ** nFilename must be the length of zFilename. When negative, strlen() will
2462 ** be used to calculate it.
2463 */
2464 int file_is_reserved_name(const char *zFilename, int nFilename){
2465 const char *zEnd; /* one-after-the-end of zFilename */
2466 int gotSuffix = 0; /* length of suffix (-wal, -shm, -journal) */
2467
2468 assert( zFilename && "API misuse" );
2469 if( nFilename<0 ) nFilename = (int)strlen(zFilename);
2470 if( nFilename<8 ) return 0; /* strlen("_FOSSIL_") */
2471 zEnd = zFilename + nFilename;
2472 if( nFilename>=12 ){ /* strlen("_FOSSIL_-(shm|wal)") */
2473 /* Check for (-wal, -shm, -journal) suffixes, with an eye towards
2474 ** runtime speed. */
2475 if( zEnd[-4]=='-' ){
2476 if( fossil_strnicmp("wal", &zEnd[-3], 3)
2477 && fossil_strnicmp("shm", &zEnd[-3], 3) ){
2478 return 0;
2479 }
2480 gotSuffix = 4;
2481 }else if( nFilename>=16 && zEnd[-8]=='-' ){ /*strlen(_FOSSIL_-journal) */
2482 if( fossil_strnicmp("journal", &zEnd[-7], 7) ) return 0;
2483 gotSuffix = 8;
2484 }
2485 if( gotSuffix ){
2486 assert( 4==gotSuffix || 8==gotSuffix );
2487 zEnd -= gotSuffix;
2488 nFilename -= gotSuffix;
2489 gotSuffix = 1;
2490 }
2491 assert( nFilename>=8 && "strlen(_FOSSIL_)" );
2492 assert( gotSuffix==0 || gotSuffix==1 );
2493 }
2494 switch( zEnd[-1] ){
2495 case '_':{
2496 if( fossil_strnicmp("_FOSSIL_", &zEnd[-8], 8) ) return 0;
2497 if( 8==nFilename ) return 1;
2498 return zEnd[-9]=='/' ? 2 : gotSuffix;
2499 }
2500 case 'T':
2501 case 't':{
2502 if( nFilename<9 || zEnd[-9]!='.'
2503 || fossil_strnicmp(".fslckout", &zEnd[-9], 9) ){
2504 return 0;
2505 }
2506 if( 9==nFilename ) return 1;
2507 return zEnd[-10]=='/' ? 2 : gotSuffix;
2508 }
2509 default:{
2510 return 0;
2511 }
2512 }
2513 }
2514
2515 /*
2516 ** COMMAND: test-is-reserved-name
2517 **
2518 ** Usage: %fossil test-is-ckout-db FILENAMES...
2519 **
2520 ** Passes each given name to file_is_reserved_name() and outputs one
2521 ** line per file: the result value of that function followed by the
2522 ** name.
2523 */
2524 void test_is_reserved_name_cmd(void){
2525 int i;
2526
2527 if(g.argc<3){
2528 usage("FILENAME_1 [...FILENAME_N]");
2529 }
2530 for( i = 2; i < g.argc; ++i ){
2531 const int check = file_is_reserved_name(g.argv[i], -1);
2532 fossil_print("%d %s\n", check, g.argv[i]);
2533 }
2534 }
2535
+134 -1
--- src/file.c
+++ src/file.c
@@ -323,10 +323,57 @@
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
+}
328375
329376
/*
330377
** Return 1 if zFilename is a directory. Return 0 if zFilename
331378
** does not exist. Return 2 if zFilename exists but is something
332379
** other than a directory.
@@ -570,11 +617,14 @@
570617
*/
571618
int file_setexe(const char *zFilename, int onoff){
572619
int rc = 0;
573620
#if !defined(_WIN32)
574621
struct stat buf;
575
- if( fossil_stat(zFilename, &buf, RepoFILE)!=0 || S_ISLNK(buf.st_mode) ){
622
+ if( fossil_stat(zFilename, &buf, RepoFILE)!=0
623
+ || S_ISLNK(buf.st_mode)
624
+ || S_ISDIR(buf.st_mode)
625
+ ){
576626
return 0;
577627
}
578628
if( onoff ){
579629
int targetMode = (buf.st_mode & 0444)>>2;
580630
if( (buf.st_mode & 0100)==0 ){
@@ -2397,5 +2447,88 @@
23972447
changeCount);
23982448
}else{
23992449
fossil_print("Touched %d file(s)\n", changeCount);
24002450
}
24012451
}
2452
+
2453
+/*
2454
+** Returns non-zero if the specified file name ends with any reserved name,
2455
+** e.g.: _FOSSIL_ or .fslckout. Specifically, it returns 1 for exact match
2456
+** or 2 for a tail match on a longer file name.
2457
+**
2458
+** For the sake of efficiency, zFilename must be a canonical name, e.g. an
2459
+** absolute path using only forward slash ('/') as a directory separator.
2460
+**
2461
+** nFilename must be the length of zFilename. When negative, strlen() will
2462
+** be used to calculate it.
2463
+*/
2464
+int file_is_reserved_name(const char *zFilename, int nFilename){
2465
+ const char *zEnd; /* one-after-the-end of zFilename */
2466
+ int gotSuffix = 0; /* length of suffix (-wal, -shm, -journal) */
2467
+
2468
+ assert( zFilename && "API misuse" );
2469
+ if( nFilename<0 ) nFilename = (int)strlen(zFilename);
2470
+ if( nFilename<8 ) return 0; /* strlen("_FOSSIL_") */
2471
+ zEnd = zFilename + nFilename;
2472
+ if( nFilename>=12 ){ /* strlen("_FOSSIL_-(shm|wal)") */
2473
+ /* Check for (-wal, -shm, -journal) suffixes, with an eye towards
2474
+ ** runtime speed. */
2475
+ if( zEnd[-4]=='-' ){
2476
+ if( fossil_strnicmp("wal", &zEnd[-3], 3)
2477
+ && fossil_strnicmp("shm", &zEnd[-3], 3) ){
2478
+ return 0;
2479
+ }
2480
+ gotSuffix = 4;
2481
+ }else if( nFilename>=16 && zEnd[-8]=='-' ){ /*strlen(_FOSSIL_-journal) */
2482
+ if( fossil_strnicmp("journal", &zEnd[-7], 7) ) return 0;
2483
+ gotSuffix = 8;
2484
+ }
2485
+ if( gotSuffix ){
2486
+ assert( 4==gotSuffix || 8==gotSuffix );
2487
+ zEnd -= gotSuffix;
2488
+ nFilename -= gotSuffix;
2489
+ gotSuffix = 1;
2490
+ }
2491
+ assert( nFilename>=8 && "strlen(_FOSSIL_)" );
2492
+ assert( gotSuffix==0 || gotSuffix==1 );
2493
+ }
2494
+ switch( zEnd[-1] ){
2495
+ case '_':{
2496
+ if( fossil_strnicmp("_FOSSIL_", &zEnd[-8], 8) ) return 0;
2497
+ if( 8==nFilename ) return 1;
2498
+ return zEnd[-9]=='/' ? 2 : gotSuffix;
2499
+ }
2500
+ case 'T':
2501
+ case 't':{
2502
+ if( nFilename<9 || zEnd[-9]!='.'
2503
+ || fossil_strnicmp(".fslckout", &zEnd[-9], 9) ){
2504
+ return 0;
2505
+ }
2506
+ if( 9==nFilename ) return 1;
2507
+ return zEnd[-10]=='/' ? 2 : gotSuffix;
2508
+ }
2509
+ default:{
2510
+ return 0;
2511
+ }
2512
+ }
2513
+}
2514
+
2515
+/*
2516
+** COMMAND: test-is-reserved-name
2517
+**
2518
+** Usage: %fossil test-is-ckout-db FILENAMES...
2519
+**
2520
+** Passes each given name to file_is_reserved_name() and outputs one
2521
+** line per file: the result value of that function followed by the
2522
+** name.
2523
+*/
2524
+void test_is_reserved_name_cmd(void){
2525
+ int i;
2526
+
2527
+ if(g.argc<3){
2528
+ usage("FILENAME_1 [...FILENAME_N]");
2529
+ }
2530
+ for( i = 2; i < g.argc; ++i ){
2531
+ const int check = file_is_reserved_name(g.argv[i], -1);
2532
+ fossil_print("%d %s\n", check, g.argv[i]);
2533
+ }
2534
+}
24022535
--- src/file.c
+++ src/file.c
@@ -323,10 +323,57 @@
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.
@@ -570,11 +617,14 @@
570 */
571 int file_setexe(const char *zFilename, int onoff){
572 int rc = 0;
573 #if !defined(_WIN32)
574 struct stat buf;
575 if( fossil_stat(zFilename, &buf, RepoFILE)!=0 || S_ISLNK(buf.st_mode) ){
 
 
 
576 return 0;
577 }
578 if( onoff ){
579 int targetMode = (buf.st_mode & 0444)>>2;
580 if( (buf.st_mode & 0100)==0 ){
@@ -2397,5 +2447,88 @@
2397 changeCount);
2398 }else{
2399 fossil_print("Touched %d file(s)\n", changeCount);
2400 }
2401 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2402
--- src/file.c
+++ src/file.c
@@ -323,10 +323,57 @@
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 ** Return 1 if zFilename is a directory. Return 0 if zFilename
378 ** does not exist. Return 2 if zFilename exists but is something
379 ** other than a directory.
@@ -570,11 +617,14 @@
617 */
618 int file_setexe(const char *zFilename, int onoff){
619 int rc = 0;
620 #if !defined(_WIN32)
621 struct stat buf;
622 if( fossil_stat(zFilename, &buf, RepoFILE)!=0
623 || S_ISLNK(buf.st_mode)
624 || S_ISDIR(buf.st_mode)
625 ){
626 return 0;
627 }
628 if( onoff ){
629 int targetMode = (buf.st_mode & 0444)>>2;
630 if( (buf.st_mode & 0100)==0 ){
@@ -2397,5 +2447,88 @@
2447 changeCount);
2448 }else{
2449 fossil_print("Touched %d file(s)\n", changeCount);
2450 }
2451 }
2452
2453 /*
2454 ** Returns non-zero if the specified file name ends with any reserved name,
2455 ** e.g.: _FOSSIL_ or .fslckout. Specifically, it returns 1 for exact match
2456 ** or 2 for a tail match on a longer file name.
2457 **
2458 ** For the sake of efficiency, zFilename must be a canonical name, e.g. an
2459 ** absolute path using only forward slash ('/') as a directory separator.
2460 **
2461 ** nFilename must be the length of zFilename. When negative, strlen() will
2462 ** be used to calculate it.
2463 */
2464 int file_is_reserved_name(const char *zFilename, int nFilename){
2465 const char *zEnd; /* one-after-the-end of zFilename */
2466 int gotSuffix = 0; /* length of suffix (-wal, -shm, -journal) */
2467
2468 assert( zFilename && "API misuse" );
2469 if( nFilename<0 ) nFilename = (int)strlen(zFilename);
2470 if( nFilename<8 ) return 0; /* strlen("_FOSSIL_") */
2471 zEnd = zFilename + nFilename;
2472 if( nFilename>=12 ){ /* strlen("_FOSSIL_-(shm|wal)") */
2473 /* Check for (-wal, -shm, -journal) suffixes, with an eye towards
2474 ** runtime speed. */
2475 if( zEnd[-4]=='-' ){
2476 if( fossil_strnicmp("wal", &zEnd[-3], 3)
2477 && fossil_strnicmp("shm", &zEnd[-3], 3) ){
2478 return 0;
2479 }
2480 gotSuffix = 4;
2481 }else if( nFilename>=16 && zEnd[-8]=='-' ){ /*strlen(_FOSSIL_-journal) */
2482 if( fossil_strnicmp("journal", &zEnd[-7], 7) ) return 0;
2483 gotSuffix = 8;
2484 }
2485 if( gotSuffix ){
2486 assert( 4==gotSuffix || 8==gotSuffix );
2487 zEnd -= gotSuffix;
2488 nFilename -= gotSuffix;
2489 gotSuffix = 1;
2490 }
2491 assert( nFilename>=8 && "strlen(_FOSSIL_)" );
2492 assert( gotSuffix==0 || gotSuffix==1 );
2493 }
2494 switch( zEnd[-1] ){
2495 case '_':{
2496 if( fossil_strnicmp("_FOSSIL_", &zEnd[-8], 8) ) return 0;
2497 if( 8==nFilename ) return 1;
2498 return zEnd[-9]=='/' ? 2 : gotSuffix;
2499 }
2500 case 'T':
2501 case 't':{
2502 if( nFilename<9 || zEnd[-9]!='.'
2503 || fossil_strnicmp(".fslckout", &zEnd[-9], 9) ){
2504 return 0;
2505 }
2506 if( 9==nFilename ) return 1;
2507 return zEnd[-10]=='/' ? 2 : gotSuffix;
2508 }
2509 default:{
2510 return 0;
2511 }
2512 }
2513 }
2514
2515 /*
2516 ** COMMAND: test-is-reserved-name
2517 **
2518 ** Usage: %fossil test-is-ckout-db FILENAMES...
2519 **
2520 ** Passes each given name to file_is_reserved_name() and outputs one
2521 ** line per file: the result value of that function followed by the
2522 ** name.
2523 */
2524 void test_is_reserved_name_cmd(void){
2525 int i;
2526
2527 if(g.argc<3){
2528 usage("FILENAME_1 [...FILENAME_N]");
2529 }
2530 for( i = 2; i < g.argc; ++i ){
2531 const int check = file_is_reserved_name(g.argv[i], -1);
2532 fossil_print("%d %s\n", check, g.argv[i]);
2533 }
2534 }
2535
+134 -1
--- src/file.c
+++ src/file.c
@@ -323,10 +323,57 @@
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
+}
328375
329376
/*
330377
** Return 1 if zFilename is a directory. Return 0 if zFilename
331378
** does not exist. Return 2 if zFilename exists but is something
332379
** other than a directory.
@@ -570,11 +617,14 @@
570617
*/
571618
int file_setexe(const char *zFilename, int onoff){
572619
int rc = 0;
573620
#if !defined(_WIN32)
574621
struct stat buf;
575
- if( fossil_stat(zFilename, &buf, RepoFILE)!=0 || S_ISLNK(buf.st_mode) ){
622
+ if( fossil_stat(zFilename, &buf, RepoFILE)!=0
623
+ || S_ISLNK(buf.st_mode)
624
+ || S_ISDIR(buf.st_mode)
625
+ ){
576626
return 0;
577627
}
578628
if( onoff ){
579629
int targetMode = (buf.st_mode & 0444)>>2;
580630
if( (buf.st_mode & 0100)==0 ){
@@ -2397,5 +2447,88 @@
23972447
changeCount);
23982448
}else{
23992449
fossil_print("Touched %d file(s)\n", changeCount);
24002450
}
24012451
}
2452
+
2453
+/*
2454
+** Returns non-zero if the specified file name ends with any reserved name,
2455
+** e.g.: _FOSSIL_ or .fslckout. Specifically, it returns 1 for exact match
2456
+** or 2 for a tail match on a longer file name.
2457
+**
2458
+** For the sake of efficiency, zFilename must be a canonical name, e.g. an
2459
+** absolute path using only forward slash ('/') as a directory separator.
2460
+**
2461
+** nFilename must be the length of zFilename. When negative, strlen() will
2462
+** be used to calculate it.
2463
+*/
2464
+int file_is_reserved_name(const char *zFilename, int nFilename){
2465
+ const char *zEnd; /* one-after-the-end of zFilename */
2466
+ int gotSuffix = 0; /* length of suffix (-wal, -shm, -journal) */
2467
+
2468
+ assert( zFilename && "API misuse" );
2469
+ if( nFilename<0 ) nFilename = (int)strlen(zFilename);
2470
+ if( nFilename<8 ) return 0; /* strlen("_FOSSIL_") */
2471
+ zEnd = zFilename + nFilename;
2472
+ if( nFilename>=12 ){ /* strlen("_FOSSIL_-(shm|wal)") */
2473
+ /* Check for (-wal, -shm, -journal) suffixes, with an eye towards
2474
+ ** runtime speed. */
2475
+ if( zEnd[-4]=='-' ){
2476
+ if( fossil_strnicmp("wal", &zEnd[-3], 3)
2477
+ && fossil_strnicmp("shm", &zEnd[-3], 3) ){
2478
+ return 0;
2479
+ }
2480
+ gotSuffix = 4;
2481
+ }else if( nFilename>=16 && zEnd[-8]=='-' ){ /*strlen(_FOSSIL_-journal) */
2482
+ if( fossil_strnicmp("journal", &zEnd[-7], 7) ) return 0;
2483
+ gotSuffix = 8;
2484
+ }
2485
+ if( gotSuffix ){
2486
+ assert( 4==gotSuffix || 8==gotSuffix );
2487
+ zEnd -= gotSuffix;
2488
+ nFilename -= gotSuffix;
2489
+ gotSuffix = 1;
2490
+ }
2491
+ assert( nFilename>=8 && "strlen(_FOSSIL_)" );
2492
+ assert( gotSuffix==0 || gotSuffix==1 );
2493
+ }
2494
+ switch( zEnd[-1] ){
2495
+ case '_':{
2496
+ if( fossil_strnicmp("_FOSSIL_", &zEnd[-8], 8) ) return 0;
2497
+ if( 8==nFilename ) return 1;
2498
+ return zEnd[-9]=='/' ? 2 : gotSuffix;
2499
+ }
2500
+ case 'T':
2501
+ case 't':{
2502
+ if( nFilename<9 || zEnd[-9]!='.'
2503
+ || fossil_strnicmp(".fslckout", &zEnd[-9], 9) ){
2504
+ return 0;
2505
+ }
2506
+ if( 9==nFilename ) return 1;
2507
+ return zEnd[-10]=='/' ? 2 : gotSuffix;
2508
+ }
2509
+ default:{
2510
+ return 0;
2511
+ }
2512
+ }
2513
+}
2514
+
2515
+/*
2516
+** COMMAND: test-is-reserved-name
2517
+**
2518
+** Usage: %fossil test-is-ckout-db FILENAMES...
2519
+**
2520
+** Passes each given name to file_is_reserved_name() and outputs one
2521
+** line per file: the result value of that function followed by the
2522
+** name.
2523
+*/
2524
+void test_is_reserved_name_cmd(void){
2525
+ int i;
2526
+
2527
+ if(g.argc<3){
2528
+ usage("FILENAME_1 [...FILENAME_N]");
2529
+ }
2530
+ for( i = 2; i < g.argc; ++i ){
2531
+ const int check = file_is_reserved_name(g.argv[i], -1);
2532
+ fossil_print("%d %s\n", check, g.argv[i]);
2533
+ }
2534
+}
24022535
--- src/file.c
+++ src/file.c
@@ -323,10 +323,57 @@
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.
@@ -570,11 +617,14 @@
570 */
571 int file_setexe(const char *zFilename, int onoff){
572 int rc = 0;
573 #if !defined(_WIN32)
574 struct stat buf;
575 if( fossil_stat(zFilename, &buf, RepoFILE)!=0 || S_ISLNK(buf.st_mode) ){
 
 
 
576 return 0;
577 }
578 if( onoff ){
579 int targetMode = (buf.st_mode & 0444)>>2;
580 if( (buf.st_mode & 0100)==0 ){
@@ -2397,5 +2447,88 @@
2397 changeCount);
2398 }else{
2399 fossil_print("Touched %d file(s)\n", changeCount);
2400 }
2401 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2402
--- src/file.c
+++ src/file.c
@@ -323,10 +323,57 @@
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 ** Return 1 if zFilename is a directory. Return 0 if zFilename
378 ** does not exist. Return 2 if zFilename exists but is something
379 ** other than a directory.
@@ -570,11 +617,14 @@
617 */
618 int file_setexe(const char *zFilename, int onoff){
619 int rc = 0;
620 #if !defined(_WIN32)
621 struct stat buf;
622 if( fossil_stat(zFilename, &buf, RepoFILE)!=0
623 || S_ISLNK(buf.st_mode)
624 || S_ISDIR(buf.st_mode)
625 ){
626 return 0;
627 }
628 if( onoff ){
629 int targetMode = (buf.st_mode & 0444)>>2;
630 if( (buf.st_mode & 0100)==0 ){
@@ -2397,5 +2447,88 @@
2447 changeCount);
2448 }else{
2449 fossil_print("Touched %d file(s)\n", changeCount);
2450 }
2451 }
2452
2453 /*
2454 ** Returns non-zero if the specified file name ends with any reserved name,
2455 ** e.g.: _FOSSIL_ or .fslckout. Specifically, it returns 1 for exact match
2456 ** or 2 for a tail match on a longer file name.
2457 **
2458 ** For the sake of efficiency, zFilename must be a canonical name, e.g. an
2459 ** absolute path using only forward slash ('/') as a directory separator.
2460 **
2461 ** nFilename must be the length of zFilename. When negative, strlen() will
2462 ** be used to calculate it.
2463 */
2464 int file_is_reserved_name(const char *zFilename, int nFilename){
2465 const char *zEnd; /* one-after-the-end of zFilename */
2466 int gotSuffix = 0; /* length of suffix (-wal, -shm, -journal) */
2467
2468 assert( zFilename && "API misuse" );
2469 if( nFilename<0 ) nFilename = (int)strlen(zFilename);
2470 if( nFilename<8 ) return 0; /* strlen("_FOSSIL_") */
2471 zEnd = zFilename + nFilename;
2472 if( nFilename>=12 ){ /* strlen("_FOSSIL_-(shm|wal)") */
2473 /* Check for (-wal, -shm, -journal) suffixes, with an eye towards
2474 ** runtime speed. */
2475 if( zEnd[-4]=='-' ){
2476 if( fossil_strnicmp("wal", &zEnd[-3], 3)
2477 && fossil_strnicmp("shm", &zEnd[-3], 3) ){
2478 return 0;
2479 }
2480 gotSuffix = 4;
2481 }else if( nFilename>=16 && zEnd[-8]=='-' ){ /*strlen(_FOSSIL_-journal) */
2482 if( fossil_strnicmp("journal", &zEnd[-7], 7) ) return 0;
2483 gotSuffix = 8;
2484 }
2485 if( gotSuffix ){
2486 assert( 4==gotSuffix || 8==gotSuffix );
2487 zEnd -= gotSuffix;
2488 nFilename -= gotSuffix;
2489 gotSuffix = 1;
2490 }
2491 assert( nFilename>=8 && "strlen(_FOSSIL_)" );
2492 assert( gotSuffix==0 || gotSuffix==1 );
2493 }
2494 switch( zEnd[-1] ){
2495 case '_':{
2496 if( fossil_strnicmp("_FOSSIL_", &zEnd[-8], 8) ) return 0;
2497 if( 8==nFilename ) return 1;
2498 return zEnd[-9]=='/' ? 2 : gotSuffix;
2499 }
2500 case 'T':
2501 case 't':{
2502 if( nFilename<9 || zEnd[-9]!='.'
2503 || fossil_strnicmp(".fslckout", &zEnd[-9], 9) ){
2504 return 0;
2505 }
2506 if( 9==nFilename ) return 1;
2507 return zEnd[-10]=='/' ? 2 : gotSuffix;
2508 }
2509 default:{
2510 return 0;
2511 }
2512 }
2513 }
2514
2515 /*
2516 ** COMMAND: test-is-reserved-name
2517 **
2518 ** Usage: %fossil test-is-ckout-db FILENAMES...
2519 **
2520 ** Passes each given name to file_is_reserved_name() and outputs one
2521 ** line per file: the result value of that function followed by the
2522 ** name.
2523 */
2524 void test_is_reserved_name_cmd(void){
2525 int i;
2526
2527 if(g.argc<3){
2528 usage("FILENAME_1 [...FILENAME_N]");
2529 }
2530 for( i = 2; i < g.argc; ++i ){
2531 const int check = file_is_reserved_name(g.argv[i], -1);
2532 fossil_print("%d %s\n", check, g.argv[i]);
2533 }
2534 }
2535
+134 -1
--- src/file.c
+++ src/file.c
@@ -323,10 +323,57 @@
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
+}
328375
329376
/*
330377
** Return 1 if zFilename is a directory. Return 0 if zFilename
331378
** does not exist. Return 2 if zFilename exists but is something
332379
** other than a directory.
@@ -570,11 +617,14 @@
570617
*/
571618
int file_setexe(const char *zFilename, int onoff){
572619
int rc = 0;
573620
#if !defined(_WIN32)
574621
struct stat buf;
575
- if( fossil_stat(zFilename, &buf, RepoFILE)!=0 || S_ISLNK(buf.st_mode) ){
622
+ if( fossil_stat(zFilename, &buf, RepoFILE)!=0
623
+ || S_ISLNK(buf.st_mode)
624
+ || S_ISDIR(buf.st_mode)
625
+ ){
576626
return 0;
577627
}
578628
if( onoff ){
579629
int targetMode = (buf.st_mode & 0444)>>2;
580630
if( (buf.st_mode & 0100)==0 ){
@@ -2397,5 +2447,88 @@
23972447
changeCount);
23982448
}else{
23992449
fossil_print("Touched %d file(s)\n", changeCount);
24002450
}
24012451
}
2452
+
2453
+/*
2454
+** Returns non-zero if the specified file name ends with any reserved name,
2455
+** e.g.: _FOSSIL_ or .fslckout. Specifically, it returns 1 for exact match
2456
+** or 2 for a tail match on a longer file name.
2457
+**
2458
+** For the sake of efficiency, zFilename must be a canonical name, e.g. an
2459
+** absolute path using only forward slash ('/') as a directory separator.
2460
+**
2461
+** nFilename must be the length of zFilename. When negative, strlen() will
2462
+** be used to calculate it.
2463
+*/
2464
+int file_is_reserved_name(const char *zFilename, int nFilename){
2465
+ const char *zEnd; /* one-after-the-end of zFilename */
2466
+ int gotSuffix = 0; /* length of suffix (-wal, -shm, -journal) */
2467
+
2468
+ assert( zFilename && "API misuse" );
2469
+ if( nFilename<0 ) nFilename = (int)strlen(zFilename);
2470
+ if( nFilename<8 ) return 0; /* strlen("_FOSSIL_") */
2471
+ zEnd = zFilename + nFilename;
2472
+ if( nFilename>=12 ){ /* strlen("_FOSSIL_-(shm|wal)") */
2473
+ /* Check for (-wal, -shm, -journal) suffixes, with an eye towards
2474
+ ** runtime speed. */
2475
+ if( zEnd[-4]=='-' ){
2476
+ if( fossil_strnicmp("wal", &zEnd[-3], 3)
2477
+ && fossil_strnicmp("shm", &zEnd[-3], 3) ){
2478
+ return 0;
2479
+ }
2480
+ gotSuffix = 4;
2481
+ }else if( nFilename>=16 && zEnd[-8]=='-' ){ /*strlen(_FOSSIL_-journal) */
2482
+ if( fossil_strnicmp("journal", &zEnd[-7], 7) ) return 0;
2483
+ gotSuffix = 8;
2484
+ }
2485
+ if( gotSuffix ){
2486
+ assert( 4==gotSuffix || 8==gotSuffix );
2487
+ zEnd -= gotSuffix;
2488
+ nFilename -= gotSuffix;
2489
+ gotSuffix = 1;
2490
+ }
2491
+ assert( nFilename>=8 && "strlen(_FOSSIL_)" );
2492
+ assert( gotSuffix==0 || gotSuffix==1 );
2493
+ }
2494
+ switch( zEnd[-1] ){
2495
+ case '_':{
2496
+ if( fossil_strnicmp("_FOSSIL_", &zEnd[-8], 8) ) return 0;
2497
+ if( 8==nFilename ) return 1;
2498
+ return zEnd[-9]=='/' ? 2 : gotSuffix;
2499
+ }
2500
+ case 'T':
2501
+ case 't':{
2502
+ if( nFilename<9 || zEnd[-9]!='.'
2503
+ || fossil_strnicmp(".fslckout", &zEnd[-9], 9) ){
2504
+ return 0;
2505
+ }
2506
+ if( 9==nFilename ) return 1;
2507
+ return zEnd[-10]=='/' ? 2 : gotSuffix;
2508
+ }
2509
+ default:{
2510
+ return 0;
2511
+ }
2512
+ }
2513
+}
2514
+
2515
+/*
2516
+** COMMAND: test-is-reserved-name
2517
+**
2518
+** Usage: %fossil test-is-ckout-db FILENAMES...
2519
+**
2520
+** Passes each given name to file_is_reserved_name() and outputs one
2521
+** line per file: the result value of that function followed by the
2522
+** name.
2523
+*/
2524
+void test_is_reserved_name_cmd(void){
2525
+ int i;
2526
+
2527
+ if(g.argc<3){
2528
+ usage("FILENAME_1 [...FILENAME_N]");
2529
+ }
2530
+ for( i = 2; i < g.argc; ++i ){
2531
+ const int check = file_is_reserved_name(g.argv[i], -1);
2532
+ fossil_print("%d %s\n", check, g.argv[i]);
2533
+ }
2534
+}
24022535
--- src/file.c
+++ src/file.c
@@ -323,10 +323,57 @@
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.
@@ -570,11 +617,14 @@
570 */
571 int file_setexe(const char *zFilename, int onoff){
572 int rc = 0;
573 #if !defined(_WIN32)
574 struct stat buf;
575 if( fossil_stat(zFilename, &buf, RepoFILE)!=0 || S_ISLNK(buf.st_mode) ){
 
 
 
576 return 0;
577 }
578 if( onoff ){
579 int targetMode = (buf.st_mode & 0444)>>2;
580 if( (buf.st_mode & 0100)==0 ){
@@ -2397,5 +2447,88 @@
2397 changeCount);
2398 }else{
2399 fossil_print("Touched %d file(s)\n", changeCount);
2400 }
2401 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2402
--- src/file.c
+++ src/file.c
@@ -323,10 +323,57 @@
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 ** Return 1 if zFilename is a directory. Return 0 if zFilename
378 ** does not exist. Return 2 if zFilename exists but is something
379 ** other than a directory.
@@ -570,11 +617,14 @@
617 */
618 int file_setexe(const char *zFilename, int onoff){
619 int rc = 0;
620 #if !defined(_WIN32)
621 struct stat buf;
622 if( fossil_stat(zFilename, &buf, RepoFILE)!=0
623 || S_ISLNK(buf.st_mode)
624 || S_ISDIR(buf.st_mode)
625 ){
626 return 0;
627 }
628 if( onoff ){
629 int targetMode = (buf.st_mode & 0444)>>2;
630 if( (buf.st_mode & 0100)==0 ){
@@ -2397,5 +2447,88 @@
2447 changeCount);
2448 }else{
2449 fossil_print("Touched %d file(s)\n", changeCount);
2450 }
2451 }
2452
2453 /*
2454 ** Returns non-zero if the specified file name ends with any reserved name,
2455 ** e.g.: _FOSSIL_ or .fslckout. Specifically, it returns 1 for exact match
2456 ** or 2 for a tail match on a longer file name.
2457 **
2458 ** For the sake of efficiency, zFilename must be a canonical name, e.g. an
2459 ** absolute path using only forward slash ('/') as a directory separator.
2460 **
2461 ** nFilename must be the length of zFilename. When negative, strlen() will
2462 ** be used to calculate it.
2463 */
2464 int file_is_reserved_name(const char *zFilename, int nFilename){
2465 const char *zEnd; /* one-after-the-end of zFilename */
2466 int gotSuffix = 0; /* length of suffix (-wal, -shm, -journal) */
2467
2468 assert( zFilename && "API misuse" );
2469 if( nFilename<0 ) nFilename = (int)strlen(zFilename);
2470 if( nFilename<8 ) return 0; /* strlen("_FOSSIL_") */
2471 zEnd = zFilename + nFilename;
2472 if( nFilename>=12 ){ /* strlen("_FOSSIL_-(shm|wal)") */
2473 /* Check for (-wal, -shm, -journal) suffixes, with an eye towards
2474 ** runtime speed. */
2475 if( zEnd[-4]=='-' ){
2476 if( fossil_strnicmp("wal", &zEnd[-3], 3)
2477 && fossil_strnicmp("shm", &zEnd[-3], 3) ){
2478 return 0;
2479 }
2480 gotSuffix = 4;
2481 }else if( nFilename>=16 && zEnd[-8]=='-' ){ /*strlen(_FOSSIL_-journal) */
2482 if( fossil_strnicmp("journal", &zEnd[-7], 7) ) return 0;
2483 gotSuffix = 8;
2484 }
2485 if( gotSuffix ){
2486 assert( 4==gotSuffix || 8==gotSuffix );
2487 zEnd -= gotSuffix;
2488 nFilename -= gotSuffix;
2489 gotSuffix = 1;
2490 }
2491 assert( nFilename>=8 && "strlen(_FOSSIL_)" );
2492 assert( gotSuffix==0 || gotSuffix==1 );
2493 }
2494 switch( zEnd[-1] ){
2495 case '_':{
2496 if( fossil_strnicmp("_FOSSIL_", &zEnd[-8], 8) ) return 0;
2497 if( 8==nFilename ) return 1;
2498 return zEnd[-9]=='/' ? 2 : gotSuffix;
2499 }
2500 case 'T':
2501 case 't':{
2502 if( nFilename<9 || zEnd[-9]!='.'
2503 || fossil_strnicmp(".fslckout", &zEnd[-9], 9) ){
2504 return 0;
2505 }
2506 if( 9==nFilename ) return 1;
2507 return zEnd[-10]=='/' ? 2 : gotSuffix;
2508 }
2509 default:{
2510 return 0;
2511 }
2512 }
2513 }
2514
2515 /*
2516 ** COMMAND: test-is-reserved-name
2517 **
2518 ** Usage: %fossil test-is-ckout-db FILENAMES...
2519 **
2520 ** Passes each given name to file_is_reserved_name() and outputs one
2521 ** line per file: the result value of that function followed by the
2522 ** name.
2523 */
2524 void test_is_reserved_name_cmd(void){
2525 int i;
2526
2527 if(g.argc<3){
2528 usage("FILENAME_1 [...FILENAME_N]");
2529 }
2530 for( i = 2; i < g.argc; ++i ){
2531 const int check = file_is_reserved_name(g.argv[i], -1);
2532 fossil_print("%d %s\n", check, g.argv[i]);
2533 }
2534 }
2535
+134 -1
--- src/file.c
+++ src/file.c
@@ -323,10 +323,57 @@
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
+}
328375
329376
/*
330377
** Return 1 if zFilename is a directory. Return 0 if zFilename
331378
** does not exist. Return 2 if zFilename exists but is something
332379
** other than a directory.
@@ -570,11 +617,14 @@
570617
*/
571618
int file_setexe(const char *zFilename, int onoff){
572619
int rc = 0;
573620
#if !defined(_WIN32)
574621
struct stat buf;
575
- if( fossil_stat(zFilename, &buf, RepoFILE)!=0 || S_ISLNK(buf.st_mode) ){
622
+ if( fossil_stat(zFilename, &buf, RepoFILE)!=0
623
+ || S_ISLNK(buf.st_mode)
624
+ || S_ISDIR(buf.st_mode)
625
+ ){
576626
return 0;
577627
}
578628
if( onoff ){
579629
int targetMode = (buf.st_mode & 0444)>>2;
580630
if( (buf.st_mode & 0100)==0 ){
@@ -2397,5 +2447,88 @@
23972447
changeCount);
23982448
}else{
23992449
fossil_print("Touched %d file(s)\n", changeCount);
24002450
}
24012451
}
2452
+
2453
+/*
2454
+** Returns non-zero if the specified file name ends with any reserved name,
2455
+** e.g.: _FOSSIL_ or .fslckout. Specifically, it returns 1 for exact match
2456
+** or 2 for a tail match on a longer file name.
2457
+**
2458
+** For the sake of efficiency, zFilename must be a canonical name, e.g. an
2459
+** absolute path using only forward slash ('/') as a directory separator.
2460
+**
2461
+** nFilename must be the length of zFilename. When negative, strlen() will
2462
+** be used to calculate it.
2463
+*/
2464
+int file_is_reserved_name(const char *zFilename, int nFilename){
2465
+ const char *zEnd; /* one-after-the-end of zFilename */
2466
+ int gotSuffix = 0; /* length of suffix (-wal, -shm, -journal) */
2467
+
2468
+ assert( zFilename && "API misuse" );
2469
+ if( nFilename<0 ) nFilename = (int)strlen(zFilename);
2470
+ if( nFilename<8 ) return 0; /* strlen("_FOSSIL_") */
2471
+ zEnd = zFilename + nFilename;
2472
+ if( nFilename>=12 ){ /* strlen("_FOSSIL_-(shm|wal)") */
2473
+ /* Check for (-wal, -shm, -journal) suffixes, with an eye towards
2474
+ ** runtime speed. */
2475
+ if( zEnd[-4]=='-' ){
2476
+ if( fossil_strnicmp("wal", &zEnd[-3], 3)
2477
+ && fossil_strnicmp("shm", &zEnd[-3], 3) ){
2478
+ return 0;
2479
+ }
2480
+ gotSuffix = 4;
2481
+ }else if( nFilename>=16 && zEnd[-8]=='-' ){ /*strlen(_FOSSIL_-journal) */
2482
+ if( fossil_strnicmp("journal", &zEnd[-7], 7) ) return 0;
2483
+ gotSuffix = 8;
2484
+ }
2485
+ if( gotSuffix ){
2486
+ assert( 4==gotSuffix || 8==gotSuffix );
2487
+ zEnd -= gotSuffix;
2488
+ nFilename -= gotSuffix;
2489
+ gotSuffix = 1;
2490
+ }
2491
+ assert( nFilename>=8 && "strlen(_FOSSIL_)" );
2492
+ assert( gotSuffix==0 || gotSuffix==1 );
2493
+ }
2494
+ switch( zEnd[-1] ){
2495
+ case '_':{
2496
+ if( fossil_strnicmp("_FOSSIL_", &zEnd[-8], 8) ) return 0;
2497
+ if( 8==nFilename ) return 1;
2498
+ return zEnd[-9]=='/' ? 2 : gotSuffix;
2499
+ }
2500
+ case 'T':
2501
+ case 't':{
2502
+ if( nFilename<9 || zEnd[-9]!='.'
2503
+ || fossil_strnicmp(".fslckout", &zEnd[-9], 9) ){
2504
+ return 0;
2505
+ }
2506
+ if( 9==nFilename ) return 1;
2507
+ return zEnd[-10]=='/' ? 2 : gotSuffix;
2508
+ }
2509
+ default:{
2510
+ return 0;
2511
+ }
2512
+ }
2513
+}
2514
+
2515
+/*
2516
+** COMMAND: test-is-reserved-name
2517
+**
2518
+** Usage: %fossil test-is-ckout-db FILENAMES...
2519
+**
2520
+** Passes each given name to file_is_reserved_name() and outputs one
2521
+** line per file: the result value of that function followed by the
2522
+** name.
2523
+*/
2524
+void test_is_reserved_name_cmd(void){
2525
+ int i;
2526
+
2527
+ if(g.argc<3){
2528
+ usage("FILENAME_1 [...FILENAME_N]");
2529
+ }
2530
+ for( i = 2; i < g.argc; ++i ){
2531
+ const int check = file_is_reserved_name(g.argv[i], -1);
2532
+ fossil_print("%d %s\n", check, g.argv[i]);
2533
+ }
2534
+}
24022535
--- src/file.c
+++ src/file.c
@@ -323,10 +323,57 @@
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.
@@ -570,11 +617,14 @@
570 */
571 int file_setexe(const char *zFilename, int onoff){
572 int rc = 0;
573 #if !defined(_WIN32)
574 struct stat buf;
575 if( fossil_stat(zFilename, &buf, RepoFILE)!=0 || S_ISLNK(buf.st_mode) ){
 
 
 
576 return 0;
577 }
578 if( onoff ){
579 int targetMode = (buf.st_mode & 0444)>>2;
580 if( (buf.st_mode & 0100)==0 ){
@@ -2397,5 +2447,88 @@
2397 changeCount);
2398 }else{
2399 fossil_print("Touched %d file(s)\n", changeCount);
2400 }
2401 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2402
--- src/file.c
+++ src/file.c
@@ -323,10 +323,57 @@
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 ** Return 1 if zFilename is a directory. Return 0 if zFilename
378 ** does not exist. Return 2 if zFilename exists but is something
379 ** other than a directory.
@@ -570,11 +617,14 @@
617 */
618 int file_setexe(const char *zFilename, int onoff){
619 int rc = 0;
620 #if !defined(_WIN32)
621 struct stat buf;
622 if( fossil_stat(zFilename, &buf, RepoFILE)!=0
623 || S_ISLNK(buf.st_mode)
624 || S_ISDIR(buf.st_mode)
625 ){
626 return 0;
627 }
628 if( onoff ){
629 int targetMode = (buf.st_mode & 0444)>>2;
630 if( (buf.st_mode & 0100)==0 ){
@@ -2397,5 +2447,88 @@
2447 changeCount);
2448 }else{
2449 fossil_print("Touched %d file(s)\n", changeCount);
2450 }
2451 }
2452
2453 /*
2454 ** Returns non-zero if the specified file name ends with any reserved name,
2455 ** e.g.: _FOSSIL_ or .fslckout. Specifically, it returns 1 for exact match
2456 ** or 2 for a tail match on a longer file name.
2457 **
2458 ** For the sake of efficiency, zFilename must be a canonical name, e.g. an
2459 ** absolute path using only forward slash ('/') as a directory separator.
2460 **
2461 ** nFilename must be the length of zFilename. When negative, strlen() will
2462 ** be used to calculate it.
2463 */
2464 int file_is_reserved_name(const char *zFilename, int nFilename){
2465 const char *zEnd; /* one-after-the-end of zFilename */
2466 int gotSuffix = 0; /* length of suffix (-wal, -shm, -journal) */
2467
2468 assert( zFilename && "API misuse" );
2469 if( nFilename<0 ) nFilename = (int)strlen(zFilename);
2470 if( nFilename<8 ) return 0; /* strlen("_FOSSIL_") */
2471 zEnd = zFilename + nFilename;
2472 if( nFilename>=12 ){ /* strlen("_FOSSIL_-(shm|wal)") */
2473 /* Check for (-wal, -shm, -journal) suffixes, with an eye towards
2474 ** runtime speed. */
2475 if( zEnd[-4]=='-' ){
2476 if( fossil_strnicmp("wal", &zEnd[-3], 3)
2477 && fossil_strnicmp("shm", &zEnd[-3], 3) ){
2478 return 0;
2479 }
2480 gotSuffix = 4;
2481 }else if( nFilename>=16 && zEnd[-8]=='-' ){ /*strlen(_FOSSIL_-journal) */
2482 if( fossil_strnicmp("journal", &zEnd[-7], 7) ) return 0;
2483 gotSuffix = 8;
2484 }
2485 if( gotSuffix ){
2486 assert( 4==gotSuffix || 8==gotSuffix );
2487 zEnd -= gotSuffix;
2488 nFilename -= gotSuffix;
2489 gotSuffix = 1;
2490 }
2491 assert( nFilename>=8 && "strlen(_FOSSIL_)" );
2492 assert( gotSuffix==0 || gotSuffix==1 );
2493 }
2494 switch( zEnd[-1] ){
2495 case '_':{
2496 if( fossil_strnicmp("_FOSSIL_", &zEnd[-8], 8) ) return 0;
2497 if( 8==nFilename ) return 1;
2498 return zEnd[-9]=='/' ? 2 : gotSuffix;
2499 }
2500 case 'T':
2501 case 't':{
2502 if( nFilename<9 || zEnd[-9]!='.'
2503 || fossil_strnicmp(".fslckout", &zEnd[-9], 9) ){
2504 return 0;
2505 }
2506 if( 9==nFilename ) return 1;
2507 return zEnd[-10]=='/' ? 2 : gotSuffix;
2508 }
2509 default:{
2510 return 0;
2511 }
2512 }
2513 }
2514
2515 /*
2516 ** COMMAND: test-is-reserved-name
2517 **
2518 ** Usage: %fossil test-is-ckout-db FILENAMES...
2519 **
2520 ** Passes each given name to file_is_reserved_name() and outputs one
2521 ** line per file: the result value of that function followed by the
2522 ** name.
2523 */
2524 void test_is_reserved_name_cmd(void){
2525 int i;
2526
2527 if(g.argc<3){
2528 usage("FILENAME_1 [...FILENAME_N]");
2529 }
2530 for( i = 2; i < g.argc; ++i ){
2531 const int check = file_is_reserved_name(g.argv[i], -1);
2532 fossil_print("%d %s\n", check, g.argv[i]);
2533 }
2534 }
2535
+134 -1
--- src/file.c
+++ src/file.c
@@ -323,10 +323,57 @@
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
+}
328375
329376
/*
330377
** Return 1 if zFilename is a directory. Return 0 if zFilename
331378
** does not exist. Return 2 if zFilename exists but is something
332379
** other than a directory.
@@ -570,11 +617,14 @@
570617
*/
571618
int file_setexe(const char *zFilename, int onoff){
572619
int rc = 0;
573620
#if !defined(_WIN32)
574621
struct stat buf;
575
- if( fossil_stat(zFilename, &buf, RepoFILE)!=0 || S_ISLNK(buf.st_mode) ){
622
+ if( fossil_stat(zFilename, &buf, RepoFILE)!=0
623
+ || S_ISLNK(buf.st_mode)
624
+ || S_ISDIR(buf.st_mode)
625
+ ){
576626
return 0;
577627
}
578628
if( onoff ){
579629
int targetMode = (buf.st_mode & 0444)>>2;
580630
if( (buf.st_mode & 0100)==0 ){
@@ -2397,5 +2447,88 @@
23972447
changeCount);
23982448
}else{
23992449
fossil_print("Touched %d file(s)\n", changeCount);
24002450
}
24012451
}
2452
+
2453
+/*
2454
+** Returns non-zero if the specified file name ends with any reserved name,
2455
+** e.g.: _FOSSIL_ or .fslckout. Specifically, it returns 1 for exact match
2456
+** or 2 for a tail match on a longer file name.
2457
+**
2458
+** For the sake of efficiency, zFilename must be a canonical name, e.g. an
2459
+** absolute path using only forward slash ('/') as a directory separator.
2460
+**
2461
+** nFilename must be the length of zFilename. When negative, strlen() will
2462
+** be used to calculate it.
2463
+*/
2464
+int file_is_reserved_name(const char *zFilename, int nFilename){
2465
+ const char *zEnd; /* one-after-the-end of zFilename */
2466
+ int gotSuffix = 0; /* length of suffix (-wal, -shm, -journal) */
2467
+
2468
+ assert( zFilename && "API misuse" );
2469
+ if( nFilename<0 ) nFilename = (int)strlen(zFilename);
2470
+ if( nFilename<8 ) return 0; /* strlen("_FOSSIL_") */
2471
+ zEnd = zFilename + nFilename;
2472
+ if( nFilename>=12 ){ /* strlen("_FOSSIL_-(shm|wal)") */
2473
+ /* Check for (-wal, -shm, -journal) suffixes, with an eye towards
2474
+ ** runtime speed. */
2475
+ if( zEnd[-4]=='-' ){
2476
+ if( fossil_strnicmp("wal", &zEnd[-3], 3)
2477
+ && fossil_strnicmp("shm", &zEnd[-3], 3) ){
2478
+ return 0;
2479
+ }
2480
+ gotSuffix = 4;
2481
+ }else if( nFilename>=16 && zEnd[-8]=='-' ){ /*strlen(_FOSSIL_-journal) */
2482
+ if( fossil_strnicmp("journal", &zEnd[-7], 7) ) return 0;
2483
+ gotSuffix = 8;
2484
+ }
2485
+ if( gotSuffix ){
2486
+ assert( 4==gotSuffix || 8==gotSuffix );
2487
+ zEnd -= gotSuffix;
2488
+ nFilename -= gotSuffix;
2489
+ gotSuffix = 1;
2490
+ }
2491
+ assert( nFilename>=8 && "strlen(_FOSSIL_)" );
2492
+ assert( gotSuffix==0 || gotSuffix==1 );
2493
+ }
2494
+ switch( zEnd[-1] ){
2495
+ case '_':{
2496
+ if( fossil_strnicmp("_FOSSIL_", &zEnd[-8], 8) ) return 0;
2497
+ if( 8==nFilename ) return 1;
2498
+ return zEnd[-9]=='/' ? 2 : gotSuffix;
2499
+ }
2500
+ case 'T':
2501
+ case 't':{
2502
+ if( nFilename<9 || zEnd[-9]!='.'
2503
+ || fossil_strnicmp(".fslckout", &zEnd[-9], 9) ){
2504
+ return 0;
2505
+ }
2506
+ if( 9==nFilename ) return 1;
2507
+ return zEnd[-10]=='/' ? 2 : gotSuffix;
2508
+ }
2509
+ default:{
2510
+ return 0;
2511
+ }
2512
+ }
2513
+}
2514
+
2515
+/*
2516
+** COMMAND: test-is-reserved-name
2517
+**
2518
+** Usage: %fossil test-is-ckout-db FILENAMES...
2519
+**
2520
+** Passes each given name to file_is_reserved_name() and outputs one
2521
+** line per file: the result value of that function followed by the
2522
+** name.
2523
+*/
2524
+void test_is_reserved_name_cmd(void){
2525
+ int i;
2526
+
2527
+ if(g.argc<3){
2528
+ usage("FILENAME_1 [...FILENAME_N]");
2529
+ }
2530
+ for( i = 2; i < g.argc; ++i ){
2531
+ const int check = file_is_reserved_name(g.argv[i], -1);
2532
+ fossil_print("%d %s\n", check, g.argv[i]);
2533
+ }
2534
+}
24022535
--- src/file.c
+++ src/file.c
@@ -323,10 +323,57 @@
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.
@@ -570,11 +617,14 @@
570 */
571 int file_setexe(const char *zFilename, int onoff){
572 int rc = 0;
573 #if !defined(_WIN32)
574 struct stat buf;
575 if( fossil_stat(zFilename, &buf, RepoFILE)!=0 || S_ISLNK(buf.st_mode) ){
 
 
 
576 return 0;
577 }
578 if( onoff ){
579 int targetMode = (buf.st_mode & 0444)>>2;
580 if( (buf.st_mode & 0100)==0 ){
@@ -2397,5 +2447,88 @@
2397 changeCount);
2398 }else{
2399 fossil_print("Touched %d file(s)\n", changeCount);
2400 }
2401 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2402
--- src/file.c
+++ src/file.c
@@ -323,10 +323,57 @@
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 ** Return 1 if zFilename is a directory. Return 0 if zFilename
378 ** does not exist. Return 2 if zFilename exists but is something
379 ** other than a directory.
@@ -570,11 +617,14 @@
617 */
618 int file_setexe(const char *zFilename, int onoff){
619 int rc = 0;
620 #if !defined(_WIN32)
621 struct stat buf;
622 if( fossil_stat(zFilename, &buf, RepoFILE)!=0
623 || S_ISLNK(buf.st_mode)
624 || S_ISDIR(buf.st_mode)
625 ){
626 return 0;
627 }
628 if( onoff ){
629 int targetMode = (buf.st_mode & 0444)>>2;
630 if( (buf.st_mode & 0100)==0 ){
@@ -2397,5 +2447,88 @@
2447 changeCount);
2448 }else{
2449 fossil_print("Touched %d file(s)\n", changeCount);
2450 }
2451 }
2452
2453 /*
2454 ** Returns non-zero if the specified file name ends with any reserved name,
2455 ** e.g.: _FOSSIL_ or .fslckout. Specifically, it returns 1 for exact match
2456 ** or 2 for a tail match on a longer file name.
2457 **
2458 ** For the sake of efficiency, zFilename must be a canonical name, e.g. an
2459 ** absolute path using only forward slash ('/') as a directory separator.
2460 **
2461 ** nFilename must be the length of zFilename. When negative, strlen() will
2462 ** be used to calculate it.
2463 */
2464 int file_is_reserved_name(const char *zFilename, int nFilename){
2465 const char *zEnd; /* one-after-the-end of zFilename */
2466 int gotSuffix = 0; /* length of suffix (-wal, -shm, -journal) */
2467
2468 assert( zFilename && "API misuse" );
2469 if( nFilename<0 ) nFilename = (int)strlen(zFilename);
2470 if( nFilename<8 ) return 0; /* strlen("_FOSSIL_") */
2471 zEnd = zFilename + nFilename;
2472 if( nFilename>=12 ){ /* strlen("_FOSSIL_-(shm|wal)") */
2473 /* Check for (-wal, -shm, -journal) suffixes, with an eye towards
2474 ** runtime speed. */
2475 if( zEnd[-4]=='-' ){
2476 if( fossil_strnicmp("wal", &zEnd[-3], 3)
2477 && fossil_strnicmp("shm", &zEnd[-3], 3) ){
2478 return 0;
2479 }
2480 gotSuffix = 4;
2481 }else if( nFilename>=16 && zEnd[-8]=='-' ){ /*strlen(_FOSSIL_-journal) */
2482 if( fossil_strnicmp("journal", &zEnd[-7], 7) ) return 0;
2483 gotSuffix = 8;
2484 }
2485 if( gotSuffix ){
2486 assert( 4==gotSuffix || 8==gotSuffix );
2487 zEnd -= gotSuffix;
2488 nFilename -= gotSuffix;
2489 gotSuffix = 1;
2490 }
2491 assert( nFilename>=8 && "strlen(_FOSSIL_)" );
2492 assert( gotSuffix==0 || gotSuffix==1 );
2493 }
2494 switch( zEnd[-1] ){
2495 case '_':{
2496 if( fossil_strnicmp("_FOSSIL_", &zEnd[-8], 8) ) return 0;
2497 if( 8==nFilename ) return 1;
2498 return zEnd[-9]=='/' ? 2 : gotSuffix;
2499 }
2500 case 'T':
2501 case 't':{
2502 if( nFilename<9 || zEnd[-9]!='.'
2503 || fossil_strnicmp(".fslckout", &zEnd[-9], 9) ){
2504 return 0;
2505 }
2506 if( 9==nFilename ) return 1;
2507 return zEnd[-10]=='/' ? 2 : gotSuffix;
2508 }
2509 default:{
2510 return 0;
2511 }
2512 }
2513 }
2514
2515 /*
2516 ** COMMAND: test-is-reserved-name
2517 **
2518 ** Usage: %fossil test-is-ckout-db FILENAMES...
2519 **
2520 ** Passes each given name to file_is_reserved_name() and outputs one
2521 ** line per file: the result value of that function followed by the
2522 ** name.
2523 */
2524 void test_is_reserved_name_cmd(void){
2525 int i;
2526
2527 if(g.argc<3){
2528 usage("FILENAME_1 [...FILENAME_N]");
2529 }
2530 for( i = 2; i < g.argc; ++i ){
2531 const int check = file_is_reserved_name(g.argv[i], -1);
2532 fossil_print("%d %s\n", check, g.argv[i]);
2533 }
2534 }
2535
+134 -1
--- src/file.c
+++ src/file.c
@@ -323,10 +323,57 @@
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
+}
328375
329376
/*
330377
** Return 1 if zFilename is a directory. Return 0 if zFilename
331378
** does not exist. Return 2 if zFilename exists but is something
332379
** other than a directory.
@@ -570,11 +617,14 @@
570617
*/
571618
int file_setexe(const char *zFilename, int onoff){
572619
int rc = 0;
573620
#if !defined(_WIN32)
574621
struct stat buf;
575
- if( fossil_stat(zFilename, &buf, RepoFILE)!=0 || S_ISLNK(buf.st_mode) ){
622
+ if( fossil_stat(zFilename, &buf, RepoFILE)!=0
623
+ || S_ISLNK(buf.st_mode)
624
+ || S_ISDIR(buf.st_mode)
625
+ ){
576626
return 0;
577627
}
578628
if( onoff ){
579629
int targetMode = (buf.st_mode & 0444)>>2;
580630
if( (buf.st_mode & 0100)==0 ){
@@ -2397,5 +2447,88 @@
23972447
changeCount);
23982448
}else{
23992449
fossil_print("Touched %d file(s)\n", changeCount);
24002450
}
24012451
}
2452
+
2453
+/*
2454
+** Returns non-zero if the specified file name ends with any reserved name,
2455
+** e.g.: _FOSSIL_ or .fslckout. Specifically, it returns 1 for exact match
2456
+** or 2 for a tail match on a longer file name.
2457
+**
2458
+** For the sake of efficiency, zFilename must be a canonical name, e.g. an
2459
+** absolute path using only forward slash ('/') as a directory separator.
2460
+**
2461
+** nFilename must be the length of zFilename. When negative, strlen() will
2462
+** be used to calculate it.
2463
+*/
2464
+int file_is_reserved_name(const char *zFilename, int nFilename){
2465
+ const char *zEnd; /* one-after-the-end of zFilename */
2466
+ int gotSuffix = 0; /* length of suffix (-wal, -shm, -journal) */
2467
+
2468
+ assert( zFilename && "API misuse" );
2469
+ if( nFilename<0 ) nFilename = (int)strlen(zFilename);
2470
+ if( nFilename<8 ) return 0; /* strlen("_FOSSIL_") */
2471
+ zEnd = zFilename + nFilename;
2472
+ if( nFilename>=12 ){ /* strlen("_FOSSIL_-(shm|wal)") */
2473
+ /* Check for (-wal, -shm, -journal) suffixes, with an eye towards
2474
+ ** runtime speed. */
2475
+ if( zEnd[-4]=='-' ){
2476
+ if( fossil_strnicmp("wal", &zEnd[-3], 3)
2477
+ && fossil_strnicmp("shm", &zEnd[-3], 3) ){
2478
+ return 0;
2479
+ }
2480
+ gotSuffix = 4;
2481
+ }else if( nFilename>=16 && zEnd[-8]=='-' ){ /*strlen(_FOSSIL_-journal) */
2482
+ if( fossil_strnicmp("journal", &zEnd[-7], 7) ) return 0;
2483
+ gotSuffix = 8;
2484
+ }
2485
+ if( gotSuffix ){
2486
+ assert( 4==gotSuffix || 8==gotSuffix );
2487
+ zEnd -= gotSuffix;
2488
+ nFilename -= gotSuffix;
2489
+ gotSuffix = 1;
2490
+ }
2491
+ assert( nFilename>=8 && "strlen(_FOSSIL_)" );
2492
+ assert( gotSuffix==0 || gotSuffix==1 );
2493
+ }
2494
+ switch( zEnd[-1] ){
2495
+ case '_':{
2496
+ if( fossil_strnicmp("_FOSSIL_", &zEnd[-8], 8) ) return 0;
2497
+ if( 8==nFilename ) return 1;
2498
+ return zEnd[-9]=='/' ? 2 : gotSuffix;
2499
+ }
2500
+ case 'T':
2501
+ case 't':{
2502
+ if( nFilename<9 || zEnd[-9]!='.'
2503
+ || fossil_strnicmp(".fslckout", &zEnd[-9], 9) ){
2504
+ return 0;
2505
+ }
2506
+ if( 9==nFilename ) return 1;
2507
+ return zEnd[-10]=='/' ? 2 : gotSuffix;
2508
+ }
2509
+ default:{
2510
+ return 0;
2511
+ }
2512
+ }
2513
+}
2514
+
2515
+/*
2516
+** COMMAND: test-is-reserved-name
2517
+**
2518
+** Usage: %fossil test-is-ckout-db FILENAMES...
2519
+**
2520
+** Passes each given name to file_is_reserved_name() and outputs one
2521
+** line per file: the result value of that function followed by the
2522
+** name.
2523
+*/
2524
+void test_is_reserved_name_cmd(void){
2525
+ int i;
2526
+
2527
+ if(g.argc<3){
2528
+ usage("FILENAME_1 [...FILENAME_N]");
2529
+ }
2530
+ for( i = 2; i < g.argc; ++i ){
2531
+ const int check = file_is_reserved_name(g.argv[i], -1);
2532
+ fossil_print("%d %s\n", check, g.argv[i]);
2533
+ }
2534
+}
24022535
--- src/file.c
+++ src/file.c
@@ -323,10 +323,57 @@
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.
@@ -570,11 +617,14 @@
570 */
571 int file_setexe(const char *zFilename, int onoff){
572 int rc = 0;
573 #if !defined(_WIN32)
574 struct stat buf;
575 if( fossil_stat(zFilename, &buf, RepoFILE)!=0 || S_ISLNK(buf.st_mode) ){
 
 
 
576 return 0;
577 }
578 if( onoff ){
579 int targetMode = (buf.st_mode & 0444)>>2;
580 if( (buf.st_mode & 0100)==0 ){
@@ -2397,5 +2447,88 @@
2397 changeCount);
2398 }else{
2399 fossil_print("Touched %d file(s)\n", changeCount);
2400 }
2401 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2402
--- src/file.c
+++ src/file.c
@@ -323,10 +323,57 @@
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 ** Return 1 if zFilename is a directory. Return 0 if zFilename
378 ** does not exist. Return 2 if zFilename exists but is something
379 ** other than a directory.
@@ -570,11 +617,14 @@
617 */
618 int file_setexe(const char *zFilename, int onoff){
619 int rc = 0;
620 #if !defined(_WIN32)
621 struct stat buf;
622 if( fossil_stat(zFilename, &buf, RepoFILE)!=0
623 || S_ISLNK(buf.st_mode)
624 || S_ISDIR(buf.st_mode)
625 ){
626 return 0;
627 }
628 if( onoff ){
629 int targetMode = (buf.st_mode & 0444)>>2;
630 if( (buf.st_mode & 0100)==0 ){
@@ -2397,5 +2447,88 @@
2447 changeCount);
2448 }else{
2449 fossil_print("Touched %d file(s)\n", changeCount);
2450 }
2451 }
2452
2453 /*
2454 ** Returns non-zero if the specified file name ends with any reserved name,
2455 ** e.g.: _FOSSIL_ or .fslckout. Specifically, it returns 1 for exact match
2456 ** or 2 for a tail match on a longer file name.
2457 **
2458 ** For the sake of efficiency, zFilename must be a canonical name, e.g. an
2459 ** absolute path using only forward slash ('/') as a directory separator.
2460 **
2461 ** nFilename must be the length of zFilename. When negative, strlen() will
2462 ** be used to calculate it.
2463 */
2464 int file_is_reserved_name(const char *zFilename, int nFilename){
2465 const char *zEnd; /* one-after-the-end of zFilename */
2466 int gotSuffix = 0; /* length of suffix (-wal, -shm, -journal) */
2467
2468 assert( zFilename && "API misuse" );
2469 if( nFilename<0 ) nFilename = (int)strlen(zFilename);
2470 if( nFilename<8 ) return 0; /* strlen("_FOSSIL_") */
2471 zEnd = zFilename + nFilename;
2472 if( nFilename>=12 ){ /* strlen("_FOSSIL_-(shm|wal)") */
2473 /* Check for (-wal, -shm, -journal) suffixes, with an eye towards
2474 ** runtime speed. */
2475 if( zEnd[-4]=='-' ){
2476 if( fossil_strnicmp("wal", &zEnd[-3], 3)
2477 && fossil_strnicmp("shm", &zEnd[-3], 3) ){
2478 return 0;
2479 }
2480 gotSuffix = 4;
2481 }else if( nFilename>=16 && zEnd[-8]=='-' ){ /*strlen(_FOSSIL_-journal) */
2482 if( fossil_strnicmp("journal", &zEnd[-7], 7) ) return 0;
2483 gotSuffix = 8;
2484 }
2485 if( gotSuffix ){
2486 assert( 4==gotSuffix || 8==gotSuffix );
2487 zEnd -= gotSuffix;
2488 nFilename -= gotSuffix;
2489 gotSuffix = 1;
2490 }
2491 assert( nFilename>=8 && "strlen(_FOSSIL_)" );
2492 assert( gotSuffix==0 || gotSuffix==1 );
2493 }
2494 switch( zEnd[-1] ){
2495 case '_':{
2496 if( fossil_strnicmp("_FOSSIL_", &zEnd[-8], 8) ) return 0;
2497 if( 8==nFilename ) return 1;
2498 return zEnd[-9]=='/' ? 2 : gotSuffix;
2499 }
2500 case 'T':
2501 case 't':{
2502 if( nFilename<9 || zEnd[-9]!='.'
2503 || fossil_strnicmp(".fslckout", &zEnd[-9], 9) ){
2504 return 0;
2505 }
2506 if( 9==nFilename ) return 1;
2507 return zEnd[-10]=='/' ? 2 : gotSuffix;
2508 }
2509 default:{
2510 return 0;
2511 }
2512 }
2513 }
2514
2515 /*
2516 ** COMMAND: test-is-reserved-name
2517 **
2518 ** Usage: %fossil test-is-ckout-db FILENAMES...
2519 **
2520 ** Passes each given name to file_is_reserved_name() and outputs one
2521 ** line per file: the result value of that function followed by the
2522 ** name.
2523 */
2524 void test_is_reserved_name_cmd(void){
2525 int i;
2526
2527 if(g.argc<3){
2528 usage("FILENAME_1 [...FILENAME_N]");
2529 }
2530 for( i = 2; i < g.argc; ++i ){
2531 const int check = file_is_reserved_name(g.argv[i], -1);
2532 fossil_print("%d %s\n", check, g.argv[i]);
2533 }
2534 }
2535
+134 -1
--- src/file.c
+++ src/file.c
@@ -323,10 +323,57 @@
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
+}
328375
329376
/*
330377
** Return 1 if zFilename is a directory. Return 0 if zFilename
331378
** does not exist. Return 2 if zFilename exists but is something
332379
** other than a directory.
@@ -570,11 +617,14 @@
570617
*/
571618
int file_setexe(const char *zFilename, int onoff){
572619
int rc = 0;
573620
#if !defined(_WIN32)
574621
struct stat buf;
575
- if( fossil_stat(zFilename, &buf, RepoFILE)!=0 || S_ISLNK(buf.st_mode) ){
622
+ if( fossil_stat(zFilename, &buf, RepoFILE)!=0
623
+ || S_ISLNK(buf.st_mode)
624
+ || S_ISDIR(buf.st_mode)
625
+ ){
576626
return 0;
577627
}
578628
if( onoff ){
579629
int targetMode = (buf.st_mode & 0444)>>2;
580630
if( (buf.st_mode & 0100)==0 ){
@@ -2397,5 +2447,88 @@
23972447
changeCount);
23982448
}else{
23992449
fossil_print("Touched %d file(s)\n", changeCount);
24002450
}
24012451
}
2452
+
2453
+/*
2454
+** Returns non-zero if the specified file name ends with any reserved name,
2455
+** e.g.: _FOSSIL_ or .fslckout. Specifically, it returns 1 for exact match
2456
+** or 2 for a tail match on a longer file name.
2457
+**
2458
+** For the sake of efficiency, zFilename must be a canonical name, e.g. an
2459
+** absolute path using only forward slash ('/') as a directory separator.
2460
+**
2461
+** nFilename must be the length of zFilename. When negative, strlen() will
2462
+** be used to calculate it.
2463
+*/
2464
+int file_is_reserved_name(const char *zFilename, int nFilename){
2465
+ const char *zEnd; /* one-after-the-end of zFilename */
2466
+ int gotSuffix = 0; /* length of suffix (-wal, -shm, -journal) */
2467
+
2468
+ assert( zFilename && "API misuse" );
2469
+ if( nFilename<0 ) nFilename = (int)strlen(zFilename);
2470
+ if( nFilename<8 ) return 0; /* strlen("_FOSSIL_") */
2471
+ zEnd = zFilename + nFilename;
2472
+ if( nFilename>=12 ){ /* strlen("_FOSSIL_-(shm|wal)") */
2473
+ /* Check for (-wal, -shm, -journal) suffixes, with an eye towards
2474
+ ** runtime speed. */
2475
+ if( zEnd[-4]=='-' ){
2476
+ if( fossil_strnicmp("wal", &zEnd[-3], 3)
2477
+ && fossil_strnicmp("shm", &zEnd[-3], 3) ){
2478
+ return 0;
2479
+ }
2480
+ gotSuffix = 4;
2481
+ }else if( nFilename>=16 && zEnd[-8]=='-' ){ /*strlen(_FOSSIL_-journal) */
2482
+ if( fossil_strnicmp("journal", &zEnd[-7], 7) ) return 0;
2483
+ gotSuffix = 8;
2484
+ }
2485
+ if( gotSuffix ){
2486
+ assert( 4==gotSuffix || 8==gotSuffix );
2487
+ zEnd -= gotSuffix;
2488
+ nFilename -= gotSuffix;
2489
+ gotSuffix = 1;
2490
+ }
2491
+ assert( nFilename>=8 && "strlen(_FOSSIL_)" );
2492
+ assert( gotSuffix==0 || gotSuffix==1 );
2493
+ }
2494
+ switch( zEnd[-1] ){
2495
+ case '_':{
2496
+ if( fossil_strnicmp("_FOSSIL_", &zEnd[-8], 8) ) return 0;
2497
+ if( 8==nFilename ) return 1;
2498
+ return zEnd[-9]=='/' ? 2 : gotSuffix;
2499
+ }
2500
+ case 'T':
2501
+ case 't':{
2502
+ if( nFilename<9 || zEnd[-9]!='.'
2503
+ || fossil_strnicmp(".fslckout", &zEnd[-9], 9) ){
2504
+ return 0;
2505
+ }
2506
+ if( 9==nFilename ) return 1;
2507
+ return zEnd[-10]=='/' ? 2 : gotSuffix;
2508
+ }
2509
+ default:{
2510
+ return 0;
2511
+ }
2512
+ }
2513
+}
2514
+
2515
+/*
2516
+** COMMAND: test-is-reserved-name
2517
+**
2518
+** Usage: %fossil test-is-ckout-db FILENAMES...
2519
+**
2520
+** Passes each given name to file_is_reserved_name() and outputs one
2521
+** line per file: the result value of that function followed by the
2522
+** name.
2523
+*/
2524
+void test_is_reserved_name_cmd(void){
2525
+ int i;
2526
+
2527
+ if(g.argc<3){
2528
+ usage("FILENAME_1 [...FILENAME_N]");
2529
+ }
2530
+ for( i = 2; i < g.argc; ++i ){
2531
+ const int check = file_is_reserved_name(g.argv[i], -1);
2532
+ fossil_print("%d %s\n", check, g.argv[i]);
2533
+ }
2534
+}
24022535
--- src/file.c
+++ src/file.c
@@ -323,10 +323,57 @@
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.
@@ -570,11 +617,14 @@
570 */
571 int file_setexe(const char *zFilename, int onoff){
572 int rc = 0;
573 #if !defined(_WIN32)
574 struct stat buf;
575 if( fossil_stat(zFilename, &buf, RepoFILE)!=0 || S_ISLNK(buf.st_mode) ){
 
 
 
576 return 0;
577 }
578 if( onoff ){
579 int targetMode = (buf.st_mode & 0444)>>2;
580 if( (buf.st_mode & 0100)==0 ){
@@ -2397,5 +2447,88 @@
2397 changeCount);
2398 }else{
2399 fossil_print("Touched %d file(s)\n", changeCount);
2400 }
2401 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2402
--- src/file.c
+++ src/file.c
@@ -323,10 +323,57 @@
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 ** Return 1 if zFilename is a directory. Return 0 if zFilename
378 ** does not exist. Return 2 if zFilename exists but is something
379 ** other than a directory.
@@ -570,11 +617,14 @@
617 */
618 int file_setexe(const char *zFilename, int onoff){
619 int rc = 0;
620 #if !defined(_WIN32)
621 struct stat buf;
622 if( fossil_stat(zFilename, &buf, RepoFILE)!=0
623 || S_ISLNK(buf.st_mode)
624 || S_ISDIR(buf.st_mode)
625 ){
626 return 0;
627 }
628 if( onoff ){
629 int targetMode = (buf.st_mode & 0444)>>2;
630 if( (buf.st_mode & 0100)==0 ){
@@ -2397,5 +2447,88 @@
2447 changeCount);
2448 }else{
2449 fossil_print("Touched %d file(s)\n", changeCount);
2450 }
2451 }
2452
2453 /*
2454 ** Returns non-zero if the specified file name ends with any reserved name,
2455 ** e.g.: _FOSSIL_ or .fslckout. Specifically, it returns 1 for exact match
2456 ** or 2 for a tail match on a longer file name.
2457 **
2458 ** For the sake of efficiency, zFilename must be a canonical name, e.g. an
2459 ** absolute path using only forward slash ('/') as a directory separator.
2460 **
2461 ** nFilename must be the length of zFilename. When negative, strlen() will
2462 ** be used to calculate it.
2463 */
2464 int file_is_reserved_name(const char *zFilename, int nFilename){
2465 const char *zEnd; /* one-after-the-end of zFilename */
2466 int gotSuffix = 0; /* length of suffix (-wal, -shm, -journal) */
2467
2468 assert( zFilename && "API misuse" );
2469 if( nFilename<0 ) nFilename = (int)strlen(zFilename);
2470 if( nFilename<8 ) return 0; /* strlen("_FOSSIL_") */
2471 zEnd = zFilename + nFilename;
2472 if( nFilename>=12 ){ /* strlen("_FOSSIL_-(shm|wal)") */
2473 /* Check for (-wal, -shm, -journal) suffixes, with an eye towards
2474 ** runtime speed. */
2475 if( zEnd[-4]=='-' ){
2476 if( fossil_strnicmp("wal", &zEnd[-3], 3)
2477 && fossil_strnicmp("shm", &zEnd[-3], 3) ){
2478 return 0;
2479 }
2480 gotSuffix = 4;
2481 }else if( nFilename>=16 && zEnd[-8]=='-' ){ /*strlen(_FOSSIL_-journal) */
2482 if( fossil_strnicmp("journal", &zEnd[-7], 7) ) return 0;
2483 gotSuffix = 8;
2484 }
2485 if( gotSuffix ){
2486 assert( 4==gotSuffix || 8==gotSuffix );
2487 zEnd -= gotSuffix;
2488 nFilename -= gotSuffix;
2489 gotSuffix = 1;
2490 }
2491 assert( nFilename>=8 && "strlen(_FOSSIL_)" );
2492 assert( gotSuffix==0 || gotSuffix==1 );
2493 }
2494 switch( zEnd[-1] ){
2495 case '_':{
2496 if( fossil_strnicmp("_FOSSIL_", &zEnd[-8], 8) ) return 0;
2497 if( 8==nFilename ) return 1;
2498 return zEnd[-9]=='/' ? 2 : gotSuffix;
2499 }
2500 case 'T':
2501 case 't':{
2502 if( nFilename<9 || zEnd[-9]!='.'
2503 || fossil_strnicmp(".fslckout", &zEnd[-9], 9) ){
2504 return 0;
2505 }
2506 if( 9==nFilename ) return 1;
2507 return zEnd[-10]=='/' ? 2 : gotSuffix;
2508 }
2509 default:{
2510 return 0;
2511 }
2512 }
2513 }
2514
2515 /*
2516 ** COMMAND: test-is-reserved-name
2517 **
2518 ** Usage: %fossil test-is-ckout-db FILENAMES...
2519 **
2520 ** Passes each given name to file_is_reserved_name() and outputs one
2521 ** line per file: the result value of that function followed by the
2522 ** name.
2523 */
2524 void test_is_reserved_name_cmd(void){
2525 int i;
2526
2527 if(g.argc<3){
2528 usage("FILENAME_1 [...FILENAME_N]");
2529 }
2530 for( i = 2; i < g.argc; ++i ){
2531 const int check = file_is_reserved_name(g.argv[i], -1);
2532 fossil_print("%d %s\n", check, g.argv[i]);
2533 }
2534 }
2535
+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
+21 -3
--- src/manifest.c
+++ src/manifest.c
@@ -481,14 +481,23 @@
481481
blob_appendf(pErr, "line 1 not recognized");
482482
return 0;
483483
}
484484
/* Then verify the Z-card.
485485
*/
486
+#if 1
487
+ /* Disable this ***ONLY*** (ONLY!) when testing hand-written inputs
488
+ for card-related syntax errors. */
486489
if( verify_z_card(z, n, pErr)==2 ){
487490
blob_reset(pContent);
488491
return 0;
489492
}
493
+#else
494
+#warning ACHTUNG - z-card check is disabled for testing purposes.
495
+ if(0 && verify_z_card(NULL, 0, NULL)){
496
+ /*avoid unused static func error*/
497
+ }
498
+#endif
490499
491500
/* Allocate a Manifest object to hold the parsed control artifact.
492501
*/
493502
p = fossil_malloc( sizeof(*p) );
494503
memset(p, 0, sizeof(*p));
@@ -601,10 +610,11 @@
601610
case 'E': {
602611
if( p->rEventDate>0.0 ) SYNTAX("more than one E-card");
603612
p->rEventDate = db_double(0.0,"SELECT julianday(%Q)", next_token(&x,0));
604613
if( p->rEventDate<=0.0 ) SYNTAX("malformed date on E-card");
605614
p->zEventId = next_token(&x, &sz);
615
+ if( p->zEventId==0 ) SYNTAX("missing hash on E-card");
606616
if( !hname_validate(p->zEventId, sz) ){
607617
SYNTAX("malformed hash on E-card");
608618
}
609619
p->type = CFTYPE_EVENT;
610620
break;
@@ -625,10 +635,11 @@
625635
if( !file_is_simple_pathname_nonstrict(zName) ){
626636
SYNTAX("F-card filename is not a simple path");
627637
}
628638
zUuid = next_token(&x, &sz);
629639
if( p->zBaseline==0 || zUuid!=0 ){
640
+ if( zUuid==0 ) SYNTAX("missing hash on F-card");
630641
if( !hname_validate(zUuid,sz) ){
631642
SYNTAX("F-card hash invalid");
632643
}
633644
}
634645
zPerm = next_token(&x,0);
@@ -643,17 +654,24 @@
643654
p->nFileAlloc = p->nFileAlloc*2 + 10;
644655
p->aFile = fossil_realloc(p->aFile,
645656
p->nFileAlloc*sizeof(p->aFile[0]) );
646657
}
647658
i = p->nFile++;
659
+ if( i>0 && fossil_strcmp(p->aFile[i-1].zName, zName)>=0 ){
660
+ SYNTAX("incorrect F-card sort order");
661
+ }
662
+ if( file_is_reserved_name(zName,-1) ){
663
+ /* If reserved names leaked into historical manifests due to
664
+ ** slack oversight by older versions of Fossil, simply ignore
665
+ ** those files */
666
+ p->nFile--;
667
+ break;
668
+ }
648669
p->aFile[i].zName = zName;
649670
p->aFile[i].zUuid = zUuid;
650671
p->aFile[i].zPerm = zPerm;
651672
p->aFile[i].zPrior = zPriorName;
652
- if( i>0 && fossil_strcmp(p->aFile[i-1].zName, zName)>=0 ){
653
- SYNTAX("incorrect F-card sort order");
654
- }
655673
p->type = CFTYPE_MANIFEST;
656674
break;
657675
}
658676
659677
/*
660678
--- src/manifest.c
+++ src/manifest.c
@@ -481,14 +481,23 @@
481 blob_appendf(pErr, "line 1 not recognized");
482 return 0;
483 }
484 /* Then verify the Z-card.
485 */
 
 
 
486 if( verify_z_card(z, n, pErr)==2 ){
487 blob_reset(pContent);
488 return 0;
489 }
 
 
 
 
 
 
490
491 /* Allocate a Manifest object to hold the parsed control artifact.
492 */
493 p = fossil_malloc( sizeof(*p) );
494 memset(p, 0, sizeof(*p));
@@ -601,10 +610,11 @@
601 case 'E': {
602 if( p->rEventDate>0.0 ) SYNTAX("more than one E-card");
603 p->rEventDate = db_double(0.0,"SELECT julianday(%Q)", next_token(&x,0));
604 if( p->rEventDate<=0.0 ) SYNTAX("malformed date on E-card");
605 p->zEventId = next_token(&x, &sz);
 
606 if( !hname_validate(p->zEventId, sz) ){
607 SYNTAX("malformed hash on E-card");
608 }
609 p->type = CFTYPE_EVENT;
610 break;
@@ -625,10 +635,11 @@
625 if( !file_is_simple_pathname_nonstrict(zName) ){
626 SYNTAX("F-card filename is not a simple path");
627 }
628 zUuid = next_token(&x, &sz);
629 if( p->zBaseline==0 || zUuid!=0 ){
 
630 if( !hname_validate(zUuid,sz) ){
631 SYNTAX("F-card hash invalid");
632 }
633 }
634 zPerm = next_token(&x,0);
@@ -643,17 +654,24 @@
643 p->nFileAlloc = p->nFileAlloc*2 + 10;
644 p->aFile = fossil_realloc(p->aFile,
645 p->nFileAlloc*sizeof(p->aFile[0]) );
646 }
647 i = p->nFile++;
 
 
 
 
 
 
 
 
 
 
648 p->aFile[i].zName = zName;
649 p->aFile[i].zUuid = zUuid;
650 p->aFile[i].zPerm = zPerm;
651 p->aFile[i].zPrior = zPriorName;
652 if( i>0 && fossil_strcmp(p->aFile[i-1].zName, zName)>=0 ){
653 SYNTAX("incorrect F-card sort order");
654 }
655 p->type = CFTYPE_MANIFEST;
656 break;
657 }
658
659 /*
660
--- src/manifest.c
+++ src/manifest.c
@@ -481,14 +481,23 @@
481 blob_appendf(pErr, "line 1 not recognized");
482 return 0;
483 }
484 /* Then verify the Z-card.
485 */
486 #if 1
487 /* Disable this ***ONLY*** (ONLY!) when testing hand-written inputs
488 for card-related syntax errors. */
489 if( verify_z_card(z, n, pErr)==2 ){
490 blob_reset(pContent);
491 return 0;
492 }
493 #else
494 #warning ACHTUNG - z-card check is disabled for testing purposes.
495 if(0 && verify_z_card(NULL, 0, NULL)){
496 /*avoid unused static func error*/
497 }
498 #endif
499
500 /* Allocate a Manifest object to hold the parsed control artifact.
501 */
502 p = fossil_malloc( sizeof(*p) );
503 memset(p, 0, sizeof(*p));
@@ -601,10 +610,11 @@
610 case 'E': {
611 if( p->rEventDate>0.0 ) SYNTAX("more than one E-card");
612 p->rEventDate = db_double(0.0,"SELECT julianday(%Q)", next_token(&x,0));
613 if( p->rEventDate<=0.0 ) SYNTAX("malformed date on E-card");
614 p->zEventId = next_token(&x, &sz);
615 if( p->zEventId==0 ) SYNTAX("missing hash on E-card");
616 if( !hname_validate(p->zEventId, sz) ){
617 SYNTAX("malformed hash on E-card");
618 }
619 p->type = CFTYPE_EVENT;
620 break;
@@ -625,10 +635,11 @@
635 if( !file_is_simple_pathname_nonstrict(zName) ){
636 SYNTAX("F-card filename is not a simple path");
637 }
638 zUuid = next_token(&x, &sz);
639 if( p->zBaseline==0 || zUuid!=0 ){
640 if( zUuid==0 ) SYNTAX("missing hash on F-card");
641 if( !hname_validate(zUuid,sz) ){
642 SYNTAX("F-card hash invalid");
643 }
644 }
645 zPerm = next_token(&x,0);
@@ -643,17 +654,24 @@
654 p->nFileAlloc = p->nFileAlloc*2 + 10;
655 p->aFile = fossil_realloc(p->aFile,
656 p->nFileAlloc*sizeof(p->aFile[0]) );
657 }
658 i = p->nFile++;
659 if( i>0 && fossil_strcmp(p->aFile[i-1].zName, zName)>=0 ){
660 SYNTAX("incorrect F-card sort order");
661 }
662 if( file_is_reserved_name(zName,-1) ){
663 /* If reserved names leaked into historical manifests due to
664 ** slack oversight by older versions of Fossil, simply ignore
665 ** those files */
666 p->nFile--;
667 break;
668 }
669 p->aFile[i].zName = zName;
670 p->aFile[i].zUuid = zUuid;
671 p->aFile[i].zPerm = zPerm;
672 p->aFile[i].zPrior = zPriorName;
 
 
 
673 p->type = CFTYPE_MANIFEST;
674 break;
675 }
676
677 /*
678
+21 -3
--- src/manifest.c
+++ src/manifest.c
@@ -481,14 +481,23 @@
481481
blob_appendf(pErr, "line 1 not recognized");
482482
return 0;
483483
}
484484
/* Then verify the Z-card.
485485
*/
486
+#if 1
487
+ /* Disable this ***ONLY*** (ONLY!) when testing hand-written inputs
488
+ for card-related syntax errors. */
486489
if( verify_z_card(z, n, pErr)==2 ){
487490
blob_reset(pContent);
488491
return 0;
489492
}
493
+#else
494
+#warning ACHTUNG - z-card check is disabled for testing purposes.
495
+ if(0 && verify_z_card(NULL, 0, NULL)){
496
+ /*avoid unused static func error*/
497
+ }
498
+#endif
490499
491500
/* Allocate a Manifest object to hold the parsed control artifact.
492501
*/
493502
p = fossil_malloc( sizeof(*p) );
494503
memset(p, 0, sizeof(*p));
@@ -601,10 +610,11 @@
601610
case 'E': {
602611
if( p->rEventDate>0.0 ) SYNTAX("more than one E-card");
603612
p->rEventDate = db_double(0.0,"SELECT julianday(%Q)", next_token(&x,0));
604613
if( p->rEventDate<=0.0 ) SYNTAX("malformed date on E-card");
605614
p->zEventId = next_token(&x, &sz);
615
+ if( p->zEventId==0 ) SYNTAX("missing hash on E-card");
606616
if( !hname_validate(p->zEventId, sz) ){
607617
SYNTAX("malformed hash on E-card");
608618
}
609619
p->type = CFTYPE_EVENT;
610620
break;
@@ -625,10 +635,11 @@
625635
if( !file_is_simple_pathname_nonstrict(zName) ){
626636
SYNTAX("F-card filename is not a simple path");
627637
}
628638
zUuid = next_token(&x, &sz);
629639
if( p->zBaseline==0 || zUuid!=0 ){
640
+ if( zUuid==0 ) SYNTAX("missing hash on F-card");
630641
if( !hname_validate(zUuid,sz) ){
631642
SYNTAX("F-card hash invalid");
632643
}
633644
}
634645
zPerm = next_token(&x,0);
@@ -643,17 +654,24 @@
643654
p->nFileAlloc = p->nFileAlloc*2 + 10;
644655
p->aFile = fossil_realloc(p->aFile,
645656
p->nFileAlloc*sizeof(p->aFile[0]) );
646657
}
647658
i = p->nFile++;
659
+ if( i>0 && fossil_strcmp(p->aFile[i-1].zName, zName)>=0 ){
660
+ SYNTAX("incorrect F-card sort order");
661
+ }
662
+ if( file_is_reserved_name(zName,-1) ){
663
+ /* If reserved names leaked into historical manifests due to
664
+ ** slack oversight by older versions of Fossil, simply ignore
665
+ ** those files */
666
+ p->nFile--;
667
+ break;
668
+ }
648669
p->aFile[i].zName = zName;
649670
p->aFile[i].zUuid = zUuid;
650671
p->aFile[i].zPerm = zPerm;
651672
p->aFile[i].zPrior = zPriorName;
652
- if( i>0 && fossil_strcmp(p->aFile[i-1].zName, zName)>=0 ){
653
- SYNTAX("incorrect F-card sort order");
654
- }
655673
p->type = CFTYPE_MANIFEST;
656674
break;
657675
}
658676
659677
/*
660678
--- src/manifest.c
+++ src/manifest.c
@@ -481,14 +481,23 @@
481 blob_appendf(pErr, "line 1 not recognized");
482 return 0;
483 }
484 /* Then verify the Z-card.
485 */
 
 
 
486 if( verify_z_card(z, n, pErr)==2 ){
487 blob_reset(pContent);
488 return 0;
489 }
 
 
 
 
 
 
490
491 /* Allocate a Manifest object to hold the parsed control artifact.
492 */
493 p = fossil_malloc( sizeof(*p) );
494 memset(p, 0, sizeof(*p));
@@ -601,10 +610,11 @@
601 case 'E': {
602 if( p->rEventDate>0.0 ) SYNTAX("more than one E-card");
603 p->rEventDate = db_double(0.0,"SELECT julianday(%Q)", next_token(&x,0));
604 if( p->rEventDate<=0.0 ) SYNTAX("malformed date on E-card");
605 p->zEventId = next_token(&x, &sz);
 
606 if( !hname_validate(p->zEventId, sz) ){
607 SYNTAX("malformed hash on E-card");
608 }
609 p->type = CFTYPE_EVENT;
610 break;
@@ -625,10 +635,11 @@
625 if( !file_is_simple_pathname_nonstrict(zName) ){
626 SYNTAX("F-card filename is not a simple path");
627 }
628 zUuid = next_token(&x, &sz);
629 if( p->zBaseline==0 || zUuid!=0 ){
 
630 if( !hname_validate(zUuid,sz) ){
631 SYNTAX("F-card hash invalid");
632 }
633 }
634 zPerm = next_token(&x,0);
@@ -643,17 +654,24 @@
643 p->nFileAlloc = p->nFileAlloc*2 + 10;
644 p->aFile = fossil_realloc(p->aFile,
645 p->nFileAlloc*sizeof(p->aFile[0]) );
646 }
647 i = p->nFile++;
 
 
 
 
 
 
 
 
 
 
648 p->aFile[i].zName = zName;
649 p->aFile[i].zUuid = zUuid;
650 p->aFile[i].zPerm = zPerm;
651 p->aFile[i].zPrior = zPriorName;
652 if( i>0 && fossil_strcmp(p->aFile[i-1].zName, zName)>=0 ){
653 SYNTAX("incorrect F-card sort order");
654 }
655 p->type = CFTYPE_MANIFEST;
656 break;
657 }
658
659 /*
660
--- src/manifest.c
+++ src/manifest.c
@@ -481,14 +481,23 @@
481 blob_appendf(pErr, "line 1 not recognized");
482 return 0;
483 }
484 /* Then verify the Z-card.
485 */
486 #if 1
487 /* Disable this ***ONLY*** (ONLY!) when testing hand-written inputs
488 for card-related syntax errors. */
489 if( verify_z_card(z, n, pErr)==2 ){
490 blob_reset(pContent);
491 return 0;
492 }
493 #else
494 #warning ACHTUNG - z-card check is disabled for testing purposes.
495 if(0 && verify_z_card(NULL, 0, NULL)){
496 /*avoid unused static func error*/
497 }
498 #endif
499
500 /* Allocate a Manifest object to hold the parsed control artifact.
501 */
502 p = fossil_malloc( sizeof(*p) );
503 memset(p, 0, sizeof(*p));
@@ -601,10 +610,11 @@
610 case 'E': {
611 if( p->rEventDate>0.0 ) SYNTAX("more than one E-card");
612 p->rEventDate = db_double(0.0,"SELECT julianday(%Q)", next_token(&x,0));
613 if( p->rEventDate<=0.0 ) SYNTAX("malformed date on E-card");
614 p->zEventId = next_token(&x, &sz);
615 if( p->zEventId==0 ) SYNTAX("missing hash on E-card");
616 if( !hname_validate(p->zEventId, sz) ){
617 SYNTAX("malformed hash on E-card");
618 }
619 p->type = CFTYPE_EVENT;
620 break;
@@ -625,10 +635,11 @@
635 if( !file_is_simple_pathname_nonstrict(zName) ){
636 SYNTAX("F-card filename is not a simple path");
637 }
638 zUuid = next_token(&x, &sz);
639 if( p->zBaseline==0 || zUuid!=0 ){
640 if( zUuid==0 ) SYNTAX("missing hash on F-card");
641 if( !hname_validate(zUuid,sz) ){
642 SYNTAX("F-card hash invalid");
643 }
644 }
645 zPerm = next_token(&x,0);
@@ -643,17 +654,24 @@
654 p->nFileAlloc = p->nFileAlloc*2 + 10;
655 p->aFile = fossil_realloc(p->aFile,
656 p->nFileAlloc*sizeof(p->aFile[0]) );
657 }
658 i = p->nFile++;
659 if( i>0 && fossil_strcmp(p->aFile[i-1].zName, zName)>=0 ){
660 SYNTAX("incorrect F-card sort order");
661 }
662 if( file_is_reserved_name(zName,-1) ){
663 /* If reserved names leaked into historical manifests due to
664 ** slack oversight by older versions of Fossil, simply ignore
665 ** those files */
666 p->nFile--;
667 break;
668 }
669 p->aFile[i].zName = zName;
670 p->aFile[i].zUuid = zUuid;
671 p->aFile[i].zPerm = zPerm;
672 p->aFile[i].zPrior = zPriorName;
 
 
 
673 p->type = CFTYPE_MANIFEST;
674 break;
675 }
676
677 /*
678
+21 -3
--- src/manifest.c
+++ src/manifest.c
@@ -481,14 +481,23 @@
481481
blob_appendf(pErr, "line 1 not recognized");
482482
return 0;
483483
}
484484
/* Then verify the Z-card.
485485
*/
486
+#if 1
487
+ /* Disable this ***ONLY*** (ONLY!) when testing hand-written inputs
488
+ for card-related syntax errors. */
486489
if( verify_z_card(z, n, pErr)==2 ){
487490
blob_reset(pContent);
488491
return 0;
489492
}
493
+#else
494
+#warning ACHTUNG - z-card check is disabled for testing purposes.
495
+ if(0 && verify_z_card(NULL, 0, NULL)){
496
+ /*avoid unused static func error*/
497
+ }
498
+#endif
490499
491500
/* Allocate a Manifest object to hold the parsed control artifact.
492501
*/
493502
p = fossil_malloc( sizeof(*p) );
494503
memset(p, 0, sizeof(*p));
@@ -601,10 +610,11 @@
601610
case 'E': {
602611
if( p->rEventDate>0.0 ) SYNTAX("more than one E-card");
603612
p->rEventDate = db_double(0.0,"SELECT julianday(%Q)", next_token(&x,0));
604613
if( p->rEventDate<=0.0 ) SYNTAX("malformed date on E-card");
605614
p->zEventId = next_token(&x, &sz);
615
+ if( p->zEventId==0 ) SYNTAX("missing hash on E-card");
606616
if( !hname_validate(p->zEventId, sz) ){
607617
SYNTAX("malformed hash on E-card");
608618
}
609619
p->type = CFTYPE_EVENT;
610620
break;
@@ -625,10 +635,11 @@
625635
if( !file_is_simple_pathname_nonstrict(zName) ){
626636
SYNTAX("F-card filename is not a simple path");
627637
}
628638
zUuid = next_token(&x, &sz);
629639
if( p->zBaseline==0 || zUuid!=0 ){
640
+ if( zUuid==0 ) SYNTAX("missing hash on F-card");
630641
if( !hname_validate(zUuid,sz) ){
631642
SYNTAX("F-card hash invalid");
632643
}
633644
}
634645
zPerm = next_token(&x,0);
@@ -643,17 +654,24 @@
643654
p->nFileAlloc = p->nFileAlloc*2 + 10;
644655
p->aFile = fossil_realloc(p->aFile,
645656
p->nFileAlloc*sizeof(p->aFile[0]) );
646657
}
647658
i = p->nFile++;
659
+ if( i>0 && fossil_strcmp(p->aFile[i-1].zName, zName)>=0 ){
660
+ SYNTAX("incorrect F-card sort order");
661
+ }
662
+ if( file_is_reserved_name(zName,-1) ){
663
+ /* If reserved names leaked into historical manifests due to
664
+ ** slack oversight by older versions of Fossil, simply ignore
665
+ ** those files */
666
+ p->nFile--;
667
+ break;
668
+ }
648669
p->aFile[i].zName = zName;
649670
p->aFile[i].zUuid = zUuid;
650671
p->aFile[i].zPerm = zPerm;
651672
p->aFile[i].zPrior = zPriorName;
652
- if( i>0 && fossil_strcmp(p->aFile[i-1].zName, zName)>=0 ){
653
- SYNTAX("incorrect F-card sort order");
654
- }
655673
p->type = CFTYPE_MANIFEST;
656674
break;
657675
}
658676
659677
/*
660678
--- src/manifest.c
+++ src/manifest.c
@@ -481,14 +481,23 @@
481 blob_appendf(pErr, "line 1 not recognized");
482 return 0;
483 }
484 /* Then verify the Z-card.
485 */
 
 
 
486 if( verify_z_card(z, n, pErr)==2 ){
487 blob_reset(pContent);
488 return 0;
489 }
 
 
 
 
 
 
490
491 /* Allocate a Manifest object to hold the parsed control artifact.
492 */
493 p = fossil_malloc( sizeof(*p) );
494 memset(p, 0, sizeof(*p));
@@ -601,10 +610,11 @@
601 case 'E': {
602 if( p->rEventDate>0.0 ) SYNTAX("more than one E-card");
603 p->rEventDate = db_double(0.0,"SELECT julianday(%Q)", next_token(&x,0));
604 if( p->rEventDate<=0.0 ) SYNTAX("malformed date on E-card");
605 p->zEventId = next_token(&x, &sz);
 
606 if( !hname_validate(p->zEventId, sz) ){
607 SYNTAX("malformed hash on E-card");
608 }
609 p->type = CFTYPE_EVENT;
610 break;
@@ -625,10 +635,11 @@
625 if( !file_is_simple_pathname_nonstrict(zName) ){
626 SYNTAX("F-card filename is not a simple path");
627 }
628 zUuid = next_token(&x, &sz);
629 if( p->zBaseline==0 || zUuid!=0 ){
 
630 if( !hname_validate(zUuid,sz) ){
631 SYNTAX("F-card hash invalid");
632 }
633 }
634 zPerm = next_token(&x,0);
@@ -643,17 +654,24 @@
643 p->nFileAlloc = p->nFileAlloc*2 + 10;
644 p->aFile = fossil_realloc(p->aFile,
645 p->nFileAlloc*sizeof(p->aFile[0]) );
646 }
647 i = p->nFile++;
 
 
 
 
 
 
 
 
 
 
648 p->aFile[i].zName = zName;
649 p->aFile[i].zUuid = zUuid;
650 p->aFile[i].zPerm = zPerm;
651 p->aFile[i].zPrior = zPriorName;
652 if( i>0 && fossil_strcmp(p->aFile[i-1].zName, zName)>=0 ){
653 SYNTAX("incorrect F-card sort order");
654 }
655 p->type = CFTYPE_MANIFEST;
656 break;
657 }
658
659 /*
660
--- src/manifest.c
+++ src/manifest.c
@@ -481,14 +481,23 @@
481 blob_appendf(pErr, "line 1 not recognized");
482 return 0;
483 }
484 /* Then verify the Z-card.
485 */
486 #if 1
487 /* Disable this ***ONLY*** (ONLY!) when testing hand-written inputs
488 for card-related syntax errors. */
489 if( verify_z_card(z, n, pErr)==2 ){
490 blob_reset(pContent);
491 return 0;
492 }
493 #else
494 #warning ACHTUNG - z-card check is disabled for testing purposes.
495 if(0 && verify_z_card(NULL, 0, NULL)){
496 /*avoid unused static func error*/
497 }
498 #endif
499
500 /* Allocate a Manifest object to hold the parsed control artifact.
501 */
502 p = fossil_malloc( sizeof(*p) );
503 memset(p, 0, sizeof(*p));
@@ -601,10 +610,11 @@
610 case 'E': {
611 if( p->rEventDate>0.0 ) SYNTAX("more than one E-card");
612 p->rEventDate = db_double(0.0,"SELECT julianday(%Q)", next_token(&x,0));
613 if( p->rEventDate<=0.0 ) SYNTAX("malformed date on E-card");
614 p->zEventId = next_token(&x, &sz);
615 if( p->zEventId==0 ) SYNTAX("missing hash on E-card");
616 if( !hname_validate(p->zEventId, sz) ){
617 SYNTAX("malformed hash on E-card");
618 }
619 p->type = CFTYPE_EVENT;
620 break;
@@ -625,10 +635,11 @@
635 if( !file_is_simple_pathname_nonstrict(zName) ){
636 SYNTAX("F-card filename is not a simple path");
637 }
638 zUuid = next_token(&x, &sz);
639 if( p->zBaseline==0 || zUuid!=0 ){
640 if( zUuid==0 ) SYNTAX("missing hash on F-card");
641 if( !hname_validate(zUuid,sz) ){
642 SYNTAX("F-card hash invalid");
643 }
644 }
645 zPerm = next_token(&x,0);
@@ -643,17 +654,24 @@
654 p->nFileAlloc = p->nFileAlloc*2 + 10;
655 p->aFile = fossil_realloc(p->aFile,
656 p->nFileAlloc*sizeof(p->aFile[0]) );
657 }
658 i = p->nFile++;
659 if( i>0 && fossil_strcmp(p->aFile[i-1].zName, zName)>=0 ){
660 SYNTAX("incorrect F-card sort order");
661 }
662 if( file_is_reserved_name(zName,-1) ){
663 /* If reserved names leaked into historical manifests due to
664 ** slack oversight by older versions of Fossil, simply ignore
665 ** those files */
666 p->nFile--;
667 break;
668 }
669 p->aFile[i].zName = zName;
670 p->aFile[i].zUuid = zUuid;
671 p->aFile[i].zPerm = zPerm;
672 p->aFile[i].zPrior = zPriorName;
 
 
 
673 p->type = CFTYPE_MANIFEST;
674 break;
675 }
676
677 /*
678
+21 -3
--- src/manifest.c
+++ src/manifest.c
@@ -481,14 +481,23 @@
481481
blob_appendf(pErr, "line 1 not recognized");
482482
return 0;
483483
}
484484
/* Then verify the Z-card.
485485
*/
486
+#if 1
487
+ /* Disable this ***ONLY*** (ONLY!) when testing hand-written inputs
488
+ for card-related syntax errors. */
486489
if( verify_z_card(z, n, pErr)==2 ){
487490
blob_reset(pContent);
488491
return 0;
489492
}
493
+#else
494
+#warning ACHTUNG - z-card check is disabled for testing purposes.
495
+ if(0 && verify_z_card(NULL, 0, NULL)){
496
+ /*avoid unused static func error*/
497
+ }
498
+#endif
490499
491500
/* Allocate a Manifest object to hold the parsed control artifact.
492501
*/
493502
p = fossil_malloc( sizeof(*p) );
494503
memset(p, 0, sizeof(*p));
@@ -601,10 +610,11 @@
601610
case 'E': {
602611
if( p->rEventDate>0.0 ) SYNTAX("more than one E-card");
603612
p->rEventDate = db_double(0.0,"SELECT julianday(%Q)", next_token(&x,0));
604613
if( p->rEventDate<=0.0 ) SYNTAX("malformed date on E-card");
605614
p->zEventId = next_token(&x, &sz);
615
+ if( p->zEventId==0 ) SYNTAX("missing hash on E-card");
606616
if( !hname_validate(p->zEventId, sz) ){
607617
SYNTAX("malformed hash on E-card");
608618
}
609619
p->type = CFTYPE_EVENT;
610620
break;
@@ -625,10 +635,11 @@
625635
if( !file_is_simple_pathname_nonstrict(zName) ){
626636
SYNTAX("F-card filename is not a simple path");
627637
}
628638
zUuid = next_token(&x, &sz);
629639
if( p->zBaseline==0 || zUuid!=0 ){
640
+ if( zUuid==0 ) SYNTAX("missing hash on F-card");
630641
if( !hname_validate(zUuid,sz) ){
631642
SYNTAX("F-card hash invalid");
632643
}
633644
}
634645
zPerm = next_token(&x,0);
@@ -643,17 +654,24 @@
643654
p->nFileAlloc = p->nFileAlloc*2 + 10;
644655
p->aFile = fossil_realloc(p->aFile,
645656
p->nFileAlloc*sizeof(p->aFile[0]) );
646657
}
647658
i = p->nFile++;
659
+ if( i>0 && fossil_strcmp(p->aFile[i-1].zName, zName)>=0 ){
660
+ SYNTAX("incorrect F-card sort order");
661
+ }
662
+ if( file_is_reserved_name(zName,-1) ){
663
+ /* If reserved names leaked into historical manifests due to
664
+ ** slack oversight by older versions of Fossil, simply ignore
665
+ ** those files */
666
+ p->nFile--;
667
+ break;
668
+ }
648669
p->aFile[i].zName = zName;
649670
p->aFile[i].zUuid = zUuid;
650671
p->aFile[i].zPerm = zPerm;
651672
p->aFile[i].zPrior = zPriorName;
652
- if( i>0 && fossil_strcmp(p->aFile[i-1].zName, zName)>=0 ){
653
- SYNTAX("incorrect F-card sort order");
654
- }
655673
p->type = CFTYPE_MANIFEST;
656674
break;
657675
}
658676
659677
/*
660678
--- src/manifest.c
+++ src/manifest.c
@@ -481,14 +481,23 @@
481 blob_appendf(pErr, "line 1 not recognized");
482 return 0;
483 }
484 /* Then verify the Z-card.
485 */
 
 
 
486 if( verify_z_card(z, n, pErr)==2 ){
487 blob_reset(pContent);
488 return 0;
489 }
 
 
 
 
 
 
490
491 /* Allocate a Manifest object to hold the parsed control artifact.
492 */
493 p = fossil_malloc( sizeof(*p) );
494 memset(p, 0, sizeof(*p));
@@ -601,10 +610,11 @@
601 case 'E': {
602 if( p->rEventDate>0.0 ) SYNTAX("more than one E-card");
603 p->rEventDate = db_double(0.0,"SELECT julianday(%Q)", next_token(&x,0));
604 if( p->rEventDate<=0.0 ) SYNTAX("malformed date on E-card");
605 p->zEventId = next_token(&x, &sz);
 
606 if( !hname_validate(p->zEventId, sz) ){
607 SYNTAX("malformed hash on E-card");
608 }
609 p->type = CFTYPE_EVENT;
610 break;
@@ -625,10 +635,11 @@
625 if( !file_is_simple_pathname_nonstrict(zName) ){
626 SYNTAX("F-card filename is not a simple path");
627 }
628 zUuid = next_token(&x, &sz);
629 if( p->zBaseline==0 || zUuid!=0 ){
 
630 if( !hname_validate(zUuid,sz) ){
631 SYNTAX("F-card hash invalid");
632 }
633 }
634 zPerm = next_token(&x,0);
@@ -643,17 +654,24 @@
643 p->nFileAlloc = p->nFileAlloc*2 + 10;
644 p->aFile = fossil_realloc(p->aFile,
645 p->nFileAlloc*sizeof(p->aFile[0]) );
646 }
647 i = p->nFile++;
 
 
 
 
 
 
 
 
 
 
648 p->aFile[i].zName = zName;
649 p->aFile[i].zUuid = zUuid;
650 p->aFile[i].zPerm = zPerm;
651 p->aFile[i].zPrior = zPriorName;
652 if( i>0 && fossil_strcmp(p->aFile[i-1].zName, zName)>=0 ){
653 SYNTAX("incorrect F-card sort order");
654 }
655 p->type = CFTYPE_MANIFEST;
656 break;
657 }
658
659 /*
660
--- src/manifest.c
+++ src/manifest.c
@@ -481,14 +481,23 @@
481 blob_appendf(pErr, "line 1 not recognized");
482 return 0;
483 }
484 /* Then verify the Z-card.
485 */
486 #if 1
487 /* Disable this ***ONLY*** (ONLY!) when testing hand-written inputs
488 for card-related syntax errors. */
489 if( verify_z_card(z, n, pErr)==2 ){
490 blob_reset(pContent);
491 return 0;
492 }
493 #else
494 #warning ACHTUNG - z-card check is disabled for testing purposes.
495 if(0 && verify_z_card(NULL, 0, NULL)){
496 /*avoid unused static func error*/
497 }
498 #endif
499
500 /* Allocate a Manifest object to hold the parsed control artifact.
501 */
502 p = fossil_malloc( sizeof(*p) );
503 memset(p, 0, sizeof(*p));
@@ -601,10 +610,11 @@
610 case 'E': {
611 if( p->rEventDate>0.0 ) SYNTAX("more than one E-card");
612 p->rEventDate = db_double(0.0,"SELECT julianday(%Q)", next_token(&x,0));
613 if( p->rEventDate<=0.0 ) SYNTAX("malformed date on E-card");
614 p->zEventId = next_token(&x, &sz);
615 if( p->zEventId==0 ) SYNTAX("missing hash on E-card");
616 if( !hname_validate(p->zEventId, sz) ){
617 SYNTAX("malformed hash on E-card");
618 }
619 p->type = CFTYPE_EVENT;
620 break;
@@ -625,10 +635,11 @@
635 if( !file_is_simple_pathname_nonstrict(zName) ){
636 SYNTAX("F-card filename is not a simple path");
637 }
638 zUuid = next_token(&x, &sz);
639 if( p->zBaseline==0 || zUuid!=0 ){
640 if( zUuid==0 ) SYNTAX("missing hash on F-card");
641 if( !hname_validate(zUuid,sz) ){
642 SYNTAX("F-card hash invalid");
643 }
644 }
645 zPerm = next_token(&x,0);
@@ -643,17 +654,24 @@
654 p->nFileAlloc = p->nFileAlloc*2 + 10;
655 p->aFile = fossil_realloc(p->aFile,
656 p->nFileAlloc*sizeof(p->aFile[0]) );
657 }
658 i = p->nFile++;
659 if( i>0 && fossil_strcmp(p->aFile[i-1].zName, zName)>=0 ){
660 SYNTAX("incorrect F-card sort order");
661 }
662 if( file_is_reserved_name(zName,-1) ){
663 /* If reserved names leaked into historical manifests due to
664 ** slack oversight by older versions of Fossil, simply ignore
665 ** those files */
666 p->nFile--;
667 break;
668 }
669 p->aFile[i].zName = zName;
670 p->aFile[i].zUuid = zUuid;
671 p->aFile[i].zPerm = zPerm;
672 p->aFile[i].zPrior = zPriorName;
 
 
 
673 p->type = CFTYPE_MANIFEST;
674 break;
675 }
676
677 /*
678
+21 -3
--- src/manifest.c
+++ src/manifest.c
@@ -481,14 +481,23 @@
481481
blob_appendf(pErr, "line 1 not recognized");
482482
return 0;
483483
}
484484
/* Then verify the Z-card.
485485
*/
486
+#if 1
487
+ /* Disable this ***ONLY*** (ONLY!) when testing hand-written inputs
488
+ for card-related syntax errors. */
486489
if( verify_z_card(z, n, pErr)==2 ){
487490
blob_reset(pContent);
488491
return 0;
489492
}
493
+#else
494
+#warning ACHTUNG - z-card check is disabled for testing purposes.
495
+ if(0 && verify_z_card(NULL, 0, NULL)){
496
+ /*avoid unused static func error*/
497
+ }
498
+#endif
490499
491500
/* Allocate a Manifest object to hold the parsed control artifact.
492501
*/
493502
p = fossil_malloc( sizeof(*p) );
494503
memset(p, 0, sizeof(*p));
@@ -601,10 +610,11 @@
601610
case 'E': {
602611
if( p->rEventDate>0.0 ) SYNTAX("more than one E-card");
603612
p->rEventDate = db_double(0.0,"SELECT julianday(%Q)", next_token(&x,0));
604613
if( p->rEventDate<=0.0 ) SYNTAX("malformed date on E-card");
605614
p->zEventId = next_token(&x, &sz);
615
+ if( p->zEventId==0 ) SYNTAX("missing hash on E-card");
606616
if( !hname_validate(p->zEventId, sz) ){
607617
SYNTAX("malformed hash on E-card");
608618
}
609619
p->type = CFTYPE_EVENT;
610620
break;
@@ -625,10 +635,11 @@
625635
if( !file_is_simple_pathname_nonstrict(zName) ){
626636
SYNTAX("F-card filename is not a simple path");
627637
}
628638
zUuid = next_token(&x, &sz);
629639
if( p->zBaseline==0 || zUuid!=0 ){
640
+ if( zUuid==0 ) SYNTAX("missing hash on F-card");
630641
if( !hname_validate(zUuid,sz) ){
631642
SYNTAX("F-card hash invalid");
632643
}
633644
}
634645
zPerm = next_token(&x,0);
@@ -643,17 +654,24 @@
643654
p->nFileAlloc = p->nFileAlloc*2 + 10;
644655
p->aFile = fossil_realloc(p->aFile,
645656
p->nFileAlloc*sizeof(p->aFile[0]) );
646657
}
647658
i = p->nFile++;
659
+ if( i>0 && fossil_strcmp(p->aFile[i-1].zName, zName)>=0 ){
660
+ SYNTAX("incorrect F-card sort order");
661
+ }
662
+ if( file_is_reserved_name(zName,-1) ){
663
+ /* If reserved names leaked into historical manifests due to
664
+ ** slack oversight by older versions of Fossil, simply ignore
665
+ ** those files */
666
+ p->nFile--;
667
+ break;
668
+ }
648669
p->aFile[i].zName = zName;
649670
p->aFile[i].zUuid = zUuid;
650671
p->aFile[i].zPerm = zPerm;
651672
p->aFile[i].zPrior = zPriorName;
652
- if( i>0 && fossil_strcmp(p->aFile[i-1].zName, zName)>=0 ){
653
- SYNTAX("incorrect F-card sort order");
654
- }
655673
p->type = CFTYPE_MANIFEST;
656674
break;
657675
}
658676
659677
/*
660678
--- src/manifest.c
+++ src/manifest.c
@@ -481,14 +481,23 @@
481 blob_appendf(pErr, "line 1 not recognized");
482 return 0;
483 }
484 /* Then verify the Z-card.
485 */
 
 
 
486 if( verify_z_card(z, n, pErr)==2 ){
487 blob_reset(pContent);
488 return 0;
489 }
 
 
 
 
 
 
490
491 /* Allocate a Manifest object to hold the parsed control artifact.
492 */
493 p = fossil_malloc( sizeof(*p) );
494 memset(p, 0, sizeof(*p));
@@ -601,10 +610,11 @@
601 case 'E': {
602 if( p->rEventDate>0.0 ) SYNTAX("more than one E-card");
603 p->rEventDate = db_double(0.0,"SELECT julianday(%Q)", next_token(&x,0));
604 if( p->rEventDate<=0.0 ) SYNTAX("malformed date on E-card");
605 p->zEventId = next_token(&x, &sz);
 
606 if( !hname_validate(p->zEventId, sz) ){
607 SYNTAX("malformed hash on E-card");
608 }
609 p->type = CFTYPE_EVENT;
610 break;
@@ -625,10 +635,11 @@
625 if( !file_is_simple_pathname_nonstrict(zName) ){
626 SYNTAX("F-card filename is not a simple path");
627 }
628 zUuid = next_token(&x, &sz);
629 if( p->zBaseline==0 || zUuid!=0 ){
 
630 if( !hname_validate(zUuid,sz) ){
631 SYNTAX("F-card hash invalid");
632 }
633 }
634 zPerm = next_token(&x,0);
@@ -643,17 +654,24 @@
643 p->nFileAlloc = p->nFileAlloc*2 + 10;
644 p->aFile = fossil_realloc(p->aFile,
645 p->nFileAlloc*sizeof(p->aFile[0]) );
646 }
647 i = p->nFile++;
 
 
 
 
 
 
 
 
 
 
648 p->aFile[i].zName = zName;
649 p->aFile[i].zUuid = zUuid;
650 p->aFile[i].zPerm = zPerm;
651 p->aFile[i].zPrior = zPriorName;
652 if( i>0 && fossil_strcmp(p->aFile[i-1].zName, zName)>=0 ){
653 SYNTAX("incorrect F-card sort order");
654 }
655 p->type = CFTYPE_MANIFEST;
656 break;
657 }
658
659 /*
660
--- src/manifest.c
+++ src/manifest.c
@@ -481,14 +481,23 @@
481 blob_appendf(pErr, "line 1 not recognized");
482 return 0;
483 }
484 /* Then verify the Z-card.
485 */
486 #if 1
487 /* Disable this ***ONLY*** (ONLY!) when testing hand-written inputs
488 for card-related syntax errors. */
489 if( verify_z_card(z, n, pErr)==2 ){
490 blob_reset(pContent);
491 return 0;
492 }
493 #else
494 #warning ACHTUNG - z-card check is disabled for testing purposes.
495 if(0 && verify_z_card(NULL, 0, NULL)){
496 /*avoid unused static func error*/
497 }
498 #endif
499
500 /* Allocate a Manifest object to hold the parsed control artifact.
501 */
502 p = fossil_malloc( sizeof(*p) );
503 memset(p, 0, sizeof(*p));
@@ -601,10 +610,11 @@
610 case 'E': {
611 if( p->rEventDate>0.0 ) SYNTAX("more than one E-card");
612 p->rEventDate = db_double(0.0,"SELECT julianday(%Q)", next_token(&x,0));
613 if( p->rEventDate<=0.0 ) SYNTAX("malformed date on E-card");
614 p->zEventId = next_token(&x, &sz);
615 if( p->zEventId==0 ) SYNTAX("missing hash on E-card");
616 if( !hname_validate(p->zEventId, sz) ){
617 SYNTAX("malformed hash on E-card");
618 }
619 p->type = CFTYPE_EVENT;
620 break;
@@ -625,10 +635,11 @@
635 if( !file_is_simple_pathname_nonstrict(zName) ){
636 SYNTAX("F-card filename is not a simple path");
637 }
638 zUuid = next_token(&x, &sz);
639 if( p->zBaseline==0 || zUuid!=0 ){
640 if( zUuid==0 ) SYNTAX("missing hash on F-card");
641 if( !hname_validate(zUuid,sz) ){
642 SYNTAX("F-card hash invalid");
643 }
644 }
645 zPerm = next_token(&x,0);
@@ -643,17 +654,24 @@
654 p->nFileAlloc = p->nFileAlloc*2 + 10;
655 p->aFile = fossil_realloc(p->aFile,
656 p->nFileAlloc*sizeof(p->aFile[0]) );
657 }
658 i = p->nFile++;
659 if( i>0 && fossil_strcmp(p->aFile[i-1].zName, zName)>=0 ){
660 SYNTAX("incorrect F-card sort order");
661 }
662 if( file_is_reserved_name(zName,-1) ){
663 /* If reserved names leaked into historical manifests due to
664 ** slack oversight by older versions of Fossil, simply ignore
665 ** those files */
666 p->nFile--;
667 break;
668 }
669 p->aFile[i].zName = zName;
670 p->aFile[i].zUuid = zUuid;
671 p->aFile[i].zPerm = zPerm;
672 p->aFile[i].zPrior = zPriorName;
 
 
 
673 p->type = CFTYPE_MANIFEST;
674 break;
675 }
676
677 /*
678
+21 -3
--- src/manifest.c
+++ src/manifest.c
@@ -481,14 +481,23 @@
481481
blob_appendf(pErr, "line 1 not recognized");
482482
return 0;
483483
}
484484
/* Then verify the Z-card.
485485
*/
486
+#if 1
487
+ /* Disable this ***ONLY*** (ONLY!) when testing hand-written inputs
488
+ for card-related syntax errors. */
486489
if( verify_z_card(z, n, pErr)==2 ){
487490
blob_reset(pContent);
488491
return 0;
489492
}
493
+#else
494
+#warning ACHTUNG - z-card check is disabled for testing purposes.
495
+ if(0 && verify_z_card(NULL, 0, NULL)){
496
+ /*avoid unused static func error*/
497
+ }
498
+#endif
490499
491500
/* Allocate a Manifest object to hold the parsed control artifact.
492501
*/
493502
p = fossil_malloc( sizeof(*p) );
494503
memset(p, 0, sizeof(*p));
@@ -601,10 +610,11 @@
601610
case 'E': {
602611
if( p->rEventDate>0.0 ) SYNTAX("more than one E-card");
603612
p->rEventDate = db_double(0.0,"SELECT julianday(%Q)", next_token(&x,0));
604613
if( p->rEventDate<=0.0 ) SYNTAX("malformed date on E-card");
605614
p->zEventId = next_token(&x, &sz);
615
+ if( p->zEventId==0 ) SYNTAX("missing hash on E-card");
606616
if( !hname_validate(p->zEventId, sz) ){
607617
SYNTAX("malformed hash on E-card");
608618
}
609619
p->type = CFTYPE_EVENT;
610620
break;
@@ -625,10 +635,11 @@
625635
if( !file_is_simple_pathname_nonstrict(zName) ){
626636
SYNTAX("F-card filename is not a simple path");
627637
}
628638
zUuid = next_token(&x, &sz);
629639
if( p->zBaseline==0 || zUuid!=0 ){
640
+ if( zUuid==0 ) SYNTAX("missing hash on F-card");
630641
if( !hname_validate(zUuid,sz) ){
631642
SYNTAX("F-card hash invalid");
632643
}
633644
}
634645
zPerm = next_token(&x,0);
@@ -643,17 +654,24 @@
643654
p->nFileAlloc = p->nFileAlloc*2 + 10;
644655
p->aFile = fossil_realloc(p->aFile,
645656
p->nFileAlloc*sizeof(p->aFile[0]) );
646657
}
647658
i = p->nFile++;
659
+ if( i>0 && fossil_strcmp(p->aFile[i-1].zName, zName)>=0 ){
660
+ SYNTAX("incorrect F-card sort order");
661
+ }
662
+ if( file_is_reserved_name(zName,-1) ){
663
+ /* If reserved names leaked into historical manifests due to
664
+ ** slack oversight by older versions of Fossil, simply ignore
665
+ ** those files */
666
+ p->nFile--;
667
+ break;
668
+ }
648669
p->aFile[i].zName = zName;
649670
p->aFile[i].zUuid = zUuid;
650671
p->aFile[i].zPerm = zPerm;
651672
p->aFile[i].zPrior = zPriorName;
652
- if( i>0 && fossil_strcmp(p->aFile[i-1].zName, zName)>=0 ){
653
- SYNTAX("incorrect F-card sort order");
654
- }
655673
p->type = CFTYPE_MANIFEST;
656674
break;
657675
}
658676
659677
/*
660678
--- src/manifest.c
+++ src/manifest.c
@@ -481,14 +481,23 @@
481 blob_appendf(pErr, "line 1 not recognized");
482 return 0;
483 }
484 /* Then verify the Z-card.
485 */
 
 
 
486 if( verify_z_card(z, n, pErr)==2 ){
487 blob_reset(pContent);
488 return 0;
489 }
 
 
 
 
 
 
490
491 /* Allocate a Manifest object to hold the parsed control artifact.
492 */
493 p = fossil_malloc( sizeof(*p) );
494 memset(p, 0, sizeof(*p));
@@ -601,10 +610,11 @@
601 case 'E': {
602 if( p->rEventDate>0.0 ) SYNTAX("more than one E-card");
603 p->rEventDate = db_double(0.0,"SELECT julianday(%Q)", next_token(&x,0));
604 if( p->rEventDate<=0.0 ) SYNTAX("malformed date on E-card");
605 p->zEventId = next_token(&x, &sz);
 
606 if( !hname_validate(p->zEventId, sz) ){
607 SYNTAX("malformed hash on E-card");
608 }
609 p->type = CFTYPE_EVENT;
610 break;
@@ -625,10 +635,11 @@
625 if( !file_is_simple_pathname_nonstrict(zName) ){
626 SYNTAX("F-card filename is not a simple path");
627 }
628 zUuid = next_token(&x, &sz);
629 if( p->zBaseline==0 || zUuid!=0 ){
 
630 if( !hname_validate(zUuid,sz) ){
631 SYNTAX("F-card hash invalid");
632 }
633 }
634 zPerm = next_token(&x,0);
@@ -643,17 +654,24 @@
643 p->nFileAlloc = p->nFileAlloc*2 + 10;
644 p->aFile = fossil_realloc(p->aFile,
645 p->nFileAlloc*sizeof(p->aFile[0]) );
646 }
647 i = p->nFile++;
 
 
 
 
 
 
 
 
 
 
648 p->aFile[i].zName = zName;
649 p->aFile[i].zUuid = zUuid;
650 p->aFile[i].zPerm = zPerm;
651 p->aFile[i].zPrior = zPriorName;
652 if( i>0 && fossil_strcmp(p->aFile[i-1].zName, zName)>=0 ){
653 SYNTAX("incorrect F-card sort order");
654 }
655 p->type = CFTYPE_MANIFEST;
656 break;
657 }
658
659 /*
660
--- src/manifest.c
+++ src/manifest.c
@@ -481,14 +481,23 @@
481 blob_appendf(pErr, "line 1 not recognized");
482 return 0;
483 }
484 /* Then verify the Z-card.
485 */
486 #if 1
487 /* Disable this ***ONLY*** (ONLY!) when testing hand-written inputs
488 for card-related syntax errors. */
489 if( verify_z_card(z, n, pErr)==2 ){
490 blob_reset(pContent);
491 return 0;
492 }
493 #else
494 #warning ACHTUNG - z-card check is disabled for testing purposes.
495 if(0 && verify_z_card(NULL, 0, NULL)){
496 /*avoid unused static func error*/
497 }
498 #endif
499
500 /* Allocate a Manifest object to hold the parsed control artifact.
501 */
502 p = fossil_malloc( sizeof(*p) );
503 memset(p, 0, sizeof(*p));
@@ -601,10 +610,11 @@
610 case 'E': {
611 if( p->rEventDate>0.0 ) SYNTAX("more than one E-card");
612 p->rEventDate = db_double(0.0,"SELECT julianday(%Q)", next_token(&x,0));
613 if( p->rEventDate<=0.0 ) SYNTAX("malformed date on E-card");
614 p->zEventId = next_token(&x, &sz);
615 if( p->zEventId==0 ) SYNTAX("missing hash on E-card");
616 if( !hname_validate(p->zEventId, sz) ){
617 SYNTAX("malformed hash on E-card");
618 }
619 p->type = CFTYPE_EVENT;
620 break;
@@ -625,10 +635,11 @@
635 if( !file_is_simple_pathname_nonstrict(zName) ){
636 SYNTAX("F-card filename is not a simple path");
637 }
638 zUuid = next_token(&x, &sz);
639 if( p->zBaseline==0 || zUuid!=0 ){
640 if( zUuid==0 ) SYNTAX("missing hash on F-card");
641 if( !hname_validate(zUuid,sz) ){
642 SYNTAX("F-card hash invalid");
643 }
644 }
645 zPerm = next_token(&x,0);
@@ -643,17 +654,24 @@
654 p->nFileAlloc = p->nFileAlloc*2 + 10;
655 p->aFile = fossil_realloc(p->aFile,
656 p->nFileAlloc*sizeof(p->aFile[0]) );
657 }
658 i = p->nFile++;
659 if( i>0 && fossil_strcmp(p->aFile[i-1].zName, zName)>=0 ){
660 SYNTAX("incorrect F-card sort order");
661 }
662 if( file_is_reserved_name(zName,-1) ){
663 /* If reserved names leaked into historical manifests due to
664 ** slack oversight by older versions of Fossil, simply ignore
665 ** those files */
666 p->nFile--;
667 break;
668 }
669 p->aFile[i].zName = zName;
670 p->aFile[i].zUuid = zUuid;
671 p->aFile[i].zPerm = zPerm;
672 p->aFile[i].zPrior = zPriorName;
 
 
 
673 p->type = CFTYPE_MANIFEST;
674 break;
675 }
676
677 /*
678
+21 -3
--- src/manifest.c
+++ src/manifest.c
@@ -481,14 +481,23 @@
481481
blob_appendf(pErr, "line 1 not recognized");
482482
return 0;
483483
}
484484
/* Then verify the Z-card.
485485
*/
486
+#if 1
487
+ /* Disable this ***ONLY*** (ONLY!) when testing hand-written inputs
488
+ for card-related syntax errors. */
486489
if( verify_z_card(z, n, pErr)==2 ){
487490
blob_reset(pContent);
488491
return 0;
489492
}
493
+#else
494
+#warning ACHTUNG - z-card check is disabled for testing purposes.
495
+ if(0 && verify_z_card(NULL, 0, NULL)){
496
+ /*avoid unused static func error*/
497
+ }
498
+#endif
490499
491500
/* Allocate a Manifest object to hold the parsed control artifact.
492501
*/
493502
p = fossil_malloc( sizeof(*p) );
494503
memset(p, 0, sizeof(*p));
@@ -601,10 +610,11 @@
601610
case 'E': {
602611
if( p->rEventDate>0.0 ) SYNTAX("more than one E-card");
603612
p->rEventDate = db_double(0.0,"SELECT julianday(%Q)", next_token(&x,0));
604613
if( p->rEventDate<=0.0 ) SYNTAX("malformed date on E-card");
605614
p->zEventId = next_token(&x, &sz);
615
+ if( p->zEventId==0 ) SYNTAX("missing hash on E-card");
606616
if( !hname_validate(p->zEventId, sz) ){
607617
SYNTAX("malformed hash on E-card");
608618
}
609619
p->type = CFTYPE_EVENT;
610620
break;
@@ -625,10 +635,11 @@
625635
if( !file_is_simple_pathname_nonstrict(zName) ){
626636
SYNTAX("F-card filename is not a simple path");
627637
}
628638
zUuid = next_token(&x, &sz);
629639
if( p->zBaseline==0 || zUuid!=0 ){
640
+ if( zUuid==0 ) SYNTAX("missing hash on F-card");
630641
if( !hname_validate(zUuid,sz) ){
631642
SYNTAX("F-card hash invalid");
632643
}
633644
}
634645
zPerm = next_token(&x,0);
@@ -643,17 +654,24 @@
643654
p->nFileAlloc = p->nFileAlloc*2 + 10;
644655
p->aFile = fossil_realloc(p->aFile,
645656
p->nFileAlloc*sizeof(p->aFile[0]) );
646657
}
647658
i = p->nFile++;
659
+ if( i>0 && fossil_strcmp(p->aFile[i-1].zName, zName)>=0 ){
660
+ SYNTAX("incorrect F-card sort order");
661
+ }
662
+ if( file_is_reserved_name(zName,-1) ){
663
+ /* If reserved names leaked into historical manifests due to
664
+ ** slack oversight by older versions of Fossil, simply ignore
665
+ ** those files */
666
+ p->nFile--;
667
+ break;
668
+ }
648669
p->aFile[i].zName = zName;
649670
p->aFile[i].zUuid = zUuid;
650671
p->aFile[i].zPerm = zPerm;
651672
p->aFile[i].zPrior = zPriorName;
652
- if( i>0 && fossil_strcmp(p->aFile[i-1].zName, zName)>=0 ){
653
- SYNTAX("incorrect F-card sort order");
654
- }
655673
p->type = CFTYPE_MANIFEST;
656674
break;
657675
}
658676
659677
/*
660678
--- src/manifest.c
+++ src/manifest.c
@@ -481,14 +481,23 @@
481 blob_appendf(pErr, "line 1 not recognized");
482 return 0;
483 }
484 /* Then verify the Z-card.
485 */
 
 
 
486 if( verify_z_card(z, n, pErr)==2 ){
487 blob_reset(pContent);
488 return 0;
489 }
 
 
 
 
 
 
490
491 /* Allocate a Manifest object to hold the parsed control artifact.
492 */
493 p = fossil_malloc( sizeof(*p) );
494 memset(p, 0, sizeof(*p));
@@ -601,10 +610,11 @@
601 case 'E': {
602 if( p->rEventDate>0.0 ) SYNTAX("more than one E-card");
603 p->rEventDate = db_double(0.0,"SELECT julianday(%Q)", next_token(&x,0));
604 if( p->rEventDate<=0.0 ) SYNTAX("malformed date on E-card");
605 p->zEventId = next_token(&x, &sz);
 
606 if( !hname_validate(p->zEventId, sz) ){
607 SYNTAX("malformed hash on E-card");
608 }
609 p->type = CFTYPE_EVENT;
610 break;
@@ -625,10 +635,11 @@
625 if( !file_is_simple_pathname_nonstrict(zName) ){
626 SYNTAX("F-card filename is not a simple path");
627 }
628 zUuid = next_token(&x, &sz);
629 if( p->zBaseline==0 || zUuid!=0 ){
 
630 if( !hname_validate(zUuid,sz) ){
631 SYNTAX("F-card hash invalid");
632 }
633 }
634 zPerm = next_token(&x,0);
@@ -643,17 +654,24 @@
643 p->nFileAlloc = p->nFileAlloc*2 + 10;
644 p->aFile = fossil_realloc(p->aFile,
645 p->nFileAlloc*sizeof(p->aFile[0]) );
646 }
647 i = p->nFile++;
 
 
 
 
 
 
 
 
 
 
648 p->aFile[i].zName = zName;
649 p->aFile[i].zUuid = zUuid;
650 p->aFile[i].zPerm = zPerm;
651 p->aFile[i].zPrior = zPriorName;
652 if( i>0 && fossil_strcmp(p->aFile[i-1].zName, zName)>=0 ){
653 SYNTAX("incorrect F-card sort order");
654 }
655 p->type = CFTYPE_MANIFEST;
656 break;
657 }
658
659 /*
660
--- src/manifest.c
+++ src/manifest.c
@@ -481,14 +481,23 @@
481 blob_appendf(pErr, "line 1 not recognized");
482 return 0;
483 }
484 /* Then verify the Z-card.
485 */
486 #if 1
487 /* Disable this ***ONLY*** (ONLY!) when testing hand-written inputs
488 for card-related syntax errors. */
489 if( verify_z_card(z, n, pErr)==2 ){
490 blob_reset(pContent);
491 return 0;
492 }
493 #else
494 #warning ACHTUNG - z-card check is disabled for testing purposes.
495 if(0 && verify_z_card(NULL, 0, NULL)){
496 /*avoid unused static func error*/
497 }
498 #endif
499
500 /* Allocate a Manifest object to hold the parsed control artifact.
501 */
502 p = fossil_malloc( sizeof(*p) );
503 memset(p, 0, sizeof(*p));
@@ -601,10 +610,11 @@
610 case 'E': {
611 if( p->rEventDate>0.0 ) SYNTAX("more than one E-card");
612 p->rEventDate = db_double(0.0,"SELECT julianday(%Q)", next_token(&x,0));
613 if( p->rEventDate<=0.0 ) SYNTAX("malformed date on E-card");
614 p->zEventId = next_token(&x, &sz);
615 if( p->zEventId==0 ) SYNTAX("missing hash on E-card");
616 if( !hname_validate(p->zEventId, sz) ){
617 SYNTAX("malformed hash on E-card");
618 }
619 p->type = CFTYPE_EVENT;
620 break;
@@ -625,10 +635,11 @@
635 if( !file_is_simple_pathname_nonstrict(zName) ){
636 SYNTAX("F-card filename is not a simple path");
637 }
638 zUuid = next_token(&x, &sz);
639 if( p->zBaseline==0 || zUuid!=0 ){
640 if( zUuid==0 ) SYNTAX("missing hash on F-card");
641 if( !hname_validate(zUuid,sz) ){
642 SYNTAX("F-card hash invalid");
643 }
644 }
645 zPerm = next_token(&x,0);
@@ -643,17 +654,24 @@
654 p->nFileAlloc = p->nFileAlloc*2 + 10;
655 p->aFile = fossil_realloc(p->aFile,
656 p->nFileAlloc*sizeof(p->aFile[0]) );
657 }
658 i = p->nFile++;
659 if( i>0 && fossil_strcmp(p->aFile[i-1].zName, zName)>=0 ){
660 SYNTAX("incorrect F-card sort order");
661 }
662 if( file_is_reserved_name(zName,-1) ){
663 /* If reserved names leaked into historical manifests due to
664 ** slack oversight by older versions of Fossil, simply ignore
665 ** those files */
666 p->nFile--;
667 break;
668 }
669 p->aFile[i].zName = zName;
670 p->aFile[i].zUuid = zUuid;
671 p->aFile[i].zPerm = zPerm;
672 p->aFile[i].zPrior = zPriorName;
 
 
 
673 p->type = CFTYPE_MANIFEST;
674 break;
675 }
676
677 /*
678
+21 -3
--- src/manifest.c
+++ src/manifest.c
@@ -481,14 +481,23 @@
481481
blob_appendf(pErr, "line 1 not recognized");
482482
return 0;
483483
}
484484
/* Then verify the Z-card.
485485
*/
486
+#if 1
487
+ /* Disable this ***ONLY*** (ONLY!) when testing hand-written inputs
488
+ for card-related syntax errors. */
486489
if( verify_z_card(z, n, pErr)==2 ){
487490
blob_reset(pContent);
488491
return 0;
489492
}
493
+#else
494
+#warning ACHTUNG - z-card check is disabled for testing purposes.
495
+ if(0 && verify_z_card(NULL, 0, NULL)){
496
+ /*avoid unused static func error*/
497
+ }
498
+#endif
490499
491500
/* Allocate a Manifest object to hold the parsed control artifact.
492501
*/
493502
p = fossil_malloc( sizeof(*p) );
494503
memset(p, 0, sizeof(*p));
@@ -601,10 +610,11 @@
601610
case 'E': {
602611
if( p->rEventDate>0.0 ) SYNTAX("more than one E-card");
603612
p->rEventDate = db_double(0.0,"SELECT julianday(%Q)", next_token(&x,0));
604613
if( p->rEventDate<=0.0 ) SYNTAX("malformed date on E-card");
605614
p->zEventId = next_token(&x, &sz);
615
+ if( p->zEventId==0 ) SYNTAX("missing hash on E-card");
606616
if( !hname_validate(p->zEventId, sz) ){
607617
SYNTAX("malformed hash on E-card");
608618
}
609619
p->type = CFTYPE_EVENT;
610620
break;
@@ -625,10 +635,11 @@
625635
if( !file_is_simple_pathname_nonstrict(zName) ){
626636
SYNTAX("F-card filename is not a simple path");
627637
}
628638
zUuid = next_token(&x, &sz);
629639
if( p->zBaseline==0 || zUuid!=0 ){
640
+ if( zUuid==0 ) SYNTAX("missing hash on F-card");
630641
if( !hname_validate(zUuid,sz) ){
631642
SYNTAX("F-card hash invalid");
632643
}
633644
}
634645
zPerm = next_token(&x,0);
@@ -643,17 +654,24 @@
643654
p->nFileAlloc = p->nFileAlloc*2 + 10;
644655
p->aFile = fossil_realloc(p->aFile,
645656
p->nFileAlloc*sizeof(p->aFile[0]) );
646657
}
647658
i = p->nFile++;
659
+ if( i>0 && fossil_strcmp(p->aFile[i-1].zName, zName)>=0 ){
660
+ SYNTAX("incorrect F-card sort order");
661
+ }
662
+ if( file_is_reserved_name(zName,-1) ){
663
+ /* If reserved names leaked into historical manifests due to
664
+ ** slack oversight by older versions of Fossil, simply ignore
665
+ ** those files */
666
+ p->nFile--;
667
+ break;
668
+ }
648669
p->aFile[i].zName = zName;
649670
p->aFile[i].zUuid = zUuid;
650671
p->aFile[i].zPerm = zPerm;
651672
p->aFile[i].zPrior = zPriorName;
652
- if( i>0 && fossil_strcmp(p->aFile[i-1].zName, zName)>=0 ){
653
- SYNTAX("incorrect F-card sort order");
654
- }
655673
p->type = CFTYPE_MANIFEST;
656674
break;
657675
}
658676
659677
/*
660678
--- src/manifest.c
+++ src/manifest.c
@@ -481,14 +481,23 @@
481 blob_appendf(pErr, "line 1 not recognized");
482 return 0;
483 }
484 /* Then verify the Z-card.
485 */
 
 
 
486 if( verify_z_card(z, n, pErr)==2 ){
487 blob_reset(pContent);
488 return 0;
489 }
 
 
 
 
 
 
490
491 /* Allocate a Manifest object to hold the parsed control artifact.
492 */
493 p = fossil_malloc( sizeof(*p) );
494 memset(p, 0, sizeof(*p));
@@ -601,10 +610,11 @@
601 case 'E': {
602 if( p->rEventDate>0.0 ) SYNTAX("more than one E-card");
603 p->rEventDate = db_double(0.0,"SELECT julianday(%Q)", next_token(&x,0));
604 if( p->rEventDate<=0.0 ) SYNTAX("malformed date on E-card");
605 p->zEventId = next_token(&x, &sz);
 
606 if( !hname_validate(p->zEventId, sz) ){
607 SYNTAX("malformed hash on E-card");
608 }
609 p->type = CFTYPE_EVENT;
610 break;
@@ -625,10 +635,11 @@
625 if( !file_is_simple_pathname_nonstrict(zName) ){
626 SYNTAX("F-card filename is not a simple path");
627 }
628 zUuid = next_token(&x, &sz);
629 if( p->zBaseline==0 || zUuid!=0 ){
 
630 if( !hname_validate(zUuid,sz) ){
631 SYNTAX("F-card hash invalid");
632 }
633 }
634 zPerm = next_token(&x,0);
@@ -643,17 +654,24 @@
643 p->nFileAlloc = p->nFileAlloc*2 + 10;
644 p->aFile = fossil_realloc(p->aFile,
645 p->nFileAlloc*sizeof(p->aFile[0]) );
646 }
647 i = p->nFile++;
 
 
 
 
 
 
 
 
 
 
648 p->aFile[i].zName = zName;
649 p->aFile[i].zUuid = zUuid;
650 p->aFile[i].zPerm = zPerm;
651 p->aFile[i].zPrior = zPriorName;
652 if( i>0 && fossil_strcmp(p->aFile[i-1].zName, zName)>=0 ){
653 SYNTAX("incorrect F-card sort order");
654 }
655 p->type = CFTYPE_MANIFEST;
656 break;
657 }
658
659 /*
660
--- src/manifest.c
+++ src/manifest.c
@@ -481,14 +481,23 @@
481 blob_appendf(pErr, "line 1 not recognized");
482 return 0;
483 }
484 /* Then verify the Z-card.
485 */
486 #if 1
487 /* Disable this ***ONLY*** (ONLY!) when testing hand-written inputs
488 for card-related syntax errors. */
489 if( verify_z_card(z, n, pErr)==2 ){
490 blob_reset(pContent);
491 return 0;
492 }
493 #else
494 #warning ACHTUNG - z-card check is disabled for testing purposes.
495 if(0 && verify_z_card(NULL, 0, NULL)){
496 /*avoid unused static func error*/
497 }
498 #endif
499
500 /* Allocate a Manifest object to hold the parsed control artifact.
501 */
502 p = fossil_malloc( sizeof(*p) );
503 memset(p, 0, sizeof(*p));
@@ -601,10 +610,11 @@
610 case 'E': {
611 if( p->rEventDate>0.0 ) SYNTAX("more than one E-card");
612 p->rEventDate = db_double(0.0,"SELECT julianday(%Q)", next_token(&x,0));
613 if( p->rEventDate<=0.0 ) SYNTAX("malformed date on E-card");
614 p->zEventId = next_token(&x, &sz);
615 if( p->zEventId==0 ) SYNTAX("missing hash on E-card");
616 if( !hname_validate(p->zEventId, sz) ){
617 SYNTAX("malformed hash on E-card");
618 }
619 p->type = CFTYPE_EVENT;
620 break;
@@ -625,10 +635,11 @@
635 if( !file_is_simple_pathname_nonstrict(zName) ){
636 SYNTAX("F-card filename is not a simple path");
637 }
638 zUuid = next_token(&x, &sz);
639 if( p->zBaseline==0 || zUuid!=0 ){
640 if( zUuid==0 ) SYNTAX("missing hash on F-card");
641 if( !hname_validate(zUuid,sz) ){
642 SYNTAX("F-card hash invalid");
643 }
644 }
645 zPerm = next_token(&x,0);
@@ -643,17 +654,24 @@
654 p->nFileAlloc = p->nFileAlloc*2 + 10;
655 p->aFile = fossil_realloc(p->aFile,
656 p->nFileAlloc*sizeof(p->aFile[0]) );
657 }
658 i = p->nFile++;
659 if( i>0 && fossil_strcmp(p->aFile[i-1].zName, zName)>=0 ){
660 SYNTAX("incorrect F-card sort order");
661 }
662 if( file_is_reserved_name(zName,-1) ){
663 /* If reserved names leaked into historical manifests due to
664 ** slack oversight by older versions of Fossil, simply ignore
665 ** those files */
666 p->nFile--;
667 break;
668 }
669 p->aFile[i].zName = zName;
670 p->aFile[i].zUuid = zUuid;
671 p->aFile[i].zPerm = zPerm;
672 p->aFile[i].zPrior = zPriorName;
 
 
 
673 p->type = CFTYPE_MANIFEST;
674 break;
675 }
676
677 /*
678
+21 -3
--- src/manifest.c
+++ src/manifest.c
@@ -481,14 +481,23 @@
481481
blob_appendf(pErr, "line 1 not recognized");
482482
return 0;
483483
}
484484
/* Then verify the Z-card.
485485
*/
486
+#if 1
487
+ /* Disable this ***ONLY*** (ONLY!) when testing hand-written inputs
488
+ for card-related syntax errors. */
486489
if( verify_z_card(z, n, pErr)==2 ){
487490
blob_reset(pContent);
488491
return 0;
489492
}
493
+#else
494
+#warning ACHTUNG - z-card check is disabled for testing purposes.
495
+ if(0 && verify_z_card(NULL, 0, NULL)){
496
+ /*avoid unused static func error*/
497
+ }
498
+#endif
490499
491500
/* Allocate a Manifest object to hold the parsed control artifact.
492501
*/
493502
p = fossil_malloc( sizeof(*p) );
494503
memset(p, 0, sizeof(*p));
@@ -601,10 +610,11 @@
601610
case 'E': {
602611
if( p->rEventDate>0.0 ) SYNTAX("more than one E-card");
603612
p->rEventDate = db_double(0.0,"SELECT julianday(%Q)", next_token(&x,0));
604613
if( p->rEventDate<=0.0 ) SYNTAX("malformed date on E-card");
605614
p->zEventId = next_token(&x, &sz);
615
+ if( p->zEventId==0 ) SYNTAX("missing hash on E-card");
606616
if( !hname_validate(p->zEventId, sz) ){
607617
SYNTAX("malformed hash on E-card");
608618
}
609619
p->type = CFTYPE_EVENT;
610620
break;
@@ -625,10 +635,11 @@
625635
if( !file_is_simple_pathname_nonstrict(zName) ){
626636
SYNTAX("F-card filename is not a simple path");
627637
}
628638
zUuid = next_token(&x, &sz);
629639
if( p->zBaseline==0 || zUuid!=0 ){
640
+ if( zUuid==0 ) SYNTAX("missing hash on F-card");
630641
if( !hname_validate(zUuid,sz) ){
631642
SYNTAX("F-card hash invalid");
632643
}
633644
}
634645
zPerm = next_token(&x,0);
@@ -643,17 +654,24 @@
643654
p->nFileAlloc = p->nFileAlloc*2 + 10;
644655
p->aFile = fossil_realloc(p->aFile,
645656
p->nFileAlloc*sizeof(p->aFile[0]) );
646657
}
647658
i = p->nFile++;
659
+ if( i>0 && fossil_strcmp(p->aFile[i-1].zName, zName)>=0 ){
660
+ SYNTAX("incorrect F-card sort order");
661
+ }
662
+ if( file_is_reserved_name(zName,-1) ){
663
+ /* If reserved names leaked into historical manifests due to
664
+ ** slack oversight by older versions of Fossil, simply ignore
665
+ ** those files */
666
+ p->nFile--;
667
+ break;
668
+ }
648669
p->aFile[i].zName = zName;
649670
p->aFile[i].zUuid = zUuid;
650671
p->aFile[i].zPerm = zPerm;
651672
p->aFile[i].zPrior = zPriorName;
652
- if( i>0 && fossil_strcmp(p->aFile[i-1].zName, zName)>=0 ){
653
- SYNTAX("incorrect F-card sort order");
654
- }
655673
p->type = CFTYPE_MANIFEST;
656674
break;
657675
}
658676
659677
/*
660678
--- src/manifest.c
+++ src/manifest.c
@@ -481,14 +481,23 @@
481 blob_appendf(pErr, "line 1 not recognized");
482 return 0;
483 }
484 /* Then verify the Z-card.
485 */
 
 
 
486 if( verify_z_card(z, n, pErr)==2 ){
487 blob_reset(pContent);
488 return 0;
489 }
 
 
 
 
 
 
490
491 /* Allocate a Manifest object to hold the parsed control artifact.
492 */
493 p = fossil_malloc( sizeof(*p) );
494 memset(p, 0, sizeof(*p));
@@ -601,10 +610,11 @@
601 case 'E': {
602 if( p->rEventDate>0.0 ) SYNTAX("more than one E-card");
603 p->rEventDate = db_double(0.0,"SELECT julianday(%Q)", next_token(&x,0));
604 if( p->rEventDate<=0.0 ) SYNTAX("malformed date on E-card");
605 p->zEventId = next_token(&x, &sz);
 
606 if( !hname_validate(p->zEventId, sz) ){
607 SYNTAX("malformed hash on E-card");
608 }
609 p->type = CFTYPE_EVENT;
610 break;
@@ -625,10 +635,11 @@
625 if( !file_is_simple_pathname_nonstrict(zName) ){
626 SYNTAX("F-card filename is not a simple path");
627 }
628 zUuid = next_token(&x, &sz);
629 if( p->zBaseline==0 || zUuid!=0 ){
 
630 if( !hname_validate(zUuid,sz) ){
631 SYNTAX("F-card hash invalid");
632 }
633 }
634 zPerm = next_token(&x,0);
@@ -643,17 +654,24 @@
643 p->nFileAlloc = p->nFileAlloc*2 + 10;
644 p->aFile = fossil_realloc(p->aFile,
645 p->nFileAlloc*sizeof(p->aFile[0]) );
646 }
647 i = p->nFile++;
 
 
 
 
 
 
 
 
 
 
648 p->aFile[i].zName = zName;
649 p->aFile[i].zUuid = zUuid;
650 p->aFile[i].zPerm = zPerm;
651 p->aFile[i].zPrior = zPriorName;
652 if( i>0 && fossil_strcmp(p->aFile[i-1].zName, zName)>=0 ){
653 SYNTAX("incorrect F-card sort order");
654 }
655 p->type = CFTYPE_MANIFEST;
656 break;
657 }
658
659 /*
660
--- src/manifest.c
+++ src/manifest.c
@@ -481,14 +481,23 @@
481 blob_appendf(pErr, "line 1 not recognized");
482 return 0;
483 }
484 /* Then verify the Z-card.
485 */
486 #if 1
487 /* Disable this ***ONLY*** (ONLY!) when testing hand-written inputs
488 for card-related syntax errors. */
489 if( verify_z_card(z, n, pErr)==2 ){
490 blob_reset(pContent);
491 return 0;
492 }
493 #else
494 #warning ACHTUNG - z-card check is disabled for testing purposes.
495 if(0 && verify_z_card(NULL, 0, NULL)){
496 /*avoid unused static func error*/
497 }
498 #endif
499
500 /* Allocate a Manifest object to hold the parsed control artifact.
501 */
502 p = fossil_malloc( sizeof(*p) );
503 memset(p, 0, sizeof(*p));
@@ -601,10 +610,11 @@
610 case 'E': {
611 if( p->rEventDate>0.0 ) SYNTAX("more than one E-card");
612 p->rEventDate = db_double(0.0,"SELECT julianday(%Q)", next_token(&x,0));
613 if( p->rEventDate<=0.0 ) SYNTAX("malformed date on E-card");
614 p->zEventId = next_token(&x, &sz);
615 if( p->zEventId==0 ) SYNTAX("missing hash on E-card");
616 if( !hname_validate(p->zEventId, sz) ){
617 SYNTAX("malformed hash on E-card");
618 }
619 p->type = CFTYPE_EVENT;
620 break;
@@ -625,10 +635,11 @@
635 if( !file_is_simple_pathname_nonstrict(zName) ){
636 SYNTAX("F-card filename is not a simple path");
637 }
638 zUuid = next_token(&x, &sz);
639 if( p->zBaseline==0 || zUuid!=0 ){
640 if( zUuid==0 ) SYNTAX("missing hash on F-card");
641 if( !hname_validate(zUuid,sz) ){
642 SYNTAX("F-card hash invalid");
643 }
644 }
645 zPerm = next_token(&x,0);
@@ -643,17 +654,24 @@
654 p->nFileAlloc = p->nFileAlloc*2 + 10;
655 p->aFile = fossil_realloc(p->aFile,
656 p->nFileAlloc*sizeof(p->aFile[0]) );
657 }
658 i = p->nFile++;
659 if( i>0 && fossil_strcmp(p->aFile[i-1].zName, zName)>=0 ){
660 SYNTAX("incorrect F-card sort order");
661 }
662 if( file_is_reserved_name(zName,-1) ){
663 /* If reserved names leaked into historical manifests due to
664 ** slack oversight by older versions of Fossil, simply ignore
665 ** those files */
666 p->nFile--;
667 break;
668 }
669 p->aFile[i].zName = zName;
670 p->aFile[i].zUuid = zUuid;
671 p->aFile[i].zPerm = zPerm;
672 p->aFile[i].zPrior = zPriorName;
 
 
 
673 p->type = CFTYPE_MANIFEST;
674 break;
675 }
676
677 /*
678
+21 -3
--- src/manifest.c
+++ src/manifest.c
@@ -481,14 +481,23 @@
481481
blob_appendf(pErr, "line 1 not recognized");
482482
return 0;
483483
}
484484
/* Then verify the Z-card.
485485
*/
486
+#if 1
487
+ /* Disable this ***ONLY*** (ONLY!) when testing hand-written inputs
488
+ for card-related syntax errors. */
486489
if( verify_z_card(z, n, pErr)==2 ){
487490
blob_reset(pContent);
488491
return 0;
489492
}
493
+#else
494
+#warning ACHTUNG - z-card check is disabled for testing purposes.
495
+ if(0 && verify_z_card(NULL, 0, NULL)){
496
+ /*avoid unused static func error*/
497
+ }
498
+#endif
490499
491500
/* Allocate a Manifest object to hold the parsed control artifact.
492501
*/
493502
p = fossil_malloc( sizeof(*p) );
494503
memset(p, 0, sizeof(*p));
@@ -601,10 +610,11 @@
601610
case 'E': {
602611
if( p->rEventDate>0.0 ) SYNTAX("more than one E-card");
603612
p->rEventDate = db_double(0.0,"SELECT julianday(%Q)", next_token(&x,0));
604613
if( p->rEventDate<=0.0 ) SYNTAX("malformed date on E-card");
605614
p->zEventId = next_token(&x, &sz);
615
+ if( p->zEventId==0 ) SYNTAX("missing hash on E-card");
606616
if( !hname_validate(p->zEventId, sz) ){
607617
SYNTAX("malformed hash on E-card");
608618
}
609619
p->type = CFTYPE_EVENT;
610620
break;
@@ -625,10 +635,11 @@
625635
if( !file_is_simple_pathname_nonstrict(zName) ){
626636
SYNTAX("F-card filename is not a simple path");
627637
}
628638
zUuid = next_token(&x, &sz);
629639
if( p->zBaseline==0 || zUuid!=0 ){
640
+ if( zUuid==0 ) SYNTAX("missing hash on F-card");
630641
if( !hname_validate(zUuid,sz) ){
631642
SYNTAX("F-card hash invalid");
632643
}
633644
}
634645
zPerm = next_token(&x,0);
@@ -643,17 +654,24 @@
643654
p->nFileAlloc = p->nFileAlloc*2 + 10;
644655
p->aFile = fossil_realloc(p->aFile,
645656
p->nFileAlloc*sizeof(p->aFile[0]) );
646657
}
647658
i = p->nFile++;
659
+ if( i>0 && fossil_strcmp(p->aFile[i-1].zName, zName)>=0 ){
660
+ SYNTAX("incorrect F-card sort order");
661
+ }
662
+ if( file_is_reserved_name(zName,-1) ){
663
+ /* If reserved names leaked into historical manifests due to
664
+ ** slack oversight by older versions of Fossil, simply ignore
665
+ ** those files */
666
+ p->nFile--;
667
+ break;
668
+ }
648669
p->aFile[i].zName = zName;
649670
p->aFile[i].zUuid = zUuid;
650671
p->aFile[i].zPerm = zPerm;
651672
p->aFile[i].zPrior = zPriorName;
652
- if( i>0 && fossil_strcmp(p->aFile[i-1].zName, zName)>=0 ){
653
- SYNTAX("incorrect F-card sort order");
654
- }
655673
p->type = CFTYPE_MANIFEST;
656674
break;
657675
}
658676
659677
/*
660678
--- src/manifest.c
+++ src/manifest.c
@@ -481,14 +481,23 @@
481 blob_appendf(pErr, "line 1 not recognized");
482 return 0;
483 }
484 /* Then verify the Z-card.
485 */
 
 
 
486 if( verify_z_card(z, n, pErr)==2 ){
487 blob_reset(pContent);
488 return 0;
489 }
 
 
 
 
 
 
490
491 /* Allocate a Manifest object to hold the parsed control artifact.
492 */
493 p = fossil_malloc( sizeof(*p) );
494 memset(p, 0, sizeof(*p));
@@ -601,10 +610,11 @@
601 case 'E': {
602 if( p->rEventDate>0.0 ) SYNTAX("more than one E-card");
603 p->rEventDate = db_double(0.0,"SELECT julianday(%Q)", next_token(&x,0));
604 if( p->rEventDate<=0.0 ) SYNTAX("malformed date on E-card");
605 p->zEventId = next_token(&x, &sz);
 
606 if( !hname_validate(p->zEventId, sz) ){
607 SYNTAX("malformed hash on E-card");
608 }
609 p->type = CFTYPE_EVENT;
610 break;
@@ -625,10 +635,11 @@
625 if( !file_is_simple_pathname_nonstrict(zName) ){
626 SYNTAX("F-card filename is not a simple path");
627 }
628 zUuid = next_token(&x, &sz);
629 if( p->zBaseline==0 || zUuid!=0 ){
 
630 if( !hname_validate(zUuid,sz) ){
631 SYNTAX("F-card hash invalid");
632 }
633 }
634 zPerm = next_token(&x,0);
@@ -643,17 +654,24 @@
643 p->nFileAlloc = p->nFileAlloc*2 + 10;
644 p->aFile = fossil_realloc(p->aFile,
645 p->nFileAlloc*sizeof(p->aFile[0]) );
646 }
647 i = p->nFile++;
 
 
 
 
 
 
 
 
 
 
648 p->aFile[i].zName = zName;
649 p->aFile[i].zUuid = zUuid;
650 p->aFile[i].zPerm = zPerm;
651 p->aFile[i].zPrior = zPriorName;
652 if( i>0 && fossil_strcmp(p->aFile[i-1].zName, zName)>=0 ){
653 SYNTAX("incorrect F-card sort order");
654 }
655 p->type = CFTYPE_MANIFEST;
656 break;
657 }
658
659 /*
660
--- src/manifest.c
+++ src/manifest.c
@@ -481,14 +481,23 @@
481 blob_appendf(pErr, "line 1 not recognized");
482 return 0;
483 }
484 /* Then verify the Z-card.
485 */
486 #if 1
487 /* Disable this ***ONLY*** (ONLY!) when testing hand-written inputs
488 for card-related syntax errors. */
489 if( verify_z_card(z, n, pErr)==2 ){
490 blob_reset(pContent);
491 return 0;
492 }
493 #else
494 #warning ACHTUNG - z-card check is disabled for testing purposes.
495 if(0 && verify_z_card(NULL, 0, NULL)){
496 /*avoid unused static func error*/
497 }
498 #endif
499
500 /* Allocate a Manifest object to hold the parsed control artifact.
501 */
502 p = fossil_malloc( sizeof(*p) );
503 memset(p, 0, sizeof(*p));
@@ -601,10 +610,11 @@
610 case 'E': {
611 if( p->rEventDate>0.0 ) SYNTAX("more than one E-card");
612 p->rEventDate = db_double(0.0,"SELECT julianday(%Q)", next_token(&x,0));
613 if( p->rEventDate<=0.0 ) SYNTAX("malformed date on E-card");
614 p->zEventId = next_token(&x, &sz);
615 if( p->zEventId==0 ) SYNTAX("missing hash on E-card");
616 if( !hname_validate(p->zEventId, sz) ){
617 SYNTAX("malformed hash on E-card");
618 }
619 p->type = CFTYPE_EVENT;
620 break;
@@ -625,10 +635,11 @@
635 if( !file_is_simple_pathname_nonstrict(zName) ){
636 SYNTAX("F-card filename is not a simple path");
637 }
638 zUuid = next_token(&x, &sz);
639 if( p->zBaseline==0 || zUuid!=0 ){
640 if( zUuid==0 ) SYNTAX("missing hash on F-card");
641 if( !hname_validate(zUuid,sz) ){
642 SYNTAX("F-card hash invalid");
643 }
644 }
645 zPerm = next_token(&x,0);
@@ -643,17 +654,24 @@
654 p->nFileAlloc = p->nFileAlloc*2 + 10;
655 p->aFile = fossil_realloc(p->aFile,
656 p->nFileAlloc*sizeof(p->aFile[0]) );
657 }
658 i = p->nFile++;
659 if( i>0 && fossil_strcmp(p->aFile[i-1].zName, zName)>=0 ){
660 SYNTAX("incorrect F-card sort order");
661 }
662 if( file_is_reserved_name(zName,-1) ){
663 /* If reserved names leaked into historical manifests due to
664 ** slack oversight by older versions of Fossil, simply ignore
665 ** those files */
666 p->nFile--;
667 break;
668 }
669 p->aFile[i].zName = zName;
670 p->aFile[i].zUuid = zUuid;
671 p->aFile[i].zPerm = zPerm;
672 p->aFile[i].zPrior = zPriorName;
 
 
 
673 p->type = CFTYPE_MANIFEST;
674 break;
675 }
676
677 /*
678
+3 -3
--- src/report.c
+++ src/report.c
@@ -230,15 +230,15 @@
230230
231231
/*
232232
** Activate the query authorizer
233233
*/
234234
void report_restrict_sql(char **pzErr){
235
- sqlite3_set_authorizer(g.db, report_query_authorizer, (void*)pzErr);
235
+ db_set_authorizer(report_query_authorizer,(void*)pzErr,"Ticket-Report");
236236
sqlite3_limit(g.db, SQLITE_LIMIT_VDBE_OP, 10000);
237237
}
238238
void report_unrestrict_sql(void){
239
- sqlite3_set_authorizer(g.db, 0, 0);
239
+ db_clear_authorizer();
240240
}
241241
242242
243243
/*
244244
** Check the given SQL to see if is a valid query that does not
@@ -680,11 +680,11 @@
680680
*/
681681
if( pState->nCount==0 ){
682682
/* Turn off the authorizer. It is no longer doing anything since the
683683
** query has already been prepared.
684684
*/
685
- sqlite3_set_authorizer(g.db, 0, 0);
685
+ db_clear_authorizer();
686686
687687
/* Figure out the number of columns, the column that determines background
688688
** color, and whether or not this row of data is represented by multiple
689689
** rows in the table.
690690
*/
691691
--- src/report.c
+++ src/report.c
@@ -230,15 +230,15 @@
230
231 /*
232 ** Activate the query authorizer
233 */
234 void report_restrict_sql(char **pzErr){
235 sqlite3_set_authorizer(g.db, report_query_authorizer, (void*)pzErr);
236 sqlite3_limit(g.db, SQLITE_LIMIT_VDBE_OP, 10000);
237 }
238 void report_unrestrict_sql(void){
239 sqlite3_set_authorizer(g.db, 0, 0);
240 }
241
242
243 /*
244 ** Check the given SQL to see if is a valid query that does not
@@ -680,11 +680,11 @@
680 */
681 if( pState->nCount==0 ){
682 /* Turn off the authorizer. It is no longer doing anything since the
683 ** query has already been prepared.
684 */
685 sqlite3_set_authorizer(g.db, 0, 0);
686
687 /* Figure out the number of columns, the column that determines background
688 ** color, and whether or not this row of data is represented by multiple
689 ** rows in the table.
690 */
691
--- src/report.c
+++ src/report.c
@@ -230,15 +230,15 @@
230
231 /*
232 ** Activate the query authorizer
233 */
234 void report_restrict_sql(char **pzErr){
235 db_set_authorizer(report_query_authorizer,(void*)pzErr,"Ticket-Report");
236 sqlite3_limit(g.db, SQLITE_LIMIT_VDBE_OP, 10000);
237 }
238 void report_unrestrict_sql(void){
239 db_clear_authorizer();
240 }
241
242
243 /*
244 ** Check the given SQL to see if is a valid query that does not
@@ -680,11 +680,11 @@
680 */
681 if( pState->nCount==0 ){
682 /* Turn off the authorizer. It is no longer doing anything since the
683 ** query has already been prepared.
684 */
685 db_clear_authorizer();
686
687 /* Figure out the number of columns, the column that determines background
688 ** color, and whether or not this row of data is represented by multiple
689 ** rows in the table.
690 */
691
+3 -3
--- src/report.c
+++ src/report.c
@@ -230,15 +230,15 @@
230230
231231
/*
232232
** Activate the query authorizer
233233
*/
234234
void report_restrict_sql(char **pzErr){
235
- sqlite3_set_authorizer(g.db, report_query_authorizer, (void*)pzErr);
235
+ db_set_authorizer(report_query_authorizer,(void*)pzErr,"Ticket-Report");
236236
sqlite3_limit(g.db, SQLITE_LIMIT_VDBE_OP, 10000);
237237
}
238238
void report_unrestrict_sql(void){
239
- sqlite3_set_authorizer(g.db, 0, 0);
239
+ db_clear_authorizer();
240240
}
241241
242242
243243
/*
244244
** Check the given SQL to see if is a valid query that does not
@@ -680,11 +680,11 @@
680680
*/
681681
if( pState->nCount==0 ){
682682
/* Turn off the authorizer. It is no longer doing anything since the
683683
** query has already been prepared.
684684
*/
685
- sqlite3_set_authorizer(g.db, 0, 0);
685
+ db_clear_authorizer();
686686
687687
/* Figure out the number of columns, the column that determines background
688688
** color, and whether or not this row of data is represented by multiple
689689
** rows in the table.
690690
*/
691691
--- src/report.c
+++ src/report.c
@@ -230,15 +230,15 @@
230
231 /*
232 ** Activate the query authorizer
233 */
234 void report_restrict_sql(char **pzErr){
235 sqlite3_set_authorizer(g.db, report_query_authorizer, (void*)pzErr);
236 sqlite3_limit(g.db, SQLITE_LIMIT_VDBE_OP, 10000);
237 }
238 void report_unrestrict_sql(void){
239 sqlite3_set_authorizer(g.db, 0, 0);
240 }
241
242
243 /*
244 ** Check the given SQL to see if is a valid query that does not
@@ -680,11 +680,11 @@
680 */
681 if( pState->nCount==0 ){
682 /* Turn off the authorizer. It is no longer doing anything since the
683 ** query has already been prepared.
684 */
685 sqlite3_set_authorizer(g.db, 0, 0);
686
687 /* Figure out the number of columns, the column that determines background
688 ** color, and whether or not this row of data is represented by multiple
689 ** rows in the table.
690 */
691
--- src/report.c
+++ src/report.c
@@ -230,15 +230,15 @@
230
231 /*
232 ** Activate the query authorizer
233 */
234 void report_restrict_sql(char **pzErr){
235 db_set_authorizer(report_query_authorizer,(void*)pzErr,"Ticket-Report");
236 sqlite3_limit(g.db, SQLITE_LIMIT_VDBE_OP, 10000);
237 }
238 void report_unrestrict_sql(void){
239 db_clear_authorizer();
240 }
241
242
243 /*
244 ** Check the given SQL to see if is a valid query that does not
@@ -680,11 +680,11 @@
680 */
681 if( pState->nCount==0 ){
682 /* Turn off the authorizer. It is no longer doing anything since the
683 ** query has already been prepared.
684 */
685 db_clear_authorizer();
686
687 /* Figure out the number of columns, the column that determines background
688 ** color, and whether or not this row of data is represented by multiple
689 ** rows in the table.
690 */
691
+72
--- src/tkt.c
+++ src/tkt.c
@@ -370,10 +370,79 @@
370370
Th_FossilInit(TH_INIT_DEFAULT);
371371
Th_Store("uuid", zUuid);
372372
zConfig = ticket_change_code();
373373
return Th_Eval(g.interp, 0, zConfig, -1);
374374
}
375
+
376
+/*
377
+** An authorizer function for the SQL used to initialize the
378
+** schema for the ticketing system. Only allow CREATE TABLE and
379
+** CREATE INDEX for tables whose names begin with "ticket" and
380
+** changes to tables whose names begin with "ticket".
381
+*/
382
+static int ticket_schema_auth(
383
+ void *pNErr,
384
+ int eCode,
385
+ const char *z0,
386
+ const char *z1,
387
+ const char *z2,
388
+ const char *z3
389
+){
390
+ switch( eCode ){
391
+ case SQLITE_CREATE_TABLE: {
392
+ if( sqlite3_stricmp(z2,"main")!=0
393
+ && sqlite3_stricmp(z2,"repository")!=0
394
+ ){
395
+ goto ticket_schema_error;
396
+ }
397
+ if( sqlite3_strnicmp(z0,"ticket",6)!=0 ){
398
+ goto ticket_schema_error;
399
+ }
400
+ break;
401
+ }
402
+ case SQLITE_CREATE_INDEX: {
403
+ if( sqlite3_stricmp(z2,"main")!=0
404
+ && sqlite3_stricmp(z2,"repository")!=0
405
+ ){
406
+ goto ticket_schema_error;
407
+ }
408
+ if( sqlite3_strnicmp(z1,"ticket",6)!=0 ){
409
+ goto ticket_schema_error;
410
+ }
411
+ break;
412
+ }
413
+ case SQLITE_INSERT:
414
+ case SQLITE_UPDATE:
415
+ case SQLITE_DELETE: {
416
+ if( sqlite3_stricmp(z2,"main")!=0
417
+ && sqlite3_stricmp(z2,"repository")!=0
418
+ ){
419
+ goto ticket_schema_error;
420
+ }
421
+ if( sqlite3_strnicmp(z0,"ticket",6)!=0
422
+ && sqlite3_strnicmp(z0,"sqlite_",7)!=0
423
+ ){
424
+ goto ticket_schema_error;
425
+ }
426
+ break;
427
+ }
428
+ case SQLITE_REINDEX:
429
+ case SQLITE_TRANSACTION:
430
+ case SQLITE_READ: {
431
+ break;
432
+ }
433
+ default: {
434
+ goto ticket_schema_error;
435
+ }
436
+ }
437
+ return SQLITE_OK;
438
+
439
+ticket_schema_error:
440
+ if( pNErr ) *(int*)pNErr = 1;
441
+ return SQLITE_DENY;
442
+}
443
+
375444
376445
/*
377446
** Recreate the TICKET and TICKETCHNG tables.
378447
*/
379448
void ticket_create_table(int separateConnection){
@@ -384,14 +453,17 @@
384453
"DROP TABLE IF EXISTS ticketchng;"
385454
);
386455
zSql = ticket_table_schema();
387456
if( separateConnection ){
388457
if( db_transaction_nesting_depth() ) db_end_transaction(0);
458
+ db_set_authorizer(ticket_schema_auth,0,"Ticket-Schema");
389459
db_init_database(g.zRepositoryName, zSql, 0);
390460
}else{
461
+ db_set_authorizer(ticket_schema_auth,0,"Ticket-Schema");
391462
db_multi_exec("%s", zSql/*safe-for-%s*/);
392463
}
464
+ db_clear_authorizer();
393465
fossil_free(zSql);
394466
}
395467
396468
/*
397469
** Repopulate the TICKET and TICKETCHNG tables from scratch using all
398470
--- src/tkt.c
+++ src/tkt.c
@@ -370,10 +370,79 @@
370 Th_FossilInit(TH_INIT_DEFAULT);
371 Th_Store("uuid", zUuid);
372 zConfig = ticket_change_code();
373 return Th_Eval(g.interp, 0, zConfig, -1);
374 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
375
376 /*
377 ** Recreate the TICKET and TICKETCHNG tables.
378 */
379 void ticket_create_table(int separateConnection){
@@ -384,14 +453,17 @@
384 "DROP TABLE IF EXISTS ticketchng;"
385 );
386 zSql = ticket_table_schema();
387 if( separateConnection ){
388 if( db_transaction_nesting_depth() ) db_end_transaction(0);
 
389 db_init_database(g.zRepositoryName, zSql, 0);
390 }else{
 
391 db_multi_exec("%s", zSql/*safe-for-%s*/);
392 }
 
393 fossil_free(zSql);
394 }
395
396 /*
397 ** Repopulate the TICKET and TICKETCHNG tables from scratch using all
398
--- src/tkt.c
+++ src/tkt.c
@@ -370,10 +370,79 @@
370 Th_FossilInit(TH_INIT_DEFAULT);
371 Th_Store("uuid", zUuid);
372 zConfig = ticket_change_code();
373 return Th_Eval(g.interp, 0, zConfig, -1);
374 }
375
376 /*
377 ** An authorizer function for the SQL used to initialize the
378 ** schema for the ticketing system. Only allow CREATE TABLE and
379 ** CREATE INDEX for tables whose names begin with "ticket" and
380 ** changes to tables whose names begin with "ticket".
381 */
382 static int ticket_schema_auth(
383 void *pNErr,
384 int eCode,
385 const char *z0,
386 const char *z1,
387 const char *z2,
388 const char *z3
389 ){
390 switch( eCode ){
391 case SQLITE_CREATE_TABLE: {
392 if( sqlite3_stricmp(z2,"main")!=0
393 && sqlite3_stricmp(z2,"repository")!=0
394 ){
395 goto ticket_schema_error;
396 }
397 if( sqlite3_strnicmp(z0,"ticket",6)!=0 ){
398 goto ticket_schema_error;
399 }
400 break;
401 }
402 case SQLITE_CREATE_INDEX: {
403 if( sqlite3_stricmp(z2,"main")!=0
404 && sqlite3_stricmp(z2,"repository")!=0
405 ){
406 goto ticket_schema_error;
407 }
408 if( sqlite3_strnicmp(z1,"ticket",6)!=0 ){
409 goto ticket_schema_error;
410 }
411 break;
412 }
413 case SQLITE_INSERT:
414 case SQLITE_UPDATE:
415 case SQLITE_DELETE: {
416 if( sqlite3_stricmp(z2,"main")!=0
417 && sqlite3_stricmp(z2,"repository")!=0
418 ){
419 goto ticket_schema_error;
420 }
421 if( sqlite3_strnicmp(z0,"ticket",6)!=0
422 && sqlite3_strnicmp(z0,"sqlite_",7)!=0
423 ){
424 goto ticket_schema_error;
425 }
426 break;
427 }
428 case SQLITE_REINDEX:
429 case SQLITE_TRANSACTION:
430 case SQLITE_READ: {
431 break;
432 }
433 default: {
434 goto ticket_schema_error;
435 }
436 }
437 return SQLITE_OK;
438
439 ticket_schema_error:
440 if( pNErr ) *(int*)pNErr = 1;
441 return SQLITE_DENY;
442 }
443
444
445 /*
446 ** Recreate the TICKET and TICKETCHNG tables.
447 */
448 void ticket_create_table(int separateConnection){
@@ -384,14 +453,17 @@
453 "DROP TABLE IF EXISTS ticketchng;"
454 );
455 zSql = ticket_table_schema();
456 if( separateConnection ){
457 if( db_transaction_nesting_depth() ) db_end_transaction(0);
458 db_set_authorizer(ticket_schema_auth,0,"Ticket-Schema");
459 db_init_database(g.zRepositoryName, zSql, 0);
460 }else{
461 db_set_authorizer(ticket_schema_auth,0,"Ticket-Schema");
462 db_multi_exec("%s", zSql/*safe-for-%s*/);
463 }
464 db_clear_authorizer();
465 fossil_free(zSql);
466 }
467
468 /*
469 ** Repopulate the TICKET and TICKETCHNG tables from scratch using all
470
+72
--- src/tkt.c
+++ src/tkt.c
@@ -370,10 +370,79 @@
370370
Th_FossilInit(TH_INIT_DEFAULT);
371371
Th_Store("uuid", zUuid);
372372
zConfig = ticket_change_code();
373373
return Th_Eval(g.interp, 0, zConfig, -1);
374374
}
375
+
376
+/*
377
+** An authorizer function for the SQL used to initialize the
378
+** schema for the ticketing system. Only allow CREATE TABLE and
379
+** CREATE INDEX for tables whose names begin with "ticket" and
380
+** changes to tables whose names begin with "ticket".
381
+*/
382
+static int ticket_schema_auth(
383
+ void *pNErr,
384
+ int eCode,
385
+ const char *z0,
386
+ const char *z1,
387
+ const char *z2,
388
+ const char *z3
389
+){
390
+ switch( eCode ){
391
+ case SQLITE_CREATE_TABLE: {
392
+ if( sqlite3_stricmp(z2,"main")!=0
393
+ && sqlite3_stricmp(z2,"repository")!=0
394
+ ){
395
+ goto ticket_schema_error;
396
+ }
397
+ if( sqlite3_strnicmp(z0,"ticket",6)!=0 ){
398
+ goto ticket_schema_error;
399
+ }
400
+ break;
401
+ }
402
+ case SQLITE_CREATE_INDEX: {
403
+ if( sqlite3_stricmp(z2,"main")!=0
404
+ && sqlite3_stricmp(z2,"repository")!=0
405
+ ){
406
+ goto ticket_schema_error;
407
+ }
408
+ if( sqlite3_strnicmp(z1,"ticket",6)!=0 ){
409
+ goto ticket_schema_error;
410
+ }
411
+ break;
412
+ }
413
+ case SQLITE_INSERT:
414
+ case SQLITE_UPDATE:
415
+ case SQLITE_DELETE: {
416
+ if( sqlite3_stricmp(z2,"main")!=0
417
+ && sqlite3_stricmp(z2,"repository")!=0
418
+ ){
419
+ goto ticket_schema_error;
420
+ }
421
+ if( sqlite3_strnicmp(z0,"ticket",6)!=0
422
+ && sqlite3_strnicmp(z0,"sqlite_",7)!=0
423
+ ){
424
+ goto ticket_schema_error;
425
+ }
426
+ break;
427
+ }
428
+ case SQLITE_REINDEX:
429
+ case SQLITE_TRANSACTION:
430
+ case SQLITE_READ: {
431
+ break;
432
+ }
433
+ default: {
434
+ goto ticket_schema_error;
435
+ }
436
+ }
437
+ return SQLITE_OK;
438
+
439
+ticket_schema_error:
440
+ if( pNErr ) *(int*)pNErr = 1;
441
+ return SQLITE_DENY;
442
+}
443
+
375444
376445
/*
377446
** Recreate the TICKET and TICKETCHNG tables.
378447
*/
379448
void ticket_create_table(int separateConnection){
@@ -384,14 +453,17 @@
384453
"DROP TABLE IF EXISTS ticketchng;"
385454
);
386455
zSql = ticket_table_schema();
387456
if( separateConnection ){
388457
if( db_transaction_nesting_depth() ) db_end_transaction(0);
458
+ db_set_authorizer(ticket_schema_auth,0,"Ticket-Schema");
389459
db_init_database(g.zRepositoryName, zSql, 0);
390460
}else{
461
+ db_set_authorizer(ticket_schema_auth,0,"Ticket-Schema");
391462
db_multi_exec("%s", zSql/*safe-for-%s*/);
392463
}
464
+ db_clear_authorizer();
393465
fossil_free(zSql);
394466
}
395467
396468
/*
397469
** Repopulate the TICKET and TICKETCHNG tables from scratch using all
398470
--- src/tkt.c
+++ src/tkt.c
@@ -370,10 +370,79 @@
370 Th_FossilInit(TH_INIT_DEFAULT);
371 Th_Store("uuid", zUuid);
372 zConfig = ticket_change_code();
373 return Th_Eval(g.interp, 0, zConfig, -1);
374 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
375
376 /*
377 ** Recreate the TICKET and TICKETCHNG tables.
378 */
379 void ticket_create_table(int separateConnection){
@@ -384,14 +453,17 @@
384 "DROP TABLE IF EXISTS ticketchng;"
385 );
386 zSql = ticket_table_schema();
387 if( separateConnection ){
388 if( db_transaction_nesting_depth() ) db_end_transaction(0);
 
389 db_init_database(g.zRepositoryName, zSql, 0);
390 }else{
 
391 db_multi_exec("%s", zSql/*safe-for-%s*/);
392 }
 
393 fossil_free(zSql);
394 }
395
396 /*
397 ** Repopulate the TICKET and TICKETCHNG tables from scratch using all
398
--- src/tkt.c
+++ src/tkt.c
@@ -370,10 +370,79 @@
370 Th_FossilInit(TH_INIT_DEFAULT);
371 Th_Store("uuid", zUuid);
372 zConfig = ticket_change_code();
373 return Th_Eval(g.interp, 0, zConfig, -1);
374 }
375
376 /*
377 ** An authorizer function for the SQL used to initialize the
378 ** schema for the ticketing system. Only allow CREATE TABLE and
379 ** CREATE INDEX for tables whose names begin with "ticket" and
380 ** changes to tables whose names begin with "ticket".
381 */
382 static int ticket_schema_auth(
383 void *pNErr,
384 int eCode,
385 const char *z0,
386 const char *z1,
387 const char *z2,
388 const char *z3
389 ){
390 switch( eCode ){
391 case SQLITE_CREATE_TABLE: {
392 if( sqlite3_stricmp(z2,"main")!=0
393 && sqlite3_stricmp(z2,"repository")!=0
394 ){
395 goto ticket_schema_error;
396 }
397 if( sqlite3_strnicmp(z0,"ticket",6)!=0 ){
398 goto ticket_schema_error;
399 }
400 break;
401 }
402 case SQLITE_CREATE_INDEX: {
403 if( sqlite3_stricmp(z2,"main")!=0
404 && sqlite3_stricmp(z2,"repository")!=0
405 ){
406 goto ticket_schema_error;
407 }
408 if( sqlite3_strnicmp(z1,"ticket",6)!=0 ){
409 goto ticket_schema_error;
410 }
411 break;
412 }
413 case SQLITE_INSERT:
414 case SQLITE_UPDATE:
415 case SQLITE_DELETE: {
416 if( sqlite3_stricmp(z2,"main")!=0
417 && sqlite3_stricmp(z2,"repository")!=0
418 ){
419 goto ticket_schema_error;
420 }
421 if( sqlite3_strnicmp(z0,"ticket",6)!=0
422 && sqlite3_strnicmp(z0,"sqlite_",7)!=0
423 ){
424 goto ticket_schema_error;
425 }
426 break;
427 }
428 case SQLITE_REINDEX:
429 case SQLITE_TRANSACTION:
430 case SQLITE_READ: {
431 break;
432 }
433 default: {
434 goto ticket_schema_error;
435 }
436 }
437 return SQLITE_OK;
438
439 ticket_schema_error:
440 if( pNErr ) *(int*)pNErr = 1;
441 return SQLITE_DENY;
442 }
443
444
445 /*
446 ** Recreate the TICKET and TICKETCHNG tables.
447 */
448 void ticket_create_table(int separateConnection){
@@ -384,14 +453,17 @@
453 "DROP TABLE IF EXISTS ticketchng;"
454 );
455 zSql = ticket_table_schema();
456 if( separateConnection ){
457 if( db_transaction_nesting_depth() ) db_end_transaction(0);
458 db_set_authorizer(ticket_schema_auth,0,"Ticket-Schema");
459 db_init_database(g.zRepositoryName, zSql, 0);
460 }else{
461 db_set_authorizer(ticket_schema_auth,0,"Ticket-Schema");
462 db_multi_exec("%s", zSql/*safe-for-%s*/);
463 }
464 db_clear_authorizer();
465 fossil_free(zSql);
466 }
467
468 /*
469 ** Repopulate the TICKET and TICKETCHNG tables from scratch using all
470
+72
--- src/tkt.c
+++ src/tkt.c
@@ -370,10 +370,79 @@
370370
Th_FossilInit(TH_INIT_DEFAULT);
371371
Th_Store("uuid", zUuid);
372372
zConfig = ticket_change_code();
373373
return Th_Eval(g.interp, 0, zConfig, -1);
374374
}
375
+
376
+/*
377
+** An authorizer function for the SQL used to initialize the
378
+** schema for the ticketing system. Only allow CREATE TABLE and
379
+** CREATE INDEX for tables whose names begin with "ticket" and
380
+** changes to tables whose names begin with "ticket".
381
+*/
382
+static int ticket_schema_auth(
383
+ void *pNErr,
384
+ int eCode,
385
+ const char *z0,
386
+ const char *z1,
387
+ const char *z2,
388
+ const char *z3
389
+){
390
+ switch( eCode ){
391
+ case SQLITE_CREATE_TABLE: {
392
+ if( sqlite3_stricmp(z2,"main")!=0
393
+ && sqlite3_stricmp(z2,"repository")!=0
394
+ ){
395
+ goto ticket_schema_error;
396
+ }
397
+ if( sqlite3_strnicmp(z0,"ticket",6)!=0 ){
398
+ goto ticket_schema_error;
399
+ }
400
+ break;
401
+ }
402
+ case SQLITE_CREATE_INDEX: {
403
+ if( sqlite3_stricmp(z2,"main")!=0
404
+ && sqlite3_stricmp(z2,"repository")!=0
405
+ ){
406
+ goto ticket_schema_error;
407
+ }
408
+ if( sqlite3_strnicmp(z1,"ticket",6)!=0 ){
409
+ goto ticket_schema_error;
410
+ }
411
+ break;
412
+ }
413
+ case SQLITE_INSERT:
414
+ case SQLITE_UPDATE:
415
+ case SQLITE_DELETE: {
416
+ if( sqlite3_stricmp(z2,"main")!=0
417
+ && sqlite3_stricmp(z2,"repository")!=0
418
+ ){
419
+ goto ticket_schema_error;
420
+ }
421
+ if( sqlite3_strnicmp(z0,"ticket",6)!=0
422
+ && sqlite3_strnicmp(z0,"sqlite_",7)!=0
423
+ ){
424
+ goto ticket_schema_error;
425
+ }
426
+ break;
427
+ }
428
+ case SQLITE_REINDEX:
429
+ case SQLITE_TRANSACTION:
430
+ case SQLITE_READ: {
431
+ break;
432
+ }
433
+ default: {
434
+ goto ticket_schema_error;
435
+ }
436
+ }
437
+ return SQLITE_OK;
438
+
439
+ticket_schema_error:
440
+ if( pNErr ) *(int*)pNErr = 1;
441
+ return SQLITE_DENY;
442
+}
443
+
375444
376445
/*
377446
** Recreate the TICKET and TICKETCHNG tables.
378447
*/
379448
void ticket_create_table(int separateConnection){
@@ -384,14 +453,17 @@
384453
"DROP TABLE IF EXISTS ticketchng;"
385454
);
386455
zSql = ticket_table_schema();
387456
if( separateConnection ){
388457
if( db_transaction_nesting_depth() ) db_end_transaction(0);
458
+ db_set_authorizer(ticket_schema_auth,0,"Ticket-Schema");
389459
db_init_database(g.zRepositoryName, zSql, 0);
390460
}else{
461
+ db_set_authorizer(ticket_schema_auth,0,"Ticket-Schema");
391462
db_multi_exec("%s", zSql/*safe-for-%s*/);
392463
}
464
+ db_clear_authorizer();
393465
fossil_free(zSql);
394466
}
395467
396468
/*
397469
** Repopulate the TICKET and TICKETCHNG tables from scratch using all
398470
--- src/tkt.c
+++ src/tkt.c
@@ -370,10 +370,79 @@
370 Th_FossilInit(TH_INIT_DEFAULT);
371 Th_Store("uuid", zUuid);
372 zConfig = ticket_change_code();
373 return Th_Eval(g.interp, 0, zConfig, -1);
374 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
375
376 /*
377 ** Recreate the TICKET and TICKETCHNG tables.
378 */
379 void ticket_create_table(int separateConnection){
@@ -384,14 +453,17 @@
384 "DROP TABLE IF EXISTS ticketchng;"
385 );
386 zSql = ticket_table_schema();
387 if( separateConnection ){
388 if( db_transaction_nesting_depth() ) db_end_transaction(0);
 
389 db_init_database(g.zRepositoryName, zSql, 0);
390 }else{
 
391 db_multi_exec("%s", zSql/*safe-for-%s*/);
392 }
 
393 fossil_free(zSql);
394 }
395
396 /*
397 ** Repopulate the TICKET and TICKETCHNG tables from scratch using all
398
--- src/tkt.c
+++ src/tkt.c
@@ -370,10 +370,79 @@
370 Th_FossilInit(TH_INIT_DEFAULT);
371 Th_Store("uuid", zUuid);
372 zConfig = ticket_change_code();
373 return Th_Eval(g.interp, 0, zConfig, -1);
374 }
375
376 /*
377 ** An authorizer function for the SQL used to initialize the
378 ** schema for the ticketing system. Only allow CREATE TABLE and
379 ** CREATE INDEX for tables whose names begin with "ticket" and
380 ** changes to tables whose names begin with "ticket".
381 */
382 static int ticket_schema_auth(
383 void *pNErr,
384 int eCode,
385 const char *z0,
386 const char *z1,
387 const char *z2,
388 const char *z3
389 ){
390 switch( eCode ){
391 case SQLITE_CREATE_TABLE: {
392 if( sqlite3_stricmp(z2,"main")!=0
393 && sqlite3_stricmp(z2,"repository")!=0
394 ){
395 goto ticket_schema_error;
396 }
397 if( sqlite3_strnicmp(z0,"ticket",6)!=0 ){
398 goto ticket_schema_error;
399 }
400 break;
401 }
402 case SQLITE_CREATE_INDEX: {
403 if( sqlite3_stricmp(z2,"main")!=0
404 && sqlite3_stricmp(z2,"repository")!=0
405 ){
406 goto ticket_schema_error;
407 }
408 if( sqlite3_strnicmp(z1,"ticket",6)!=0 ){
409 goto ticket_schema_error;
410 }
411 break;
412 }
413 case SQLITE_INSERT:
414 case SQLITE_UPDATE:
415 case SQLITE_DELETE: {
416 if( sqlite3_stricmp(z2,"main")!=0
417 && sqlite3_stricmp(z2,"repository")!=0
418 ){
419 goto ticket_schema_error;
420 }
421 if( sqlite3_strnicmp(z0,"ticket",6)!=0
422 && sqlite3_strnicmp(z0,"sqlite_",7)!=0
423 ){
424 goto ticket_schema_error;
425 }
426 break;
427 }
428 case SQLITE_REINDEX:
429 case SQLITE_TRANSACTION:
430 case SQLITE_READ: {
431 break;
432 }
433 default: {
434 goto ticket_schema_error;
435 }
436 }
437 return SQLITE_OK;
438
439 ticket_schema_error:
440 if( pNErr ) *(int*)pNErr = 1;
441 return SQLITE_DENY;
442 }
443
444
445 /*
446 ** Recreate the TICKET and TICKETCHNG tables.
447 */
448 void ticket_create_table(int separateConnection){
@@ -384,14 +453,17 @@
453 "DROP TABLE IF EXISTS ticketchng;"
454 );
455 zSql = ticket_table_schema();
456 if( separateConnection ){
457 if( db_transaction_nesting_depth() ) db_end_transaction(0);
458 db_set_authorizer(ticket_schema_auth,0,"Ticket-Schema");
459 db_init_database(g.zRepositoryName, zSql, 0);
460 }else{
461 db_set_authorizer(ticket_schema_auth,0,"Ticket-Schema");
462 db_multi_exec("%s", zSql/*safe-for-%s*/);
463 }
464 db_clear_authorizer();
465 fossil_free(zSql);
466 }
467
468 /*
469 ** Repopulate the TICKET and TICKETCHNG tables from scratch using all
470
+72
--- src/tkt.c
+++ src/tkt.c
@@ -370,10 +370,79 @@
370370
Th_FossilInit(TH_INIT_DEFAULT);
371371
Th_Store("uuid", zUuid);
372372
zConfig = ticket_change_code();
373373
return Th_Eval(g.interp, 0, zConfig, -1);
374374
}
375
+
376
+/*
377
+** An authorizer function for the SQL used to initialize the
378
+** schema for the ticketing system. Only allow CREATE TABLE and
379
+** CREATE INDEX for tables whose names begin with "ticket" and
380
+** changes to tables whose names begin with "ticket".
381
+*/
382
+static int ticket_schema_auth(
383
+ void *pNErr,
384
+ int eCode,
385
+ const char *z0,
386
+ const char *z1,
387
+ const char *z2,
388
+ const char *z3
389
+){
390
+ switch( eCode ){
391
+ case SQLITE_CREATE_TABLE: {
392
+ if( sqlite3_stricmp(z2,"main")!=0
393
+ && sqlite3_stricmp(z2,"repository")!=0
394
+ ){
395
+ goto ticket_schema_error;
396
+ }
397
+ if( sqlite3_strnicmp(z0,"ticket",6)!=0 ){
398
+ goto ticket_schema_error;
399
+ }
400
+ break;
401
+ }
402
+ case SQLITE_CREATE_INDEX: {
403
+ if( sqlite3_stricmp(z2,"main")!=0
404
+ && sqlite3_stricmp(z2,"repository")!=0
405
+ ){
406
+ goto ticket_schema_error;
407
+ }
408
+ if( sqlite3_strnicmp(z1,"ticket",6)!=0 ){
409
+ goto ticket_schema_error;
410
+ }
411
+ break;
412
+ }
413
+ case SQLITE_INSERT:
414
+ case SQLITE_UPDATE:
415
+ case SQLITE_DELETE: {
416
+ if( sqlite3_stricmp(z2,"main")!=0
417
+ && sqlite3_stricmp(z2,"repository")!=0
418
+ ){
419
+ goto ticket_schema_error;
420
+ }
421
+ if( sqlite3_strnicmp(z0,"ticket",6)!=0
422
+ && sqlite3_strnicmp(z0,"sqlite_",7)!=0
423
+ ){
424
+ goto ticket_schema_error;
425
+ }
426
+ break;
427
+ }
428
+ case SQLITE_REINDEX:
429
+ case SQLITE_TRANSACTION:
430
+ case SQLITE_READ: {
431
+ break;
432
+ }
433
+ default: {
434
+ goto ticket_schema_error;
435
+ }
436
+ }
437
+ return SQLITE_OK;
438
+
439
+ticket_schema_error:
440
+ if( pNErr ) *(int*)pNErr = 1;
441
+ return SQLITE_DENY;
442
+}
443
+
375444
376445
/*
377446
** Recreate the TICKET and TICKETCHNG tables.
378447
*/
379448
void ticket_create_table(int separateConnection){
@@ -384,14 +453,17 @@
384453
"DROP TABLE IF EXISTS ticketchng;"
385454
);
386455
zSql = ticket_table_schema();
387456
if( separateConnection ){
388457
if( db_transaction_nesting_depth() ) db_end_transaction(0);
458
+ db_set_authorizer(ticket_schema_auth,0,"Ticket-Schema");
389459
db_init_database(g.zRepositoryName, zSql, 0);
390460
}else{
461
+ db_set_authorizer(ticket_schema_auth,0,"Ticket-Schema");
391462
db_multi_exec("%s", zSql/*safe-for-%s*/);
392463
}
464
+ db_clear_authorizer();
393465
fossil_free(zSql);
394466
}
395467
396468
/*
397469
** Repopulate the TICKET and TICKETCHNG tables from scratch using all
398470
--- src/tkt.c
+++ src/tkt.c
@@ -370,10 +370,79 @@
370 Th_FossilInit(TH_INIT_DEFAULT);
371 Th_Store("uuid", zUuid);
372 zConfig = ticket_change_code();
373 return Th_Eval(g.interp, 0, zConfig, -1);
374 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
375
376 /*
377 ** Recreate the TICKET and TICKETCHNG tables.
378 */
379 void ticket_create_table(int separateConnection){
@@ -384,14 +453,17 @@
384 "DROP TABLE IF EXISTS ticketchng;"
385 );
386 zSql = ticket_table_schema();
387 if( separateConnection ){
388 if( db_transaction_nesting_depth() ) db_end_transaction(0);
 
389 db_init_database(g.zRepositoryName, zSql, 0);
390 }else{
 
391 db_multi_exec("%s", zSql/*safe-for-%s*/);
392 }
 
393 fossil_free(zSql);
394 }
395
396 /*
397 ** Repopulate the TICKET and TICKETCHNG tables from scratch using all
398
--- src/tkt.c
+++ src/tkt.c
@@ -370,10 +370,79 @@
370 Th_FossilInit(TH_INIT_DEFAULT);
371 Th_Store("uuid", zUuid);
372 zConfig = ticket_change_code();
373 return Th_Eval(g.interp, 0, zConfig, -1);
374 }
375
376 /*
377 ** An authorizer function for the SQL used to initialize the
378 ** schema for the ticketing system. Only allow CREATE TABLE and
379 ** CREATE INDEX for tables whose names begin with "ticket" and
380 ** changes to tables whose names begin with "ticket".
381 */
382 static int ticket_schema_auth(
383 void *pNErr,
384 int eCode,
385 const char *z0,
386 const char *z1,
387 const char *z2,
388 const char *z3
389 ){
390 switch( eCode ){
391 case SQLITE_CREATE_TABLE: {
392 if( sqlite3_stricmp(z2,"main")!=0
393 && sqlite3_stricmp(z2,"repository")!=0
394 ){
395 goto ticket_schema_error;
396 }
397 if( sqlite3_strnicmp(z0,"ticket",6)!=0 ){
398 goto ticket_schema_error;
399 }
400 break;
401 }
402 case SQLITE_CREATE_INDEX: {
403 if( sqlite3_stricmp(z2,"main")!=0
404 && sqlite3_stricmp(z2,"repository")!=0
405 ){
406 goto ticket_schema_error;
407 }
408 if( sqlite3_strnicmp(z1,"ticket",6)!=0 ){
409 goto ticket_schema_error;
410 }
411 break;
412 }
413 case SQLITE_INSERT:
414 case SQLITE_UPDATE:
415 case SQLITE_DELETE: {
416 if( sqlite3_stricmp(z2,"main")!=0
417 && sqlite3_stricmp(z2,"repository")!=0
418 ){
419 goto ticket_schema_error;
420 }
421 if( sqlite3_strnicmp(z0,"ticket",6)!=0
422 && sqlite3_strnicmp(z0,"sqlite_",7)!=0
423 ){
424 goto ticket_schema_error;
425 }
426 break;
427 }
428 case SQLITE_REINDEX:
429 case SQLITE_TRANSACTION:
430 case SQLITE_READ: {
431 break;
432 }
433 default: {
434 goto ticket_schema_error;
435 }
436 }
437 return SQLITE_OK;
438
439 ticket_schema_error:
440 if( pNErr ) *(int*)pNErr = 1;
441 return SQLITE_DENY;
442 }
443
444
445 /*
446 ** Recreate the TICKET and TICKETCHNG tables.
447 */
448 void ticket_create_table(int separateConnection){
@@ -384,14 +453,17 @@
453 "DROP TABLE IF EXISTS ticketchng;"
454 );
455 zSql = ticket_table_schema();
456 if( separateConnection ){
457 if( db_transaction_nesting_depth() ) db_end_transaction(0);
458 db_set_authorizer(ticket_schema_auth,0,"Ticket-Schema");
459 db_init_database(g.zRepositoryName, zSql, 0);
460 }else{
461 db_set_authorizer(ticket_schema_auth,0,"Ticket-Schema");
462 db_multi_exec("%s", zSql/*safe-for-%s*/);
463 }
464 db_clear_authorizer();
465 fossil_free(zSql);
466 }
467
468 /*
469 ** Repopulate the TICKET and TICKETCHNG tables from scratch using all
470
+72
--- src/tkt.c
+++ src/tkt.c
@@ -370,10 +370,79 @@
370370
Th_FossilInit(TH_INIT_DEFAULT);
371371
Th_Store("uuid", zUuid);
372372
zConfig = ticket_change_code();
373373
return Th_Eval(g.interp, 0, zConfig, -1);
374374
}
375
+
376
+/*
377
+** An authorizer function for the SQL used to initialize the
378
+** schema for the ticketing system. Only allow CREATE TABLE and
379
+** CREATE INDEX for tables whose names begin with "ticket" and
380
+** changes to tables whose names begin with "ticket".
381
+*/
382
+static int ticket_schema_auth(
383
+ void *pNErr,
384
+ int eCode,
385
+ const char *z0,
386
+ const char *z1,
387
+ const char *z2,
388
+ const char *z3
389
+){
390
+ switch( eCode ){
391
+ case SQLITE_CREATE_TABLE: {
392
+ if( sqlite3_stricmp(z2,"main")!=0
393
+ && sqlite3_stricmp(z2,"repository")!=0
394
+ ){
395
+ goto ticket_schema_error;
396
+ }
397
+ if( sqlite3_strnicmp(z0,"ticket",6)!=0 ){
398
+ goto ticket_schema_error;
399
+ }
400
+ break;
401
+ }
402
+ case SQLITE_CREATE_INDEX: {
403
+ if( sqlite3_stricmp(z2,"main")!=0
404
+ && sqlite3_stricmp(z2,"repository")!=0
405
+ ){
406
+ goto ticket_schema_error;
407
+ }
408
+ if( sqlite3_strnicmp(z1,"ticket",6)!=0 ){
409
+ goto ticket_schema_error;
410
+ }
411
+ break;
412
+ }
413
+ case SQLITE_INSERT:
414
+ case SQLITE_UPDATE:
415
+ case SQLITE_DELETE: {
416
+ if( sqlite3_stricmp(z2,"main")!=0
417
+ && sqlite3_stricmp(z2,"repository")!=0
418
+ ){
419
+ goto ticket_schema_error;
420
+ }
421
+ if( sqlite3_strnicmp(z0,"ticket",6)!=0
422
+ && sqlite3_strnicmp(z0,"sqlite_",7)!=0
423
+ ){
424
+ goto ticket_schema_error;
425
+ }
426
+ break;
427
+ }
428
+ case SQLITE_REINDEX:
429
+ case SQLITE_TRANSACTION:
430
+ case SQLITE_READ: {
431
+ break;
432
+ }
433
+ default: {
434
+ goto ticket_schema_error;
435
+ }
436
+ }
437
+ return SQLITE_OK;
438
+
439
+ticket_schema_error:
440
+ if( pNErr ) *(int*)pNErr = 1;
441
+ return SQLITE_DENY;
442
+}
443
+
375444
376445
/*
377446
** Recreate the TICKET and TICKETCHNG tables.
378447
*/
379448
void ticket_create_table(int separateConnection){
@@ -384,14 +453,17 @@
384453
"DROP TABLE IF EXISTS ticketchng;"
385454
);
386455
zSql = ticket_table_schema();
387456
if( separateConnection ){
388457
if( db_transaction_nesting_depth() ) db_end_transaction(0);
458
+ db_set_authorizer(ticket_schema_auth,0,"Ticket-Schema");
389459
db_init_database(g.zRepositoryName, zSql, 0);
390460
}else{
461
+ db_set_authorizer(ticket_schema_auth,0,"Ticket-Schema");
391462
db_multi_exec("%s", zSql/*safe-for-%s*/);
392463
}
464
+ db_clear_authorizer();
393465
fossil_free(zSql);
394466
}
395467
396468
/*
397469
** Repopulate the TICKET and TICKETCHNG tables from scratch using all
398470
--- src/tkt.c
+++ src/tkt.c
@@ -370,10 +370,79 @@
370 Th_FossilInit(TH_INIT_DEFAULT);
371 Th_Store("uuid", zUuid);
372 zConfig = ticket_change_code();
373 return Th_Eval(g.interp, 0, zConfig, -1);
374 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
375
376 /*
377 ** Recreate the TICKET and TICKETCHNG tables.
378 */
379 void ticket_create_table(int separateConnection){
@@ -384,14 +453,17 @@
384 "DROP TABLE IF EXISTS ticketchng;"
385 );
386 zSql = ticket_table_schema();
387 if( separateConnection ){
388 if( db_transaction_nesting_depth() ) db_end_transaction(0);
 
389 db_init_database(g.zRepositoryName, zSql, 0);
390 }else{
 
391 db_multi_exec("%s", zSql/*safe-for-%s*/);
392 }
 
393 fossil_free(zSql);
394 }
395
396 /*
397 ** Repopulate the TICKET and TICKETCHNG tables from scratch using all
398
--- src/tkt.c
+++ src/tkt.c
@@ -370,10 +370,79 @@
370 Th_FossilInit(TH_INIT_DEFAULT);
371 Th_Store("uuid", zUuid);
372 zConfig = ticket_change_code();
373 return Th_Eval(g.interp, 0, zConfig, -1);
374 }
375
376 /*
377 ** An authorizer function for the SQL used to initialize the
378 ** schema for the ticketing system. Only allow CREATE TABLE and
379 ** CREATE INDEX for tables whose names begin with "ticket" and
380 ** changes to tables whose names begin with "ticket".
381 */
382 static int ticket_schema_auth(
383 void *pNErr,
384 int eCode,
385 const char *z0,
386 const char *z1,
387 const char *z2,
388 const char *z3
389 ){
390 switch( eCode ){
391 case SQLITE_CREATE_TABLE: {
392 if( sqlite3_stricmp(z2,"main")!=0
393 && sqlite3_stricmp(z2,"repository")!=0
394 ){
395 goto ticket_schema_error;
396 }
397 if( sqlite3_strnicmp(z0,"ticket",6)!=0 ){
398 goto ticket_schema_error;
399 }
400 break;
401 }
402 case SQLITE_CREATE_INDEX: {
403 if( sqlite3_stricmp(z2,"main")!=0
404 && sqlite3_stricmp(z2,"repository")!=0
405 ){
406 goto ticket_schema_error;
407 }
408 if( sqlite3_strnicmp(z1,"ticket",6)!=0 ){
409 goto ticket_schema_error;
410 }
411 break;
412 }
413 case SQLITE_INSERT:
414 case SQLITE_UPDATE:
415 case SQLITE_DELETE: {
416 if( sqlite3_stricmp(z2,"main")!=0
417 && sqlite3_stricmp(z2,"repository")!=0
418 ){
419 goto ticket_schema_error;
420 }
421 if( sqlite3_strnicmp(z0,"ticket",6)!=0
422 && sqlite3_strnicmp(z0,"sqlite_",7)!=0
423 ){
424 goto ticket_schema_error;
425 }
426 break;
427 }
428 case SQLITE_REINDEX:
429 case SQLITE_TRANSACTION:
430 case SQLITE_READ: {
431 break;
432 }
433 default: {
434 goto ticket_schema_error;
435 }
436 }
437 return SQLITE_OK;
438
439 ticket_schema_error:
440 if( pNErr ) *(int*)pNErr = 1;
441 return SQLITE_DENY;
442 }
443
444
445 /*
446 ** Recreate the TICKET and TICKETCHNG tables.
447 */
448 void ticket_create_table(int separateConnection){
@@ -384,14 +453,17 @@
453 "DROP TABLE IF EXISTS ticketchng;"
454 );
455 zSql = ticket_table_schema();
456 if( separateConnection ){
457 if( db_transaction_nesting_depth() ) db_end_transaction(0);
458 db_set_authorizer(ticket_schema_auth,0,"Ticket-Schema");
459 db_init_database(g.zRepositoryName, zSql, 0);
460 }else{
461 db_set_authorizer(ticket_schema_auth,0,"Ticket-Schema");
462 db_multi_exec("%s", zSql/*safe-for-%s*/);
463 }
464 db_clear_authorizer();
465 fossil_free(zSql);
466 }
467
468 /*
469 ** Repopulate the TICKET and TICKETCHNG tables from scratch using all
470
+72
--- src/tkt.c
+++ src/tkt.c
@@ -370,10 +370,79 @@
370370
Th_FossilInit(TH_INIT_DEFAULT);
371371
Th_Store("uuid", zUuid);
372372
zConfig = ticket_change_code();
373373
return Th_Eval(g.interp, 0, zConfig, -1);
374374
}
375
+
376
+/*
377
+** An authorizer function for the SQL used to initialize the
378
+** schema for the ticketing system. Only allow CREATE TABLE and
379
+** CREATE INDEX for tables whose names begin with "ticket" and
380
+** changes to tables whose names begin with "ticket".
381
+*/
382
+static int ticket_schema_auth(
383
+ void *pNErr,
384
+ int eCode,
385
+ const char *z0,
386
+ const char *z1,
387
+ const char *z2,
388
+ const char *z3
389
+){
390
+ switch( eCode ){
391
+ case SQLITE_CREATE_TABLE: {
392
+ if( sqlite3_stricmp(z2,"main")!=0
393
+ && sqlite3_stricmp(z2,"repository")!=0
394
+ ){
395
+ goto ticket_schema_error;
396
+ }
397
+ if( sqlite3_strnicmp(z0,"ticket",6)!=0 ){
398
+ goto ticket_schema_error;
399
+ }
400
+ break;
401
+ }
402
+ case SQLITE_CREATE_INDEX: {
403
+ if( sqlite3_stricmp(z2,"main")!=0
404
+ && sqlite3_stricmp(z2,"repository")!=0
405
+ ){
406
+ goto ticket_schema_error;
407
+ }
408
+ if( sqlite3_strnicmp(z1,"ticket",6)!=0 ){
409
+ goto ticket_schema_error;
410
+ }
411
+ break;
412
+ }
413
+ case SQLITE_INSERT:
414
+ case SQLITE_UPDATE:
415
+ case SQLITE_DELETE: {
416
+ if( sqlite3_stricmp(z2,"main")!=0
417
+ && sqlite3_stricmp(z2,"repository")!=0
418
+ ){
419
+ goto ticket_schema_error;
420
+ }
421
+ if( sqlite3_strnicmp(z0,"ticket",6)!=0
422
+ && sqlite3_strnicmp(z0,"sqlite_",7)!=0
423
+ ){
424
+ goto ticket_schema_error;
425
+ }
426
+ break;
427
+ }
428
+ case SQLITE_REINDEX:
429
+ case SQLITE_TRANSACTION:
430
+ case SQLITE_READ: {
431
+ break;
432
+ }
433
+ default: {
434
+ goto ticket_schema_error;
435
+ }
436
+ }
437
+ return SQLITE_OK;
438
+
439
+ticket_schema_error:
440
+ if( pNErr ) *(int*)pNErr = 1;
441
+ return SQLITE_DENY;
442
+}
443
+
375444
376445
/*
377446
** Recreate the TICKET and TICKETCHNG tables.
378447
*/
379448
void ticket_create_table(int separateConnection){
@@ -384,14 +453,17 @@
384453
"DROP TABLE IF EXISTS ticketchng;"
385454
);
386455
zSql = ticket_table_schema();
387456
if( separateConnection ){
388457
if( db_transaction_nesting_depth() ) db_end_transaction(0);
458
+ db_set_authorizer(ticket_schema_auth,0,"Ticket-Schema");
389459
db_init_database(g.zRepositoryName, zSql, 0);
390460
}else{
461
+ db_set_authorizer(ticket_schema_auth,0,"Ticket-Schema");
391462
db_multi_exec("%s", zSql/*safe-for-%s*/);
392463
}
464
+ db_clear_authorizer();
393465
fossil_free(zSql);
394466
}
395467
396468
/*
397469
** Repopulate the TICKET and TICKETCHNG tables from scratch using all
398470
--- src/tkt.c
+++ src/tkt.c
@@ -370,10 +370,79 @@
370 Th_FossilInit(TH_INIT_DEFAULT);
371 Th_Store("uuid", zUuid);
372 zConfig = ticket_change_code();
373 return Th_Eval(g.interp, 0, zConfig, -1);
374 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
375
376 /*
377 ** Recreate the TICKET and TICKETCHNG tables.
378 */
379 void ticket_create_table(int separateConnection){
@@ -384,14 +453,17 @@
384 "DROP TABLE IF EXISTS ticketchng;"
385 );
386 zSql = ticket_table_schema();
387 if( separateConnection ){
388 if( db_transaction_nesting_depth() ) db_end_transaction(0);
 
389 db_init_database(g.zRepositoryName, zSql, 0);
390 }else{
 
391 db_multi_exec("%s", zSql/*safe-for-%s*/);
392 }
 
393 fossil_free(zSql);
394 }
395
396 /*
397 ** Repopulate the TICKET and TICKETCHNG tables from scratch using all
398
--- src/tkt.c
+++ src/tkt.c
@@ -370,10 +370,79 @@
370 Th_FossilInit(TH_INIT_DEFAULT);
371 Th_Store("uuid", zUuid);
372 zConfig = ticket_change_code();
373 return Th_Eval(g.interp, 0, zConfig, -1);
374 }
375
376 /*
377 ** An authorizer function for the SQL used to initialize the
378 ** schema for the ticketing system. Only allow CREATE TABLE and
379 ** CREATE INDEX for tables whose names begin with "ticket" and
380 ** changes to tables whose names begin with "ticket".
381 */
382 static int ticket_schema_auth(
383 void *pNErr,
384 int eCode,
385 const char *z0,
386 const char *z1,
387 const char *z2,
388 const char *z3
389 ){
390 switch( eCode ){
391 case SQLITE_CREATE_TABLE: {
392 if( sqlite3_stricmp(z2,"main")!=0
393 && sqlite3_stricmp(z2,"repository")!=0
394 ){
395 goto ticket_schema_error;
396 }
397 if( sqlite3_strnicmp(z0,"ticket",6)!=0 ){
398 goto ticket_schema_error;
399 }
400 break;
401 }
402 case SQLITE_CREATE_INDEX: {
403 if( sqlite3_stricmp(z2,"main")!=0
404 && sqlite3_stricmp(z2,"repository")!=0
405 ){
406 goto ticket_schema_error;
407 }
408 if( sqlite3_strnicmp(z1,"ticket",6)!=0 ){
409 goto ticket_schema_error;
410 }
411 break;
412 }
413 case SQLITE_INSERT:
414 case SQLITE_UPDATE:
415 case SQLITE_DELETE: {
416 if( sqlite3_stricmp(z2,"main")!=0
417 && sqlite3_stricmp(z2,"repository")!=0
418 ){
419 goto ticket_schema_error;
420 }
421 if( sqlite3_strnicmp(z0,"ticket",6)!=0
422 && sqlite3_strnicmp(z0,"sqlite_",7)!=0
423 ){
424 goto ticket_schema_error;
425 }
426 break;
427 }
428 case SQLITE_REINDEX:
429 case SQLITE_TRANSACTION:
430 case SQLITE_READ: {
431 break;
432 }
433 default: {
434 goto ticket_schema_error;
435 }
436 }
437 return SQLITE_OK;
438
439 ticket_schema_error:
440 if( pNErr ) *(int*)pNErr = 1;
441 return SQLITE_DENY;
442 }
443
444
445 /*
446 ** Recreate the TICKET and TICKETCHNG tables.
447 */
448 void ticket_create_table(int separateConnection){
@@ -384,14 +453,17 @@
453 "DROP TABLE IF EXISTS ticketchng;"
454 );
455 zSql = ticket_table_schema();
456 if( separateConnection ){
457 if( db_transaction_nesting_depth() ) db_end_transaction(0);
458 db_set_authorizer(ticket_schema_auth,0,"Ticket-Schema");
459 db_init_database(g.zRepositoryName, zSql, 0);
460 }else{
461 db_set_authorizer(ticket_schema_auth,0,"Ticket-Schema");
462 db_multi_exec("%s", zSql/*safe-for-%s*/);
463 }
464 db_clear_authorizer();
465 fossil_free(zSql);
466 }
467
468 /*
469 ** Repopulate the TICKET and TICKETCHNG tables from scratch using all
470
+72
--- src/tkt.c
+++ src/tkt.c
@@ -370,10 +370,79 @@
370370
Th_FossilInit(TH_INIT_DEFAULT);
371371
Th_Store("uuid", zUuid);
372372
zConfig = ticket_change_code();
373373
return Th_Eval(g.interp, 0, zConfig, -1);
374374
}
375
+
376
+/*
377
+** An authorizer function for the SQL used to initialize the
378
+** schema for the ticketing system. Only allow CREATE TABLE and
379
+** CREATE INDEX for tables whose names begin with "ticket" and
380
+** changes to tables whose names begin with "ticket".
381
+*/
382
+static int ticket_schema_auth(
383
+ void *pNErr,
384
+ int eCode,
385
+ const char *z0,
386
+ const char *z1,
387
+ const char *z2,
388
+ const char *z3
389
+){
390
+ switch( eCode ){
391
+ case SQLITE_CREATE_TABLE: {
392
+ if( sqlite3_stricmp(z2,"main")!=0
393
+ && sqlite3_stricmp(z2,"repository")!=0
394
+ ){
395
+ goto ticket_schema_error;
396
+ }
397
+ if( sqlite3_strnicmp(z0,"ticket",6)!=0 ){
398
+ goto ticket_schema_error;
399
+ }
400
+ break;
401
+ }
402
+ case SQLITE_CREATE_INDEX: {
403
+ if( sqlite3_stricmp(z2,"main")!=0
404
+ && sqlite3_stricmp(z2,"repository")!=0
405
+ ){
406
+ goto ticket_schema_error;
407
+ }
408
+ if( sqlite3_strnicmp(z1,"ticket",6)!=0 ){
409
+ goto ticket_schema_error;
410
+ }
411
+ break;
412
+ }
413
+ case SQLITE_INSERT:
414
+ case SQLITE_UPDATE:
415
+ case SQLITE_DELETE: {
416
+ if( sqlite3_stricmp(z2,"main")!=0
417
+ && sqlite3_stricmp(z2,"repository")!=0
418
+ ){
419
+ goto ticket_schema_error;
420
+ }
421
+ if( sqlite3_strnicmp(z0,"ticket",6)!=0
422
+ && sqlite3_strnicmp(z0,"sqlite_",7)!=0
423
+ ){
424
+ goto ticket_schema_error;
425
+ }
426
+ break;
427
+ }
428
+ case SQLITE_REINDEX:
429
+ case SQLITE_TRANSACTION:
430
+ case SQLITE_READ: {
431
+ break;
432
+ }
433
+ default: {
434
+ goto ticket_schema_error;
435
+ }
436
+ }
437
+ return SQLITE_OK;
438
+
439
+ticket_schema_error:
440
+ if( pNErr ) *(int*)pNErr = 1;
441
+ return SQLITE_DENY;
442
+}
443
+
375444
376445
/*
377446
** Recreate the TICKET and TICKETCHNG tables.
378447
*/
379448
void ticket_create_table(int separateConnection){
@@ -384,14 +453,17 @@
384453
"DROP TABLE IF EXISTS ticketchng;"
385454
);
386455
zSql = ticket_table_schema();
387456
if( separateConnection ){
388457
if( db_transaction_nesting_depth() ) db_end_transaction(0);
458
+ db_set_authorizer(ticket_schema_auth,0,"Ticket-Schema");
389459
db_init_database(g.zRepositoryName, zSql, 0);
390460
}else{
461
+ db_set_authorizer(ticket_schema_auth,0,"Ticket-Schema");
391462
db_multi_exec("%s", zSql/*safe-for-%s*/);
392463
}
464
+ db_clear_authorizer();
393465
fossil_free(zSql);
394466
}
395467
396468
/*
397469
** Repopulate the TICKET and TICKETCHNG tables from scratch using all
398470
--- src/tkt.c
+++ src/tkt.c
@@ -370,10 +370,79 @@
370 Th_FossilInit(TH_INIT_DEFAULT);
371 Th_Store("uuid", zUuid);
372 zConfig = ticket_change_code();
373 return Th_Eval(g.interp, 0, zConfig, -1);
374 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
375
376 /*
377 ** Recreate the TICKET and TICKETCHNG tables.
378 */
379 void ticket_create_table(int separateConnection){
@@ -384,14 +453,17 @@
384 "DROP TABLE IF EXISTS ticketchng;"
385 );
386 zSql = ticket_table_schema();
387 if( separateConnection ){
388 if( db_transaction_nesting_depth() ) db_end_transaction(0);
 
389 db_init_database(g.zRepositoryName, zSql, 0);
390 }else{
 
391 db_multi_exec("%s", zSql/*safe-for-%s*/);
392 }
 
393 fossil_free(zSql);
394 }
395
396 /*
397 ** Repopulate the TICKET and TICKETCHNG tables from scratch using all
398
--- src/tkt.c
+++ src/tkt.c
@@ -370,10 +370,79 @@
370 Th_FossilInit(TH_INIT_DEFAULT);
371 Th_Store("uuid", zUuid);
372 zConfig = ticket_change_code();
373 return Th_Eval(g.interp, 0, zConfig, -1);
374 }
375
376 /*
377 ** An authorizer function for the SQL used to initialize the
378 ** schema for the ticketing system. Only allow CREATE TABLE and
379 ** CREATE INDEX for tables whose names begin with "ticket" and
380 ** changes to tables whose names begin with "ticket".
381 */
382 static int ticket_schema_auth(
383 void *pNErr,
384 int eCode,
385 const char *z0,
386 const char *z1,
387 const char *z2,
388 const char *z3
389 ){
390 switch( eCode ){
391 case SQLITE_CREATE_TABLE: {
392 if( sqlite3_stricmp(z2,"main")!=0
393 && sqlite3_stricmp(z2,"repository")!=0
394 ){
395 goto ticket_schema_error;
396 }
397 if( sqlite3_strnicmp(z0,"ticket",6)!=0 ){
398 goto ticket_schema_error;
399 }
400 break;
401 }
402 case SQLITE_CREATE_INDEX: {
403 if( sqlite3_stricmp(z2,"main")!=0
404 && sqlite3_stricmp(z2,"repository")!=0
405 ){
406 goto ticket_schema_error;
407 }
408 if( sqlite3_strnicmp(z1,"ticket",6)!=0 ){
409 goto ticket_schema_error;
410 }
411 break;
412 }
413 case SQLITE_INSERT:
414 case SQLITE_UPDATE:
415 case SQLITE_DELETE: {
416 if( sqlite3_stricmp(z2,"main")!=0
417 && sqlite3_stricmp(z2,"repository")!=0
418 ){
419 goto ticket_schema_error;
420 }
421 if( sqlite3_strnicmp(z0,"ticket",6)!=0
422 && sqlite3_strnicmp(z0,"sqlite_",7)!=0
423 ){
424 goto ticket_schema_error;
425 }
426 break;
427 }
428 case SQLITE_REINDEX:
429 case SQLITE_TRANSACTION:
430 case SQLITE_READ: {
431 break;
432 }
433 default: {
434 goto ticket_schema_error;
435 }
436 }
437 return SQLITE_OK;
438
439 ticket_schema_error:
440 if( pNErr ) *(int*)pNErr = 1;
441 return SQLITE_DENY;
442 }
443
444
445 /*
446 ** Recreate the TICKET and TICKETCHNG tables.
447 */
448 void ticket_create_table(int separateConnection){
@@ -384,14 +453,17 @@
453 "DROP TABLE IF EXISTS ticketchng;"
454 );
455 zSql = ticket_table_schema();
456 if( separateConnection ){
457 if( db_transaction_nesting_depth() ) db_end_transaction(0);
458 db_set_authorizer(ticket_schema_auth,0,"Ticket-Schema");
459 db_init_database(g.zRepositoryName, zSql, 0);
460 }else{
461 db_set_authorizer(ticket_schema_auth,0,"Ticket-Schema");
462 db_multi_exec("%s", zSql/*safe-for-%s*/);
463 }
464 db_clear_authorizer();
465 fossil_free(zSql);
466 }
467
468 /*
469 ** Repopulate the TICKET and TICKETCHNG tables from scratch using all
470
+72
--- src/tkt.c
+++ src/tkt.c
@@ -370,10 +370,79 @@
370370
Th_FossilInit(TH_INIT_DEFAULT);
371371
Th_Store("uuid", zUuid);
372372
zConfig = ticket_change_code();
373373
return Th_Eval(g.interp, 0, zConfig, -1);
374374
}
375
+
376
+/*
377
+** An authorizer function for the SQL used to initialize the
378
+** schema for the ticketing system. Only allow CREATE TABLE and
379
+** CREATE INDEX for tables whose names begin with "ticket" and
380
+** changes to tables whose names begin with "ticket".
381
+*/
382
+static int ticket_schema_auth(
383
+ void *pNErr,
384
+ int eCode,
385
+ const char *z0,
386
+ const char *z1,
387
+ const char *z2,
388
+ const char *z3
389
+){
390
+ switch( eCode ){
391
+ case SQLITE_CREATE_TABLE: {
392
+ if( sqlite3_stricmp(z2,"main")!=0
393
+ && sqlite3_stricmp(z2,"repository")!=0
394
+ ){
395
+ goto ticket_schema_error;
396
+ }
397
+ if( sqlite3_strnicmp(z0,"ticket",6)!=0 ){
398
+ goto ticket_schema_error;
399
+ }
400
+ break;
401
+ }
402
+ case SQLITE_CREATE_INDEX: {
403
+ if( sqlite3_stricmp(z2,"main")!=0
404
+ && sqlite3_stricmp(z2,"repository")!=0
405
+ ){
406
+ goto ticket_schema_error;
407
+ }
408
+ if( sqlite3_strnicmp(z1,"ticket",6)!=0 ){
409
+ goto ticket_schema_error;
410
+ }
411
+ break;
412
+ }
413
+ case SQLITE_INSERT:
414
+ case SQLITE_UPDATE:
415
+ case SQLITE_DELETE: {
416
+ if( sqlite3_stricmp(z2,"main")!=0
417
+ && sqlite3_stricmp(z2,"repository")!=0
418
+ ){
419
+ goto ticket_schema_error;
420
+ }
421
+ if( sqlite3_strnicmp(z0,"ticket",6)!=0
422
+ && sqlite3_strnicmp(z0,"sqlite_",7)!=0
423
+ ){
424
+ goto ticket_schema_error;
425
+ }
426
+ break;
427
+ }
428
+ case SQLITE_REINDEX:
429
+ case SQLITE_TRANSACTION:
430
+ case SQLITE_READ: {
431
+ break;
432
+ }
433
+ default: {
434
+ goto ticket_schema_error;
435
+ }
436
+ }
437
+ return SQLITE_OK;
438
+
439
+ticket_schema_error:
440
+ if( pNErr ) *(int*)pNErr = 1;
441
+ return SQLITE_DENY;
442
+}
443
+
375444
376445
/*
377446
** Recreate the TICKET and TICKETCHNG tables.
378447
*/
379448
void ticket_create_table(int separateConnection){
@@ -384,14 +453,17 @@
384453
"DROP TABLE IF EXISTS ticketchng;"
385454
);
386455
zSql = ticket_table_schema();
387456
if( separateConnection ){
388457
if( db_transaction_nesting_depth() ) db_end_transaction(0);
458
+ db_set_authorizer(ticket_schema_auth,0,"Ticket-Schema");
389459
db_init_database(g.zRepositoryName, zSql, 0);
390460
}else{
461
+ db_set_authorizer(ticket_schema_auth,0,"Ticket-Schema");
391462
db_multi_exec("%s", zSql/*safe-for-%s*/);
392463
}
464
+ db_clear_authorizer();
393465
fossil_free(zSql);
394466
}
395467
396468
/*
397469
** Repopulate the TICKET and TICKETCHNG tables from scratch using all
398470
--- src/tkt.c
+++ src/tkt.c
@@ -370,10 +370,79 @@
370 Th_FossilInit(TH_INIT_DEFAULT);
371 Th_Store("uuid", zUuid);
372 zConfig = ticket_change_code();
373 return Th_Eval(g.interp, 0, zConfig, -1);
374 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
375
376 /*
377 ** Recreate the TICKET and TICKETCHNG tables.
378 */
379 void ticket_create_table(int separateConnection){
@@ -384,14 +453,17 @@
384 "DROP TABLE IF EXISTS ticketchng;"
385 );
386 zSql = ticket_table_schema();
387 if( separateConnection ){
388 if( db_transaction_nesting_depth() ) db_end_transaction(0);
 
389 db_init_database(g.zRepositoryName, zSql, 0);
390 }else{
 
391 db_multi_exec("%s", zSql/*safe-for-%s*/);
392 }
 
393 fossil_free(zSql);
394 }
395
396 /*
397 ** Repopulate the TICKET and TICKETCHNG tables from scratch using all
398
--- src/tkt.c
+++ src/tkt.c
@@ -370,10 +370,79 @@
370 Th_FossilInit(TH_INIT_DEFAULT);
371 Th_Store("uuid", zUuid);
372 zConfig = ticket_change_code();
373 return Th_Eval(g.interp, 0, zConfig, -1);
374 }
375
376 /*
377 ** An authorizer function for the SQL used to initialize the
378 ** schema for the ticketing system. Only allow CREATE TABLE and
379 ** CREATE INDEX for tables whose names begin with "ticket" and
380 ** changes to tables whose names begin with "ticket".
381 */
382 static int ticket_schema_auth(
383 void *pNErr,
384 int eCode,
385 const char *z0,
386 const char *z1,
387 const char *z2,
388 const char *z3
389 ){
390 switch( eCode ){
391 case SQLITE_CREATE_TABLE: {
392 if( sqlite3_stricmp(z2,"main")!=0
393 && sqlite3_stricmp(z2,"repository")!=0
394 ){
395 goto ticket_schema_error;
396 }
397 if( sqlite3_strnicmp(z0,"ticket",6)!=0 ){
398 goto ticket_schema_error;
399 }
400 break;
401 }
402 case SQLITE_CREATE_INDEX: {
403 if( sqlite3_stricmp(z2,"main")!=0
404 && sqlite3_stricmp(z2,"repository")!=0
405 ){
406 goto ticket_schema_error;
407 }
408 if( sqlite3_strnicmp(z1,"ticket",6)!=0 ){
409 goto ticket_schema_error;
410 }
411 break;
412 }
413 case SQLITE_INSERT:
414 case SQLITE_UPDATE:
415 case SQLITE_DELETE: {
416 if( sqlite3_stricmp(z2,"main")!=0
417 && sqlite3_stricmp(z2,"repository")!=0
418 ){
419 goto ticket_schema_error;
420 }
421 if( sqlite3_strnicmp(z0,"ticket",6)!=0
422 && sqlite3_strnicmp(z0,"sqlite_",7)!=0
423 ){
424 goto ticket_schema_error;
425 }
426 break;
427 }
428 case SQLITE_REINDEX:
429 case SQLITE_TRANSACTION:
430 case SQLITE_READ: {
431 break;
432 }
433 default: {
434 goto ticket_schema_error;
435 }
436 }
437 return SQLITE_OK;
438
439 ticket_schema_error:
440 if( pNErr ) *(int*)pNErr = 1;
441 return SQLITE_DENY;
442 }
443
444
445 /*
446 ** Recreate the TICKET and TICKETCHNG tables.
447 */
448 void ticket_create_table(int separateConnection){
@@ -384,14 +453,17 @@
453 "DROP TABLE IF EXISTS ticketchng;"
454 );
455 zSql = ticket_table_schema();
456 if( separateConnection ){
457 if( db_transaction_nesting_depth() ) db_end_transaction(0);
458 db_set_authorizer(ticket_schema_auth,0,"Ticket-Schema");
459 db_init_database(g.zRepositoryName, zSql, 0);
460 }else{
461 db_set_authorizer(ticket_schema_auth,0,"Ticket-Schema");
462 db_multi_exec("%s", zSql/*safe-for-%s*/);
463 }
464 db_clear_authorizer();
465 fossil_free(zSql);
466 }
467
468 /*
469 ** Repopulate the TICKET and TICKETCHNG tables from scratch using all
470
+3 -3
--- src/url.c
+++ src/url.c
@@ -50,11 +50,11 @@
5050
int isHttps; /* True if a "https:" url */
5151
int isSsh; /* True if an "ssh:" url */
5252
int isAlias; /* Input URL was an alias */
5353
char *name; /* Hostname for http: or filename for file: */
5454
char *hostname; /* The HOST: parameter on http headers */
55
- const char *protocol; /* "http" or "https" or "ssh" */
55
+ const char *protocol; /* "http" or "https" or "ssh" or "file" */
5656
int port; /* TCP port number for http: or https: */
5757
int dfltPort; /* The default port for the given protocol */
5858
char *path; /* Pathname for http: */
5959
char *user; /* User id for http: */
6060
char *passwd; /* Password for http: */
@@ -76,11 +76,11 @@
7676
** as follows:
7777
**
7878
** isFile True if FILE:
7979
** isHttps True if HTTPS:
8080
** isSsh True if SSH:
81
-** protocol "http" or "https" or "file"
81
+** protocol "http" or "https" or "file" or "ssh"
8282
** name Hostname for HTTP:, HTTPS:, SSH:. Filename for FILE:
8383
** port TCP port number for HTTP or HTTPS.
8484
** dfltPort Default TCP port number (80 or 443).
8585
** path Path name for HTTP or HTTPS.
8686
** user Userid.
@@ -305,11 +305,11 @@
305305
** form last-sync-pw.
306306
**
307307
** g.url.isFile True if FILE:
308308
** g.url.isHttps True if HTTPS:
309309
** g.url.isSsh True if SSH:
310
-** g.url.protocol "http" or "https" or "file"
310
+** g.url.protocol "http" or "https" or "file" or "ssh"
311311
** g.url.name Hostname for HTTP:, HTTPS:, SSH:. Filename for FILE:
312312
** g.url.port TCP port number for HTTP or HTTPS.
313313
** g.url.dfltPort Default TCP port number (80 or 443).
314314
** g.url.path Path name for HTTP or HTTPS.
315315
** g.url.user Userid.
316316
--- src/url.c
+++ src/url.c
@@ -50,11 +50,11 @@
50 int isHttps; /* True if a "https:" url */
51 int isSsh; /* True if an "ssh:" url */
52 int isAlias; /* Input URL was an alias */
53 char *name; /* Hostname for http: or filename for file: */
54 char *hostname; /* The HOST: parameter on http headers */
55 const char *protocol; /* "http" or "https" or "ssh" */
56 int port; /* TCP port number for http: or https: */
57 int dfltPort; /* The default port for the given protocol */
58 char *path; /* Pathname for http: */
59 char *user; /* User id for http: */
60 char *passwd; /* Password for http: */
@@ -76,11 +76,11 @@
76 ** as follows:
77 **
78 ** isFile True if FILE:
79 ** isHttps True if HTTPS:
80 ** isSsh True if SSH:
81 ** protocol "http" or "https" or "file"
82 ** name Hostname for HTTP:, HTTPS:, SSH:. Filename for FILE:
83 ** port TCP port number for HTTP or HTTPS.
84 ** dfltPort Default TCP port number (80 or 443).
85 ** path Path name for HTTP or HTTPS.
86 ** user Userid.
@@ -305,11 +305,11 @@
305 ** form last-sync-pw.
306 **
307 ** g.url.isFile True if FILE:
308 ** g.url.isHttps True if HTTPS:
309 ** g.url.isSsh True if SSH:
310 ** g.url.protocol "http" or "https" or "file"
311 ** g.url.name Hostname for HTTP:, HTTPS:, SSH:. Filename for FILE:
312 ** g.url.port TCP port number for HTTP or HTTPS.
313 ** g.url.dfltPort Default TCP port number (80 or 443).
314 ** g.url.path Path name for HTTP or HTTPS.
315 ** g.url.user Userid.
316
--- src/url.c
+++ src/url.c
@@ -50,11 +50,11 @@
50 int isHttps; /* True if a "https:" url */
51 int isSsh; /* True if an "ssh:" url */
52 int isAlias; /* Input URL was an alias */
53 char *name; /* Hostname for http: or filename for file: */
54 char *hostname; /* The HOST: parameter on http headers */
55 const char *protocol; /* "http" or "https" or "ssh" or "file" */
56 int port; /* TCP port number for http: or https: */
57 int dfltPort; /* The default port for the given protocol */
58 char *path; /* Pathname for http: */
59 char *user; /* User id for http: */
60 char *passwd; /* Password for http: */
@@ -76,11 +76,11 @@
76 ** as follows:
77 **
78 ** isFile True if FILE:
79 ** isHttps True if HTTPS:
80 ** isSsh True if SSH:
81 ** protocol "http" or "https" or "file" or "ssh"
82 ** name Hostname for HTTP:, HTTPS:, SSH:. Filename for FILE:
83 ** port TCP port number for HTTP or HTTPS.
84 ** dfltPort Default TCP port number (80 or 443).
85 ** path Path name for HTTP or HTTPS.
86 ** user Userid.
@@ -305,11 +305,11 @@
305 ** form last-sync-pw.
306 **
307 ** g.url.isFile True if FILE:
308 ** g.url.isHttps True if HTTPS:
309 ** g.url.isSsh True if SSH:
310 ** g.url.protocol "http" or "https" or "file" or "ssh"
311 ** g.url.name Hostname for HTTP:, HTTPS:, SSH:. Filename for FILE:
312 ** g.url.port TCP port number for HTTP or HTTPS.
313 ** g.url.dfltPort Default TCP port number (80 or 443).
314 ** g.url.path Path name for HTTP or HTTPS.
315 ** g.url.user Userid.
316
--- src/vfile.c
+++ src/vfile.c
@@ -307,10 +307,11 @@
307307
g.zLocalRoot, id);
308308
}
309309
while( db_step(&q)==SQLITE_ROW ){
310310
int id, rid, isExe, isLink;
311311
const char *zName;
312
+ int n;
312313
313314
id = db_column_int(&q, 0);
314315
zName = db_column_text(&q, 1);
315316
rid = db_column_int(&q, 2);
316317
isExe = db_column_int(&q, 3);
@@ -339,10 +340,16 @@
339340
blob_reset(&content);
340341
continue;
341342
}
342343
}
343344
if( verbose ) fossil_print("%s\n", &zName[nRepos]);
345
+ n = file_nondir_objects_on_path(g.zLocalRoot, zName);
346
+ if( n ){
347
+ fossil_fatal("cannot write %s because "
348
+ "non-directory object %.*s is in the way",
349
+ zName, n, zName);
350
+ }
344351
if( file_isdir(zName, RepoFILE)==1 ){
345352
/*TODO(dchest): remove directories? */
346353
fossil_fatal("%s is directory, cannot overwrite", zName);
347354
}
348355
if( file_size(zName, RepoFILE)>=0 && (isLink || file_islink(0)) ){
349356
--- src/vfile.c
+++ src/vfile.c
@@ -307,10 +307,11 @@
307 g.zLocalRoot, id);
308 }
309 while( db_step(&q)==SQLITE_ROW ){
310 int id, rid, isExe, isLink;
311 const char *zName;
 
312
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);
@@ -339,10 +340,16 @@
339 blob_reset(&content);
340 continue;
341 }
342 }
343 if( verbose ) fossil_print("%s\n", &zName[nRepos]);
 
 
 
 
 
 
344 if( file_isdir(zName, RepoFILE)==1 ){
345 /*TODO(dchest): remove directories? */
346 fossil_fatal("%s is directory, cannot overwrite", zName);
347 }
348 if( file_size(zName, RepoFILE)>=0 && (isLink || file_islink(0)) ){
349
--- src/vfile.c
+++ src/vfile.c
@@ -307,10 +307,11 @@
307 g.zLocalRoot, id);
308 }
309 while( db_step(&q)==SQLITE_ROW ){
310 int id, rid, isExe, isLink;
311 const char *zName;
312 int n;
313
314 id = db_column_int(&q, 0);
315 zName = db_column_text(&q, 1);
316 rid = db_column_int(&q, 2);
317 isExe = db_column_int(&q, 3);
@@ -339,10 +340,16 @@
340 blob_reset(&content);
341 continue;
342 }
343 }
344 if( verbose ) fossil_print("%s\n", &zName[nRepos]);
345 n = file_nondir_objects_on_path(g.zLocalRoot, zName);
346 if( n ){
347 fossil_fatal("cannot write %s because "
348 "non-directory object %.*s is in the way",
349 zName, n, zName);
350 }
351 if( file_isdir(zName, RepoFILE)==1 ){
352 /*TODO(dchest): remove directories? */
353 fossil_fatal("%s is directory, cannot overwrite", zName);
354 }
355 if( file_size(zName, RepoFILE)>=0 && (isLink || file_islink(0)) ){
356
--- src/vfile.c
+++ src/vfile.c
@@ -307,10 +307,11 @@
307307
g.zLocalRoot, id);
308308
}
309309
while( db_step(&q)==SQLITE_ROW ){
310310
int id, rid, isExe, isLink;
311311
const char *zName;
312
+ int n;
312313
313314
id = db_column_int(&q, 0);
314315
zName = db_column_text(&q, 1);
315316
rid = db_column_int(&q, 2);
316317
isExe = db_column_int(&q, 3);
@@ -339,10 +340,16 @@
339340
blob_reset(&content);
340341
continue;
341342
}
342343
}
343344
if( verbose ) fossil_print("%s\n", &zName[nRepos]);
345
+ n = file_nondir_objects_on_path(g.zLocalRoot, zName);
346
+ if( n ){
347
+ fossil_fatal("cannot write %s because "
348
+ "non-directory object %.*s is in the way",
349
+ zName, n, zName);
350
+ }
344351
if( file_isdir(zName, RepoFILE)==1 ){
345352
/*TODO(dchest): remove directories? */
346353
fossil_fatal("%s is directory, cannot overwrite", zName);
347354
}
348355
if( file_size(zName, RepoFILE)>=0 && (isLink || file_islink(0)) ){
349356
--- src/vfile.c
+++ src/vfile.c
@@ -307,10 +307,11 @@
307 g.zLocalRoot, id);
308 }
309 while( db_step(&q)==SQLITE_ROW ){
310 int id, rid, isExe, isLink;
311 const char *zName;
 
312
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);
@@ -339,10 +340,16 @@
339 blob_reset(&content);
340 continue;
341 }
342 }
343 if( verbose ) fossil_print("%s\n", &zName[nRepos]);
 
 
 
 
 
 
344 if( file_isdir(zName, RepoFILE)==1 ){
345 /*TODO(dchest): remove directories? */
346 fossil_fatal("%s is directory, cannot overwrite", zName);
347 }
348 if( file_size(zName, RepoFILE)>=0 && (isLink || file_islink(0)) ){
349
--- src/vfile.c
+++ src/vfile.c
@@ -307,10 +307,11 @@
307 g.zLocalRoot, id);
308 }
309 while( db_step(&q)==SQLITE_ROW ){
310 int id, rid, isExe, isLink;
311 const char *zName;
312 int n;
313
314 id = db_column_int(&q, 0);
315 zName = db_column_text(&q, 1);
316 rid = db_column_int(&q, 2);
317 isExe = db_column_int(&q, 3);
@@ -339,10 +340,16 @@
340 blob_reset(&content);
341 continue;
342 }
343 }
344 if( verbose ) fossil_print("%s\n", &zName[nRepos]);
345 n = file_nondir_objects_on_path(g.zLocalRoot, zName);
346 if( n ){
347 fossil_fatal("cannot write %s because "
348 "non-directory object %.*s is in the way",
349 zName, n, zName);
350 }
351 if( file_isdir(zName, RepoFILE)==1 ){
352 /*TODO(dchest): remove directories? */
353 fossil_fatal("%s is directory, cannot overwrite", zName);
354 }
355 if( file_size(zName, RepoFILE)>=0 && (isLink || file_islink(0)) ){
356
--- src/vfile.c
+++ src/vfile.c
@@ -307,10 +307,11 @@
307307
g.zLocalRoot, id);
308308
}
309309
while( db_step(&q)==SQLITE_ROW ){
310310
int id, rid, isExe, isLink;
311311
const char *zName;
312
+ int n;
312313
313314
id = db_column_int(&q, 0);
314315
zName = db_column_text(&q, 1);
315316
rid = db_column_int(&q, 2);
316317
isExe = db_column_int(&q, 3);
@@ -339,10 +340,16 @@
339340
blob_reset(&content);
340341
continue;
341342
}
342343
}
343344
if( verbose ) fossil_print("%s\n", &zName[nRepos]);
345
+ n = file_nondir_objects_on_path(g.zLocalRoot, zName);
346
+ if( n ){
347
+ fossil_fatal("cannot write %s because "
348
+ "non-directory object %.*s is in the way",
349
+ zName, n, zName);
350
+ }
344351
if( file_isdir(zName, RepoFILE)==1 ){
345352
/*TODO(dchest): remove directories? */
346353
fossil_fatal("%s is directory, cannot overwrite", zName);
347354
}
348355
if( file_size(zName, RepoFILE)>=0 && (isLink || file_islink(0)) ){
349356
--- src/vfile.c
+++ src/vfile.c
@@ -307,10 +307,11 @@
307 g.zLocalRoot, id);
308 }
309 while( db_step(&q)==SQLITE_ROW ){
310 int id, rid, isExe, isLink;
311 const char *zName;
 
312
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);
@@ -339,10 +340,16 @@
339 blob_reset(&content);
340 continue;
341 }
342 }
343 if( verbose ) fossil_print("%s\n", &zName[nRepos]);
 
 
 
 
 
 
344 if( file_isdir(zName, RepoFILE)==1 ){
345 /*TODO(dchest): remove directories? */
346 fossil_fatal("%s is directory, cannot overwrite", zName);
347 }
348 if( file_size(zName, RepoFILE)>=0 && (isLink || file_islink(0)) ){
349
--- src/vfile.c
+++ src/vfile.c
@@ -307,10 +307,11 @@
307 g.zLocalRoot, id);
308 }
309 while( db_step(&q)==SQLITE_ROW ){
310 int id, rid, isExe, isLink;
311 const char *zName;
312 int n;
313
314 id = db_column_int(&q, 0);
315 zName = db_column_text(&q, 1);
316 rid = db_column_int(&q, 2);
317 isExe = db_column_int(&q, 3);
@@ -339,10 +340,16 @@
340 blob_reset(&content);
341 continue;
342 }
343 }
344 if( verbose ) fossil_print("%s\n", &zName[nRepos]);
345 n = file_nondir_objects_on_path(g.zLocalRoot, zName);
346 if( n ){
347 fossil_fatal("cannot write %s because "
348 "non-directory object %.*s is in the way",
349 zName, n, zName);
350 }
351 if( file_isdir(zName, RepoFILE)==1 ){
352 /*TODO(dchest): remove directories? */
353 fossil_fatal("%s is directory, cannot overwrite", zName);
354 }
355 if( file_size(zName, RepoFILE)>=0 && (isLink || file_islink(0)) ){
356
--- src/vfile.c
+++ src/vfile.c
@@ -307,10 +307,11 @@
307307
g.zLocalRoot, id);
308308
}
309309
while( db_step(&q)==SQLITE_ROW ){
310310
int id, rid, isExe, isLink;
311311
const char *zName;
312
+ int n;
312313
313314
id = db_column_int(&q, 0);
314315
zName = db_column_text(&q, 1);
315316
rid = db_column_int(&q, 2);
316317
isExe = db_column_int(&q, 3);
@@ -339,10 +340,16 @@
339340
blob_reset(&content);
340341
continue;
341342
}
342343
}
343344
if( verbose ) fossil_print("%s\n", &zName[nRepos]);
345
+ n = file_nondir_objects_on_path(g.zLocalRoot, zName);
346
+ if( n ){
347
+ fossil_fatal("cannot write %s because "
348
+ "non-directory object %.*s is in the way",
349
+ zName, n, zName);
350
+ }
344351
if( file_isdir(zName, RepoFILE)==1 ){
345352
/*TODO(dchest): remove directories? */
346353
fossil_fatal("%s is directory, cannot overwrite", zName);
347354
}
348355
if( file_size(zName, RepoFILE)>=0 && (isLink || file_islink(0)) ){
349356
--- src/vfile.c
+++ src/vfile.c
@@ -307,10 +307,11 @@
307 g.zLocalRoot, id);
308 }
309 while( db_step(&q)==SQLITE_ROW ){
310 int id, rid, isExe, isLink;
311 const char *zName;
 
312
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);
@@ -339,10 +340,16 @@
339 blob_reset(&content);
340 continue;
341 }
342 }
343 if( verbose ) fossil_print("%s\n", &zName[nRepos]);
 
 
 
 
 
 
344 if( file_isdir(zName, RepoFILE)==1 ){
345 /*TODO(dchest): remove directories? */
346 fossil_fatal("%s is directory, cannot overwrite", zName);
347 }
348 if( file_size(zName, RepoFILE)>=0 && (isLink || file_islink(0)) ){
349
--- src/vfile.c
+++ src/vfile.c
@@ -307,10 +307,11 @@
307 g.zLocalRoot, id);
308 }
309 while( db_step(&q)==SQLITE_ROW ){
310 int id, rid, isExe, isLink;
311 const char *zName;
312 int n;
313
314 id = db_column_int(&q, 0);
315 zName = db_column_text(&q, 1);
316 rid = db_column_int(&q, 2);
317 isExe = db_column_int(&q, 3);
@@ -339,10 +340,16 @@
340 blob_reset(&content);
341 continue;
342 }
343 }
344 if( verbose ) fossil_print("%s\n", &zName[nRepos]);
345 n = file_nondir_objects_on_path(g.zLocalRoot, zName);
346 if( n ){
347 fossil_fatal("cannot write %s because "
348 "non-directory object %.*s is in the way",
349 zName, n, zName);
350 }
351 if( file_isdir(zName, RepoFILE)==1 ){
352 /*TODO(dchest): remove directories? */
353 fossil_fatal("%s is directory, cannot overwrite", zName);
354 }
355 if( file_size(zName, RepoFILE)>=0 && (isLink || file_islink(0)) ){
356
--- src/vfile.c
+++ src/vfile.c
@@ -307,10 +307,11 @@
307307
g.zLocalRoot, id);
308308
}
309309
while( db_step(&q)==SQLITE_ROW ){
310310
int id, rid, isExe, isLink;
311311
const char *zName;
312
+ int n;
312313
313314
id = db_column_int(&q, 0);
314315
zName = db_column_text(&q, 1);
315316
rid = db_column_int(&q, 2);
316317
isExe = db_column_int(&q, 3);
@@ -339,10 +340,16 @@
339340
blob_reset(&content);
340341
continue;
341342
}
342343
}
343344
if( verbose ) fossil_print("%s\n", &zName[nRepos]);
345
+ n = file_nondir_objects_on_path(g.zLocalRoot, zName);
346
+ if( n ){
347
+ fossil_fatal("cannot write %s because "
348
+ "non-directory object %.*s is in the way",
349
+ zName, n, zName);
350
+ }
344351
if( file_isdir(zName, RepoFILE)==1 ){
345352
/*TODO(dchest): remove directories? */
346353
fossil_fatal("%s is directory, cannot overwrite", zName);
347354
}
348355
if( file_size(zName, RepoFILE)>=0 && (isLink || file_islink(0)) ){
349356
--- src/vfile.c
+++ src/vfile.c
@@ -307,10 +307,11 @@
307 g.zLocalRoot, id);
308 }
309 while( db_step(&q)==SQLITE_ROW ){
310 int id, rid, isExe, isLink;
311 const char *zName;
 
312
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);
@@ -339,10 +340,16 @@
339 blob_reset(&content);
340 continue;
341 }
342 }
343 if( verbose ) fossil_print("%s\n", &zName[nRepos]);
 
 
 
 
 
 
344 if( file_isdir(zName, RepoFILE)==1 ){
345 /*TODO(dchest): remove directories? */
346 fossil_fatal("%s is directory, cannot overwrite", zName);
347 }
348 if( file_size(zName, RepoFILE)>=0 && (isLink || file_islink(0)) ){
349
--- src/vfile.c
+++ src/vfile.c
@@ -307,10 +307,11 @@
307 g.zLocalRoot, id);
308 }
309 while( db_step(&q)==SQLITE_ROW ){
310 int id, rid, isExe, isLink;
311 const char *zName;
312 int n;
313
314 id = db_column_int(&q, 0);
315 zName = db_column_text(&q, 1);
316 rid = db_column_int(&q, 2);
317 isExe = db_column_int(&q, 3);
@@ -339,10 +340,16 @@
340 blob_reset(&content);
341 continue;
342 }
343 }
344 if( verbose ) fossil_print("%s\n", &zName[nRepos]);
345 n = file_nondir_objects_on_path(g.zLocalRoot, zName);
346 if( n ){
347 fossil_fatal("cannot write %s because "
348 "non-directory object %.*s is in the way",
349 zName, n, zName);
350 }
351 if( file_isdir(zName, RepoFILE)==1 ){
352 /*TODO(dchest): remove directories? */
353 fossil_fatal("%s is directory, cannot overwrite", zName);
354 }
355 if( file_size(zName, RepoFILE)>=0 && (isLink || file_islink(0)) ){
356
--- src/vfile.c
+++ src/vfile.c
@@ -307,10 +307,11 @@
307307
g.zLocalRoot, id);
308308
}
309309
while( db_step(&q)==SQLITE_ROW ){
310310
int id, rid, isExe, isLink;
311311
const char *zName;
312
+ int n;
312313
313314
id = db_column_int(&q, 0);
314315
zName = db_column_text(&q, 1);
315316
rid = db_column_int(&q, 2);
316317
isExe = db_column_int(&q, 3);
@@ -339,10 +340,16 @@
339340
blob_reset(&content);
340341
continue;
341342
}
342343
}
343344
if( verbose ) fossil_print("%s\n", &zName[nRepos]);
345
+ n = file_nondir_objects_on_path(g.zLocalRoot, zName);
346
+ if( n ){
347
+ fossil_fatal("cannot write %s because "
348
+ "non-directory object %.*s is in the way",
349
+ zName, n, zName);
350
+ }
344351
if( file_isdir(zName, RepoFILE)==1 ){
345352
/*TODO(dchest): remove directories? */
346353
fossil_fatal("%s is directory, cannot overwrite", zName);
347354
}
348355
if( file_size(zName, RepoFILE)>=0 && (isLink || file_islink(0)) ){
349356
--- src/vfile.c
+++ src/vfile.c
@@ -307,10 +307,11 @@
307 g.zLocalRoot, id);
308 }
309 while( db_step(&q)==SQLITE_ROW ){
310 int id, rid, isExe, isLink;
311 const char *zName;
 
312
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);
@@ -339,10 +340,16 @@
339 blob_reset(&content);
340 continue;
341 }
342 }
343 if( verbose ) fossil_print("%s\n", &zName[nRepos]);
 
 
 
 
 
 
344 if( file_isdir(zName, RepoFILE)==1 ){
345 /*TODO(dchest): remove directories? */
346 fossil_fatal("%s is directory, cannot overwrite", zName);
347 }
348 if( file_size(zName, RepoFILE)>=0 && (isLink || file_islink(0)) ){
349
--- src/vfile.c
+++ src/vfile.c
@@ -307,10 +307,11 @@
307 g.zLocalRoot, id);
308 }
309 while( db_step(&q)==SQLITE_ROW ){
310 int id, rid, isExe, isLink;
311 const char *zName;
312 int n;
313
314 id = db_column_int(&q, 0);
315 zName = db_column_text(&q, 1);
316 rid = db_column_int(&q, 2);
317 isExe = db_column_int(&q, 3);
@@ -339,10 +340,16 @@
340 blob_reset(&content);
341 continue;
342 }
343 }
344 if( verbose ) fossil_print("%s\n", &zName[nRepos]);
345 n = file_nondir_objects_on_path(g.zLocalRoot, zName);
346 if( n ){
347 fossil_fatal("cannot write %s because "
348 "non-directory object %.*s is in the way",
349 zName, n, zName);
350 }
351 if( file_isdir(zName, RepoFILE)==1 ){
352 /*TODO(dchest): remove directories? */
353 fossil_fatal("%s is directory, cannot overwrite", zName);
354 }
355 if( file_size(zName, RepoFILE)>=0 && (isLink || file_islink(0)) ){
356

Keyboard Shortcuts

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