Fossil SCM
Merge additional symlink fixes. Back out comment-only changes from url.c.
Commit
0ea17c2b11b5bc63f69aabc3a183419d9413b0a603760958137a986443212760
Parent
fe1264d35df2fe1…
18 files changed
+11
-5
+11
-5
+25
+25
+25
+25
+2
+4
-2
+2
+2
+2
+3
-3
+3
-3
+3
-3
+3
-3
+3
-7
+3
-7
+3
-7
+11
-5
| --- src/add.c | ||
| +++ src/add.c | ||
| @@ -156,10 +156,11 @@ | ||
| 156 | 156 | */ |
| 157 | 157 | static int add_one_file( |
| 158 | 158 | const char *zPath, /* Tree-name of file to add. */ |
| 159 | 159 | int vid /* Add to this VFILE */ |
| 160 | 160 | ){ |
| 161 | + int doSkip = 0; | |
| 161 | 162 | if( !file_is_simple_pathname(zPath, 1) ){ |
| 162 | 163 | fossil_warning("filename contains illegal characters: %s", zPath); |
| 163 | 164 | return 0; |
| 164 | 165 | } |
| 165 | 166 | if( db_exists("SELECT 1 FROM vfile" |
| @@ -168,17 +169,22 @@ | ||
| 168 | 169 | " WHERE pathname=%Q %s AND deleted", |
| 169 | 170 | zPath, filename_collation()); |
| 170 | 171 | }else{ |
| 171 | 172 | char *zFullname = mprintf("%s%s", g.zLocalRoot, zPath); |
| 172 | 173 | int isExe = file_isexe(zFullname, RepoFILE); |
| 173 | - db_multi_exec( | |
| 174 | - "INSERT INTO vfile(vid,deleted,rid,mrid,pathname,isexe,islink,mhash)" | |
| 175 | - "VALUES(%d,0,0,0,%Q,%d,%d,NULL)", | |
| 176 | - vid, zPath, isExe, file_islink(0)); | |
| 174 | + if( file_nondir_objects_on_path(g.zLocalRoot, zFullname) ){ | |
| 175 | + /* Do not add unsafe files to the vfile */ | |
| 176 | + doSkip = 1; | |
| 177 | + }else{ | |
| 178 | + db_multi_exec( | |
| 179 | + "INSERT INTO vfile(vid,deleted,rid,mrid,pathname,isexe,islink,mhash)" | |
| 180 | + "VALUES(%d,0,0,0,%Q,%d,%d,NULL)", | |
| 181 | + vid, zPath, isExe, file_islink(0)); | |
| 182 | + } | |
| 177 | 183 | fossil_free(zFullname); |
| 178 | 184 | } |
| 179 | - if( db_changes() ){ | |
| 185 | + if( db_changes() && !doSkip ){ | |
| 180 | 186 | fossil_print("ADDED %s\n", zPath); |
| 181 | 187 | return 1; |
| 182 | 188 | }else{ |
| 183 | 189 | fossil_print("SKIP %s\n", zPath); |
| 184 | 190 | return 0; |
| 185 | 191 |
| --- src/add.c | |
| +++ src/add.c | |
| @@ -156,10 +156,11 @@ | |
| 156 | */ |
| 157 | static int add_one_file( |
| 158 | const char *zPath, /* Tree-name of file to add. */ |
| 159 | int vid /* Add to this VFILE */ |
| 160 | ){ |
| 161 | if( !file_is_simple_pathname(zPath, 1) ){ |
| 162 | fossil_warning("filename contains illegal characters: %s", zPath); |
| 163 | return 0; |
| 164 | } |
| 165 | if( db_exists("SELECT 1 FROM vfile" |
| @@ -168,17 +169,22 @@ | |
| 168 | " WHERE pathname=%Q %s AND deleted", |
| 169 | zPath, filename_collation()); |
| 170 | }else{ |
| 171 | char *zFullname = mprintf("%s%s", g.zLocalRoot, zPath); |
| 172 | int isExe = file_isexe(zFullname, RepoFILE); |
| 173 | db_multi_exec( |
| 174 | "INSERT INTO vfile(vid,deleted,rid,mrid,pathname,isexe,islink,mhash)" |
| 175 | "VALUES(%d,0,0,0,%Q,%d,%d,NULL)", |
| 176 | vid, zPath, isExe, file_islink(0)); |
| 177 | fossil_free(zFullname); |
| 178 | } |
| 179 | if( db_changes() ){ |
| 180 | fossil_print("ADDED %s\n", zPath); |
| 181 | return 1; |
| 182 | }else{ |
| 183 | fossil_print("SKIP %s\n", zPath); |
| 184 | return 0; |
| 185 |
| --- src/add.c | |
| +++ src/add.c | |
| @@ -156,10 +156,11 @@ | |
| 156 | */ |
| 157 | static int add_one_file( |
| 158 | const char *zPath, /* Tree-name of file to add. */ |
| 159 | int vid /* Add to this VFILE */ |
| 160 | ){ |
| 161 | int doSkip = 0; |
| 162 | if( !file_is_simple_pathname(zPath, 1) ){ |
| 163 | fossil_warning("filename contains illegal characters: %s", zPath); |
| 164 | return 0; |
| 165 | } |
| 166 | if( db_exists("SELECT 1 FROM vfile" |
| @@ -168,17 +169,22 @@ | |
| 169 | " WHERE pathname=%Q %s AND deleted", |
| 170 | zPath, filename_collation()); |
| 171 | }else{ |
| 172 | char *zFullname = mprintf("%s%s", g.zLocalRoot, zPath); |
| 173 | int isExe = file_isexe(zFullname, RepoFILE); |
| 174 | if( file_nondir_objects_on_path(g.zLocalRoot, zFullname) ){ |
| 175 | /* Do not add unsafe files to the vfile */ |
| 176 | doSkip = 1; |
| 177 | }else{ |
| 178 | db_multi_exec( |
| 179 | "INSERT INTO vfile(vid,deleted,rid,mrid,pathname,isexe,islink,mhash)" |
| 180 | "VALUES(%d,0,0,0,%Q,%d,%d,NULL)", |
| 181 | vid, zPath, isExe, file_islink(0)); |
| 182 | } |
| 183 | fossil_free(zFullname); |
| 184 | } |
| 185 | if( db_changes() && !doSkip ){ |
| 186 | fossil_print("ADDED %s\n", zPath); |
| 187 | return 1; |
| 188 | }else{ |
| 189 | fossil_print("SKIP %s\n", zPath); |
| 190 | return 0; |
| 191 |
+11
-5
| --- src/add.c | ||
| +++ src/add.c | ||
| @@ -156,10 +156,11 @@ | ||
| 156 | 156 | */ |
| 157 | 157 | static int add_one_file( |
| 158 | 158 | const char *zPath, /* Tree-name of file to add. */ |
| 159 | 159 | int vid /* Add to this VFILE */ |
| 160 | 160 | ){ |
| 161 | + int doSkip = 0; | |
| 161 | 162 | if( !file_is_simple_pathname(zPath, 1) ){ |
| 162 | 163 | fossil_warning("filename contains illegal characters: %s", zPath); |
| 163 | 164 | return 0; |
| 164 | 165 | } |
| 165 | 166 | if( db_exists("SELECT 1 FROM vfile" |
| @@ -168,17 +169,22 @@ | ||
| 168 | 169 | " WHERE pathname=%Q %s AND deleted", |
| 169 | 170 | zPath, filename_collation()); |
| 170 | 171 | }else{ |
| 171 | 172 | char *zFullname = mprintf("%s%s", g.zLocalRoot, zPath); |
| 172 | 173 | int isExe = file_isexe(zFullname, RepoFILE); |
| 173 | - db_multi_exec( | |
| 174 | - "INSERT INTO vfile(vid,deleted,rid,mrid,pathname,isexe,islink,mhash)" | |
| 175 | - "VALUES(%d,0,0,0,%Q,%d,%d,NULL)", | |
| 176 | - vid, zPath, isExe, file_islink(0)); | |
| 174 | + if( file_nondir_objects_on_path(g.zLocalRoot, zFullname) ){ | |
| 175 | + /* Do not add unsafe files to the vfile */ | |
| 176 | + doSkip = 1; | |
| 177 | + }else{ | |
| 178 | + db_multi_exec( | |
| 179 | + "INSERT INTO vfile(vid,deleted,rid,mrid,pathname,isexe,islink,mhash)" | |
| 180 | + "VALUES(%d,0,0,0,%Q,%d,%d,NULL)", | |
| 181 | + vid, zPath, isExe, file_islink(0)); | |
| 182 | + } | |
| 177 | 183 | fossil_free(zFullname); |
| 178 | 184 | } |
| 179 | - if( db_changes() ){ | |
| 185 | + if( db_changes() && !doSkip ){ | |
| 180 | 186 | fossil_print("ADDED %s\n", zPath); |
| 181 | 187 | return 1; |
| 182 | 188 | }else{ |
| 183 | 189 | fossil_print("SKIP %s\n", zPath); |
| 184 | 190 | return 0; |
| 185 | 191 |
| --- src/add.c | |
| +++ src/add.c | |
| @@ -156,10 +156,11 @@ | |
| 156 | */ |
| 157 | static int add_one_file( |
| 158 | const char *zPath, /* Tree-name of file to add. */ |
| 159 | int vid /* Add to this VFILE */ |
| 160 | ){ |
| 161 | if( !file_is_simple_pathname(zPath, 1) ){ |
| 162 | fossil_warning("filename contains illegal characters: %s", zPath); |
| 163 | return 0; |
| 164 | } |
| 165 | if( db_exists("SELECT 1 FROM vfile" |
| @@ -168,17 +169,22 @@ | |
| 168 | " WHERE pathname=%Q %s AND deleted", |
| 169 | zPath, filename_collation()); |
| 170 | }else{ |
| 171 | char *zFullname = mprintf("%s%s", g.zLocalRoot, zPath); |
| 172 | int isExe = file_isexe(zFullname, RepoFILE); |
| 173 | db_multi_exec( |
| 174 | "INSERT INTO vfile(vid,deleted,rid,mrid,pathname,isexe,islink,mhash)" |
| 175 | "VALUES(%d,0,0,0,%Q,%d,%d,NULL)", |
| 176 | vid, zPath, isExe, file_islink(0)); |
| 177 | fossil_free(zFullname); |
| 178 | } |
| 179 | if( db_changes() ){ |
| 180 | fossil_print("ADDED %s\n", zPath); |
| 181 | return 1; |
| 182 | }else{ |
| 183 | fossil_print("SKIP %s\n", zPath); |
| 184 | return 0; |
| 185 |
| --- src/add.c | |
| +++ src/add.c | |
| @@ -156,10 +156,11 @@ | |
| 156 | */ |
| 157 | static int add_one_file( |
| 158 | const char *zPath, /* Tree-name of file to add. */ |
| 159 | int vid /* Add to this VFILE */ |
| 160 | ){ |
| 161 | int doSkip = 0; |
| 162 | if( !file_is_simple_pathname(zPath, 1) ){ |
| 163 | fossil_warning("filename contains illegal characters: %s", zPath); |
| 164 | return 0; |
| 165 | } |
| 166 | if( db_exists("SELECT 1 FROM vfile" |
| @@ -168,17 +169,22 @@ | |
| 169 | " WHERE pathname=%Q %s AND deleted", |
| 170 | zPath, filename_collation()); |
| 171 | }else{ |
| 172 | char *zFullname = mprintf("%s%s", g.zLocalRoot, zPath); |
| 173 | int isExe = file_isexe(zFullname, RepoFILE); |
| 174 | if( file_nondir_objects_on_path(g.zLocalRoot, zFullname) ){ |
| 175 | /* Do not add unsafe files to the vfile */ |
| 176 | doSkip = 1; |
| 177 | }else{ |
| 178 | db_multi_exec( |
| 179 | "INSERT INTO vfile(vid,deleted,rid,mrid,pathname,isexe,islink,mhash)" |
| 180 | "VALUES(%d,0,0,0,%Q,%d,%d,NULL)", |
| 181 | vid, zPath, isExe, file_islink(0)); |
| 182 | } |
| 183 | fossil_free(zFullname); |
| 184 | } |
| 185 | if( db_changes() && !doSkip ){ |
| 186 | fossil_print("ADDED %s\n", zPath); |
| 187 | return 1; |
| 188 | }else{ |
| 189 | fossil_print("SKIP %s\n", zPath); |
| 190 | return 0; |
| 191 |
+25
| --- src/file.c | ||
| +++ src/file.c | ||
| @@ -370,10 +370,35 @@ | ||
| 370 | 370 | i = j; |
| 371 | 371 | } |
| 372 | 372 | fossil_free(z); |
| 373 | 373 | return 0; |
| 374 | 374 | } |
| 375 | + | |
| 376 | +/* | |
| 377 | +** The file named zFile is suppose to be an in-tree file. Check to | |
| 378 | +** ensure that it will be safe to write to this file by verifying that | |
| 379 | +** there are no symlinks or other non-directory objects in between the | |
| 380 | +** root of the checkout and zFile. | |
| 381 | +** | |
| 382 | +** If a problem is found, print a warning message (using fossil_warning()) | |
| 383 | +** and return non-zero. If everything is ok, return zero. | |
| 384 | +*/ | |
| 385 | +int file_unsafe_in_tree_path(const char *zFile){ | |
| 386 | + int n; | |
| 387 | + if( !file_is_absolute_path(zFile) ){ | |
| 388 | + fossil_panic("%s is not an absolute pathname",zFile); | |
| 389 | + } | |
| 390 | + if( fossil_strnicmp(g.zLocalRoot, zFile, (int)strlen(g.zLocalRoot)) ){ | |
| 391 | + fossil_panic("%s is not a prefix of %s", g.zLocalRoot, zFile); | |
| 392 | + } | |
| 393 | + n = file_nondir_objects_on_path(g.zLocalRoot, zFile); | |
| 394 | + if( n ){ | |
| 395 | + fossil_warning("cannot write to %s because non-directory object %.*s" | |
| 396 | + " is in the way", zFile, n, zFile); | |
| 397 | + } | |
| 398 | + return n; | |
| 399 | +} | |
| 375 | 400 | |
| 376 | 401 | /* |
| 377 | 402 | ** Return 1 if zFilename is a directory. Return 0 if zFilename |
| 378 | 403 | ** does not exist. Return 2 if zFilename exists but is something |
| 379 | 404 | ** other than a directory. |
| 380 | 405 |
| --- src/file.c | |
| +++ src/file.c | |
| @@ -370,10 +370,35 @@ | |
| 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. |
| 380 |
| --- src/file.c | |
| +++ src/file.c | |
| @@ -370,10 +370,35 @@ | |
| 370 | i = j; |
| 371 | } |
| 372 | fossil_free(z); |
| 373 | return 0; |
| 374 | } |
| 375 | |
| 376 | /* |
| 377 | ** The file named zFile is suppose to be an in-tree file. Check to |
| 378 | ** ensure that it will be safe to write to this file by verifying that |
| 379 | ** there are no symlinks or other non-directory objects in between the |
| 380 | ** root of the checkout and zFile. |
| 381 | ** |
| 382 | ** If a problem is found, print a warning message (using fossil_warning()) |
| 383 | ** and return non-zero. If everything is ok, return zero. |
| 384 | */ |
| 385 | int file_unsafe_in_tree_path(const char *zFile){ |
| 386 | int n; |
| 387 | if( !file_is_absolute_path(zFile) ){ |
| 388 | fossil_panic("%s is not an absolute pathname",zFile); |
| 389 | } |
| 390 | if( fossil_strnicmp(g.zLocalRoot, zFile, (int)strlen(g.zLocalRoot)) ){ |
| 391 | fossil_panic("%s is not a prefix of %s", g.zLocalRoot, zFile); |
| 392 | } |
| 393 | n = file_nondir_objects_on_path(g.zLocalRoot, zFile); |
| 394 | if( n ){ |
| 395 | fossil_warning("cannot write to %s because non-directory object %.*s" |
| 396 | " is in the way", zFile, n, zFile); |
| 397 | } |
| 398 | return n; |
| 399 | } |
| 400 | |
| 401 | /* |
| 402 | ** Return 1 if zFilename is a directory. Return 0 if zFilename |
| 403 | ** does not exist. Return 2 if zFilename exists but is something |
| 404 | ** other than a directory. |
| 405 |
+25
| --- src/file.c | ||
| +++ src/file.c | ||
| @@ -370,10 +370,35 @@ | ||
| 370 | 370 | i = j; |
| 371 | 371 | } |
| 372 | 372 | fossil_free(z); |
| 373 | 373 | return 0; |
| 374 | 374 | } |
| 375 | + | |
| 376 | +/* | |
| 377 | +** The file named zFile is suppose to be an in-tree file. Check to | |
| 378 | +** ensure that it will be safe to write to this file by verifying that | |
| 379 | +** there are no symlinks or other non-directory objects in between the | |
| 380 | +** root of the checkout and zFile. | |
| 381 | +** | |
| 382 | +** If a problem is found, print a warning message (using fossil_warning()) | |
| 383 | +** and return non-zero. If everything is ok, return zero. | |
| 384 | +*/ | |
| 385 | +int file_unsafe_in_tree_path(const char *zFile){ | |
| 386 | + int n; | |
| 387 | + if( !file_is_absolute_path(zFile) ){ | |
| 388 | + fossil_panic("%s is not an absolute pathname",zFile); | |
| 389 | + } | |
| 390 | + if( fossil_strnicmp(g.zLocalRoot, zFile, (int)strlen(g.zLocalRoot)) ){ | |
| 391 | + fossil_panic("%s is not a prefix of %s", g.zLocalRoot, zFile); | |
| 392 | + } | |
| 393 | + n = file_nondir_objects_on_path(g.zLocalRoot, zFile); | |
| 394 | + if( n ){ | |
| 395 | + fossil_warning("cannot write to %s because non-directory object %.*s" | |
| 396 | + " is in the way", zFile, n, zFile); | |
| 397 | + } | |
| 398 | + return n; | |
| 399 | +} | |
| 375 | 400 | |
| 376 | 401 | /* |
| 377 | 402 | ** Return 1 if zFilename is a directory. Return 0 if zFilename |
| 378 | 403 | ** does not exist. Return 2 if zFilename exists but is something |
| 379 | 404 | ** other than a directory. |
| 380 | 405 |
| --- src/file.c | |
| +++ src/file.c | |
| @@ -370,10 +370,35 @@ | |
| 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. |
| 380 |
| --- src/file.c | |
| +++ src/file.c | |
| @@ -370,10 +370,35 @@ | |
| 370 | i = j; |
| 371 | } |
| 372 | fossil_free(z); |
| 373 | return 0; |
| 374 | } |
| 375 | |
| 376 | /* |
| 377 | ** The file named zFile is suppose to be an in-tree file. Check to |
| 378 | ** ensure that it will be safe to write to this file by verifying that |
| 379 | ** there are no symlinks or other non-directory objects in between the |
| 380 | ** root of the checkout and zFile. |
| 381 | ** |
| 382 | ** If a problem is found, print a warning message (using fossil_warning()) |
| 383 | ** and return non-zero. If everything is ok, return zero. |
| 384 | */ |
| 385 | int file_unsafe_in_tree_path(const char *zFile){ |
| 386 | int n; |
| 387 | if( !file_is_absolute_path(zFile) ){ |
| 388 | fossil_panic("%s is not an absolute pathname",zFile); |
| 389 | } |
| 390 | if( fossil_strnicmp(g.zLocalRoot, zFile, (int)strlen(g.zLocalRoot)) ){ |
| 391 | fossil_panic("%s is not a prefix of %s", g.zLocalRoot, zFile); |
| 392 | } |
| 393 | n = file_nondir_objects_on_path(g.zLocalRoot, zFile); |
| 394 | if( n ){ |
| 395 | fossil_warning("cannot write to %s because non-directory object %.*s" |
| 396 | " is in the way", zFile, n, zFile); |
| 397 | } |
| 398 | return n; |
| 399 | } |
| 400 | |
| 401 | /* |
| 402 | ** Return 1 if zFilename is a directory. Return 0 if zFilename |
| 403 | ** does not exist. Return 2 if zFilename exists but is something |
| 404 | ** other than a directory. |
| 405 |
+25
| --- src/file.c | ||
| +++ src/file.c | ||
| @@ -370,10 +370,35 @@ | ||
| 370 | 370 | i = j; |
| 371 | 371 | } |
| 372 | 372 | fossil_free(z); |
| 373 | 373 | return 0; |
| 374 | 374 | } |
| 375 | + | |
| 376 | +/* | |
| 377 | +** The file named zFile is suppose to be an in-tree file. Check to | |
| 378 | +** ensure that it will be safe to write to this file by verifying that | |
| 379 | +** there are no symlinks or other non-directory objects in between the | |
| 380 | +** root of the checkout and zFile. | |
| 381 | +** | |
| 382 | +** If a problem is found, print a warning message (using fossil_warning()) | |
| 383 | +** and return non-zero. If everything is ok, return zero. | |
| 384 | +*/ | |
| 385 | +int file_unsafe_in_tree_path(const char *zFile){ | |
| 386 | + int n; | |
| 387 | + if( !file_is_absolute_path(zFile) ){ | |
| 388 | + fossil_panic("%s is not an absolute pathname",zFile); | |
| 389 | + } | |
| 390 | + if( fossil_strnicmp(g.zLocalRoot, zFile, (int)strlen(g.zLocalRoot)) ){ | |
| 391 | + fossil_panic("%s is not a prefix of %s", g.zLocalRoot, zFile); | |
| 392 | + } | |
| 393 | + n = file_nondir_objects_on_path(g.zLocalRoot, zFile); | |
| 394 | + if( n ){ | |
| 395 | + fossil_warning("cannot write to %s because non-directory object %.*s" | |
| 396 | + " is in the way", zFile, n, zFile); | |
| 397 | + } | |
| 398 | + return n; | |
| 399 | +} | |
| 375 | 400 | |
| 376 | 401 | /* |
| 377 | 402 | ** Return 1 if zFilename is a directory. Return 0 if zFilename |
| 378 | 403 | ** does not exist. Return 2 if zFilename exists but is something |
| 379 | 404 | ** other than a directory. |
| 380 | 405 |
| --- src/file.c | |
| +++ src/file.c | |
| @@ -370,10 +370,35 @@ | |
| 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. |
| 380 |
| --- src/file.c | |
| +++ src/file.c | |
| @@ -370,10 +370,35 @@ | |
| 370 | i = j; |
| 371 | } |
| 372 | fossil_free(z); |
| 373 | return 0; |
| 374 | } |
| 375 | |
| 376 | /* |
| 377 | ** The file named zFile is suppose to be an in-tree file. Check to |
| 378 | ** ensure that it will be safe to write to this file by verifying that |
| 379 | ** there are no symlinks or other non-directory objects in between the |
| 380 | ** root of the checkout and zFile. |
| 381 | ** |
| 382 | ** If a problem is found, print a warning message (using fossil_warning()) |
| 383 | ** and return non-zero. If everything is ok, return zero. |
| 384 | */ |
| 385 | int file_unsafe_in_tree_path(const char *zFile){ |
| 386 | int n; |
| 387 | if( !file_is_absolute_path(zFile) ){ |
| 388 | fossil_panic("%s is not an absolute pathname",zFile); |
| 389 | } |
| 390 | if( fossil_strnicmp(g.zLocalRoot, zFile, (int)strlen(g.zLocalRoot)) ){ |
| 391 | fossil_panic("%s is not a prefix of %s", g.zLocalRoot, zFile); |
| 392 | } |
| 393 | n = file_nondir_objects_on_path(g.zLocalRoot, zFile); |
| 394 | if( n ){ |
| 395 | fossil_warning("cannot write to %s because non-directory object %.*s" |
| 396 | " is in the way", zFile, n, zFile); |
| 397 | } |
| 398 | return n; |
| 399 | } |
| 400 | |
| 401 | /* |
| 402 | ** Return 1 if zFilename is a directory. Return 0 if zFilename |
| 403 | ** does not exist. Return 2 if zFilename exists but is something |
| 404 | ** other than a directory. |
| 405 |
+25
| --- src/file.c | ||
| +++ src/file.c | ||
| @@ -370,10 +370,35 @@ | ||
| 370 | 370 | i = j; |
| 371 | 371 | } |
| 372 | 372 | fossil_free(z); |
| 373 | 373 | return 0; |
| 374 | 374 | } |
| 375 | + | |
| 376 | +/* | |
| 377 | +** The file named zFile is suppose to be an in-tree file. Check to | |
| 378 | +** ensure that it will be safe to write to this file by verifying that | |
| 379 | +** there are no symlinks or other non-directory objects in between the | |
| 380 | +** root of the checkout and zFile. | |
| 381 | +** | |
| 382 | +** If a problem is found, print a warning message (using fossil_warning()) | |
| 383 | +** and return non-zero. If everything is ok, return zero. | |
| 384 | +*/ | |
| 385 | +int file_unsafe_in_tree_path(const char *zFile){ | |
| 386 | + int n; | |
| 387 | + if( !file_is_absolute_path(zFile) ){ | |
| 388 | + fossil_panic("%s is not an absolute pathname",zFile); | |
| 389 | + } | |
| 390 | + if( fossil_strnicmp(g.zLocalRoot, zFile, (int)strlen(g.zLocalRoot)) ){ | |
| 391 | + fossil_panic("%s is not a prefix of %s", g.zLocalRoot, zFile); | |
| 392 | + } | |
| 393 | + n = file_nondir_objects_on_path(g.zLocalRoot, zFile); | |
| 394 | + if( n ){ | |
| 395 | + fossil_warning("cannot write to %s because non-directory object %.*s" | |
| 396 | + " is in the way", zFile, n, zFile); | |
| 397 | + } | |
| 398 | + return n; | |
| 399 | +} | |
| 375 | 400 | |
| 376 | 401 | /* |
| 377 | 402 | ** Return 1 if zFilename is a directory. Return 0 if zFilename |
| 378 | 403 | ** does not exist. Return 2 if zFilename exists but is something |
| 379 | 404 | ** other than a directory. |
| 380 | 405 |
| --- src/file.c | |
| +++ src/file.c | |
| @@ -370,10 +370,35 @@ | |
| 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. |
| 380 |
| --- src/file.c | |
| +++ src/file.c | |
| @@ -370,10 +370,35 @@ | |
| 370 | i = j; |
| 371 | } |
| 372 | fossil_free(z); |
| 373 | return 0; |
| 374 | } |
| 375 | |
| 376 | /* |
| 377 | ** The file named zFile is suppose to be an in-tree file. Check to |
| 378 | ** ensure that it will be safe to write to this file by verifying that |
| 379 | ** there are no symlinks or other non-directory objects in between the |
| 380 | ** root of the checkout and zFile. |
| 381 | ** |
| 382 | ** If a problem is found, print a warning message (using fossil_warning()) |
| 383 | ** and return non-zero. If everything is ok, return zero. |
| 384 | */ |
| 385 | int file_unsafe_in_tree_path(const char *zFile){ |
| 386 | int n; |
| 387 | if( !file_is_absolute_path(zFile) ){ |
| 388 | fossil_panic("%s is not an absolute pathname",zFile); |
| 389 | } |
| 390 | if( fossil_strnicmp(g.zLocalRoot, zFile, (int)strlen(g.zLocalRoot)) ){ |
| 391 | fossil_panic("%s is not a prefix of %s", g.zLocalRoot, zFile); |
| 392 | } |
| 393 | n = file_nondir_objects_on_path(g.zLocalRoot, zFile); |
| 394 | if( n ){ |
| 395 | fossil_warning("cannot write to %s because non-directory object %.*s" |
| 396 | " is in the way", zFile, n, zFile); |
| 397 | } |
| 398 | return n; |
| 399 | } |
| 400 | |
| 401 | /* |
| 402 | ** Return 1 if zFilename is a directory. Return 0 if zFilename |
| 403 | ** does not exist. Return 2 if zFilename exists but is something |
| 404 | ** other than a directory. |
| 405 |
+2
| --- src/stash.c | ||
| +++ src/stash.c | ||
| @@ -334,10 +334,12 @@ | ||
| 334 | 334 | blob_write_to_file(&delta, zNPath); |
| 335 | 335 | file_setexe(zNPath, isExec); |
| 336 | 336 | }else if( isRemoved ){ |
| 337 | 337 | fossil_print("DELETE %s\n", zOrig); |
| 338 | 338 | file_delete(zOPath); |
| 339 | + }else if( file_unsafe_in_tree_path(zNPath) ){ | |
| 340 | + /* Ignore the unsafe path */ | |
| 339 | 341 | }else{ |
| 340 | 342 | Blob a, b, out, disk; |
| 341 | 343 | int isNewLink = file_islink(zOPath); |
| 342 | 344 | db_ephemeral_blob(&q, 6, &delta); |
| 343 | 345 | blob_read_from_file(&disk, zOPath, RepoFILE); |
| 344 | 346 |
| --- src/stash.c | |
| +++ src/stash.c | |
| @@ -334,10 +334,12 @@ | |
| 334 | blob_write_to_file(&delta, zNPath); |
| 335 | file_setexe(zNPath, isExec); |
| 336 | }else if( isRemoved ){ |
| 337 | fossil_print("DELETE %s\n", zOrig); |
| 338 | file_delete(zOPath); |
| 339 | }else{ |
| 340 | Blob a, b, out, disk; |
| 341 | int isNewLink = file_islink(zOPath); |
| 342 | db_ephemeral_blob(&q, 6, &delta); |
| 343 | blob_read_from_file(&disk, zOPath, RepoFILE); |
| 344 |
| --- src/stash.c | |
| +++ src/stash.c | |
| @@ -334,10 +334,12 @@ | |
| 334 | blob_write_to_file(&delta, zNPath); |
| 335 | file_setexe(zNPath, isExec); |
| 336 | }else if( isRemoved ){ |
| 337 | fossil_print("DELETE %s\n", zOrig); |
| 338 | file_delete(zOPath); |
| 339 | }else if( file_unsafe_in_tree_path(zNPath) ){ |
| 340 | /* Ignore the unsafe path */ |
| 341 | }else{ |
| 342 | Blob a, b, out, disk; |
| 343 | int isNewLink = file_islink(zOPath); |
| 344 | db_ephemeral_blob(&q, 6, &delta); |
| 345 | blob_read_from_file(&disk, zOPath, RepoFILE); |
| 346 |
+4
-2
| --- src/undo.c | ||
| +++ src/undo.c | ||
| @@ -52,11 +52,11 @@ | ||
| 52 | 52 | int new_exe; |
| 53 | 53 | int new_link; |
| 54 | 54 | int old_link; |
| 55 | 55 | Blob current; |
| 56 | 56 | Blob new; |
| 57 | - zFullname = mprintf("%s/%s", g.zLocalRoot, zPathname); | |
| 57 | + zFullname = mprintf("%s%s", g.zLocalRoot, zPathname); | |
| 58 | 58 | old_link = db_column_int(&q, 3); |
| 59 | 59 | new_exists = file_size(zFullname, RepoFILE)>=0; |
| 60 | 60 | new_link = file_islink(0); |
| 61 | 61 | if( new_exists ){ |
| 62 | 62 | blob_read_from_file(¤t, zFullname, RepoFILE); |
| @@ -69,11 +69,13 @@ | ||
| 69 | 69 | old_exists = db_column_int(&q, 1); |
| 70 | 70 | old_exe = db_column_int(&q, 2); |
| 71 | 71 | if( old_exists ){ |
| 72 | 72 | db_ephemeral_blob(&q, 0, &new); |
| 73 | 73 | } |
| 74 | - if( old_exists ){ | |
| 74 | + if( file_unsafe_in_tree_path(zFullname) ){ | |
| 75 | + /* do nothign with this unsafe file */ | |
| 76 | + }else if( old_exists ){ | |
| 75 | 77 | if( new_exists ){ |
| 76 | 78 | fossil_print("%s %s\n", redoFlag ? "REDO" : "UNDO", zPathname); |
| 77 | 79 | }else{ |
| 78 | 80 | fossil_print("NEW %s\n", zPathname); |
| 79 | 81 | } |
| 80 | 82 |
| --- src/undo.c | |
| +++ src/undo.c | |
| @@ -52,11 +52,11 @@ | |
| 52 | int new_exe; |
| 53 | int new_link; |
| 54 | int old_link; |
| 55 | Blob current; |
| 56 | Blob new; |
| 57 | zFullname = mprintf("%s/%s", g.zLocalRoot, zPathname); |
| 58 | old_link = db_column_int(&q, 3); |
| 59 | new_exists = file_size(zFullname, RepoFILE)>=0; |
| 60 | new_link = file_islink(0); |
| 61 | if( new_exists ){ |
| 62 | blob_read_from_file(¤t, zFullname, RepoFILE); |
| @@ -69,11 +69,13 @@ | |
| 69 | old_exists = db_column_int(&q, 1); |
| 70 | old_exe = db_column_int(&q, 2); |
| 71 | if( old_exists ){ |
| 72 | db_ephemeral_blob(&q, 0, &new); |
| 73 | } |
| 74 | if( old_exists ){ |
| 75 | if( new_exists ){ |
| 76 | fossil_print("%s %s\n", redoFlag ? "REDO" : "UNDO", zPathname); |
| 77 | }else{ |
| 78 | fossil_print("NEW %s\n", zPathname); |
| 79 | } |
| 80 |
| --- src/undo.c | |
| +++ src/undo.c | |
| @@ -52,11 +52,11 @@ | |
| 52 | int new_exe; |
| 53 | int new_link; |
| 54 | int old_link; |
| 55 | Blob current; |
| 56 | Blob new; |
| 57 | zFullname = mprintf("%s%s", g.zLocalRoot, zPathname); |
| 58 | old_link = db_column_int(&q, 3); |
| 59 | new_exists = file_size(zFullname, RepoFILE)>=0; |
| 60 | new_link = file_islink(0); |
| 61 | if( new_exists ){ |
| 62 | blob_read_from_file(¤t, zFullname, RepoFILE); |
| @@ -69,11 +69,13 @@ | |
| 69 | old_exists = db_column_int(&q, 1); |
| 70 | old_exe = db_column_int(&q, 2); |
| 71 | if( old_exists ){ |
| 72 | db_ephemeral_blob(&q, 0, &new); |
| 73 | } |
| 74 | if( file_unsafe_in_tree_path(zFullname) ){ |
| 75 | /* do nothign with this unsafe file */ |
| 76 | }else if( old_exists ){ |
| 77 | if( new_exists ){ |
| 78 | fossil_print("%s %s\n", redoFlag ? "REDO" : "UNDO", zPathname); |
| 79 | }else{ |
| 80 | fossil_print("NEW %s\n", zPathname); |
| 81 | } |
| 82 |
+2
| --- src/update.c | ||
| +++ src/update.c | ||
| @@ -927,10 +927,12 @@ | ||
| 927 | 927 | " SET pathname=origname, origname=NULL" |
| 928 | 928 | " WHERE pathname=%Q AND origname!=pathname;" |
| 929 | 929 | "DELETE FROM vfile WHERE pathname=%Q", |
| 930 | 930 | zFile, zFile |
| 931 | 931 | ); |
| 932 | + }else if( file_unsafe_in_tree_path(zFull) ){ | |
| 933 | + /* Ignore this file */ | |
| 932 | 934 | }else{ |
| 933 | 935 | sqlite3_int64 mtime; |
| 934 | 936 | int rvChnged = 0; |
| 935 | 937 | int rvPerm = manifest_file_mperm(pRvFile); |
| 936 | 938 | |
| 937 | 939 |
| --- src/update.c | |
| +++ src/update.c | |
| @@ -927,10 +927,12 @@ | |
| 927 | " SET pathname=origname, origname=NULL" |
| 928 | " WHERE pathname=%Q AND origname!=pathname;" |
| 929 | "DELETE FROM vfile WHERE pathname=%Q", |
| 930 | zFile, zFile |
| 931 | ); |
| 932 | }else{ |
| 933 | sqlite3_int64 mtime; |
| 934 | int rvChnged = 0; |
| 935 | int rvPerm = manifest_file_mperm(pRvFile); |
| 936 | |
| 937 |
| --- src/update.c | |
| +++ src/update.c | |
| @@ -927,10 +927,12 @@ | |
| 927 | " SET pathname=origname, origname=NULL" |
| 928 | " WHERE pathname=%Q AND origname!=pathname;" |
| 929 | "DELETE FROM vfile WHERE pathname=%Q", |
| 930 | zFile, zFile |
| 931 | ); |
| 932 | }else if( file_unsafe_in_tree_path(zFull) ){ |
| 933 | /* Ignore this file */ |
| 934 | }else{ |
| 935 | sqlite3_int64 mtime; |
| 936 | int rvChnged = 0; |
| 937 | int rvPerm = manifest_file_mperm(pRvFile); |
| 938 | |
| 939 |
+2
| --- src/update.c | ||
| +++ src/update.c | ||
| @@ -927,10 +927,12 @@ | ||
| 927 | 927 | " SET pathname=origname, origname=NULL" |
| 928 | 928 | " WHERE pathname=%Q AND origname!=pathname;" |
| 929 | 929 | "DELETE FROM vfile WHERE pathname=%Q", |
| 930 | 930 | zFile, zFile |
| 931 | 931 | ); |
| 932 | + }else if( file_unsafe_in_tree_path(zFull) ){ | |
| 933 | + /* Ignore this file */ | |
| 932 | 934 | }else{ |
| 933 | 935 | sqlite3_int64 mtime; |
| 934 | 936 | int rvChnged = 0; |
| 935 | 937 | int rvPerm = manifest_file_mperm(pRvFile); |
| 936 | 938 | |
| 937 | 939 |
| --- src/update.c | |
| +++ src/update.c | |
| @@ -927,10 +927,12 @@ | |
| 927 | " SET pathname=origname, origname=NULL" |
| 928 | " WHERE pathname=%Q AND origname!=pathname;" |
| 929 | "DELETE FROM vfile WHERE pathname=%Q", |
| 930 | zFile, zFile |
| 931 | ); |
| 932 | }else{ |
| 933 | sqlite3_int64 mtime; |
| 934 | int rvChnged = 0; |
| 935 | int rvPerm = manifest_file_mperm(pRvFile); |
| 936 | |
| 937 |
| --- src/update.c | |
| +++ src/update.c | |
| @@ -927,10 +927,12 @@ | |
| 927 | " SET pathname=origname, origname=NULL" |
| 928 | " WHERE pathname=%Q AND origname!=pathname;" |
| 929 | "DELETE FROM vfile WHERE pathname=%Q", |
| 930 | zFile, zFile |
| 931 | ); |
| 932 | }else if( file_unsafe_in_tree_path(zFull) ){ |
| 933 | /* Ignore this file */ |
| 934 | }else{ |
| 935 | sqlite3_int64 mtime; |
| 936 | int rvChnged = 0; |
| 937 | int rvPerm = manifest_file_mperm(pRvFile); |
| 938 | |
| 939 |
+2
| --- src/update.c | ||
| +++ src/update.c | ||
| @@ -927,10 +927,12 @@ | ||
| 927 | 927 | " SET pathname=origname, origname=NULL" |
| 928 | 928 | " WHERE pathname=%Q AND origname!=pathname;" |
| 929 | 929 | "DELETE FROM vfile WHERE pathname=%Q", |
| 930 | 930 | zFile, zFile |
| 931 | 931 | ); |
| 932 | + }else if( file_unsafe_in_tree_path(zFull) ){ | |
| 933 | + /* Ignore this file */ | |
| 932 | 934 | }else{ |
| 933 | 935 | sqlite3_int64 mtime; |
| 934 | 936 | int rvChnged = 0; |
| 935 | 937 | int rvPerm = manifest_file_mperm(pRvFile); |
| 936 | 938 | |
| 937 | 939 |
| --- src/update.c | |
| +++ src/update.c | |
| @@ -927,10 +927,12 @@ | |
| 927 | " SET pathname=origname, origname=NULL" |
| 928 | " WHERE pathname=%Q AND origname!=pathname;" |
| 929 | "DELETE FROM vfile WHERE pathname=%Q", |
| 930 | zFile, zFile |
| 931 | ); |
| 932 | }else{ |
| 933 | sqlite3_int64 mtime; |
| 934 | int rvChnged = 0; |
| 935 | int rvPerm = manifest_file_mperm(pRvFile); |
| 936 | |
| 937 |
| --- src/update.c | |
| +++ src/update.c | |
| @@ -927,10 +927,12 @@ | |
| 927 | " SET pathname=origname, origname=NULL" |
| 928 | " WHERE pathname=%Q AND origname!=pathname;" |
| 929 | "DELETE FROM vfile WHERE pathname=%Q", |
| 930 | zFile, zFile |
| 931 | ); |
| 932 | }else if( file_unsafe_in_tree_path(zFull) ){ |
| 933 | /* Ignore this file */ |
| 934 | }else{ |
| 935 | sqlite3_int64 mtime; |
| 936 | int rvChnged = 0; |
| 937 | int rvPerm = manifest_file_mperm(pRvFile); |
| 938 | |
| 939 |
+3
-3
| --- src/url.c | ||
| +++ src/url.c | ||
| @@ -50,11 +50,11 @@ | ||
| 50 | 50 | int isHttps; /* True if a "https:" url */ |
| 51 | 51 | int isSsh; /* True if an "ssh:" url */ |
| 52 | 52 | int isAlias; /* Input URL was an alias */ |
| 53 | 53 | char *name; /* Hostname for http: or filename for file: */ |
| 54 | 54 | char *hostname; /* The HOST: parameter on http headers */ |
| 55 | - const char *protocol; /* "http" or "https" or "ssh" or "file" */ | |
| 55 | + const char *protocol; /* "http" or "https" or "ssh" */ | |
| 56 | 56 | int port; /* TCP port number for http: or https: */ |
| 57 | 57 | int dfltPort; /* The default port for the given protocol */ |
| 58 | 58 | char *path; /* Pathname for http: */ |
| 59 | 59 | char *user; /* User id for http: */ |
| 60 | 60 | char *passwd; /* Password for http: */ |
| @@ -76,11 +76,11 @@ | ||
| 76 | 76 | ** as follows: |
| 77 | 77 | ** |
| 78 | 78 | ** isFile True if FILE: |
| 79 | 79 | ** isHttps True if HTTPS: |
| 80 | 80 | ** isSsh True if SSH: |
| 81 | -** protocol "http" or "https" or "file" or "ssh" | |
| 81 | +** protocol "http" or "https" or "file" | |
| 82 | 82 | ** name Hostname for HTTP:, HTTPS:, SSH:. Filename for FILE: |
| 83 | 83 | ** port TCP port number for HTTP or HTTPS. |
| 84 | 84 | ** dfltPort Default TCP port number (80 or 443). |
| 85 | 85 | ** path Path name for HTTP or HTTPS. |
| 86 | 86 | ** user Userid. |
| @@ -305,11 +305,11 @@ | ||
| 305 | 305 | ** form last-sync-pw. |
| 306 | 306 | ** |
| 307 | 307 | ** g.url.isFile True if FILE: |
| 308 | 308 | ** g.url.isHttps True if HTTPS: |
| 309 | 309 | ** g.url.isSsh True if SSH: |
| 310 | -** g.url.protocol "http" or "https" or "file" or "ssh" | |
| 310 | +** g.url.protocol "http" or "https" or "file" | |
| 311 | 311 | ** g.url.name Hostname for HTTP:, HTTPS:, SSH:. Filename for FILE: |
| 312 | 312 | ** g.url.port TCP port number for HTTP or HTTPS. |
| 313 | 313 | ** g.url.dfltPort Default TCP port number (80 or 443). |
| 314 | 314 | ** g.url.path Path name for HTTP or HTTPS. |
| 315 | 315 | ** g.url.user Userid. |
| 316 | 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/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 |
+3
-3
| --- src/url.c | ||
| +++ src/url.c | ||
| @@ -50,11 +50,11 @@ | ||
| 50 | 50 | int isHttps; /* True if a "https:" url */ |
| 51 | 51 | int isSsh; /* True if an "ssh:" url */ |
| 52 | 52 | int isAlias; /* Input URL was an alias */ |
| 53 | 53 | char *name; /* Hostname for http: or filename for file: */ |
| 54 | 54 | char *hostname; /* The HOST: parameter on http headers */ |
| 55 | - const char *protocol; /* "http" or "https" or "ssh" or "file" */ | |
| 55 | + const char *protocol; /* "http" or "https" or "ssh" */ | |
| 56 | 56 | int port; /* TCP port number for http: or https: */ |
| 57 | 57 | int dfltPort; /* The default port for the given protocol */ |
| 58 | 58 | char *path; /* Pathname for http: */ |
| 59 | 59 | char *user; /* User id for http: */ |
| 60 | 60 | char *passwd; /* Password for http: */ |
| @@ -76,11 +76,11 @@ | ||
| 76 | 76 | ** as follows: |
| 77 | 77 | ** |
| 78 | 78 | ** isFile True if FILE: |
| 79 | 79 | ** isHttps True if HTTPS: |
| 80 | 80 | ** isSsh True if SSH: |
| 81 | -** protocol "http" or "https" or "file" or "ssh" | |
| 81 | +** protocol "http" or "https" or "file" | |
| 82 | 82 | ** name Hostname for HTTP:, HTTPS:, SSH:. Filename for FILE: |
| 83 | 83 | ** port TCP port number for HTTP or HTTPS. |
| 84 | 84 | ** dfltPort Default TCP port number (80 or 443). |
| 85 | 85 | ** path Path name for HTTP or HTTPS. |
| 86 | 86 | ** user Userid. |
| @@ -305,11 +305,11 @@ | ||
| 305 | 305 | ** form last-sync-pw. |
| 306 | 306 | ** |
| 307 | 307 | ** g.url.isFile True if FILE: |
| 308 | 308 | ** g.url.isHttps True if HTTPS: |
| 309 | 309 | ** g.url.isSsh True if SSH: |
| 310 | -** g.url.protocol "http" or "https" or "file" or "ssh" | |
| 310 | +** g.url.protocol "http" or "https" or "file" | |
| 311 | 311 | ** g.url.name Hostname for HTTP:, HTTPS:, SSH:. Filename for FILE: |
| 312 | 312 | ** g.url.port TCP port number for HTTP or HTTPS. |
| 313 | 313 | ** g.url.dfltPort Default TCP port number (80 or 443). |
| 314 | 314 | ** g.url.path Path name for HTTP or HTTPS. |
| 315 | 315 | ** g.url.user Userid. |
| 316 | 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/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 |
+3
-3
| --- src/url.c | ||
| +++ src/url.c | ||
| @@ -50,11 +50,11 @@ | ||
| 50 | 50 | int isHttps; /* True if a "https:" url */ |
| 51 | 51 | int isSsh; /* True if an "ssh:" url */ |
| 52 | 52 | int isAlias; /* Input URL was an alias */ |
| 53 | 53 | char *name; /* Hostname for http: or filename for file: */ |
| 54 | 54 | char *hostname; /* The HOST: parameter on http headers */ |
| 55 | - const char *protocol; /* "http" or "https" or "ssh" or "file" */ | |
| 55 | + const char *protocol; /* "http" or "https" or "ssh" */ | |
| 56 | 56 | int port; /* TCP port number for http: or https: */ |
| 57 | 57 | int dfltPort; /* The default port for the given protocol */ |
| 58 | 58 | char *path; /* Pathname for http: */ |
| 59 | 59 | char *user; /* User id for http: */ |
| 60 | 60 | char *passwd; /* Password for http: */ |
| @@ -76,11 +76,11 @@ | ||
| 76 | 76 | ** as follows: |
| 77 | 77 | ** |
| 78 | 78 | ** isFile True if FILE: |
| 79 | 79 | ** isHttps True if HTTPS: |
| 80 | 80 | ** isSsh True if SSH: |
| 81 | -** protocol "http" or "https" or "file" or "ssh" | |
| 81 | +** protocol "http" or "https" or "file" | |
| 82 | 82 | ** name Hostname for HTTP:, HTTPS:, SSH:. Filename for FILE: |
| 83 | 83 | ** port TCP port number for HTTP or HTTPS. |
| 84 | 84 | ** dfltPort Default TCP port number (80 or 443). |
| 85 | 85 | ** path Path name for HTTP or HTTPS. |
| 86 | 86 | ** user Userid. |
| @@ -305,11 +305,11 @@ | ||
| 305 | 305 | ** form last-sync-pw. |
| 306 | 306 | ** |
| 307 | 307 | ** g.url.isFile True if FILE: |
| 308 | 308 | ** g.url.isHttps True if HTTPS: |
| 309 | 309 | ** g.url.isSsh True if SSH: |
| 310 | -** g.url.protocol "http" or "https" or "file" or "ssh" | |
| 310 | +** g.url.protocol "http" or "https" or "file" | |
| 311 | 311 | ** g.url.name Hostname for HTTP:, HTTPS:, SSH:. Filename for FILE: |
| 312 | 312 | ** g.url.port TCP port number for HTTP or HTTPS. |
| 313 | 313 | ** g.url.dfltPort Default TCP port number (80 or 443). |
| 314 | 314 | ** g.url.path Path name for HTTP or HTTPS. |
| 315 | 315 | ** g.url.user Userid. |
| 316 | 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/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 |
+3
-3
| --- src/url.c | ||
| +++ src/url.c | ||
| @@ -50,11 +50,11 @@ | ||
| 50 | 50 | int isHttps; /* True if a "https:" url */ |
| 51 | 51 | int isSsh; /* True if an "ssh:" url */ |
| 52 | 52 | int isAlias; /* Input URL was an alias */ |
| 53 | 53 | char *name; /* Hostname for http: or filename for file: */ |
| 54 | 54 | char *hostname; /* The HOST: parameter on http headers */ |
| 55 | - const char *protocol; /* "http" or "https" or "ssh" or "file" */ | |
| 55 | + const char *protocol; /* "http" or "https" or "ssh" */ | |
| 56 | 56 | int port; /* TCP port number for http: or https: */ |
| 57 | 57 | int dfltPort; /* The default port for the given protocol */ |
| 58 | 58 | char *path; /* Pathname for http: */ |
| 59 | 59 | char *user; /* User id for http: */ |
| 60 | 60 | char *passwd; /* Password for http: */ |
| @@ -76,11 +76,11 @@ | ||
| 76 | 76 | ** as follows: |
| 77 | 77 | ** |
| 78 | 78 | ** isFile True if FILE: |
| 79 | 79 | ** isHttps True if HTTPS: |
| 80 | 80 | ** isSsh True if SSH: |
| 81 | -** protocol "http" or "https" or "file" or "ssh" | |
| 81 | +** protocol "http" or "https" or "file" | |
| 82 | 82 | ** name Hostname for HTTP:, HTTPS:, SSH:. Filename for FILE: |
| 83 | 83 | ** port TCP port number for HTTP or HTTPS. |
| 84 | 84 | ** dfltPort Default TCP port number (80 or 443). |
| 85 | 85 | ** path Path name for HTTP or HTTPS. |
| 86 | 86 | ** user Userid. |
| @@ -305,11 +305,11 @@ | ||
| 305 | 305 | ** form last-sync-pw. |
| 306 | 306 | ** |
| 307 | 307 | ** g.url.isFile True if FILE: |
| 308 | 308 | ** g.url.isHttps True if HTTPS: |
| 309 | 309 | ** g.url.isSsh True if SSH: |
| 310 | -** g.url.protocol "http" or "https" or "file" or "ssh" | |
| 310 | +** g.url.protocol "http" or "https" or "file" | |
| 311 | 311 | ** g.url.name Hostname for HTTP:, HTTPS:, SSH:. Filename for FILE: |
| 312 | 312 | ** g.url.port TCP port number for HTTP or HTTPS. |
| 313 | 313 | ** g.url.dfltPort Default TCP port number (80 or 443). |
| 314 | 314 | ** g.url.path Path name for HTTP or HTTPS. |
| 315 | 315 | ** g.url.user Userid. |
| 316 | 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/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 |
+3
-7
| --- src/vfile.c | ||
| +++ src/vfile.c | ||
| @@ -307,17 +307,19 @@ | ||
| 307 | 307 | g.zLocalRoot, id); |
| 308 | 308 | } |
| 309 | 309 | while( db_step(&q)==SQLITE_ROW ){ |
| 310 | 310 | int id, rid, isExe, isLink; |
| 311 | 311 | const char *zName; |
| 312 | - int n; | |
| 313 | 312 | |
| 314 | 313 | id = db_column_int(&q, 0); |
| 315 | 314 | zName = db_column_text(&q, 1); |
| 316 | 315 | rid = db_column_int(&q, 2); |
| 317 | 316 | isExe = db_column_int(&q, 3); |
| 318 | 317 | isLink = db_column_int(&q, 4); |
| 318 | + if( file_unsafe_in_tree_path(zName) ){ | |
| 319 | + continue; | |
| 320 | + } | |
| 319 | 321 | content_get(rid, &content); |
| 320 | 322 | if( file_is_the_same(&content, zName) ){ |
| 321 | 323 | blob_reset(&content); |
| 322 | 324 | if( file_setexe(zName, isExe) ){ |
| 323 | 325 | db_multi_exec("UPDATE vfile SET mtime=%lld WHERE id=%d", |
| @@ -340,16 +342,10 @@ | ||
| 340 | 342 | blob_reset(&content); |
| 341 | 343 | continue; |
| 342 | 344 | } |
| 343 | 345 | } |
| 344 | 346 | 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 | 347 | if( file_isdir(zName, RepoFILE)==1 ){ |
| 352 | 348 | /*TODO(dchest): remove directories? */ |
| 353 | 349 | fossil_fatal("%s is directory, cannot overwrite", zName); |
| 354 | 350 | } |
| 355 | 351 | if( file_size(zName, RepoFILE)>=0 && (isLink || file_islink(0)) ){ |
| 356 | 352 |
| --- src/vfile.c | |
| +++ src/vfile.c | |
| @@ -307,17 +307,19 @@ | |
| 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); |
| 318 | isLink = db_column_int(&q, 4); |
| 319 | content_get(rid, &content); |
| 320 | if( file_is_the_same(&content, zName) ){ |
| 321 | blob_reset(&content); |
| 322 | if( file_setexe(zName, isExe) ){ |
| 323 | db_multi_exec("UPDATE vfile SET mtime=%lld WHERE id=%d", |
| @@ -340,16 +342,10 @@ | |
| 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,17 +307,19 @@ | |
| 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); |
| 317 | isLink = db_column_int(&q, 4); |
| 318 | if( file_unsafe_in_tree_path(zName) ){ |
| 319 | continue; |
| 320 | } |
| 321 | content_get(rid, &content); |
| 322 | if( file_is_the_same(&content, zName) ){ |
| 323 | blob_reset(&content); |
| 324 | if( file_setexe(zName, isExe) ){ |
| 325 | db_multi_exec("UPDATE vfile SET mtime=%lld WHERE id=%d", |
| @@ -340,16 +342,10 @@ | |
| 342 | blob_reset(&content); |
| 343 | continue; |
| 344 | } |
| 345 | } |
| 346 | if( verbose ) fossil_print("%s\n", &zName[nRepos]); |
| 347 | if( file_isdir(zName, RepoFILE)==1 ){ |
| 348 | /*TODO(dchest): remove directories? */ |
| 349 | fossil_fatal("%s is directory, cannot overwrite", zName); |
| 350 | } |
| 351 | if( file_size(zName, RepoFILE)>=0 && (isLink || file_islink(0)) ){ |
| 352 |
+3
-7
| --- src/vfile.c | ||
| +++ src/vfile.c | ||
| @@ -307,17 +307,19 @@ | ||
| 307 | 307 | g.zLocalRoot, id); |
| 308 | 308 | } |
| 309 | 309 | while( db_step(&q)==SQLITE_ROW ){ |
| 310 | 310 | int id, rid, isExe, isLink; |
| 311 | 311 | const char *zName; |
| 312 | - int n; | |
| 313 | 312 | |
| 314 | 313 | id = db_column_int(&q, 0); |
| 315 | 314 | zName = db_column_text(&q, 1); |
| 316 | 315 | rid = db_column_int(&q, 2); |
| 317 | 316 | isExe = db_column_int(&q, 3); |
| 318 | 317 | isLink = db_column_int(&q, 4); |
| 318 | + if( file_unsafe_in_tree_path(zName) ){ | |
| 319 | + continue; | |
| 320 | + } | |
| 319 | 321 | content_get(rid, &content); |
| 320 | 322 | if( file_is_the_same(&content, zName) ){ |
| 321 | 323 | blob_reset(&content); |
| 322 | 324 | if( file_setexe(zName, isExe) ){ |
| 323 | 325 | db_multi_exec("UPDATE vfile SET mtime=%lld WHERE id=%d", |
| @@ -340,16 +342,10 @@ | ||
| 340 | 342 | blob_reset(&content); |
| 341 | 343 | continue; |
| 342 | 344 | } |
| 343 | 345 | } |
| 344 | 346 | 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 | 347 | if( file_isdir(zName, RepoFILE)==1 ){ |
| 352 | 348 | /*TODO(dchest): remove directories? */ |
| 353 | 349 | fossil_fatal("%s is directory, cannot overwrite", zName); |
| 354 | 350 | } |
| 355 | 351 | if( file_size(zName, RepoFILE)>=0 && (isLink || file_islink(0)) ){ |
| 356 | 352 |
| --- src/vfile.c | |
| +++ src/vfile.c | |
| @@ -307,17 +307,19 @@ | |
| 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); |
| 318 | isLink = db_column_int(&q, 4); |
| 319 | content_get(rid, &content); |
| 320 | if( file_is_the_same(&content, zName) ){ |
| 321 | blob_reset(&content); |
| 322 | if( file_setexe(zName, isExe) ){ |
| 323 | db_multi_exec("UPDATE vfile SET mtime=%lld WHERE id=%d", |
| @@ -340,16 +342,10 @@ | |
| 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,17 +307,19 @@ | |
| 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); |
| 317 | isLink = db_column_int(&q, 4); |
| 318 | if( file_unsafe_in_tree_path(zName) ){ |
| 319 | continue; |
| 320 | } |
| 321 | content_get(rid, &content); |
| 322 | if( file_is_the_same(&content, zName) ){ |
| 323 | blob_reset(&content); |
| 324 | if( file_setexe(zName, isExe) ){ |
| 325 | db_multi_exec("UPDATE vfile SET mtime=%lld WHERE id=%d", |
| @@ -340,16 +342,10 @@ | |
| 342 | blob_reset(&content); |
| 343 | continue; |
| 344 | } |
| 345 | } |
| 346 | if( verbose ) fossil_print("%s\n", &zName[nRepos]); |
| 347 | if( file_isdir(zName, RepoFILE)==1 ){ |
| 348 | /*TODO(dchest): remove directories? */ |
| 349 | fossil_fatal("%s is directory, cannot overwrite", zName); |
| 350 | } |
| 351 | if( file_size(zName, RepoFILE)>=0 && (isLink || file_islink(0)) ){ |
| 352 |
+3
-7
| --- src/vfile.c | ||
| +++ src/vfile.c | ||
| @@ -307,17 +307,19 @@ | ||
| 307 | 307 | g.zLocalRoot, id); |
| 308 | 308 | } |
| 309 | 309 | while( db_step(&q)==SQLITE_ROW ){ |
| 310 | 310 | int id, rid, isExe, isLink; |
| 311 | 311 | const char *zName; |
| 312 | - int n; | |
| 313 | 312 | |
| 314 | 313 | id = db_column_int(&q, 0); |
| 315 | 314 | zName = db_column_text(&q, 1); |
| 316 | 315 | rid = db_column_int(&q, 2); |
| 317 | 316 | isExe = db_column_int(&q, 3); |
| 318 | 317 | isLink = db_column_int(&q, 4); |
| 318 | + if( file_unsafe_in_tree_path(zName) ){ | |
| 319 | + continue; | |
| 320 | + } | |
| 319 | 321 | content_get(rid, &content); |
| 320 | 322 | if( file_is_the_same(&content, zName) ){ |
| 321 | 323 | blob_reset(&content); |
| 322 | 324 | if( file_setexe(zName, isExe) ){ |
| 323 | 325 | db_multi_exec("UPDATE vfile SET mtime=%lld WHERE id=%d", |
| @@ -340,16 +342,10 @@ | ||
| 340 | 342 | blob_reset(&content); |
| 341 | 343 | continue; |
| 342 | 344 | } |
| 343 | 345 | } |
| 344 | 346 | 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 | 347 | if( file_isdir(zName, RepoFILE)==1 ){ |
| 352 | 348 | /*TODO(dchest): remove directories? */ |
| 353 | 349 | fossil_fatal("%s is directory, cannot overwrite", zName); |
| 354 | 350 | } |
| 355 | 351 | if( file_size(zName, RepoFILE)>=0 && (isLink || file_islink(0)) ){ |
| 356 | 352 |
| --- src/vfile.c | |
| +++ src/vfile.c | |
| @@ -307,17 +307,19 @@ | |
| 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); |
| 318 | isLink = db_column_int(&q, 4); |
| 319 | content_get(rid, &content); |
| 320 | if( file_is_the_same(&content, zName) ){ |
| 321 | blob_reset(&content); |
| 322 | if( file_setexe(zName, isExe) ){ |
| 323 | db_multi_exec("UPDATE vfile SET mtime=%lld WHERE id=%d", |
| @@ -340,16 +342,10 @@ | |
| 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,17 +307,19 @@ | |
| 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); |
| 317 | isLink = db_column_int(&q, 4); |
| 318 | if( file_unsafe_in_tree_path(zName) ){ |
| 319 | continue; |
| 320 | } |
| 321 | content_get(rid, &content); |
| 322 | if( file_is_the_same(&content, zName) ){ |
| 323 | blob_reset(&content); |
| 324 | if( file_setexe(zName, isExe) ){ |
| 325 | db_multi_exec("UPDATE vfile SET mtime=%lld WHERE id=%d", |
| @@ -340,16 +342,10 @@ | |
| 342 | blob_reset(&content); |
| 343 | continue; |
| 344 | } |
| 345 | } |
| 346 | if( verbose ) fossil_print("%s\n", &zName[nRepos]); |
| 347 | if( file_isdir(zName, RepoFILE)==1 ){ |
| 348 | /*TODO(dchest): remove directories? */ |
| 349 | fossil_fatal("%s is directory, cannot overwrite", zName); |
| 350 | } |
| 351 | if( file_size(zName, RepoFILE)>=0 && (isLink || file_islink(0)) ){ |
| 352 |