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
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/blenlib/intern/BLI_bfile.c')
-rw-r--r--source/blender/blenlib/intern/BLI_bfile.c357
1 files changed, 106 insertions, 251 deletions
diff --git a/source/blender/blenlib/intern/BLI_bfile.c b/source/blender/blenlib/intern/BLI_bfile.c
index 3306283ad3f..b9ac6875b20 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 *****
@@ -33,6 +34,7 @@
#else
#include <io.h>
#include "BLI_winstuff.h"
+ static char* find_in_pathlist(char* filename, char* pathlist);
#endif
#include <sys/types.h>
#include <sys/stat.h>
@@ -46,8 +48,6 @@
#include "BLI_storage.h"
#include "BLI_bfile.h"
-#include "GHOST_C-api.h"
-
/* Internal bfile classification flags */
#define BCF_OPEN (0)
#define BCF_FOPEN (1<<0)
@@ -62,17 +62,14 @@
/* 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 fill_paths(BFILE *bfile, const char *path, const char *relpath);
+static void free_paths(BFILE* bfile);
+
/*** Exported functions ***/
BFILE *BLI_bfile_fopen(const char *path, const char *mode, int bflags,
- BEnvVarFam envvars)
+ const char *relpath)
{
BFILE *bfile;
@@ -88,50 +85,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;
}
@@ -175,8 +207,11 @@ size_t BLI_bfile_fwrite(const void *ptr, size_t size, size_t nmemb,
{
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 +222,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 +235,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);
}
@@ -228,197 +268,9 @@ void BLI_bfile_set_error(BFILE *bfile, int error) {
}
-void BLI_bfile_init_vars() {
- char file[MAXPATHLEN];
- char temp[MAXPATHLEN];
- extern char bprogname[];
- FILE* fp;
-
- /* This one is unconditional */
- sprintf(temp, "%d", BLENDER_VERSION);
- BLI_setenv("BLENDER_VERSION", temp);
-
- /* Is this unpack&run? */
- sprintf(temp, "%s/%d/environment", dirname(bprogname), BLENDER_VERSION);
- if(BLI_exist(temp)) {
- BLI_setenv_if_new("BLENDER_SHARE", dirname(bprogname));
- } else {
- BLI_setenv_if_new("BLENDER_SHARE", (const char*)GHOST_getSystemDir());
- }
-
- strcpy(file, (const char*)GHOST_getUserDir());
- BLI_add_slash(file);
- strcat(file, LAST_SESSION_FILE);
- fp = fopen(file, "r");
- /* 1st line, read previous version */
- if (fp && (fscanf(fp, "%3c\n", temp) == 1)) {
- temp[3] = '\0';
- BLI_setenv("BLENDER_VERSION_PREV", temp);
- /* 2nd line, read previous session path if needed */
- 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)) {
- setup_temp();
- }
- } else {
- /* We have to generate it for sure */
- setup_temp();
- }
- }
- } else {
- /* Probably new user, or only <=249 before */
- BLI_setenv("BLENDER_VERSION_PREV", "0");
- setup_temp();
- }
-
- if(fp) {
- fclose(fp);
- }
-
- /* Load vars from user and system files */
- strcpy(file, (const char *)GHOST_getUserDir());
- BLI_add_slash(file);
- strcat(file, ENVIRONMENT_FILE);
- init_vars_from_file(file);
- sprintf(temp, "/%d/environment", BLENDER_VERSION);
- BLI_make_file_string("/", file, getenv("BLENDER_SHARE"), temp);
- init_vars_from_file(file);
-}
-
-
/*** Internal functions ***/
/**
- Eliminate trailing EOL by writing a \0 over it.
- Name taken from Perl.
- */
-void chomp(char* line) {
- int len = strlen(line);
-#ifndef WIN32
- if (line[len - 1] == '\n') {
- line[len - 1] = '\0';
- }
-#else
- if ((line[len - 2] == '\r' ) && ((line[len - 1] == '\n'))) {
- line[len - 2] = '\0';
- }
-#endif /* WIN32 */
-}
-
-
-/**
- Parse a file with lines like FOO=bar (comment lines have # as first
- character) assigning to envvar FOO the value bar if FOO does not
- exist yet.
- Any white space before FOO, around the = or trailing will be used,
- so beware.
- */
-#define MAX_LINE 4096
-#define ENV_VAR 256
-#define VAR_LEN 8192
-void init_vars_from_file(const char* path) {
- char line[MAX_LINE];
- char name[ENV_VAR];
- FILE *fp;
- char* separator;
- char expanded[VAR_LEN];
-
- fp = fopen(path, "r");
- if (!fp) return;
-
- while (fgets(line, MAX_LINE, fp) != NULL) {
- /* Ignore comment lines */
- if (line[0] == '#')
- continue;
-
- /* Split into envvar name and contents */
- separator = strchr(line, '=');
- if(separator && ((separator - line) < ENV_VAR)) {
- /* First remove EOL */
- chomp(line);
- strncpy(name, line, separator - line);
- name[separator - line] = '\0';
- expand_envvars(separator + 1, expanded);
- BLI_setenv_if_new(name, expanded);
- }
- }
- fclose(fp);
-}
-
-
-/**
- Look for ${} (or %%) env vars in src and expand if the var
- exists (even if empty value). If not exist, the name is left as is.
- The process is done all over src, and nested ${${}} is not supported.
- src must be \0 terminated, and dst must be big enough.
-*/
-#ifndef WIN32
- #define ENVVAR_PREFFIX "${"
- #define ENVVAR_P_SIZE 2
- #define ENVVAR_SUFFIX "}"
- #define ENVVAR_S_SIZE 1
-#else
- #define ENVVAR_PREFFIX "%"
- #define ENVVAR_P_SIZE 1
- #define ENVVAR_SUFFIX "%"
- #define ENVVAR_S_SIZE 1
-#endif /* WIN32 */
-void expand_envvars(char* src, char* dst) {
- char* hit1;
- char* hit2;
- char name[ENV_VAR];
- char* value;
- int prevlen;
- int done = 0;
- char* source = src;
-
- dst[0] = '\0';
- while (!done) {
- hit1 = strstr(source, ENVVAR_PREFFIX);
- if (hit1) {
- hit2 = strstr(hit1 + ENVVAR_P_SIZE, ENVVAR_SUFFIX);
- if (hit2) {
- /* "Copy" the leading part, if any */
- if (hit1 != source) {
- prevlen = strlen(dst);
- strncat(dst, source, hit1 - source);
- dst[prevlen + (hit1 - source)] = '\0';
- }
- /* Figure the name of the env var we just found */
- strncpy(name, hit1 + ENVVAR_P_SIZE,
- hit2 - (hit1 + ENVVAR_P_SIZE));
- name[hit2 - (hit1 + ENVVAR_P_SIZE)] = '\0';
- /* See if we can get something with that name */
- value = getenv(name);
- if (value) {
- /* Push the var value */
- strcat(dst, value);
- } else {
- /* Leave the var name, so it is clear that it failed */
- strcat(dst, ENVVAR_PREFFIX);
- strcat(dst, name);
- strcat(dst, ENVVAR_SUFFIX);
- }
- /* Continue after closing mark, like a new string */
- source = hit2 + ENVVAR_S_SIZE;
- } else {
- /* Non terminated var so "copy as is" and finish */
- strcat(dst, source);
- done = 1;
- }
- } else {
- /* "Copy" whatever is left */
- strcat(dst, source);
- done = 1;
- }
- }
-}
-
-
-/**
Return a full path if the filename exists when combined
with any item from pathlist. Or NULL otherwise.
*/
@@ -427,7 +279,9 @@ void expand_envvars(char* src, char* dst) {
#else
#define SEPARATOR ':'
#endif
-char* find_in_pathlist(char* filename, char* pathlist) {
+
+#ifdef WIN32
+static char* find_in_pathlist(char* filename, char* pathlist) {
char first[FILE_MAX + 10];
char* rest = NULL;
@@ -445,51 +299,58 @@ 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;
}
}
-
+#endif
/**
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,19 +360,13 @@ void fill_paths(BFILE *bfile, const char *path) {
/**
- Create a temp directory in safe and multiuser way.
+ Free memory used for path strings.
*/
-void setup_temp() {
- char template[MAXPATHLEN];
- char* tempdir;
-
- if(getenv("TMPDIR")) {
- sprintf(template, "%s/blender-XXXXXX", getenv("TMPDIR"));
- } else {
- sprintf(template, "/tmp/blender-XXXXXX");
-// MacOSX NSTemporaryDirectory and WIN32 ???
+static void free_paths(BFILE* bfile) {
+ if (bfile->fpath) {
+ MEM_freeN(bfile->fpath);
+ }
+ if (bfile->tpath) {
+ MEM_freeN(bfile->tpath);
}
- tempdir = mkdtemp(template);
- BLI_setenv("BLENDER_TEMP", tempdir);
}
-