321
322
323
324
325
326
327
328
329
330
331
332
333
334
|
** This routines RepoFILE - that zFilename is always a file under management.
**
** On Windows, always return False.
*/
int file_islink(const char *zFilename){
return file_perm(zFilename, RepoFILE)==PERM_LNK;
}
/*
** Return 1 if zFilename is a directory. Return 0 if zFilename
** does not exist. Return 2 if zFilename exists but is something
** other than a directory.
*/
int file_isdir(const char *zFilename, int eFType){
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
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
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
|
** This routines RepoFILE - that zFilename is always a file under management.
**
** On Windows, always return False.
*/
int file_islink(const char *zFilename){
return file_perm(zFilename, RepoFILE)==PERM_LNK;
}
/*
** Check every sub-directory of zRoot along the path to zFile.
** If any sub-directory is really an ordinary file or a symbolic link,
** return an integer which is the length of the prefix of zFile which
** is the name of that object. Return 0 if all no non-directory
** objects are found along the path.
**
** Example: Given inputs
**
** zRoot = /home/alice/project1
** zFile = /home/alice/project1/main/src/js/fileA.js
**
** Look for objects in the following order:
**
** /home/alice/project/main
** /home/alice/project/main/src
** /home/alice/project/main/src/js
**
** If any of those objects exist and are something other than a directory
** then return the length of the name of the first non-directory object
** seen.
*/
int file_nondir_objects_on_path(const char *zRoot, const char *zFile){
int i = (int)strlen(zRoot);
char *z = fossil_strdup(zFile);
assert( fossil_strnicmp(zRoot, z, i)==0 );
if( i && zRoot[i-1]=='/' ) i--;
while( z[i]=='/' ){
int j, rc;
for(j=i+1; z[j] && z[j]!='/'; j++){}
if( z[j]!='/' ) break;
z[j] = 0;
rc = file_isdir(z, SymFILE);
if( rc!=1 ){
if( rc==2 ){
fossil_free(z);
return j;
}
break;
}
z[j] = '/';
i = j;
}
fossil_free(z);
return 0;
}
/*
** The file named zFile is suppose to be an in-tree file. Check to
** ensure that it will be safe to write to this file by verifying that
** there are no symlinks or other non-directory objects in between the
** root of the checkout and zFile.
**
** If a problem is found, print a warning message (using fossil_warning())
** and return non-zero. If everything is ok, return zero.
*/
int file_unsafe_in_tree_path(const char *zFile){
int n;
if( !file_is_absolute_path(zFile) ){
fossil_panic("%s is not an absolute pathname",zFile);
}
if( fossil_strnicmp(g.zLocalRoot, zFile, (int)strlen(g.zLocalRoot)) ){
fossil_panic("%s is not a prefix of %s", g.zLocalRoot, zFile);
}
n = file_nondir_objects_on_path(g.zLocalRoot, zFile);
if( n ){
fossil_warning("cannot write to %s because non-directory object %.*s"
" is in the way", zFile, n, zFile);
}
return n;
}
/*
** Return 1 if zFilename is a directory. Return 0 if zFilename
** does not exist. Return 2 if zFilename exists but is something
** other than a directory.
*/
int file_isdir(const char *zFilename, int eFType){
|
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
|
** zFilename is a symbolic link, it is the object that zFilename points
** to that is modified.
*/
int file_setexe(const char *zFilename, int onoff){
int rc = 0;
#if !defined(_WIN32)
struct stat buf;
if( fossil_stat(zFilename, &buf, RepoFILE)!=0 || S_ISLNK(buf.st_mode) ){
return 0;
}
if( onoff ){
int targetMode = (buf.st_mode & 0444)>>2;
if( (buf.st_mode & 0100)==0 ){
chmod(zFilename, buf.st_mode | targetMode);
rc = 1;
|
|
>
>
>
|
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
|
** zFilename is a symbolic link, it is the object that zFilename points
** to that is modified.
*/
int file_setexe(const char *zFilename, int onoff){
int rc = 0;
#if !defined(_WIN32)
struct stat buf;
if( fossil_stat(zFilename, &buf, RepoFILE)!=0
|| S_ISLNK(buf.st_mode)
|| S_ISDIR(buf.st_mode)
){
return 0;
}
if( onoff ){
int targetMode = (buf.st_mode & 0444)>>2;
if( (buf.st_mode & 0100)==0 ){
chmod(zFilename, buf.st_mode | targetMode);
rc = 1;
|
2224
2225
2226
2227
2228
2229
2230
|
if( dryRunFlag!=0 ){
fossil_print("dry-run: would have touched %d file(s)\n",
changeCount);
}else{
fossil_print("Touched %d file(s)\n", changeCount);
}
}
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386
2387
2388
|
if( dryRunFlag!=0 ){
fossil_print("dry-run: would have touched %d file(s)\n",
changeCount);
}else{
fossil_print("Touched %d file(s)\n", changeCount);
}
}
/*
** Returns non-zero if the specified file name ends with any reserved name,
** e.g.: _FOSSIL_ or .fslckout. Specifically, it returns 1 for exact match
** or 2 for a tail match on a longer file name.
**
** For the sake of efficiency, zFilename must be a canonical name, e.g. an
** absolute path using only forward slash ('/') as a directory separator.
**
** nFilename must be the length of zFilename. When negative, strlen() will
** be used to calculate it.
*/
int file_is_reserved_name(const char *zFilename, int nFilename){
const char *zEnd; /* one-after-the-end of zFilename */
int gotSuffix = 0; /* length of suffix (-wal, -shm, -journal) */
assert( zFilename && "API misuse" );
if( nFilename<0 ) nFilename = (int)strlen(zFilename);
if( nFilename<8 ) return 0; /* strlen("_FOSSIL_") */
zEnd = zFilename + nFilename;
if( nFilename>=12 ){ /* strlen("_FOSSIL_-(shm|wal)") */
/* Check for (-wal, -shm, -journal) suffixes, with an eye towards
** runtime speed. */
if( zEnd[-4]=='-' ){
if( fossil_strnicmp("wal", &zEnd[-3], 3)
&& fossil_strnicmp("shm", &zEnd[-3], 3) ){
return 0;
}
gotSuffix = 4;
}else if( nFilename>=16 && zEnd[-8]=='-' ){ /*strlen(_FOSSIL_-journal) */
if( fossil_strnicmp("journal", &zEnd[-7], 7) ) return 0;
gotSuffix = 8;
}
if( gotSuffix ){
assert( 4==gotSuffix || 8==gotSuffix );
zEnd -= gotSuffix;
nFilename -= gotSuffix;
gotSuffix = 1;
}
assert( nFilename>=8 && "strlen(_FOSSIL_)" );
assert( gotSuffix==0 || gotSuffix==1 );
}
switch( zEnd[-1] ){
case '_':{
if( fossil_strnicmp("_FOSSIL_", &zEnd[-8], 8) ) return 0;
if( 8==nFilename ) return 1;
return zEnd[-9]=='/' ? 2 : gotSuffix;
}
case 'T':
case 't':{
if( nFilename<9 || zEnd[-9]!='.'
|| fossil_strnicmp(".fslckout", &zEnd[-9], 9) ){
return 0;
}
if( 9==nFilename ) return 1;
return zEnd[-10]=='/' ? 2 : gotSuffix;
}
default:{
return 0;
}
}
}
/*
** COMMAND: test-is-reserved-name
**
** Usage: %fossil test-is-ckout-db FILENAMES...
**
** Passes each given name to file_is_reserved_name() and outputs one
** line per file: the result value of that function followed by the
** name.
*/
void test_is_reserved_name_cmd(void){
int i;
if(g.argc<3){
usage("FILENAME_1 [...FILENAME_N]");
}
for( i = 2; i < g.argc; ++i ){
const int check = file_is_reserved_name(g.argv[i], -1);
fossil_print("%d %s\n", check, g.argv[i]);
}
}
|