Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
| Comment: | Improvements to the Security-Audit page - mostly in providing additional information about the files in the CGI extension folder. |
|---|---|
| Timelines: | family | ancestors | descendants | both | trunk |
| Files: | files | file ages | folders |
| SHA3-256: |
a3bc6552eea4676d3bb55ed5b40ab608 |
| User & Date: | drh 2019-08-04 20:23:46.904 |
Context
|
2019-08-04
| ||
| 20:26 | Fix a harmless compiler warning. check-in: 95a6a658d4 user: drh tags: trunk | |
| 20:23 | Improvements to the Security-Audit page - mostly in providing additional information about the files in the CGI extension folder. check-in: a3bc6552ee user: drh tags: trunk | |
|
2019-08-03
| ||
| 19:49 | Fix the repolist function for CGI server invocations, apparently broken by check-in [ec56c69fe98d26d9] check-in: 534b060007 user: drh tags: trunk | |
Changes
Changes to src/add.c.
| ︙ | ︙ | |||
326 327 328 329 330 331 332 |
file_tree_name(g.argv[i], &fullName, 0, 1);
blob_reset(&fullName);
file_canonical_name(g.argv[i], &fullName, 0);
zName = blob_str(&fullName);
isDir = file_isdir(zName, RepoFILE);
if( isDir==1 ){
| | | 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 |
file_tree_name(g.argv[i], &fullName, 0, 1);
blob_reset(&fullName);
file_canonical_name(g.argv[i], &fullName, 0);
zName = blob_str(&fullName);
isDir = file_isdir(zName, RepoFILE);
if( isDir==1 ){
vfile_scan(&fullName, nRoot-1, scanFlags, pClean, pIgnore, RepoFILE);
}else if( isDir==0 ){
fossil_warning("not found: %s", zName);
}else{
char *zTreeName = &zName[nRoot];
if( !forceFlag && glob_match(pIgnore, zTreeName) ){
Blob ans;
char cReply;
|
| ︙ | ︙ | |||
675 676 677 678 679 680 681 |
db_multi_exec("CREATE TEMP TABLE sfile(pathname TEXT PRIMARY KEY %s)",
filename_collation());
n = strlen(g.zLocalRoot);
blob_init(&path, g.zLocalRoot, n-1);
/* now we read the complete file structure into a temp table */
pClean = glob_create(zCleanFlag);
pIgnore = glob_create(zIgnoreFlag);
| | | 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 |
db_multi_exec("CREATE TEMP TABLE sfile(pathname TEXT PRIMARY KEY %s)",
filename_collation());
n = strlen(g.zLocalRoot);
blob_init(&path, g.zLocalRoot, n-1);
/* now we read the complete file structure into a temp table */
pClean = glob_create(zCleanFlag);
pIgnore = glob_create(zIgnoreFlag);
vfile_scan(&path, blob_size(&path), scanFlags, pClean, pIgnore, RepoFILE);
glob_free(pIgnore);
glob_free(pClean);
nAdd = add_files_in_sfile(vid);
/* step 2: search for missing files */
db_prepare(&q,
"SELECT pathname, %Q || pathname, deleted FROM vfile"
|
| ︙ | ︙ |
Changes to src/checkin.c.
| ︙ | ︙ | |||
78 79 80 81 82 83 84 |
int nRoot; /* length of g.zLocalRoot */
db_multi_exec("CREATE TEMP TABLE sfile(pathname TEXT PRIMARY KEY %s,"
" mtime INTEGER, size INTEGER)", filename_collation());
nRoot = (int)strlen(g.zLocalRoot);
if( argc==0 ){
blob_init(&name, g.zLocalRoot, nRoot - 1);
| | | | 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 |
int nRoot; /* length of g.zLocalRoot */
db_multi_exec("CREATE TEMP TABLE sfile(pathname TEXT PRIMARY KEY %s,"
" mtime INTEGER, size INTEGER)", filename_collation());
nRoot = (int)strlen(g.zLocalRoot);
if( argc==0 ){
blob_init(&name, g.zLocalRoot, nRoot - 1);
vfile_scan(&name, blob_size(&name), scanFlags, pIgnore, 0, RepoFILE);
blob_reset(&name);
}else{
for(i=0; i<argc; i++){
file_canonical_name(argv[i], &name, 0);
zName = blob_str(&name);
isDir = file_isdir(zName, RepoFILE);
if( isDir==1 ){
vfile_scan(&name, nRoot-1, scanFlags, pIgnore, 0, RepoFILE);
}else if( isDir==0 ){
fossil_warning("not found: %s", &zName[nRoot]);
}else if( file_access(zName, R_OK) ){
fossil_fatal("cannot open %s", &zName[nRoot]);
}else{
db_multi_exec(
"INSERT OR IGNORE INTO sfile(pathname) VALUES(%Q)",
|
| ︙ | ︙ | |||
1103 1104 1105 1106 1107 1108 1109 |
}
if( emptyDirsFlag ){
Glob *pEmptyDirs = glob_create(db_get("empty-dirs", 0));
Stmt q;
Blob root;
blob_init(&root, g.zLocalRoot, nRoot - 1);
vfile_dir_scan(&root, blob_size(&root), scanFlags, pIgnore,
| | | 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 |
}
if( emptyDirsFlag ){
Glob *pEmptyDirs = glob_create(db_get("empty-dirs", 0));
Stmt q;
Blob root;
blob_init(&root, g.zLocalRoot, nRoot - 1);
vfile_dir_scan(&root, blob_size(&root), scanFlags, pIgnore,
pEmptyDirs, RepoFILE);
blob_reset(&root);
db_prepare(&q,
"SELECT %Q || x FROM dscan_temp"
" WHERE x NOT IN (%s) AND y = 0"
" ORDER BY 1 DESC",
g.zLocalRoot, fossil_all_reserved_names(0)
);
|
| ︙ | ︙ |
Changes to src/extcgi.c.
| ︙ | ︙ | |||
72 73 74 75 76 77 78 79 80 81 82 83 84 85 | "SCRIPT_DIRECTORY", "SCRIPT_FILENAME", "SCRIPT_NAME", "SERVER_NAME", "SERVER_PORT", "SERVER_PROTOCOL", }; /* ** WEBPAGE: ext raw-content ** ** Relay an HTTP request to secondary CGI after first checking the ** login credentials and setting auxiliary environment variables ** so that the secondary CGI can be aware of the credentials and | > > > > > > > > > > > > > > > > > > > > > > > | 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 |
"SCRIPT_DIRECTORY",
"SCRIPT_FILENAME",
"SCRIPT_NAME",
"SERVER_NAME",
"SERVER_PORT",
"SERVER_PROTOCOL",
};
/*
** Check a pathname to determine if it is acceptable for use as
** extension CGI. Some pathnames are excluded for security reasons.
** Return NULL on success or a static error string if there is
** a failure.
*/
const char *ext_pathname_ok(const char *zName){
int i;
const char *zFailReason = 0;
for(i=0; zName[i]; i++){
char c = zName[i];
if( (c=='.' || c=='-') && (i==0 || zName[i-1]=='/') ){
zFailReason = "path element begins with '.' or '-'";
break;
}
if( !fossil_isalnum(c) && c!='_' && c!='-' && c!='.' && c!='/' ){
zFailReason = "illegal character in path";
break;
}
}
return zFailReason;
}
/*
** WEBPAGE: ext raw-content
**
** Relay an HTTP request to secondary CGI after first checking the
** login credentials and setting auxiliary environment variables
** so that the secondary CGI can be aware of the credentials and
|
| ︙ | ︙ | |||
129 130 131 132 133 134 135 |
zFailReason = "extroot is a relative pathname";
goto ext_not_found;
}
if( zName==0 ){
zFailReason = "no path beyond /ext";
goto ext_not_found;
}
| < < < | | < < | < < < | 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 |
zFailReason = "extroot is a relative pathname";
goto ext_not_found;
}
if( zName==0 ){
zFailReason = "no path beyond /ext";
goto ext_not_found;
}
zFailReason = ext_pathname_ok(zName);
if( zFailReason ) goto ext_not_found;
zFailReason = "???";
if( file_isdir(g.zExtRoot,ExtFILE)!=1 ){
zFailReason = "extroot is not a directory";
goto ext_not_found;
}
zPath = mprintf("%s/%s", g.zExtRoot, zName);
nRoot = (int)strlen(g.zExtRoot);
if( file_isfile(zPath, ExtFILE) ){
|
| ︙ | ︙ | |||
295 296 297 298 299 300 301 |
@ <p>Page not found: %h(zPathInfo)</p>
if( g.perm.Debug ){
@ <p>Reason for failure: %h(zFailReason)</p>
}
}
return;
}
| > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 |
@ <p>Page not found: %h(zPathInfo)</p>
if( g.perm.Debug ){
@ <p>Reason for failure: %h(zFailReason)</p>
}
}
return;
}
/*
** Create a temporary SFILE table and fill it with one entry for each file
** in the extension document root directory (g.zExtRoot). The SFILE table
** looks like this:
**
** CREATE TEMP TABLE sfile(
** pathname TEXT PRIMARY KEY,
** isexe BOOLEAN
** ) WITHOUT ROWID;
*/
void ext_files(void){
Blob base;
db_multi_exec(
"CREATE TEMP TABLE sfile(\n"
" pathname TEXT PRIMARY KEY,\n"
" isexe BOOLEAN\n"
") WITHOUT ROWID;"
);
blob_init(&base, g.zExtRoot, -1);
vfile_scan(&base, blob_size(&base),
SCAN_ALL|SCAN_ISEXE,
0, 0, ExtFILE);
blob_zero(&base);
}
/*
** WEBPAGE: extfilelist
**
** List all files in the extension CGI document root and its subfolders.
*/
void ext_filelist_page(void){
Stmt q;
login_check_credentials();
if( !g.perm.Admin ){
login_needed(0);
return;
}
ext_files();
style_header("CGI Extension Filelist");
@ <table border="0" cellspacing="0" cellpadding="3">
@ <tbody>
db_prepare(&q, "SELECT pathname, isexe FROM sfile"
" ORDER BY pathname");
while( db_step(&q)==SQLITE_ROW ){
const char *zName = db_column_text(&q,0);
int isExe = db_column_int(&q,1);
@ <tr>
if( ext_pathname_ok(zName)!=0 ){
@ <td><span style="opacity:0.5;">%h(zName)</span></td>
@ <td>data file</td>
}else{
@ <td><a href="%R/ext/%h(zName)">%h(zName)</a></td>
if( isExe ){
@ <td>CGI</td>
}else{
@ <td>static content</td>
}
}
@ </tr>
}
db_finalize(&q);
@ </tbody>
@ </table>
style_footer();
}
|
Changes to src/main.c.
| ︙ | ︙ | |||
146 147 148 149 150 151 152 153 154 155 156 157 158 159 | sqlite3_int64 now; /* Seconds since 1970 */ int repositoryOpen; /* True if the main repository database is open */ unsigned iRepoDataVers; /* Initial data version for repository database */ char *zRepositoryOption; /* Most recent cached repository option value */ char *zRepositoryName; /* Name of the repository database file */ char *zLocalDbName; /* Name of the local database file */ char *zOpenRevision; /* Check-in version to use during database open */ int localOpen; /* True if the local database is open */ char *zLocalRoot; /* The directory holding the local database */ int minPrefix; /* Number of digits needed for a distinct UUID */ int eHashPolicy; /* Current hash policy. One of HPOLICY_* */ int fSqlTrace; /* True if --sqltrace flag is present */ int fSqlStats; /* True if --sqltrace or --sqlstats are present */ int fSqlPrint; /* True if --sqlprint flag is present */ | > | 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 | sqlite3_int64 now; /* Seconds since 1970 */ int repositoryOpen; /* True if the main repository database is open */ unsigned iRepoDataVers; /* Initial data version for repository database */ char *zRepositoryOption; /* Most recent cached repository option value */ char *zRepositoryName; /* Name of the repository database file */ char *zLocalDbName; /* Name of the local database file */ char *zOpenRevision; /* Check-in version to use during database open */ char *zCmdName; /* Name of the Fossil command currently running */ int localOpen; /* True if the local database is open */ char *zLocalRoot; /* The directory holding the local database */ int minPrefix; /* Number of digits needed for a distinct UUID */ int eHashPolicy; /* Current hash policy. One of HPOLICY_* */ int fSqlTrace; /* True if --sqltrace flag is present */ int fSqlStats; /* True if --sqltrace or --sqlstats are present */ int fSqlPrint; /* True if --sqlprint flag is present */ |
| ︙ | ︙ | |||
784 785 786 787 788 789 790 791 792 793 794 795 796 797 |
g.httpOut = stdout;
g.fullHttpReply = !g.isHTTP;
fossil_panic("file descriptor 2 is not open. (fd=%d, errno=%d)",
fd, x);
}
}
#endif
rc = dispatch_name_search(zCmdName, CMDFLAG_COMMAND|CMDFLAG_PREFIX, &pCmd);
if( rc==1 ){
#ifdef FOSSIL_ENABLE_TH1_HOOKS
if( !g.isHTTP && !g.fNoThHook ){
rc = Th_CommandHook(zCmdName, 0);
}else{
rc = TH_OK;
| > | 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 |
g.httpOut = stdout;
g.fullHttpReply = !g.isHTTP;
fossil_panic("file descriptor 2 is not open. (fd=%d, errno=%d)",
fd, x);
}
}
#endif
g.zCmdName = zCmdName;
rc = dispatch_name_search(zCmdName, CMDFLAG_COMMAND|CMDFLAG_PREFIX, &pCmd);
if( rc==1 ){
#ifdef FOSSIL_ENABLE_TH1_HOOKS
if( !g.isHTTP && !g.fNoThHook ){
rc = Th_CommandHook(zCmdName, 0);
}else{
rc = TH_OK;
|
| ︙ | ︙ |
Changes to src/repolist.c.
| ︙ | ︙ | |||
131 132 133 134 135 136 137 |
/* The default case: All repositories under the g.zRepositoryName
** directory.
*/
blob_init(&base, g.zRepositoryName, -1);
sqlite3_open(":memory:", &g.db);
db_multi_exec("CREATE TABLE sfile(pathname TEXT);");
db_multi_exec("CREATE TABLE vfile(pathname);");
| | | 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 |
/* The default case: All repositories under the g.zRepositoryName
** directory.
*/
blob_init(&base, g.zRepositoryName, -1);
sqlite3_open(":memory:", &g.db);
db_multi_exec("CREATE TABLE sfile(pathname TEXT);");
db_multi_exec("CREATE TABLE vfile(pathname);");
vfile_scan(&base, blob_size(&base), 0, 0, 0, ExtFILE);
db_multi_exec("DELETE FROM sfile WHERE pathname NOT GLOB '*[^/].fossil'");
allRepo = 0;
}
n = db_int(0, "SELECT count(*) FROM sfile");
if( n==0 ){
sqlite3_close(g.db);
return 0;
|
| ︙ | ︙ |
Changes to src/security_audit.c.
| ︙ | ︙ | |||
400 401 402 403 404 405 406 |
}
}
#endif
if( g.zErrlog==0 || fossil_strcmp(g.zErrlog,"-")==0 ){
@ <li><p>
@ The server error log is disabled.
| | | | | | | | > > > > > > | > | 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 |
}
}
#endif
if( g.zErrlog==0 || fossil_strcmp(g.zErrlog,"-")==0 ){
@ <li><p>
@ The server error log is disabled.
@ To set up an error log,
if( fossil_strcmp(g.zCmdName, "cgi")==0 ){
@ make an entry like "errorlog: <i>FILENAME</i>" in the
@ CGI script at %h(P("SCRIPT_FILENAME")).
}else{
@ add the "--errorlog <i>FILENAME</i>" option to the
@ "%h(g.argv[0]) %h(g.zCmdName)" command that launched this server.
}
}else{
FILE *pTest = fossil_fopen(g.zErrlog,"a");
if( pTest==0 ){
@ <li><p>
@ <b>Error:</b>
@ There is an error log at "%h(g.zErrlog)" but that file is not
@ writable and so no logging will occur.
}else{
fclose(pTest);
@ <li><p>
@ The error log at "<a href='%R/errorlog'>%h(g.zErrlog)</a>" is
@ %,lld(file_size(g.zErrlog, ExtFILE)) bytes in size.
}
}
if( g.zExtRoot ){
int nFile;
int nCgi;
ext_files();
nFile = db_int(0, "SELECT count(*) FROM sfile");
nCgi = nFile==0 ? 0 : db_int(0,"SELECT count(*) FROM sfile WHERE isexe");
@ <li><p> CGI Extensions are enabled with a document root
@ at <a href='%R/extfilelist'>%h(g.zExtRoot)</a> holding
@ %d(nCgi) CGIs and %d(nFile-nCgi) static content and data files.
}
@ <li><p> User capability summary:
capability_summary();
if( alert_enabled() ){
@ <li><p> Email alert configuration summary:
|
| ︙ | ︙ |
Changes to src/stat.c.
| ︙ | ︙ | |||
102 103 104 105 106 107 108 |
@ </td></tr>
nPend = db_int(0,"SELECT count(*) FROM pending_alert WHERE NOT sentSep");
nDPend = db_int(0,"SELECT count(*) FROM pending_alert"
" WHERE NOT sentDigest");
@ <tr><th>Pending Alerts:</th><td>
@ %,d(nPend) normal, %,d(nDPend) digest
@ </td></tr>
| > > > | > | 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 |
@ </td></tr>
nPend = db_int(0,"SELECT count(*) FROM pending_alert WHERE NOT sentSep");
nDPend = db_int(0,"SELECT count(*) FROM pending_alert"
" WHERE NOT sentDigest");
@ <tr><th>Pending Alerts:</th><td>
@ %,d(nPend) normal, %,d(nDPend) digest
@ </td></tr>
if( g.perm.Admin ){
@ <tr><th><a href="%R/subscribers">Subscribers:</a></th><td>
}else{
@ <tr><th>Subscribers:</th><td>
}
nSub = db_int(0, "SELECT count(*) FROM subscriber");
nASub = db_int(0, "SELECT count(*) FROM subscriber WHERE sverified"
" AND NOT sdonotcall AND length(ssub)>1");
@ %,d(nASub) active, %,d(nSub) total
@ </td></tr>
}
|
| ︙ | ︙ |
Changes to src/vfile.c.
| ︙ | ︙ | |||
428 429 430 431 432 433 434 435 436 437 438 439 440 | ** Values for the scanFlags parameter to vfile_scan(). */ #define SCAN_ALL 0x001 /* Includes files that begin with "." */ #define SCAN_TEMP 0x002 /* Only Fossil-generated files like *-baseline */ #define SCAN_NESTED 0x004 /* Scan for empty dirs in nested checkouts */ #define SCAN_MTIME 0x008 /* Populate mtime column */ #define SCAN_SIZE 0x010 /* Populate size column */ #endif /* INTERFACE */ /* ** Load into table SFILE the name of every ordinary file in ** the directory pPath. Omit the first nPrefix characters of ** of pPath when inserting into the SFILE table. | > < > | > | > > | | > > > > > > > > > > | | | | > | | > | | > | 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 |
** Values for the scanFlags parameter to vfile_scan().
*/
#define SCAN_ALL 0x001 /* Includes files that begin with "." */
#define SCAN_TEMP 0x002 /* Only Fossil-generated files like *-baseline */
#define SCAN_NESTED 0x004 /* Scan for empty dirs in nested checkouts */
#define SCAN_MTIME 0x008 /* Populate mtime column */
#define SCAN_SIZE 0x010 /* Populate size column */
#define SCAN_ISEXE 0x020 /* Populate isexe column */
#endif /* INTERFACE */
/*
** Load into table SFILE the name of every ordinary file in
** the directory pPath. Omit the first nPrefix characters of
** of pPath when inserting into the SFILE table.
** Subdirectories are scanned recursively.
**
** Omit files named in VFILE if eFType==RepoFILE. Include all files
** if eFType==ExtFILE.
**
** Files whose names begin with "." are omitted unless the SCAN_ALL
** flag is set.
**
** Any files or directories that match the glob patterns pIgnore*
** are excluded from the scan. Name matching occurs after the
** first nPrefix characters are elided from the filename.
*/
void vfile_scan(
Blob *pPath, /* Directory to be scanned */
int nPrefix, /* Number of bytes in directory name */
unsigned scanFlags, /* Zero or more SCAN_xxx flags */
Glob *pIgnore1, /* Do not add files that match this GLOB */
Glob *pIgnore2, /* Omit files matching this GLOB too */
int eFType /* ExtFILE or RepoFILE */
){
DIR *d;
int origSize;
struct dirent *pEntry;
int skipAll = 0;
static Stmt ins;
static int depth = 0;
void *zNative;
origSize = blob_size(pPath);
if( pIgnore1 || pIgnore2 ){
blob_appendf(pPath, "/");
if( glob_match(pIgnore1, &blob_str(pPath)[nPrefix+1]) ) skipAll = 1;
if( glob_match(pIgnore2, &blob_str(pPath)[nPrefix+1]) ) skipAll = 1;
blob_resize(pPath, origSize);
}
if( skipAll ) return;
if( depth==0 ){
if( eFType==ExtFILE ){
db_prepare(&ins,
"INSERT OR IGNORE INTO sfile(pathname%s%s%s) VALUES(:file%s%s%s)",
scanFlags & SCAN_MTIME ? ",mtime" : "",
scanFlags & SCAN_SIZE ? ",size" : "",
scanFlags & SCAN_ISEXE ? ",isexe" : "",
scanFlags & SCAN_MTIME ? ",:mtime" : "",
scanFlags & SCAN_SIZE ? ",:size" : "",
scanFlags & SCAN_ISEXE ? ",:isexe" : ""
);
}else{
db_prepare(&ins,
"INSERT OR IGNORE INTO sfile(pathname%s%s%s) SELECT :file%s%s%s"
" WHERE NOT EXISTS(SELECT 1 FROM vfile WHERE"
" pathname=:file %s)",
scanFlags & SCAN_MTIME ? ",mtime" : "",
scanFlags & SCAN_SIZE ? ",size" : "",
scanFlags & SCAN_ISEXE ? ",isexe" : "",
scanFlags & SCAN_MTIME ? ",:mtime" : "",
scanFlags & SCAN_SIZE ? ",:size" : "",
scanFlags & SCAN_ISEXE ? ",:isexe" : "",
filename_collation()
);
}
}
depth++;
zNative = fossil_utf8_to_path(blob_str(pPath), 1);
d = opendir(zNative);
if( d ){
while( (pEntry=readdir(d))!=0 ){
|
| ︙ | ︙ | |||
502 503 504 505 506 507 508 |
blob_appendf(pPath, "/%s", zUtf8);
zPath = blob_str(pPath);
if( glob_match(pIgnore1, &zPath[nPrefix+1]) ||
glob_match(pIgnore2, &zPath[nPrefix+1]) ){
/* do nothing */
#ifdef _DIRENT_HAVE_D_TYPE
}else if( (pEntry->d_type==DT_UNKNOWN || pEntry->d_type==DT_LNK)
| | | | | | > > > | 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 |
blob_appendf(pPath, "/%s", zUtf8);
zPath = blob_str(pPath);
if( glob_match(pIgnore1, &zPath[nPrefix+1]) ||
glob_match(pIgnore2, &zPath[nPrefix+1]) ){
/* do nothing */
#ifdef _DIRENT_HAVE_D_TYPE
}else if( (pEntry->d_type==DT_UNKNOWN || pEntry->d_type==DT_LNK)
? (file_isdir(zPath, eFType)==1) : (pEntry->d_type==DT_DIR) ){
#else
}else if( file_isdir(zPath, eFType)==1 ){
#endif
if( !vfile_top_of_checkout(zPath) ){
vfile_scan(pPath, nPrefix, scanFlags, pIgnore1, pIgnore2, eFType);
}
#ifdef _DIRENT_HAVE_D_TYPE
}else if( (pEntry->d_type==DT_UNKNOWN || pEntry->d_type==DT_LNK)
? (file_isfile_or_link(zPath)) : (pEntry->d_type==DT_REG) ){
#else
}else if( file_isfile_or_link(zPath) ){
#endif
if( (scanFlags & SCAN_TEMP)==0 || is_temporary_file(zUtf8) ){
db_bind_text(&ins, ":file", &zPath[nPrefix+1]);
if( scanFlags & SCAN_MTIME ){
db_bind_int(&ins, ":mtime", file_mtime(zPath, eFType));
}
if( scanFlags & SCAN_SIZE ){
db_bind_int(&ins, ":size", file_size(zPath, eFType));
}
if( scanFlags & SCAN_ISEXE ){
db_bind_int(&ins, ":isexe", file_isexe(zPath, eFType));
}
db_step(&ins);
db_reset(&ins);
}
}
fossil_path_free(zUtf8);
blob_resize(pPath, origSize);
|
| ︙ | ︙ | |||
562 563 564 565 566 567 568 | ** Returns the total number of files found. */ int vfile_dir_scan( Blob *pPath, /* Base directory to be scanned */ int nPrefix, /* Number of bytes in base directory name */ unsigned scanFlags, /* Zero or more SCAN_xxx flags */ Glob *pIgnore1, /* Do not add directories that match this GLOB */ | | > | 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 |
** Returns the total number of files found.
*/
int vfile_dir_scan(
Blob *pPath, /* Base directory to be scanned */
int nPrefix, /* Number of bytes in base directory name */
unsigned scanFlags, /* Zero or more SCAN_xxx flags */
Glob *pIgnore1, /* Do not add directories that match this GLOB */
Glob *pIgnore2, /* Omit directories matching this GLOB too */
int eFType /* ExtFILE or RepoFILE */
){
int result = 0;
DIR *d;
int origSize;
struct dirent *pEntry;
int skipAll = 0;
static Stmt ins;
|
| ︙ | ︙ | |||
622 623 624 625 626 627 628 |
blob_appendf(pPath, "/%s", zUtf8);
zPath = blob_str(pPath);
if( glob_match(pIgnore1, &zPath[nPrefix+1]) ||
glob_match(pIgnore2, &zPath[nPrefix+1]) ){
/* do nothing */
#ifdef _DIRENT_HAVE_D_TYPE
}else if( (pEntry->d_type==DT_UNKNOWN || pEntry->d_type==DT_LNK)
| | | | | 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 |
blob_appendf(pPath, "/%s", zUtf8);
zPath = blob_str(pPath);
if( glob_match(pIgnore1, &zPath[nPrefix+1]) ||
glob_match(pIgnore2, &zPath[nPrefix+1]) ){
/* do nothing */
#ifdef _DIRENT_HAVE_D_TYPE
}else if( (pEntry->d_type==DT_UNKNOWN || pEntry->d_type==DT_LNK)
? (file_isdir(zPath, eFType)==1) : (pEntry->d_type==DT_DIR) ){
#else
}else if( file_isdir(zPath, eFType)==1 ){
#endif
if( (scanFlags & SCAN_NESTED) || !vfile_top_of_checkout(zPath) ){
char *zSavePath = mprintf("%s", zPath);
int count = vfile_dir_scan(pPath, nPrefix, scanFlags, pIgnore1,
pIgnore2, eFType);
db_bind_text(&ins, ":file", &zSavePath[nPrefix+1]);
db_bind_int(&ins, ":count", count);
db_step(&ins);
db_reset(&ins);
fossil_free(zSavePath);
result += count; /* found X normal files? */
}
|
| ︙ | ︙ |