diff options
Diffstat (limited to 'source/blender/blenlib/intern/BLI_bfile.c')
-rw-r--r-- | source/blender/blenlib/intern/BLI_bfile.c | 192 |
1 files changed, 134 insertions, 58 deletions
diff --git a/source/blender/blenlib/intern/BLI_bfile.c b/source/blender/blenlib/intern/BLI_bfile.c index b5dd764d6c6..dc593e23bdc 100644 --- a/source/blender/blenlib/intern/BLI_bfile.c +++ b/source/blender/blenlib/intern/BLI_bfile.c @@ -1,4 +1,5 @@ -/* +/* -*- indent-tabs-mode:t; tab-width:4; -*- + * * $Id$ * * ***** BEGIN GPL LICENSE BLOCK ***** @@ -62,17 +63,19 @@ /* Declaration of internal functions */ -void chomp(char* line); -void expand_envvars(char* src, char* dst); -void fill_paths(BFILE *bfile, const char *path); -char* find_in_pathlist(char* filename, char* pathlist); -void init_vars_from_file(const char* path); -void setup_temp(); +static void chomp(char* line); +static void expand_envvars(char* src, char* dst); +static void fill_paths(BFILE *bfile, const char *path, const char *relpath); +static char* find_in_pathlist(char* filename, char* pathlist); +static void init_vars_from_file(const char* path); +static void free_paths(BFILE* bfile); +static void setup_temp(); + /*** Exported functions ***/ BFILE *BLI_bfile_fopen(const char *path, const char *mode, int bflags, - BEnvVarFam envvars) + const char *relpath) { BFILE *bfile; @@ -88,50 +91,85 @@ BFILE *BLI_bfile_fopen(const char *path, const char *mode, int bflags, a BCF_AT_END | BCF_WRITE a+ BCF_AT_END | BCF_WRITE | BCF_READ */ - if(strchr(mode, 'r')) + if (strchr(mode, 'r')) bfile->classf |= BCF_READ; - if(strchr(mode, 'w')) + if (strchr(mode, 'w')) bfile->classf |= (BCF_DISCARD | BCF_WRITE); - if(strchr(mode, 'a')) + if (strchr(mode, 'a')) bfile->classf |= (BCF_AT_END | BCF_WRITE); - if(strchr(mode, '+')) + if (strchr(mode, '+')) bfile->classf |= (BCF_READ | BCF_WRITE); - fill_paths(bfile, path); + fill_paths(bfile, path, relpath); bfile->stream = fopen(bfile->tpath, mode); - // detect failed fopen + if (!(bfile->stream)) { + free_paths(bfile); + MEM_freeN(bfile); + return NULL; + } + bfile->fd = fileno(bfile->stream); + return bfile; } BFILE *BLI_bfile_open(const char *pathname, int flags, int bflags, - BEnvVarFam envvars) + const char *relpath) { BFILE *bfile; + char fopen_mode[3]; bfile = MEM_mallocN(sizeof(BFILE), "bfile-open"); bfile->classf = BCF_OPEN; bfile->uflags = bflags; /* Easy mapping for open() */ - if(flags & O_RDONLY) + if (flags & O_RDONLY) bfile->classf |= BCF_READ; - if(flags & O_WRONLY) + if (flags & O_WRONLY) bfile->classf |= BCF_WRITE; - if(flags & O_RDWR) + if (flags & O_RDWR) bfile->classf |= (BCF_READ | BCF_WRITE); - if(flags & O_APPEND) + if (flags & O_APPEND) bfile->classf |= BCF_AT_END; - if(flags & O_TRUNC) + if (flags & O_TRUNC) bfile->classf |= BCF_DISCARD; - fill_paths(bfile, pathname); + fill_paths(bfile, pathname, relpath); bfile->fd = open(bfile->tpath, flags); - // detect failed open -// bfile->stream = fdopen(bfile->fd, XXX); /* MSWindows _fdopen? */ + if (bfile->fd == -1) { + free_paths(bfile); + MEM_freeN(bfile); + return NULL; + } + + fopen_mode[0] = 'r'; + fopen_mode[1] = '\0'; + fopen_mode[2] = '\0'; + if (bfile->classf & BCF_DISCARD) { + fopen_mode[0] = 'w'; + if (bfile->classf & BCF_READ) { + fopen_mode[1] = '+'; + } + } else if (bfile->classf & BCF_AT_END) { + fopen_mode[0] = 'a'; + if (bfile->classf & BCF_READ) { + fopen_mode[1] = '+'; + } + } else if (bfile->classf & BCF_WRITE) { + fopen_mode[1] = '+'; + } + + bfile->stream = fdopen(bfile->fd, fopen_mode); /* MSWindows _fdopen? */ + if (!(bfile->stream)) { + free_paths(bfile); + MEM_freeN(bfile); + return NULL; + } + return bfile; } @@ -171,12 +209,15 @@ ssize_t BLI_bfile_read(BFILE *f, void *buf, size_t count) { size_t BLI_bfile_fwrite(const void *ptr, size_t size, size_t nmemb, - BFILE *f) + BFILE *f) { size_t ret; + if (f == NULL) + return 0; + ret = fwrite(ptr, size, nmemb, f->stream); - if (ret < 0) { + if (ret <= 0) { f->error = 1; } @@ -187,8 +228,11 @@ size_t BLI_bfile_fwrite(const void *ptr, size_t size, size_t nmemb, size_t BLI_bfile_fread(void *ptr, size_t size, size_t nmemb, BFILE *f) { size_t ret; + if (f == NULL) + return 0; + ret = fread(ptr, size, nmemb, f->stream); - if ((ret < 0) && ferror(f->stream)) { + if ((ret <= 0) && ferror(f->stream)) { f->error = 1; } @@ -197,21 +241,23 @@ size_t BLI_bfile_fread(void *ptr, size_t size, size_t nmemb, BFILE *f) { void BLI_bfile_close(BFILE *bfile) { - if((bfile->classf | BCF_WRITE) && - !(bfile->uflags | BFILE_RAW)) { + if ((bfile->classf | BCF_WRITE) && + !(bfile->uflags | BFILE_RAW)) { + int error; /* Make sure data is on disk */ + error = fsync(bfile->fd); + /* fsync the directory too? */ /* Move to final name if no errors */ + if (!(bfile->error) && !error) { + rename(bfile->tpath, bfile->fpath); + } } /* Normal close */ /* Cleanup */ - if(bfile->fpath) { - MEM_freeN(bfile->fpath); - } - if(bfile->tpath) { - MEM_freeN(bfile->tpath); - } + free_paths(bfile); + MEM_freeN(bfile); } @@ -240,7 +286,7 @@ void BLI_bfile_init_vars() { /* Is this unpack&run? */ sprintf(temp, "%s/%d/environment", dirname(bprogname), BLENDER_VERSION); - if(BLI_exist(temp)) { + if (BLI_exist(temp)) { BLI_setenv_if_new("BLENDER_SHARE", dirname(bprogname)); } else { BLI_setenv_if_new("BLENDER_SHARE", (const char*)GHOST_getSystemDir()); @@ -255,12 +301,12 @@ void BLI_bfile_init_vars() { temp[3] = '\0'; BLI_setenv("BLENDER_VERSION_PREV", temp); /* 2nd line, read previous session path if needed */ - if(!getenv("BLENDER_TEMP")) { + if (!getenv("BLENDER_TEMP")) { if ((fgets(temp, MAXPATHLEN, fp) != NULL)) { /* Clean any \n */ chomp(temp); /* Check the dir is still there or generate new one */ - if(!BLI_exist(temp)) { + if (!BLI_exist(temp)) { setup_temp(); } } else { @@ -274,7 +320,15 @@ void BLI_bfile_init_vars() { setup_temp(); } - if(fp) { + if (fp) { + fclose(fp); + } + + /* Loaded session info (or created), so time to store current data */ + // TODO use own fuctions to get safe saving + fp = fopen(file, "w"); + if (fp) { + fprintf(fp, "%s\n%s\n", getenv("BLENDER_VERSION"), getenv("BLENDER_TEMP")); fclose(fp); } @@ -295,7 +349,7 @@ void BLI_bfile_init_vars() { Eliminate trailing EOL by writing a \0 over it. Name taken from Perl. */ -void chomp(char* line) { +static void chomp(char* line) { int len = strlen(line); #ifndef WIN32 if (line[len - 1] == '\n') { @@ -319,7 +373,7 @@ void chomp(char* line) { #define MAX_LINE 4096 #define ENV_VAR 256 #define VAR_LEN 8192 -void init_vars_from_file(const char* path) { +static void init_vars_from_file(const char* path) { char line[MAX_LINE]; char name[ENV_VAR]; FILE *fp; @@ -336,7 +390,7 @@ void init_vars_from_file(const char* path) { /* Split into envvar name and contents */ separator = strchr(line, '='); - if(separator && ((separator - line) < ENV_VAR)) { + if (separator && ((separator - line) < ENV_VAR)) { /* First remove EOL */ chomp(line); strncpy(name, line, separator - line); @@ -366,7 +420,7 @@ void init_vars_from_file(const char* path) { #define ENVVAR_SUFFIX "%" #define ENVVAR_S_SIZE 1 #endif /* WIN32 */ -void expand_envvars(char* src, char* dst) { +static void expand_envvars(char* src, char* dst) { char* hit1; char* hit2; char name[ENV_VAR]; @@ -427,7 +481,7 @@ void expand_envvars(char* src, char* dst) { #else #define SEPARATOR ':' #endif -char* find_in_pathlist(char* filename, char* pathlist) { +static char* find_in_pathlist(char* filename, char* pathlist) { char first[FILE_MAX + 10]; char* rest = NULL; @@ -445,12 +499,12 @@ char* find_in_pathlist(char* filename, char* pathlist) { /* Check if combination exists */ BLI_add_slash(first); strcat(first, filename); - if(BLI_exist(first)) { + if (BLI_exist(first)) { return strdup(first); } /* First path failed, try with rest of paths if possible */ - if(rest) { + if (rest) { return find_in_pathlist(filename, rest); } else { return NULL; @@ -461,35 +515,42 @@ char* find_in_pathlist(char* filename, char* pathlist) { /** Setup fpath and tpath based in the needs of the bfile. */ -void fill_paths(BFILE *bfile, const char *path) { +static void fill_paths(BFILE *bfile, const char *path, const char *relpath) { char* source_path = NULL; char* temp_path = NULL; int bflags = bfile->uflags; - if(bflags & BFILE_NORMAL || bflags & BFILE_RAW) { + if (bflags & BFILE_NORMAL || bflags & BFILE_RAW) { // bfile->fpath is path with // replaced } - if(bflags & BFILE_TEMP) { + if (bflags & BFILE_TEMP) { temp_path = MEM_mallocN(MAXPATHLEN, "bfile-fpath-1"); snprintf(temp_path, MAXPATHLEN, "%s/%s", getenv("BLENDER_TEMP"), path); bfile->fpath = temp_path; } - if(bflags & BFILE_CONFIG) { + if (bflags & (BFILE_CONFIG_BASE | BFILE_CONFIG_DATAFILES | + BFILE_CONFIG_PYTHON | BFILE_CONFIG_PLUGINS)) { +// evars // bfile->fpath is userdir+version+path // source_path is first hit in (if using fallback to older versions) // userdir+curversion+path (... userdir+limitversion+path) sysdir+path // (limitversion is based in path, using some kind of regex or "tables") } - if(bfile->classf & BCF_WRITE && !(bflags & BFILE_RAW)) { - /* Generate temp path */ + if (bfile->classf & BCF_WRITE && !(bflags & BFILE_RAW)) { + /* Generate random named path */ temp_path = MEM_mallocN(MAXPATHLEN, "bfile-fpath-2"); snprintf(temp_path, MAXPATHLEN, "%s.XXXXXX", path); - bfile->tpath = mkdtemp(temp_path); - if(!(bfile->classf & BCF_DISCARD)) { - /* Copy data to tpath */ - if(source_path) { - // copy it from older version or sys version + bfile->fd = mkstemp(temp_path); + bfile->tpath = temp_path; + /* It will be reopened in upper levels, later */ + close(bfile->fd); + if (!(bfile->classf & BCF_DISCARD)) { + /* Copy original data into temp location */ + if (source_path) { + BLI_copy_fileops(source_path, bfile->tpath); + } else { + BLI_copy_fileops(bfile->fpath, bfile->tpath); } } } else { @@ -499,17 +560,32 @@ void fill_paths(BFILE *bfile, const char *path) { /** + Free memory used for path strings. + */ +static void free_paths(BFILE* bfile) { + if (bfile->fpath) { + MEM_freeN(bfile->fpath); + } + if (bfile->tpath) { + MEM_freeN(bfile->tpath); + } +} + + +/** Create a temp directory in safe and multiuser way. */ -void setup_temp() { +static void setup_temp() { char template[MAXPATHLEN]; char* tempdir; - if(getenv("TMPDIR")) { + if (getenv("TMPDIR")) { sprintf(template, "%s/blender-XXXXXX", getenv("TMPDIR")); } else { sprintf(template, "/tmp/blender-XXXXXX"); // MacOSX NSTemporaryDirectory and WIN32 ??? +// https://bugs.launchpad.net/cuneiform-linux/+bug/267136 +// https://svn.r-project.org/R/trunk/src/main/mkdtemp.c } tempdir = mkdtemp(template); BLI_setenv("BLENDER_TEMP", tempdir); |