Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/source
diff options
context:
space:
mode:
authorBrecht Van Lommel <brechtvanlommel@pandora.be>2010-01-29 14:26:17 +0300
committerBrecht Van Lommel <brechtvanlommel@pandora.be>2010-01-29 14:26:17 +0300
commit0621a8e08a6b0130b8f51782f4b75b2fe6a299da (patch)
tree114d4074c613dd148b734dfe1eb14446673a1a15 /source
parent014a24ff62f170c2b839d5896ed2345c2b4762a7 (diff)
Fix for lack of basic error checking in writing compressed .blend files
(which is enabled by default). If there was a problem reading or writing in the compression process, the original .blend file could get lost. Now errors are checked, and writing is done as follows: write .blend@ -> compress .blend@ to .blend@.gz -> rename .blend@.gz to .blend -> remove .blend@ We've had blender crash here, lose the original .blend and leave an empty .blend@. It is not clear to me where this would happen in practice if there is enough disk space and permissions are correct, so the actual crash is likely not fixed by this commit.
Diffstat (limited to 'source')
-rw-r--r--source/blender/blenlib/intern/fileops.c36
-rw-r--r--source/blender/blenloader/intern/writefile.c42
2 files changed, 51 insertions, 27 deletions
diff --git a/source/blender/blenlib/intern/fileops.c b/source/blender/blenlib/intern/fileops.c
index ae20eda5a59..52ebab9b1ff 100644
--- a/source/blender/blenlib/intern/fileops.c
+++ b/source/blender/blenlib/intern/fileops.c
@@ -153,29 +153,39 @@ int BLI_gzip(char *from, char *to) {
char buffer[10240];
int file;
int readsize = 0;
+ int rval= 0, err;
+ gzFile gzfile;
- gzFile gzfile = gzopen(to,"wb");
- if (NULL == gzfile) return -1;
+ gzfile = gzopen(to, "wb");
+ if(gzfile == NULL)
+ return -1;
- file = open(from,O_BINARY|O_RDONLY);
-
- if (file < 0) return -2;
+ file = open(from, O_BINARY|O_RDONLY);
+ if(file < 0)
+ return -2;
- while ( 1 )
- {
+ while(1) {
readsize = read(file, buffer, 10240);
+
+ if(readsize < 0) {
+ rval= -2; /* error happened in reading */
+ fprintf(stderr, "Error reading file %s: %s.\n", from, strerror(errno));
+ break;
+ }
+ else if(readsize == 0)
+ break; /* done reading */
- if (readsize <= 0) break;
-
- gzwrite(gzfile,buffer,readsize);
+ if(gzwrite(gzfile, buffer, readsize) <= 0) {
+ rval= -1; /* error happened in writing */
+ fprintf(stderr, "Error writing gz file %s: %s.\n", to, gzerror(gzfile, &err));
+ break;
+ }
}
gzclose(gzfile);
close(file);
-
- remove(from);
- return 0;
+ return rval;
}
/* return 1 when file can be written */
diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c
index 06b01a8be0d..06af7cb20d3 100644
--- a/source/blender/blenloader/intern/writefile.c
+++ b/source/blender/blenloader/intern/writefile.c
@@ -2445,10 +2445,11 @@ static int write_file_handle(Main *mainvar, int handle, MemFile *compare, MemFil
int BLO_write_file(Main *mainvar, char *dir, int write_flags, ReportList *reports)
{
char userfilename[FILE_MAXDIR+FILE_MAXFILE];
- char tempname[FILE_MAXDIR+FILE_MAXFILE];
+ char tempname[FILE_MAXDIR+FILE_MAXFILE+1];
int file, err, write_user_block;
- sprintf(tempname, "%s@", dir);
+ /* open temporary file, so we preserve the original in case we crash */
+ BLI_snprintf(tempname, sizeof(tempname), "%s@", dir);
file = open(tempname,O_BINARY+O_WRONLY+O_CREAT+O_TRUNC, 0666);
if(file == -1) {
@@ -2456,6 +2457,7 @@ int BLO_write_file(Main *mainvar, char *dir, int write_flags, ReportList *report
return 0;
}
+ /* remapping of relative paths to new file location */
if(write_flags & G_FILE_RELATIVE_REMAP) {
char dir1[FILE_MAXDIR+FILE_MAXFILE];
char dir2[FILE_MAXDIR+FILE_MAXFILE];
@@ -2470,7 +2472,6 @@ int BLO_write_file(Main *mainvar, char *dir, int write_flags, ReportList *report
write_flags &= ~G_FILE_RELATIVE_REMAP;
else
makeFilesAbsolute(G.sce, NULL);
-
}
BLI_make_file_string(G.sce, userfilename, BLI_gethome(), ".B25.blend");
@@ -2479,33 +2480,46 @@ int BLO_write_file(Main *mainvar, char *dir, int write_flags, ReportList *report
if(write_flags & G_FILE_RELATIVE_REMAP)
makeFilesRelative(dir, NULL); /* note, making relative to something OTHER then G.sce */
+ /* actual file writing */
err= write_file_handle(mainvar, file, NULL,NULL, write_user_block, write_flags);
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!!!
-
- int ret = BLI_gzip(tempname, dir);
+ 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", dir);
+ ret = BLI_gzip(tempname, gzname);
- if(-1==ret) {
+ if(0==ret) {
+ /* now rename to real file name, and delete temp @ file too */
+ if(BLI_rename(gzname, dir) != 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;
}
- if(-2==ret) {
+ else if(-2==ret) {
BKE_report(reports, RPT_ERROR, "Failed opening .blend file for compression.");
return 0;
}
}
- else
- if(BLI_rename(tempname, dir) != 0) {
+ else if(BLI_rename(tempname, dir) != 0) {
BKE_report(reports, RPT_ERROR, "Can't change old file. File saved with @");
return 0;
}
-
- } else {
+ }
+ else {
BKE_report(reports, RPT_ERROR, strerror(errno));
remove(tempname);