diff options
Diffstat (limited to 'source/blender/blenlib/intern/path_util.c')
-rw-r--r-- | source/blender/blenlib/intern/path_util.c | 523 |
1 files changed, 345 insertions, 178 deletions
diff --git a/source/blender/blenlib/intern/path_util.c b/source/blender/blenlib/intern/path_util.c index cf773d575e5..2359a858d51 100644 --- a/source/blender/blenlib/intern/path_util.c +++ b/source/blender/blenlib/intern/path_util.c @@ -1,4 +1,4 @@ -/** +/* * $Id$ * * ***** BEGIN GPL LICENSE BLOCK ***** @@ -32,6 +32,7 @@ #include <ctype.h> #include <string.h> #include <stdlib.h> +#include <assert.h> #include "MEM_guardedalloc.h" @@ -42,12 +43,19 @@ #include "BLI_string.h" #include "BLI_storage.h" #include "BLI_storage_types.h" +#include "BLI_utildefines.h" #include "BKE_utildefines.h" #include "BKE_blender.h" // BLENDER_VERSION #include "GHOST_Path-api.h" +#if defined WIN32 && !defined _LIBC +# include "BLI_fnmatch.h" /* use fnmatch included in blenlib */ +#else +# define _GNU_SOURCE +# include <fnmatch.h> +#endif #ifdef WIN32 #include <io.h> @@ -63,13 +71,16 @@ #else /* non windows */ -#ifdef __linux__ +#ifdef WITH_BINRELOC #include "binreloc.h" #endif #endif /* WIN32 */ /* local */ +#define UNIQUE_NAME_MAX 128 + +extern char bprogname[]; static int add_win32_extension(char *name); static char *blender_version_decimal(void); @@ -130,10 +141,41 @@ void BLI_stringenc(char *string, const char *head, const char *tail, unsigned sh sprintf(string, fmtstr, head, pic, tail); } +/* Foo.001 -> "Foo", 1 + * Returns the length of "Foo" */ +int BLI_split_name_num(char *left, int *nr, const char *name, const char delim) +{ + int a; + + *nr= 0; + a= strlen(name); + memcpy(left, name, (a + 1) * sizeof(char)); + + if(a>1 && name[a-1]==delim) return a; + + while(a--) { + if( name[a]==delim ) { + left[a]= 0; + *nr= atol(name+a+1); + /* casting down to an int, can overflow for large numbers */ + if(*nr < 0) + *nr= 0; + return a; + } + if( isdigit(name[a])==0 ) break; + + left[a]= 0; + } + + for(a= 0; name[a]; a++) + left[a]= name[a]; + + return a; +} void BLI_newname(char *name, int add) { - char head[128], tail[128]; + char head[UNIQUE_NAME_MAX], tail[UNIQUE_NAME_MAX]; int pic; unsigned short digits; @@ -153,13 +195,43 @@ void BLI_newname(char *name, int add) BLI_stringenc(name, head, tail, digits, pic); } + + +int BLI_uniquename_cb(int (*unique_check)(void *, const char *), void *arg, const char defname[], char delim, char *name, short name_len) +{ + if(name == '\0') { + BLI_strncpy(name, defname, name_len); + } + + if(unique_check(arg, name)) { + char tempname[UNIQUE_NAME_MAX]; + char left[UNIQUE_NAME_MAX]; + int number; + int len= BLI_split_name_num(left, &number, name, delim); + do { + int newlen= BLI_snprintf(tempname, name_len, "%s%c%03d", left, delim, number); + if(newlen >= name_len) { + len -= ((newlen + 1) - name_len); + if(len < 0) len= number= 0; + left[len]= '\0'; + } + } while(number++, unique_check(arg, tempname)); + + BLI_strncpy(name, tempname, name_len); + + return 1; + } + + return 0; +} + /* little helper macro for BLI_uniquename */ #ifndef GIVE_STRADDR #define GIVE_STRADDR(data, offset) ( ((char *)data) + offset ) #endif /* Generic function to set a unique name. It is only designed to be used in situations - * where the name is part of the struct, and also that the name is at most 128 chars long. + * where the name is part of the struct, and also that the name is at most UNIQUE_NAME_MAX chars long. * * For places where this is used, see constraint.c for example... * @@ -168,65 +240,45 @@ void BLI_newname(char *name, int add) * defname: the name that should be used by default if none is specified already * delim: the character which acts as a delimeter between parts of the name */ -void BLI_uniquename(ListBase *list, void *vlink, const char defname[], char delim, short name_offs, short len) +static int uniquename_find_dupe(ListBase *list, void *vlink, const char *name, short name_offs) { Link *link; - char tempname[128]; - int number = 1, exists = 0; - char *dot; - - /* Make sure length can be handled */ - if ((len < 0) || (len > 128)) - return; - - /* See if we are given an empty string */ - if (ELEM(NULL, vlink, defname)) - return; - - if (GIVE_STRADDR(vlink, name_offs) == '\0') { - /* give it default name first */ - BLI_strncpy(GIVE_STRADDR(vlink, name_offs), defname, len); - } - - /* See if we even need to do this */ - if (list == NULL) - return; - + for (link = list->first; link; link= link->next) { if (link != vlink) { - if (!strcmp(GIVE_STRADDR(link, name_offs), GIVE_STRADDR(vlink, name_offs))) { - exists = 1; - break; + if (!strcmp(GIVE_STRADDR(link, name_offs), name)) { + return 1; } } } - if (exists == 0) + + return 0; +} + +static int uniquename_unique_check(void *arg, const char *name) +{ + struct {ListBase *lb; void *vlink; short name_offs;} *data= arg; + return uniquename_find_dupe(data->lb, data->vlink, name, data->name_offs); +} + +void BLI_uniquename(ListBase *list, void *vlink, const char defname[], char delim, short name_offs, short name_len) +{ + struct {ListBase *lb; void *vlink; short name_offs;} data; + data.lb= list; + data.vlink= vlink; + data.name_offs= name_offs; + + assert((name_len > 1) && (name_len <= UNIQUE_NAME_MAX)); + + /* See if we are given an empty string */ + if (ELEM(NULL, vlink, defname)) return; - /* Strip off the suffix */ - dot = strrchr(GIVE_STRADDR(vlink, name_offs), delim); - if (dot) - *dot=0; - - for (number = 1; number <= 999; number++) { - BLI_snprintf(tempname, sizeof(tempname), "%s%c%03d", GIVE_STRADDR(vlink, name_offs), delim, number); - - exists = 0; - for (link= list->first; link; link= link->next) { - if (vlink != link) { - if (!strcmp(GIVE_STRADDR(link, name_offs), tempname)) { - exists = 1; - break; - } - } - } - if (exists == 0) { - BLI_strncpy(GIVE_STRADDR(vlink, name_offs), tempname, len); - return; - } - } + BLI_uniquename_cb(uniquename_unique_check, &data, defname, delim, GIVE_STRADDR(vlink, name_offs), name_len); } + + /* ******************** string encoding ***************** */ /* This is quite an ugly function... its purpose is to @@ -311,10 +363,17 @@ void BLI_cleanup_file(const char *relabase, char *dir) dir[0]= '/'; dir[1]= 0; return; - } + } + + /* support for odd paths: eg /../home/me --> /home/me + * this is a valid path in blender but we cant handle this the useual way below + * simply strip this prefix then evaluate the path as useual. pythons os.path.normpath() does this */ + while((strncmp(dir, "/../", 4)==0)) { + memmove( dir, dir + 4, strlen(dir + 4) + 1 ); + } while ( (start = strstr(dir, "/../")) ) { - eind = start + strlen("/../") - 1; + eind = start + (4 - 1) /* strlen("/../") - 1 */; a = start-dir-1; while (a>0) { if (dir[a] == '/') break; @@ -328,12 +387,12 @@ void BLI_cleanup_file(const char *relabase, char *dir) } while ( (start = strstr(dir,"/./")) ){ - eind = start + strlen("/./") - 1; + eind = start + (3 - 1) /* strlen("/./") - 1 */; memmove( start, eind, strlen(eind)+1 ); } while ( (start = strstr(dir,"//" )) ){ - eind = start + strlen("//") - 1; + eind = start + (2 - 1) /* strlen("//") - 1 */; memmove( start, eind, strlen(eind)+1 ); } @@ -360,8 +419,8 @@ void BLI_path_rel(char *file, const char *relfile) /* also bail out if relative path is not set */ if (relfile[0] == 0) return; -#ifdef WIN32 - if (strlen(relfile) > 2 && relfile[1] != ':') { +#ifdef WIN32 + if (BLI_strnlen(relfile, 3) > 2 && relfile[1] != ':') { char* ptemp; /* fix missing volume name in relative base, can happen with old recent-files.txt files */ @@ -375,7 +434,7 @@ void BLI_path_rel(char *file, const char *relfile) BLI_strncpy(temp, relfile, FILE_MAXDIR + FILE_MAXFILE); } - if (strlen(file) > 2) { + if (BLI_strnlen(file, 3) > 2) { if ( temp[1] == ':' && file[1] == ':' && temp[0] != file[0] ) return; } @@ -400,7 +459,7 @@ void BLI_path_rel(char *file, const char *relfile) char *p= temp; char *q= file; - while ((*p == *q)) { + while (*p == *q) { ++p; ++q; /* dont search beyond the end of the string * in the rare case they match */ @@ -458,13 +517,9 @@ int BLI_has_parent(char *path) int BLI_parent_dir(char *path) { -#ifdef WIN32 - static char *parent_dir="..\\"; -#else - static char *parent_dir="../"; -#endif + static char parent_dir[]= {'.', '.', SEP, '\0'}; /* "../" or "..\\" */ char tmp[FILE_MAXDIR+FILE_MAXFILE+4]; - BLI_strncpy(tmp, path, sizeof(tmp)); + BLI_strncpy(tmp, path, sizeof(tmp)-4); BLI_add_slash(tmp); strcat(tmp, parent_dir); BLI_cleanup_dir(NULL, tmp); @@ -534,9 +589,20 @@ int BLI_path_frame(char *path, int frame, int digits) ensure_digits(path, digits); if (stringframe_chars(path, &ch_sta, &ch_end)) { /* warning, ch_end is the last # +1 */ - char tmp[FILE_MAX], format[64]; + char tmp[FILE_MAX]; +#if 0 // neat but breaks on non ascii strings. + char format[64]; sprintf(format, "%%.%ds%%.%dd%%s", ch_sta, ch_end-ch_sta); /* example result: "%.12s%.5d%s" */ sprintf(tmp, format, path, frame, path+ch_end); +#else + char format[8]; + char *p; + sprintf(format, "%%.%dd", ch_end-ch_sta); /* example result: "%.5d" */ + memcpy(tmp, path, sizeof(char) * ch_sta); + p= tmp + ch_sta; + p += sprintf(p, format, frame); + memcpy(p, path + ch_end, strlen(path + ch_end)); +#endif strcpy(path, tmp); return 1; } @@ -552,9 +618,18 @@ int BLI_path_frame_range(char *path, int sta, int end, int digits) if (stringframe_chars(path, &ch_sta, &ch_end)) { /* warning, ch_end is the last # +1 */ char tmp[FILE_MAX], format[64]; +#if 0 // neat but breaks on non ascii strings. sprintf(format, "%%.%ds%%.%dd_%%.%dd%%s", ch_sta, ch_end-ch_sta, ch_end-ch_sta); /* example result: "%.12s%.5d-%.5d%s" */ sprintf(tmp, format, path, sta, end, path+ch_end); strcpy(path, tmp); +#else + char *tmp_pt; + BLI_snprintf(format, sizeof(format), "%%.%dd-%%.%dd%%s", digits, digits); + memcpy(tmp, path, ch_sta * sizeof(char)); + tmp_pt = &tmp[ch_sta]; + tmp_pt += BLI_snprintf(tmp_pt, sizeof(tmp)-ch_sta, format, sta, end, &path[ch_end]); + memcpy(path, tmp, (int)(tmp_pt - tmp) + 1); +#endif return 1; } return 0; @@ -677,8 +752,8 @@ int BLI_path_cwd(char *path) #endif if (wasrelative==1) { - char cwd[FILE_MAXDIR + FILE_MAXFILE]; - BLI_getwdN(cwd); /* incase the full path to the blend isnt used */ + char cwd[FILE_MAXDIR + FILE_MAXFILE]= ""; + BLI_getwdN(cwd, sizeof(cwd)); /* incase the full path to the blend isnt used */ if (cwd[0] == '\0') { printf( "Could not get the current working directory - $PWD for an unknown reason."); @@ -782,11 +857,11 @@ static char *blender_version_decimal(void) return version_str; } -static int test_path(char *targetpath, char *path_base, char *path_sep, char *folder_name) +static int test_path(char *targetpath, const char *path_base, const char *path_sep, const char *folder_name) { char tmppath[FILE_MAX]; - if(path_sep) BLI_join_dirfile(tmppath, path_base, path_sep); + if(path_sep) BLI_join_dirfile(tmppath, sizeof(tmppath), path_base, path_sep); else BLI_strncpy(tmppath, path_base, sizeof(tmppath)); BLI_make_file_string("/", targetpath, tmppath, folder_name); @@ -806,7 +881,7 @@ static int test_path(char *targetpath, char *path_base, char *path_sep, char *fo } } -static int test_env_path(char *path, char *envvar) +static int test_env_path(char *path, const char *envvar) { char *env = envvar?getenv(envvar):NULL; if (!env) return 0; @@ -820,54 +895,32 @@ static int test_env_path(char *path, char *envvar) } } -static int get_path_local(char *targetpath, char *folder_name, char *subfolder_name) +static int get_path_local(char *targetpath, const char *folder_name, const char *subfolder_name) { - extern char bprogname[]; /* argv[0] from creator.c */ char bprogdir[FILE_MAX]; char relfolder[FILE_MAX]; - char cwd[FILE_MAX]; - char *s; - int i; #ifdef PATH_DEBUG2 printf("get_path_local...\n"); #endif if (subfolder_name) { - BLI_join_dirfile(relfolder, folder_name, subfolder_name); + BLI_join_dirfile(relfolder, sizeof(relfolder), folder_name, subfolder_name); } else { - BLI_strncpy(relfolder, folder_name, FILE_MAX); + BLI_strncpy(relfolder, folder_name, sizeof(relfolder)); } /* use argv[0] (bprogname) to get the path to the executable */ - s = BLI_last_slash(bprogname); - i = s - bprogname + 1; - BLI_strncpy(bprogdir, bprogname, i); - - /* try EXECUTABLE_DIR/folder_name */ - if(test_path(targetpath, bprogdir, "", relfolder)) - return 1; - - /* try CWD/release/folder_name */ - if(test_path(targetpath, BLI_getwdN(cwd), "release", relfolder)) - return 1; + BLI_split_dirfile(bprogname, bprogdir, NULL); - /* try EXECUTABLE_DIR/release/folder_name */ - if(test_path(targetpath, bprogdir, "release", relfolder)) - return 1; - - /* try EXECUTABLE_DIR/2.5/folder_name - new default directory for local blender installed files */ + /* try EXECUTABLE_DIR/2.5x/folder_name - new default directory for local blender installed files */ if(test_path(targetpath, bprogdir, blender_version_decimal(), relfolder)) return 1; - /* try ./.blender/folder_name -- DEPRECATED, need to update build systems */ - if(test_path(targetpath, bprogdir, ".blender", relfolder)) - return 1; - return 0; } -static int get_path_user(char *targetpath, char *folder_name, char *subfolder_name, char *envvar) +static int get_path_user(char *targetpath, const char *folder_name, const char *subfolder_name, const char *envvar) { char user_path[FILE_MAX]; const char *user_base_path; @@ -904,11 +957,41 @@ static int get_path_user(char *targetpath, char *folder_name, char *subfolder_na } } -static int get_path_system(char *targetpath, char *folder_name, char *subfolder_name, char *envvar) +static int get_path_system(char *targetpath, const char *folder_name, const char *subfolder_name, const char *envvar) { char system_path[FILE_MAX]; const char *system_base_path; + + /* first allow developer only overrides to the system path + * these are only used when running blender from source */ + char cwd[FILE_MAX]; + char relfolder[FILE_MAX]; + char bprogdir[FILE_MAX]; + + /* use argv[0] (bprogname) to get the path to the executable */ + BLI_split_dirfile(bprogname, bprogdir, NULL); + + if (subfolder_name) { + BLI_join_dirfile(relfolder, sizeof(relfolder), folder_name, subfolder_name); + } else { + BLI_strncpy(relfolder, folder_name, sizeof(relfolder)); + } + + /* try CWD/release/folder_name */ + if(BLI_getwdN(cwd, sizeof(cwd))) { + if(test_path(targetpath, cwd, "release", relfolder)) { + return 1; + } + } + + /* try EXECUTABLE_DIR/release/folder_name */ + if(test_path(targetpath, bprogdir, "release", relfolder)) + return 1; + /* end developer overrides */ + + + system_path[0] = '\0'; if (test_env_path(system_path, envvar)) { @@ -943,7 +1026,7 @@ static int get_path_system(char *targetpath, char *folder_name, char *subfolder_ /* get a folder out of the 'folder_id' presets for paths */ /* returns the path if found, NULL string if not */ -char *BLI_get_folder(int folder_id, char *subfolder) +char *BLI_get_folder(int folder_id, const char *subfolder) { static char path[FILE_MAX] = ""; @@ -1015,7 +1098,7 @@ char *BLI_get_folder(int folder_id, char *subfolder) return path; } -static char *BLI_get_user_folder_notest(int folder_id, char *subfolder) +char *BLI_get_user_folder_notest(int folder_id, const char *subfolder) { static char path[FILE_MAX] = ""; @@ -1029,6 +1112,9 @@ static char *BLI_get_user_folder_notest(int folder_id, char *subfolder) case BLENDER_USER_AUTOSAVE: get_path_user(path, "autosave", subfolder, "BLENDER_USER_AUTOSAVE"); break; + case BLENDER_USER_SCRIPTS: + get_path_user(path, "scripts", subfolder, "BLENDER_USER_SCRIPTS"); + break; } if ('\0' == path[0]) { return NULL; @@ -1036,12 +1122,12 @@ static char *BLI_get_user_folder_notest(int folder_id, char *subfolder) return path; } -char *BLI_get_folder_create(int folder_id, char *subfolder) +char *BLI_get_folder_create(int folder_id, const char *subfolder) { char *path; /* only for user folders */ - if (!ELEM3(folder_id, BLENDER_USER_DATAFILES, BLENDER_USER_CONFIG, BLENDER_USER_AUTOSAVE)) + if (!ELEM4(folder_id, BLENDER_USER_DATAFILES, BLENDER_USER_CONFIG, BLENDER_USER_SCRIPTS, BLENDER_USER_AUTOSAVE)) return NULL; path = BLI_get_folder(folder_id, subfolder); @@ -1099,8 +1185,9 @@ void BLI_setenv_if_new(const char *env, const char* val) void BLI_clean(char *path) { if(path==0) return; + #ifdef WIN32 - if(path && strlen(path)>2) { + if(path && BLI_strnlen(path, 3) > 2) { BLI_char_switch(path+2, '/', '\\'); } #else @@ -1120,45 +1207,31 @@ void BLI_char_switch(char *string, char from, char to) void BLI_make_exist(char *dir) { int a; - #ifdef WIN32 - BLI_char_switch(dir, '/', '\\'); - #else - BLI_char_switch(dir, '\\', '/'); - #endif - + BLI_char_switch(dir, ALTSEP, SEP); + a = strlen(dir); - -#ifdef WIN32 + while(BLI_is_dir(dir) == 0){ a --; - while(dir[a] != '\\'){ + while(dir[a] != SEP){ a--; if (a <= 0) break; } - if (a >= 0) dir[a+1] = 0; + if (a >= 0) { + dir[a+1] = '\0'; + } else { - /* defaulting to drive (usually 'C:') of Windows installation */ +#ifdef WIN32 get_default_root(dir); - break; - } - } #else - while(BLI_is_dir(dir) == 0){ - a --; - while(dir[a] != '/'){ - a--; - if (a <= 0) break; - } - if (a >= 0) dir[a+1] = 0; - else { strcpy(dir,"/"); +#endif break; } } -#endif } -void BLI_make_existing_file(char *name) +void BLI_make_existing_file(const char *name) { char di[FILE_MAXDIR+FILE_MAXFILE], fi[FILE_MAXFILE]; @@ -1196,15 +1269,14 @@ void BLI_make_file_string(const char *relabase, char *string, const char *dir, /* Get the file name, chop everything past the last slash (ie. the filename) */ strcpy(string, relabase); - lslash= (strrchr(string, '/')>strrchr(string, '\\'))?strrchr(string, '/'):strrchr(string, '\\'); - + lslash= BLI_last_slash(string); if(lslash) *(lslash+1)= 0; dir+=2; /* Skip over the relative reference */ } #ifdef WIN32 else { - if (strlen(dir) >= 2 && dir[1] == ':' ) { + if (BLI_strnlen(dir, 3) >= 2 && dir[1] == ':' ) { BLI_strncpy(string, dir, 3); dir += 2; } @@ -1250,10 +1322,10 @@ int BLI_testextensie(const char *str, const char *ext) { short a, b; int retval; - + a= strlen(str); b= strlen(ext); - + if(a==0 || b==0 || b>=a) { retval = 0; } else if (BLI_strcasecmp(ext, str + a - b)) { @@ -1261,7 +1333,7 @@ int BLI_testextensie(const char *str, const char *ext) } else { retval = 1; } - + return (retval); } @@ -1278,9 +1350,39 @@ int BLI_testextensie_array(const char *str, const char **ext_array) return 0; } +/* semicolon separated wildcards, eg: + * '*.zip;*.py;*.exe' */ +int BLI_testextensie_glob(const char *str, const char *ext_fnmatch) +{ + const char *ext_step= ext_fnmatch; + char pattern[16]; + + while(ext_step[0]) { + char *ext_next; + int len_ext; + + if((ext_next=strchr(ext_step, ';'))) { + len_ext= (int)(ext_next - ext_step) + 1; + } + else { + len_ext= sizeof(pattern); + } + + BLI_strncpy(pattern, ext_step, len_ext); + + if(fnmatch(pattern, str, FNM_CASEFOLD)==0) { + return 1; + } + ext_step += len_ext; + } + + return 0; +} + + int BLI_replace_extension(char *path, int maxlen, const char *ext) { - int a; + unsigned int a; for(a=strlen(path)-1; a>=0; a--) if(path[a] == '.' || path[a] == '/' || path[a] == '\\') @@ -1321,12 +1423,12 @@ void BLI_split_dirfile(const char *string, char *dir, char *file) } /* simple appending of filename to dir, does not check for valid path! */ -void BLI_join_dirfile(char *string, const char *dir, const char *file) +void BLI_join_dirfile(char *string, const int maxlen, const char *dir, const char *file) { int sl_dir; if(string != dir) /* compare pointers */ - BLI_strncpy(string, dir, FILE_MAX); + BLI_strncpy(string, dir, maxlen); if (!file) return; @@ -1334,7 +1436,7 @@ void BLI_join_dirfile(char *string, const char *dir, const char *file) sl_dir= BLI_add_slash(string); if (sl_dir <FILE_MAX) { - BLI_strncpy(string + sl_dir, file, FILE_MAX-sl_dir); + BLI_strncpy(string + sl_dir, file, maxlen - sl_dir); } } @@ -1409,21 +1511,21 @@ int BKE_rebase_path(char *abs, int abs_size, char *rel, int rel_size, const char /* if image is _in_ current .blend file directory */ if (!strcmp(dir, blend_dir)) { - BLI_join_dirfile(dest_path, dest_dir, base); + BLI_join_dirfile(dest_path, sizeof(dest_path), dest_dir, base); } /* "below" */ else { /* rel = image_path_dir - blend_dir */ BLI_strncpy(rel_dir, dir + len, sizeof(rel_dir)); - BLI_join_dirfile(dest_path, dest_dir, rel_dir); - BLI_join_dirfile(dest_path, dest_path, base); + BLI_join_dirfile(dest_path, sizeof(dest_path), dest_dir, rel_dir); + BLI_join_dirfile(dest_path, sizeof(dest_path), dest_path, base); } } /* image is out of current directory */ else { - BLI_join_dirfile(dest_path, dest_dir, base); + BLI_join_dirfile(dest_path, sizeof(dest_path), dest_dir, base); } if (abs) @@ -1443,6 +1545,67 @@ int BKE_rebase_path(char *abs, int abs_size, char *rel, int rel_size, const char return 1; } +char *BLI_first_slash(char *string) { + char *ffslash, *fbslash; + + ffslash= strchr(string, '/'); + fbslash= strchr(string, '\\'); + + if (!ffslash) return fbslash; + else if (!fbslash) return ffslash; + + if ((intptr_t)ffslash < (intptr_t)fbslash) return ffslash; + else return fbslash; +} + +char *BLI_last_slash(const char *string) { + char *lfslash, *lbslash; + + lfslash= strrchr(string, '/'); + lbslash= strrchr(string, '\\'); + + if (!lfslash) return lbslash; + else if (!lbslash) return lfslash; + + if ((intptr_t)lfslash < (intptr_t)lbslash) return lbslash; + else return lfslash; +} + +/* adds a slash if there isnt one there already */ +int BLI_add_slash(char *string) { + int len = strlen(string); +#ifdef WIN32 + if (len==0 || string[len-1]!='\\') { + string[len] = '\\'; + string[len+1] = '\0'; + return len+1; + } +#else + if (len==0 || string[len-1]!='/') { + string[len] = '/'; + string[len+1] = '\0'; + return len+1; + } +#endif + return len; +} + +/* removes a slash if there is one */ +void BLI_del_slash(char *string) { + int len = strlen(string); + while (len) { +#ifdef WIN32 + if (string[len-1]=='\\') { +#else + if (string[len-1]=='/') { +#endif + string[len-1] = '\0'; + len--; + } else { + break; + } + } +} static int add_win32_extension(char *name) { @@ -1485,54 +1648,54 @@ static int add_win32_extension(char *name) return (retval); } -void BLI_where_am_i(char *fullname, const char *name) +/* filename must be FILE_MAX length minimum */ +void BLI_where_am_i(char *fullname, const int maxlen, const char *name) { char filename[FILE_MAXDIR+FILE_MAXFILE]; char *path = NULL, *temp; - + #ifdef _WIN32 - char *separator = ";"; - char slash = '\\'; + const char *separator = ";"; #else - char *separator = ":"; - char slash = '/'; + const char *separator = ":"; #endif -#ifdef __linux__ +#ifdef WITH_BINRELOC /* linux uses binreloc since argv[0] is not relyable, call br_init( NULL ) first */ path = br_find_exe( NULL ); if (path) { - BLI_strncpy(fullname, path, FILE_MAXDIR+FILE_MAXFILE); + BLI_strncpy(fullname, path, maxlen); free(path); return; } #endif #ifdef _WIN32 - if(GetModuleFileName(0, fullname, FILE_MAXDIR+FILE_MAXFILE)) { - GetShortPathName(fullname, fullname, FILE_MAXDIR+FILE_MAXFILE); + if(GetModuleFileName(0, fullname, maxlen)) { + GetShortPathName(fullname, fullname, maxlen); return; } #endif /* unix and non linux */ - if (name && fullname && strlen(name)) { - strcpy(fullname, name); + if (name && name[0]) { + BLI_strncpy(fullname, name, maxlen); if (name[0] == '.') { - // relative path, prepend cwd - BLI_getwdN(fullname); - + char wdir[FILE_MAX]= ""; + BLI_getwdN(wdir, sizeof(wdir)); /* backup cwd to restore after */ + // not needed but avoids annoying /./ in name - if(name && name[0]=='.' && name[1]==slash) - BLI_join_dirfile(fullname, fullname, name+2); + if(name[1]==SEP) + BLI_join_dirfile(fullname, maxlen, wdir, name+2); else - BLI_join_dirfile(fullname, fullname, name); - - add_win32_extension(fullname); - } else if (BLI_last_slash(name)) { + BLI_join_dirfile(fullname, maxlen, wdir, name); + + add_win32_extension(fullname); /* XXX, doesnt respect length */ + } + else if (BLI_last_slash(name)) { // full path - strcpy(fullname, name); + BLI_strncpy(fullname, name, maxlen); add_win32_extension(fullname); } else { // search for binary in $PATH @@ -1547,15 +1710,15 @@ void BLI_where_am_i(char *fullname, const char *name) } else { strncpy(filename, path, sizeof(filename)); } - BLI_join_dirfile(fullname, fullname, name); + BLI_join_dirfile(fullname, maxlen, fullname, name); if (add_win32_extension(filename)) { - strcpy(fullname, filename); + BLI_strncpy(fullname, filename, maxlen); break; } } while (temp); } } -#ifndef NDEBUG +#if defined(DEBUG) if (strcmp(name, fullname)) { printf("guessing '%s' == '%s'\n", name, fullname); } @@ -1567,20 +1730,20 @@ void BLI_where_am_i(char *fullname, const char *name) // spaces and double-quotes. There's another solution to this // with spawnv(P_WAIT, bprogname, argv) instead of system() but // that's even uglier - GetShortPathName(fullname, fullname, FILE_MAXDIR+FILE_MAXFILE); -#ifndef NDEBUG + GetShortPathName(fullname, fullname, maxlen); +#if defined(DEBUG) printf("Shortname = '%s'\n", fullname); #endif #endif } } -void BLI_where_is_temp(char *fullname, int usertemp) +void BLI_where_is_temp(char *fullname, const int maxlen, int usertemp) { fullname[0] = '\0'; if (usertemp && BLI_is_dir(U.tempdir)) { - strcpy(fullname, U.tempdir); + BLI_strncpy(fullname, U.tempdir, maxlen); } @@ -1588,7 +1751,7 @@ void BLI_where_is_temp(char *fullname, int usertemp) if (fullname[0] == '\0') { char *tmp = getenv("TEMP"); /* Windows */ if (tmp && BLI_is_dir(tmp)) { - strcpy(fullname, tmp); + BLI_strncpy(fullname, tmp, maxlen); } } #else @@ -1596,28 +1759,32 @@ void BLI_where_is_temp(char *fullname, int usertemp) if (fullname[0] == '\0') { char *tmp = getenv("TMP"); if (tmp && BLI_is_dir(tmp)) { - strcpy(fullname, tmp); + BLI_strncpy(fullname, tmp, maxlen); } } if (fullname[0] == '\0') { char *tmp = getenv("TMPDIR"); if (tmp && BLI_is_dir(tmp)) { - strcpy(fullname, tmp); + BLI_strncpy(fullname, tmp, maxlen); } } #endif if (fullname[0] == '\0') { - strcpy(fullname, "/tmp/"); + BLI_strncpy(fullname, "/tmp/", maxlen); } else { /* add a trailing slash if needed */ BLI_add_slash(fullname); +#ifdef WIN32 + if(U.tempdir != fullname) { + BLI_strncpy(U.tempdir, fullname, maxlen); /* also set user pref to show %TEMP%. /tmp/ is just plain confusing for Windows users. */ + } +#endif } } char *get_install_dir(void) { - extern char bprogname[]; char *tmpname = BLI_strdup(bprogname); char *cut; |