Index: src/checkin.c ================================================================== --- src/checkin.c +++ src/checkin.c @@ -351,19 +351,19 @@ if( file_tree_name(g.zRepositoryName, &repo, 0) ){ db_multi_exec("DELETE FROM sfile WHERE x=%B", &repo); } while( db_step(&q)==SQLITE_ROW ){ if( allFlag ){ - unlink(db_column_text(&q, 0)); + file_delete(db_column_text(&q, 0)); }else{ Blob ans; char *prompt = mprintf("remove unmanaged file \"%s\" (y/N)? ", db_column_text(&q, 0)); blob_zero(&ans); prompt_user(prompt, &ans); if( blob_str(&ans)[0]=='y' ){ - unlink(db_column_text(&q, 0)); + file_delete(db_column_text(&q, 0)); } } } db_finalize(&q); } @@ -458,11 +458,11 @@ if( zIn[0]=='.' && (zIn[1]==0 || zIn[1]=='\r' || zIn[1]=='\n') ) break; blob_append(&text, zIn, -1); } } blob_remove_cr(&text); - unlink(zFile); + file_delete(zFile); free(zFile); blob_zero(pComment); while( blob_line(&text, &line) ){ int i, n; char *z; Index: src/checkout.c ================================================================== --- src/checkout.c +++ src/checkout.c @@ -157,16 +157,16 @@ free(zManFile); blob_reset(&hash); }else{ if( !db_exists("SELECT 1 FROM vfile WHERE pathname='manifest'") ){ zManFile = mprintf("%smanifest", g.zLocalRoot); - unlink(zManFile); + file_delete(zManFile); free(zManFile); } if( !db_exists("SELECT 1 FROM vfile WHERE pathname='manifest.uuid'") ){ zManFile = mprintf("%smanifest.uuid", g.zLocalRoot); - unlink(zManFile); + file_delete(zManFile); free(zManFile); } } } @@ -268,11 +268,11 @@ int i; for(i=0; (zReserved = fossil_reserved_name(i))!=0; i++){ if( manifestOnly==0 || zReserved[0]=='m' ){ char *z; z = mprintf("%s%s", g.zLocalRoot, zReserved); - unlink(z); + file_delete(z); free(z); } } } Index: src/clearsign.c ================================================================== --- src/clearsign.c +++ src/clearsign.c @@ -52,11 +52,11 @@ }else{ if( pOut!=pIn ){ blob_copy(pOut, pIn); } } - unlink(zOut); - unlink(zIn); + file_delete(zOut); + file_delete(zIn); free(zOut); free(zIn); return rc; } Index: src/clone.c ================================================================== --- src/clone.c +++ src/clone.c @@ -100,11 +100,11 @@ g.xlinkClusterOnly = 0; verify_cancel(); db_end_transaction(0); db_close(1); if( nErr ){ - unlink(g.argv[3]); + file_delete(g.argv[3]); fossil_fatal("server returned an error - clone aborted"); } db_open_repository(g.argv[3]); } db_begin_transaction(); Index: src/db.c ================================================================== --- src/db.c +++ src/db.c @@ -151,11 +151,11 @@ if( nBegin ){ sqlite3_exec(g.db, "ROLLBACK", 0, 0, 0); nBegin = 0; if( isNewRepo ){ db_close(0); - unlink(g.zRepositoryName); + file_delete(g.zRepositoryName); } } busy = 0; db_close(0); } Index: src/diffcmd.c ================================================================== --- src/diffcmd.c +++ src/diffcmd.c @@ -99,11 +99,11 @@ /* Run the external diff command */ fossil_system(blob_str(&cmd)); /* Delete the temporary file and clean up memory used */ - unlink(blob_str(&nameFile1)); + file_delete(blob_str(&nameFile1)); blob_reset(&nameFile1); blob_reset(&cmd); } } @@ -153,12 +153,12 @@ /* Run the external diff command */ fossil_system(blob_str(&cmd)); /* Delete the temporary file and clean up memory used */ - unlink(zTemp1); - unlink(zTemp2); + file_delete(zTemp1); + file_delete(zTemp2); blob_reset(&cmd); } } /* Index: src/file.c ================================================================== --- src/file.c +++ src/file.c @@ -133,10 +133,17 @@ if( z[0]=='/' ) zTail = &z[1]; z++; } return zTail; } + +/* +** Delete a file. +*/ +void file_delete(const char *zFilename){ + unlink(zFilename); +} /* ** Copy the content of a file from one place to another. */ void file_copy(const char *zFrom, const char *zTo){ @@ -151,10 +158,46 @@ fwrite(zBuf, 1, got, out); } fclose(in); fclose(out); } + +/* +** Rename a file. +*/ +void file_move(const char *zFrom, const char *zTo){ +#if defined(_WIN32) + /* if( MoveFileW(zFrom, zTo) ) return; */ +#else + if( rename(zFrom, zTo)==0 ) return; +#endif + file_copy(zFrom, zTo); + file_delete(zFrom); +} + +/* +** If the named file exists, move it out of the way so that it will not +** be overwritten by subsequent operations. +*/ +void file_dont_overwrite(const char *z){ + char *zNow; + char *zNewName; + int cnt = 0; + if( file_mtime(z)<0 ) return; + if( !file_isfile(0) ){ + fossil_fatal("cannot overwrite \"%s\" - not an ordinary file"); + } + zNow = db_text(0, "SELECT strftime('%%Y%%m%%d%%H%%M%%S', 'now')"); + while(1){ + zNewName = mprintf("%s-%s-%d", z, zNow, cnt++); + if( file_mtime(zNewName)<0 ) break; + fossil_free(zNewName); + } + fossil_free(zNow); + file_move(z, zNewName); + fossil_free(zNewName); +} /* ** Set or clear the execute bit on a file. */ void file_setexe(const char *zFilename, int onoff){ @@ -182,11 +225,11 @@ */ int file_mkdir(const char *zName, int forceFlag){ int rc = file_isdir(zName); if( rc==2 ){ if( !forceFlag ) return 1; - unlink(zName); + file_delete(zName); } if( rc!=1 ){ #if defined(_WIN32) return mkdir(zName); #else Index: src/http_transport.c ================================================================== --- src/http_transport.c +++ src/http_transport.c @@ -242,12 +242,12 @@ }else if( g.urlIsFile ){ if( transport.pFile ){ fclose(transport.pFile); transport.pFile = 0; } - unlink(transport.zInFile); - unlink(transport.zOutFile); + file_delete(transport.zInFile); + file_delete(transport.zOutFile); free(transport.zInFile); free(transport.zOutFile); }else{ socket_close(); } Index: src/import.c ================================================================== --- src/import.c +++ src/import.c @@ -643,11 +643,11 @@ pIn = fopen(g.argv[3], "rb"); }else{ pIn = stdin; fossil_binary_mode(pIn); } - if( forceFlag ) unlink(g.argv[2]); + if( forceFlag ) file_delete(g.argv[2]); db_create_repository(g.argv[2]); db_open_repository(g.argv[2]); db_open_config(0); db_multi_exec( "CREATE TEMP TABLE xtag(tname TEXT UNIQUE, trid INT, tuuid TEXT);" Index: src/merge.c ================================================================== --- src/merge.c +++ src/merge.c @@ -410,11 +410,11 @@ db_multi_exec( "UPDATE vfile SET deleted=1 WHERE id=%d", idv ); if( !nochangeFlag ){ char *zFullPath = mprintf("%s%s", g.zLocalRoot, zName); - unlink(zFullPath); + file_delete(zFullPath); free(zFullPath); } } db_finalize(&q); @@ -440,11 +440,11 @@ ); if( !nochangeFlag ){ char *zFullOldPath = mprintf("%s%s", g.zLocalRoot, zOldName); char *zFullNewPath = mprintf("%s%s", g.zLocalRoot, zNewName); file_copy(zFullOldPath, zFullNewPath); - unlink(zFullOldPath); + file_delete(zFullOldPath); free(zFullNewPath); free(zFullOldPath); } } db_finalize(&q); Index: src/stash.c ================================================================== --- src/stash.c +++ src/stash.c @@ -188,11 +188,11 @@ db_ephemeral_blob(&q, 5, &delta); blob_write_to_file(&delta, zNPath); printf("ADD %s\n", zNew); }else if( isRemoved ){ printf("DELETE %s\n", zOrig); - unlink(zOPath); + file_delete(zOPath); }else{ Blob a, b, out, disk; db_ephemeral_blob(&q, 5, &delta); blob_read_from_file(&disk, zOPath); content_get(rid, &a); @@ -216,11 +216,11 @@ blob_reset(&disk); } blob_reset(&delta); if( fossil_strcmp(zOrig,zNew)!=0 ){ undo_save(zOrig); - unlink(zOPath); + file_delete(zOPath); } } db_finalize(&q); if( nConflict ){ printf("WARNING: merge conflicts - see messages above for details.\n"); Index: src/undo.c ================================================================== --- src/undo.c +++ src/undo.c @@ -59,11 +59,11 @@ printf("NEW %s\n", zPathname); } blob_write_to_file(&new, zFullname); }else{ printf("DELETE %s\n", zPathname); - unlink(zFullname); + file_delete(zFullname); } blob_reset(&new); free(zFullname); db_finalize(&q); db_prepare(&q, Index: src/update.c ================================================================== --- src/update.c +++ src/update.c @@ -358,11 +358,11 @@ printf("CONFLICT %s - edited locally but deleted by update\n", zName); nConflict++; }else{ printf("REMOVE %s\n", zName); undo_save(zName); - if( !nochangeFlag ) unlink(zFullPath); + if( !nochangeFlag ) file_delete(zFullPath); } }else if( idt>0 && idv>0 && ridt!=ridv && chnged ){ /* Merge the changes in the current tree into the target version */ Blob e, r, t, v; int rc; @@ -386,11 +386,11 @@ }else{ if( !nochangeFlag ) blob_write_to_file(&t, zFullNewPath); printf("***** Cannot merge binary file %s\n", zNewName); nConflict++; } - if( nameChng && !nochangeFlag ) unlink(zFullPath); + if( nameChng && !nochangeFlag ) file_delete(zFullPath); blob_reset(&v); blob_reset(&e); blob_reset(&t); blob_reset(&r); }else{ Index: src/vfile.c ================================================================== --- src/vfile.c +++ src/vfile.c @@ -268,11 +268,11 @@ " WHERE vid=%d AND mrid>0", g.zLocalRoot, vid); while( db_step(&q)==SQLITE_ROW ){ const char *zName; zName = db_column_text(&q, 0); - unlink(zName); + file_delete(zName); } db_finalize(&q); db_multi_exec("UPDATE vfile SET mtime=NULL WHERE vid=%d AND mrid>0", vid); } Index: src/winhttp.c ================================================================== --- src/winhttp.c +++ src/winhttp.c @@ -123,12 +123,12 @@ end_request: if( out ) fclose(out); if( in ) fclose(in); closesocket(p->s); - unlink(zRequestFName); - unlink(zReplyFName); + file_delete(zRequestFName); + file_delete(zReplyFName); free(p); } /* ** Start a listening socket and process incoming HTTP requests on @@ -146,11 +146,11 @@ SOCKADDR_IN addr; int idCnt = 0; int iPort = mnPort; char *zNotFoundOption; - if( zStopper ) unlink(zStopper); + if( zStopper ) file_delete(zStopper); if( zNotFound ){ zNotFoundOption = mprintf(" --notfound %s", zNotFound); }else{ zNotFoundOption = ""; }