fix for [#27410] Manual save kills actual .blend file if disk space is low

- moved do_history into WM_write_file after successful write of .blend@ temporary file
- Added new file flag, to avoid writing history on writing the startup.blend, autosave files and undo.

Thanks Campbell, Brecht for review!
This commit is contained in:
Andrea Weikert
2011-06-02 12:44:59 +00:00
parent 1ba4550d27
commit b4872b84c8
4 changed files with 88 additions and 68 deletions

View File

@@ -145,6 +145,7 @@ typedef struct Global {
#define G_FILE_IGNORE_DEPRECATION_WARNINGS (1 << 22) /* deprecated */
#define G_FILE_RECOVER (1 << 23)
#define G_FILE_RELATIVE_REMAP (1 << 24)
#define G_FILE_HISTORY (1 << 25)
/* G.windowstate */
#define G_WINDOWSTATE_USERDEF 0

View File

@@ -523,7 +523,8 @@ void BKE_write_undo(bContext *C, const char *name)
static int counter= 0;
char filepath[FILE_MAXDIR+FILE_MAXFILE];
char numstr[32];
int fileflags = G.fileflags & ~(G_FILE_HISTORY); /* don't do file history on undo */
/* calculate current filepath */
counter++;
counter= counter % U.undosteps;
@@ -531,7 +532,7 @@ void BKE_write_undo(bContext *C, const char *name)
BLI_snprintf(numstr, sizeof(numstr), "%d.blend", counter);
BLI_make_file_string("/", filepath, btempdir, numstr);
success= BLO_write_file(CTX_data_main(C), filepath, G.fileflags, NULL, NULL);
success= BLO_write_file(CTX_data_main(C), filepath, fileflags, NULL, NULL);
BLI_strncpy(curundo->str, filepath, sizeof(curundo->str));
}

View File

@@ -2520,6 +2520,41 @@ static int write_file_handle(Main *mainvar, int handle, MemFile *compare, MemFil
return endwrite(wd);
}
/* do reverse file history: .blend1 -> .blend2, .blend -> .blend1 */
/* return: success(0), failure(1) */
static int do_history(const char *name, ReportList *reports)
{
char tempname1[FILE_MAXDIR+FILE_MAXFILE], tempname2[FILE_MAXDIR+FILE_MAXFILE];
int hisnr= U.versions;
if(U.versions==0) return 0;
if(strlen(name)<2) {
BKE_report(reports, RPT_ERROR, "Unable to make version backup: filename too short");
return 1;
}
while(hisnr > 1) {
BLI_snprintf(tempname1, sizeof(tempname1), "%s%d", name, hisnr-1);
BLI_snprintf(tempname2, sizeof(tempname2), "%s%d", name, hisnr);
if(BLI_rename(tempname1, tempname2)) {
BKE_report(reports, RPT_ERROR, "Unable to make version backup");
return 1;
}
hisnr--;
}
/* is needed when hisnr==1 */
BLI_snprintf(tempname1, sizeof(tempname1), "%s%d", name, hisnr);
if(BLI_rename(name, tempname1)) {
BKE_report(reports, RPT_ERROR, "Unable to make version backup");
return 1;
}
return 0;
}
/* return: success (1) */
int BLO_write_file(Main *mainvar, const char *filepath, int write_flags, ReportList *reports, int *thumb)
{
@@ -2571,48 +2606,55 @@ int BLO_write_file(Main *mainvar, const char *filepath, int write_flags, ReportL
err= write_file_handle(mainvar, file, NULL,NULL, write_user_block, write_flags, thumb);
close(file);
/* rename/compress */
if(!err) {
if(write_flags & G_FILE_COMPRESS) {
/* compressed files have the same ending as regular files... only from 2.4!!! */
char gzname[FILE_MAXDIR+FILE_MAXFILE+4];
int ret;
/* first write compressed to separate @.gz */
BLI_snprintf(gzname, sizeof(gzname), "%s@.gz", filepath);
ret = BLI_gzip(tempname, gzname);
if(0==ret) {
/* now rename to real file name, and delete temp @ file too */
if(BLI_rename(gzname, filepath) != 0) {
BKE_report(reports, RPT_ERROR, "Can't change old file. File saved with @.");
return 0;
}
BLI_delete(tempname, 0, 0);
}
else if(-1==ret) {
BKE_report(reports, RPT_ERROR, "Failed opening .gz file.");
return 0;
}
else if(-2==ret) {
BKE_report(reports, RPT_ERROR, "Failed opening .blend file for compression.");
return 0;
}
}
else if(BLI_rename(tempname, filepath) != 0) {
BKE_report(reports, RPT_ERROR, "Can't change old file. File saved with @");
return 0;
}
}
else {
if (err) {
BKE_report(reports, RPT_ERROR, strerror(errno));
remove(tempname);
return 0;
}
/* file save to temporary file was successful */
/* now do reverse file history (move .blend1 -> .blend2, .blend -> .blend1) */
if (write_flags & G_FILE_HISTORY) {
int err_hist = do_history(filepath, reports);
if (err_hist) {
BKE_report(reports, RPT_ERROR, "Version backup failed. File saved with @");
return 0;
}
}
if(write_flags & G_FILE_COMPRESS) {
/* compressed files have the same ending as regular files... only from 2.4!!! */
char gzname[FILE_MAXDIR+FILE_MAXFILE+4];
int ret;
/* first write compressed to separate @.gz */
BLI_snprintf(gzname, sizeof(gzname), "%s@.gz", filepath);
ret = BLI_gzip(tempname, gzname);
if(0==ret) {
/* now rename to real file name, and delete temp @ file too */
if(BLI_rename(gzname, filepath) != 0) {
BKE_report(reports, RPT_ERROR, "Can't change old file. File saved with @.");
return 0;
}
BLI_delete(tempname, 0, 0);
}
else if(-1==ret) {
BKE_report(reports, RPT_ERROR, "Failed opening .gz file.");
return 0;
}
else if(-2==ret) {
BKE_report(reports, RPT_ERROR, "Failed opening .blend file for compression.");
return 0;
}
}
else if(BLI_rename(tempname, filepath) != 0) {
BKE_report(reports, RPT_ERROR, "Can't change old file. File saved with @");
return 0;
}
return 1;
}

View File

@@ -620,31 +620,6 @@ static void write_history(void)
}
}
static void do_history(char *name, ReportList *reports)
{
char tempname1[FILE_MAXDIR+FILE_MAXFILE], tempname2[FILE_MAXDIR+FILE_MAXFILE];
int hisnr= U.versions;
if(U.versions==0) return;
if(strlen(name)<2) return;
while(hisnr > 1) {
BLI_snprintf(tempname1, sizeof(tempname1), "%s%d", name, hisnr-1);
BLI_snprintf(tempname2, sizeof(tempname2), "%s%d", name, hisnr);
if(BLI_rename(tempname1, tempname2))
BKE_report(reports, RPT_ERROR, "Unable to make version backup");
hisnr--;
}
/* is needed when hisnr==1 */
BLI_snprintf(tempname1, sizeof(tempname1), "%s%d", name, hisnr);
if(BLI_rename(name, tempname1))
BKE_report(reports, RPT_ERROR, "Unable to make version backup");
}
static ImBuf *blend_file_thumb(Scene *scene, int **thumb_pt)
{
/* will be scaled down, but gives some nice oversampling */
@@ -693,9 +668,11 @@ static ImBuf *blend_file_thumb(Scene *scene, int **thumb_pt)
int write_crash_blend(void)
{
char path[FILE_MAX];
int fileflags = G.fileflags & ~(G_FILE_HISTORY); /* don't do file history on crash file */
BLI_strncpy(path, G.main->name, sizeof(path));
BLI_replace_extension(path, sizeof(path), "_crash.blend");
if(BLO_write_file(G.main, path, G.fileflags, NULL, NULL)) {
if(BLO_write_file(G.main, path, fileflags, NULL, NULL)) {
printf("written: %s\n", path);
return 1;
}
@@ -753,8 +730,7 @@ int WM_write_file(bContext *C, const char *target, int fileflags, ReportList *re
/* blend file thumbnail */
ibuf_thumb= blend_file_thumb(CTX_data_scene(C), &thumb);
/* rename to .blend1, do this as last before write */
do_history(filepath, reports);
fileflags |= G_FILE_HISTORY; /* write file history */
if (BLO_write_file(CTX_data_main(C), filepath, fileflags, reports, thumb)) {
if(!copy) {
@@ -809,7 +785,7 @@ int WM_write_homefile(bContext *C, wmOperator *op)
printf("trying to save homefile at %s ", filepath);
/* force save as regular blend file */
fileflags = G.fileflags & ~(G_FILE_COMPRESS | G_FILE_AUTOPLAY | G_FILE_LOCK | G_FILE_SIGN);
fileflags = G.fileflags & ~(G_FILE_COMPRESS | G_FILE_AUTOPLAY | G_FILE_LOCK | G_FILE_SIGN | G_FILE_HISTORY);
if(BLO_write_file(CTX_data_main(C), filepath, fileflags, op->reports, NULL) == 0) {
printf("fail\n");
@@ -883,7 +859,7 @@ void wm_autosave_timer(const bContext *C, wmWindowManager *wm, wmTimer *UNUSED(w
wm_autosave_location(filepath);
/* force save as regular blend file */
fileflags = G.fileflags & ~(G_FILE_COMPRESS|G_FILE_AUTOPLAY |G_FILE_LOCK|G_FILE_SIGN);
fileflags = G.fileflags & ~(G_FILE_COMPRESS|G_FILE_AUTOPLAY |G_FILE_LOCK|G_FILE_SIGN|G_FILE_HISTORY);
/* no error reporting to console */
BLO_write_file(CTX_data_main(C), filepath, fileflags, NULL, NULL);