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:
authorGuillermo S. Romero <gsr.b3d@infernal-iceberg.com>2009-10-19 22:44:09 +0400
committerGuillermo S. Romero <gsr.b3d@infernal-iceberg.com>2009-10-19 22:44:09 +0400
commit680e724e37e10a3e6e7e42691d2e07d3dd62b6b7 (patch)
treeb995119ba65d643cc84187085cf6912ff57afcd7 /source/blender/blenlib/intern/BLI_bfile.c
parent1f4d07fd199041726d2bb77eebe702bf3351b4e8 (diff)
Continue development of bfile system.
Still not usable, but some parts could be made more portable already. Help welcome for MacOSX and MSWindows calls and paths.
Diffstat (limited to 'source/blender/blenlib/intern/BLI_bfile.c')
-rw-r--r--source/blender/blenlib/intern/BLI_bfile.c414
1 files changed, 346 insertions, 68 deletions
diff --git a/source/blender/blenlib/intern/BLI_bfile.c b/source/blender/blenlib/intern/BLI_bfile.c
index a7ce1df5712..4de1e6ce4a1 100644
--- a/source/blender/blenlib/intern/BLI_bfile.c
+++ b/source/blender/blenlib/intern/BLI_bfile.c
@@ -25,89 +25,70 @@
*/
#include <string.h>
-
+#include <stdlib.h>
#ifndef WIN32
#include <unistd.h>
#else
#include <io.h>
#include "BLI_winstuff.h"
#endif
-
+#include <sys/param.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
+#include <libgen.h>
#include "MEM_guardedalloc.h"
-
+#include "BKE_utildefines.h"
+#include "BKE_blender.h"
+#include "BLI_util.h"
+#include "BLI_fileops.h"
+#include "BLI_storage.h"
#include "BLI_bfile.h"
-// This would provide config paths and their oldest viable version
-// so if there is an uncompatible change, user's old versions are not loaded
-//#include "bfile_tables.h"
-
-/* Internal bfile type flags */
-#define BTF_OPEN (0)
-#define BTF_FOPEN (1<<0)
-#define BTF_READ (1<<1)
-#define BTF_WRITE (1<<2)
-#define BTF_AT_END (1<<3)
-#define BTF_DISCARD (1<<4)
-
-
-void fill_paths(BFILE *bfile, const char *path) {
- char* source_path = NULL;
- int bflags = bfile->uflags;
-
- if(bflags & BFILE_NORMAL || bflags & BFILE_RAW) {
-// bfile->fpath is path with // replaced
- }
- if(bflags & BFILE_TEMP) {
-// bfile->fpath is tempdir+path
- }
- if(bflags & BFILE_CONFIG) {
-// 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->type & BTF_WRITE && !(bflags & BFILE_RAW)) {
- /* Generate temp path */
- // bfile->tpath is fpath+randstring
- if(!(bfile->type & BTF_DISCARD)) {
- /* Copy data to tpath */
- if(source_path) {
- // copy it from older version or sys version
- }
- }
- } else {
- bfile->tpath = bfile->fpath;
- }
-}
-
-BFILE *BLI_bfile_fopen(const char *path, const char *mode, int bflags) {
+/* Internal bfile classification flags */
+#define BCF_OPEN (0)
+#define BCF_FOPEN (1<<0)
+#define BCF_READ (1<<1)
+#define BCF_WRITE (1<<2)
+#define BCF_AT_END (1<<3)
+#define BCF_DISCARD (1<<4)
+
+/* 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();
+
+/*** Exported functions ***/
+
+BFILE *BLI_bfile_fopen(const char *path, const char *mode, int bflags,
+ BEnvVarFam envvars)
+{
BFILE *bfile;
bfile = MEM_mallocN(sizeof(BFILE), "bfile-fopen");
- bfile->type = BTF_FOPEN;
+ bfile->classf = BCF_FOPEN;
bfile->uflags = bflags;
/* From fopen() doc, we can guess some logic:
- r BTF_READ
- r+ BTF_READ | BTF_WRITE
- w BTF_DISCARD | BTF_WRITE
- w+ BTF_DISCARD | BTF_WRITE | BTF_READ
- a BTF_AT_END | BTF_WRITE
- a+ BTF_AT_END | BTF_WRITE | BTF_READ
+ r BCF_READ
+ r+ BCF_READ | BCF_WRITE
+ w BCF_DISCARD | BCF_WRITE
+ w+ BCF_DISCARD | BCF_WRITE | BCF_READ
+ a BCF_AT_END | BCF_WRITE
+ a+ BCF_AT_END | BCF_WRITE | BCF_READ
*/
if(strchr(mode, 'r'))
- bfile->type |= BTF_READ;
+ bfile->classf |= BCF_READ;
if(strchr(mode, 'w'))
- bfile->type |= (BTF_DISCARD | BTF_WRITE);
+ bfile->classf |= (BCF_DISCARD | BCF_WRITE);
if(strchr(mode, 'a'))
- bfile->type |= (BTF_AT_END | BTF_WRITE);
+ bfile->classf |= (BCF_AT_END | BCF_WRITE);
if(strchr(mode, '+'))
- bfile->type |= (BTF_READ | BTF_WRITE);
+ bfile->classf |= (BCF_READ | BCF_WRITE);
fill_paths(bfile, path);
@@ -118,24 +99,26 @@ BFILE *BLI_bfile_fopen(const char *path, const char *mode, int bflags) {
}
-BFILE *BLI_bfile_open(const char *pathname, int flags, int bflags) {
+BFILE *BLI_bfile_open(const char *pathname, int flags, int bflags,
+ BEnvVarFam envvars)
+{
BFILE *bfile;
bfile = MEM_mallocN(sizeof(BFILE), "bfile-open");
- bfile->type = BTF_OPEN;
+ bfile->classf = BCF_OPEN;
bfile->uflags = bflags;
/* Easy mapping for open() */
if(flags & O_RDONLY)
- bfile->type |= BTF_READ;
+ bfile->classf |= BCF_READ;
if(flags & O_WRONLY)
- bfile->type |= BTF_WRITE;
+ bfile->classf |= BCF_WRITE;
if(flags & O_RDWR)
- bfile->type |= (BTF_READ | BTF_WRITE);
+ bfile->classf |= (BCF_READ | BCF_WRITE);
if(flags & O_APPEND)
- bfile->type |= BTF_AT_END;
+ bfile->classf |= BCF_AT_END;
if(flags & O_TRUNC)
- bfile->type |= BTF_DISCARD;
+ bfile->classf |= BCF_DISCARD;
fill_paths(bfile, pathname);
@@ -180,7 +163,9 @@ 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) {
+size_t BLI_bfile_fwrite(const void *ptr, size_t size, size_t nmemb,
+ BFILE *f)
+{
size_t ret;
ret = fwrite(ptr, size, nmemb, f->stream);
@@ -205,7 +190,7 @@ size_t BLI_bfile_fread(void *ptr, size_t size, size_t nmemb, BFILE *f) {
void BLI_bfile_close(BFILE *bfile) {
- if((bfile->type | BTF_WRITE) &&
+ if((bfile->classf | BCF_WRITE) &&
!(bfile->uflags | BFILE_RAW)) {
/* Make sure data is on disk */
/* Move to final name if no errors */
@@ -234,3 +219,296 @@ void BLI_bfile_set_error(BFILE *bfile, int error) {
bfile->error = error;
}
}
+
+
+#if defined(WIN32)
+ #define LAST_SESSION_FILE "%HOME%\\Blender\\last-session FIXME FIXME FIXME"
+ #define ENVIRONMENT_FILE "FIXME"
+ #define SHARED_DIRECTORY "FIXME TOO"
+#elif defined(OSX)
+ #define LAST_SESSION_FILE "${HOME}/Library/Application Support/Blender/last-session"
+ #define ENVIRONMENT_FILE "${HOME}/Library/Application Support/Blender/${BLENDER_VERSION}/environment"
+ #define SHARED_DIRECTORY "/Library/Application Support/Blender"
+#else
+ #define LAST_SESSION_FILE "${HOME}/.blender/last-session"
+ #define ENVIRONMENT_FILE "${HOME}/.blender/${BLENDER_VERSION}/environment"
+ #define SHARED_DIRECTORY "/usr/share/blender"
+#endif
+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", SHARED_DIRECTORY);
+ }
+
+ expand_envvars(LAST_SESSION_FILE, 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 */
+ expand_envvars(ENVIRONMENT_FILE, 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.
+ */
+#ifdef WIN32
+ #define SEPARATOR ';'
+#else
+ #define SEPARATOR ':'
+#endif
+char* find_in_pathlist(char* filename, char* pathlist) {
+ char first[FILE_MAX + 10];
+ char* rest = NULL;
+
+ /* Separate first path from rest, use typical separator for current OS */
+ rest = strchr(pathlist, SEPARATOR);
+ if (rest) {
+ strncpy(first, pathlist, rest - pathlist);
+ first[rest - pathlist] = '\0';
+ /* Skip the separator so it becomes a valid new pathlist */
+ rest++;
+ } else {
+ strcpy(first, pathlist);
+ }
+
+ /* Check if combination exists */
+ BLI_add_slash(first);
+ strcat(first, filename);
+ if(BLI_exist(first)) {
+ return strdup(first);
+ }
+
+ /* First path failed, try with rest of paths if possible */
+ if(rest) {
+ return find_in_pathlist(filename, rest);
+ } else {
+ return NULL;
+ }
+}
+
+
+/**
+ Setup fpath and tpath based in the needs of the bfile.
+ */
+void fill_paths(BFILE *bfile, const char *path) {
+ char* source_path = NULL;
+ int bflags = bfile->uflags;
+
+ if(bflags & BFILE_NORMAL || bflags & BFILE_RAW) {
+// bfile->fpath is path with // replaced
+ }
+ if(bflags & BFILE_TEMP) {
+// bfile->fpath is tempdir+path
+ }
+ if(bflags & BFILE_CONFIG) {
+// 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 */
+ // bfile->tpath is fpath+randstring
+ if(!(bfile->classf & BCF_DISCARD)) {
+ /* Copy data to tpath */
+ if(source_path) {
+ // copy it from older version or sys version
+ }
+ }
+ } else {
+ bfile->tpath = bfile->fpath;
+ }
+}
+
+
+/**
+ Create a temp directory in safe and multiuser way.
+ */
+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 ???
+ }
+ tempdir = mkdtemp(template);
+ BLI_setenv("BLENDER_TEMP", tempdir);
+}
+