Fossil SCM
Give a better error message when unable to open a file that uses one of the Windows reserved names, like "AUX" or "LPT3".
Commit
12c665068d8f756b9a318b6dd7381bed230ce49b
Parent
800517e1776de15…
2 files changed
+7
+39
+7
| --- src/blob.c | ||
| +++ src/blob.c | ||
| @@ -867,10 +867,17 @@ | ||
| 867 | 867 | #endif |
| 868 | 868 | }else{ |
| 869 | 869 | file_mkfolder(zFilename, 1, 0); |
| 870 | 870 | out = fossil_fopen(zFilename, "wb"); |
| 871 | 871 | if( out==0 ){ |
| 872 | +#if _WIN32 | |
| 873 | + const char *zReserved = file_is_win_reserved(zFilename); | |
| 874 | + if( zReserved ){ | |
| 875 | + fossil_fatal("cannot open \"%s\" because \"%s\" is " | |
| 876 | + "a reserved name on Windows", zFilename, zReserved); | |
| 877 | + } | |
| 878 | +#endif | |
| 872 | 879 | fossil_fatal_recursive("unable to open file \"%s\" for writing", |
| 873 | 880 | zFilename); |
| 874 | 881 | return 0; |
| 875 | 882 | } |
| 876 | 883 | blob_is_init(pBlob); |
| 877 | 884 |
| --- src/blob.c | |
| +++ src/blob.c | |
| @@ -867,10 +867,17 @@ | |
| 867 | #endif |
| 868 | }else{ |
| 869 | file_mkfolder(zFilename, 1, 0); |
| 870 | out = fossil_fopen(zFilename, "wb"); |
| 871 | if( out==0 ){ |
| 872 | fossil_fatal_recursive("unable to open file \"%s\" for writing", |
| 873 | zFilename); |
| 874 | return 0; |
| 875 | } |
| 876 | blob_is_init(pBlob); |
| 877 |
| --- src/blob.c | |
| +++ src/blob.c | |
| @@ -867,10 +867,17 @@ | |
| 867 | #endif |
| 868 | }else{ |
| 869 | file_mkfolder(zFilename, 1, 0); |
| 870 | out = fossil_fopen(zFilename, "wb"); |
| 871 | if( out==0 ){ |
| 872 | #if _WIN32 |
| 873 | const char *zReserved = file_is_win_reserved(zFilename); |
| 874 | if( zReserved ){ |
| 875 | fossil_fatal("cannot open \"%s\" because \"%s\" is " |
| 876 | "a reserved name on Windows", zFilename, zReserved); |
| 877 | } |
| 878 | #endif |
| 879 | fossil_fatal_recursive("unable to open file \"%s\" for writing", |
| 880 | zFilename); |
| 881 | return 0; |
| 882 | } |
| 883 | blob_is_init(pBlob); |
| 884 |
+39
| --- src/file.c | ||
| +++ src/file.c | ||
| @@ -1396,5 +1396,44 @@ | ||
| 1396 | 1396 | #else |
| 1397 | 1397 | FILE *f = fopen(zName, zMode); |
| 1398 | 1398 | #endif |
| 1399 | 1399 | return f; |
| 1400 | 1400 | } |
| 1401 | + | |
| 1402 | +/* | |
| 1403 | +** Return non-NULL if zFilename contains pathname elements that | |
| 1404 | +** are reserved on Windows. The returned string is the disallowed | |
| 1405 | +** path element. | |
| 1406 | +*/ | |
| 1407 | +const char *file_is_win_reserved(const char *zPath){ | |
| 1408 | + static const char *azRes[] = { "CON", "PRN", "AUX", "NUL", "COM", "LPT" }; | |
| 1409 | + static char zReturn[5]; | |
| 1410 | + int i; | |
| 1411 | + while( zPath[0] ){ | |
| 1412 | + for(i=0; i<ArraySize(azRes); i++){ | |
| 1413 | + if( sqlite3_strnicmp(zPath, azRes[i], 3)==0 | |
| 1414 | + && ((i>=4 && fossil_isdigit(zPath[3]) | |
| 1415 | + && (zPath[4]=='/' || zPath[4]=='.' || zPath[4]==0)) | |
| 1416 | + || (i<4 && (zPath[3]=='/' || zPath[3]=='.' || zPath[3]==0))) | |
| 1417 | + ){ | |
| 1418 | + sqlite3_snprintf(5,zReturn,"%.*s", i>=4 ? 4 : 3, zPath); | |
| 1419 | + return zReturn; | |
| 1420 | + } | |
| 1421 | + } | |
| 1422 | + while( zPath[0] && zPath[0]!='/' ) zPath++; | |
| 1423 | + while( zPath[0]=='/' ) zPath++; | |
| 1424 | + } | |
| 1425 | + return 0; | |
| 1426 | +} | |
| 1427 | + | |
| 1428 | +/* | |
| 1429 | +** COMMAND: test-valid-for-windows | |
| 1430 | +** Usage: fossil test-valid-for-windows FILENAME .... | |
| 1431 | +** | |
| 1432 | +** Show which filenames are not valid for Windows | |
| 1433 | +*/ | |
| 1434 | +void file_test_valid_for_windows(void){ | |
| 1435 | + int i; | |
| 1436 | + for(i=2; i<g.argc; i++){ | |
| 1437 | + fossil_print("%s %s\n", file_is_win_reserved(g.argv[i]), g.argv[i]); | |
| 1438 | + } | |
| 1439 | +} | |
| 1401 | 1440 |
| --- src/file.c | |
| +++ src/file.c | |
| @@ -1396,5 +1396,44 @@ | |
| 1396 | #else |
| 1397 | FILE *f = fopen(zName, zMode); |
| 1398 | #endif |
| 1399 | return f; |
| 1400 | } |
| 1401 |
| --- src/file.c | |
| +++ src/file.c | |
| @@ -1396,5 +1396,44 @@ | |
| 1396 | #else |
| 1397 | FILE *f = fopen(zName, zMode); |
| 1398 | #endif |
| 1399 | return f; |
| 1400 | } |
| 1401 | |
| 1402 | /* |
| 1403 | ** Return non-NULL if zFilename contains pathname elements that |
| 1404 | ** are reserved on Windows. The returned string is the disallowed |
| 1405 | ** path element. |
| 1406 | */ |
| 1407 | const char *file_is_win_reserved(const char *zPath){ |
| 1408 | static const char *azRes[] = { "CON", "PRN", "AUX", "NUL", "COM", "LPT" }; |
| 1409 | static char zReturn[5]; |
| 1410 | int i; |
| 1411 | while( zPath[0] ){ |
| 1412 | for(i=0; i<ArraySize(azRes); i++){ |
| 1413 | if( sqlite3_strnicmp(zPath, azRes[i], 3)==0 |
| 1414 | && ((i>=4 && fossil_isdigit(zPath[3]) |
| 1415 | && (zPath[4]=='/' || zPath[4]=='.' || zPath[4]==0)) |
| 1416 | || (i<4 && (zPath[3]=='/' || zPath[3]=='.' || zPath[3]==0))) |
| 1417 | ){ |
| 1418 | sqlite3_snprintf(5,zReturn,"%.*s", i>=4 ? 4 : 3, zPath); |
| 1419 | return zReturn; |
| 1420 | } |
| 1421 | } |
| 1422 | while( zPath[0] && zPath[0]!='/' ) zPath++; |
| 1423 | while( zPath[0]=='/' ) zPath++; |
| 1424 | } |
| 1425 | return 0; |
| 1426 | } |
| 1427 | |
| 1428 | /* |
| 1429 | ** COMMAND: test-valid-for-windows |
| 1430 | ** Usage: fossil test-valid-for-windows FILENAME .... |
| 1431 | ** |
| 1432 | ** Show which filenames are not valid for Windows |
| 1433 | */ |
| 1434 | void file_test_valid_for_windows(void){ |
| 1435 | int i; |
| 1436 | for(i=2; i<g.argc; i++){ |
| 1437 | fossil_print("%s %s\n", file_is_win_reserved(g.argv[i]), g.argv[i]); |
| 1438 | } |
| 1439 | } |
| 1440 |