4 * ***** BEGIN GPL LICENSE BLOCK *****
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version 2
9 * of the License, or (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software Foundation,
18 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
21 * All rights reserved.
23 * The Original Code is: all of this file.
25 * Contributor(s): none yet.
27 * ***** END GPL LICENSE BLOCK *****
29 * various string, file, list operations.
32 /** \file blender/blenlib/intern/path_util.c
42 #include "MEM_guardedalloc.h"
44 #include "DNA_listBase.h"
46 #include "BLI_fileops.h"
47 #include "BLI_path_util.h"
48 #include "BLI_string.h"
49 #include "BLI_storage.h"
50 #include "BLI_storage_types.h"
51 #include "BLI_utildefines.h"
53 #include "BKE_utildefines.h"
54 #include "BKE_blender.h" // BLENDER_VERSION
56 #include "GHOST_Path-api.h"
58 #if defined WIN32 && !defined _LIBC
59 # include "BLI_fnmatch.h" /* use fnmatch included in blenlib */
73 #define _WIN32_IE 0x0501
77 #include "BLI_winstuff.h"
79 #else /* non windows */
88 #define UNIQUE_NAME_MAX 128
90 static char bprogname[FILE_MAX]; /* path to program executable */
91 static char bprogdir[FILE_MAX]; /* path in which executable is located */
92 static char btempdir[FILE_MAX]; /* temporary directory */
94 static int add_win32_extension(char *name);
95 static char *blender_version_decimal(const int ver);
99 int BLI_stringdec(const char *string, char *head, char *tail, unsigned short *numlen)
101 unsigned short len, len2, lenlslash = 0, nums = 0, nume = 0;
103 char *lslash = BLI_last_slash(string);
104 len2 = len = strlen(string);
106 lenlslash= (int)(lslash - string);
108 while(len > lenlslash && string[--len] != '.') {};
109 if(len == lenlslash && string[len] != '.') len = len2;
111 for (i = len - 1; i >= lenlslash; i--) {
112 if (isdigit(string[i])) {
127 if (tail) strcpy(tail, &string[nume+1]);
132 if (numlen) *numlen = nume-nums+1;
133 return ((int)atoi(&(string[nums])));
135 if (tail) strcpy(tail, string + len);
137 strncpy(head, string, len);
140 if (numlen) *numlen=0;
145 void BLI_stringenc(char *string, const char *head, const char *tail, unsigned short numlen, int pic)
149 sprintf(fmtstr, "%%s%%.%dd%%s", numlen);
150 sprintf(string, fmtstr, head, pic, tail);
153 /* Foo.001 -> "Foo", 1
154 * Returns the length of "Foo" */
155 int BLI_split_name_num(char *left, int *nr, const char *name, const char delim)
161 memcpy(left, name, (a + 1) * sizeof(char));
163 if(a>1 && name[a-1]==delim) return a;
166 if( name[a]==delim ) {
169 /* casting down to an int, can overflow for large numbers */
174 if( isdigit(name[a])==0 ) break;
179 for(a= 0; name[a]; a++)
185 void BLI_newname(char *name, int add)
187 char head[UNIQUE_NAME_MAX], tail[UNIQUE_NAME_MAX];
189 unsigned short digits;
191 pic = BLI_stringdec(name, head, tail, &digits);
193 /* are we going from 100 -> 99 or from 10 -> 9 */
194 if (add < 0 && digits < 4 && digits > 0) {
197 for (i = digits; i > 1; i--) exp *= 10;
198 if (pic >= exp && (pic + add) < exp) digits--;
203 if (digits==4 && pic<0) pic= 0;
204 BLI_stringenc(name, head, tail, digits, pic);
209 int BLI_uniquename_cb(int (*unique_check)(void *, const char *), void *arg, const char defname[], char delim, char *name, short name_len)
211 if(name[0] == '\0') {
212 BLI_strncpy(name, defname, name_len);
215 if(unique_check(arg, name)) {
216 char tempname[UNIQUE_NAME_MAX];
217 char left[UNIQUE_NAME_MAX];
219 int len= BLI_split_name_num(left, &number, name, delim);
221 int newlen= BLI_snprintf(tempname, name_len, "%s%c%03d", left, delim, ++number);
222 if(newlen >= name_len) {
223 len -= ((newlen + 1) - name_len);
224 if(len < 0) len= number= 0;
227 } while(unique_check(arg, tempname));
229 BLI_strncpy(name, tempname, name_len);
237 /* little helper macro for BLI_uniquename */
239 #define GIVE_STRADDR(data, offset) ( ((char *)data) + offset )
242 /* Generic function to set a unique name. It is only designed to be used in situations
243 * where the name is part of the struct, and also that the name is at most UNIQUE_NAME_MAX chars long.
245 * For places where this is used, see constraint.c for example...
247 * name_offs: should be calculated using offsetof(structname, membername) macro from stddef.h
248 * len: maximum length of string (to prevent overflows, etc.)
249 * defname: the name that should be used by default if none is specified already
250 * delim: the character which acts as a delimeter between parts of the name
252 static int uniquename_find_dupe(ListBase *list, void *vlink, const char *name, short name_offs)
256 for (link = list->first; link; link= link->next) {
258 if (!strcmp(GIVE_STRADDR(link, name_offs), name)) {
267 static int uniquename_unique_check(void *arg, const char *name)
269 struct {ListBase *lb; void *vlink; short name_offs;} *data= arg;
270 return uniquename_find_dupe(data->lb, data->vlink, name, data->name_offs);
273 void BLI_uniquename(ListBase *list, void *vlink, const char defname[], char delim, short name_offs, short name_len)
275 struct {ListBase *lb; void *vlink; short name_offs;} data;
278 data.name_offs= name_offs;
280 assert((name_len > 1) && (name_len <= UNIQUE_NAME_MAX));
282 /* See if we are given an empty string */
283 if (ELEM(NULL, vlink, defname))
286 BLI_uniquename_cb(uniquename_unique_check, &data, defname, delim, GIVE_STRADDR(vlink, name_offs), name_len);
291 /* ******************** string encoding ***************** */
293 /* This is quite an ugly function... its purpose is to
294 * take the dir name, make it absolute, and clean it up, replacing
295 * excess file entry stuff (like /tmp/../tmp/../)
296 * note that dir isn't protected for max string names...
298 * If relbase is NULL then its ignored
301 void BLI_cleanup_path(const char *relabase, char *dir)
306 BLI_path_abs(dir, relabase);
308 if (dir[0]=='/' && dir[1]=='/') {
310 return; /* path is "//" - cant clean it */
312 dir = dir+2; /* skip the first // */
317 * memmove( start, eind, strlen(eind)+1 );
319 * strcpy( start, eind );
320 * except strcpy should not be used because there is overlap,
321 * so use memmove's slightly more obscure syntax - Campbell
326 /* Note, this should really be moved to the file selector,
327 * since this function is used in many areas */
328 if(strcmp(dir, ".")==0) { /* happens for example in FILE_MAIN */
329 get_default_root(dir);
333 while ( (start = strstr(dir, "\\..\\")) ) {
334 eind = start + strlen("\\..\\") - 1;
337 if (dir[a] == '\\') break;
343 memmove( dir+a, eind, strlen(eind)+1 );
347 while ( (start = strstr(dir,"\\.\\")) ){
348 eind = start + strlen("\\.\\") - 1;
349 memmove( start, eind, strlen(eind)+1 );
352 while ( (start = strstr(dir,"\\\\" )) ){
353 eind = start + strlen("\\\\") - 1;
354 memmove( start, eind, strlen(eind)+1 );
357 if(dir[0]=='.') { /* happens, for example in FILE_MAIN */
363 /* support for odd paths: eg /../home/me --> /home/me
364 * this is a valid path in blender but we cant handle this the useual way below
365 * simply strip this prefix then evaluate the path as useual. pythons os.path.normpath() does this */
366 while((strncmp(dir, "/../", 4)==0)) {
367 memmove( dir, dir + 4, strlen(dir + 4) + 1 );
370 while ( (start = strstr(dir, "/../")) ) {
371 eind = start + (4 - 1) /* strlen("/../") - 1 */;
374 if (dir[a] == '/') break;
380 memmove( dir+a, eind, strlen(eind)+1 );
384 while ( (start = strstr(dir,"/./")) ){
385 eind = start + (3 - 1) /* strlen("/./") - 1 */;
386 memmove( start, eind, strlen(eind)+1 );
389 while ( (start = strstr(dir,"//" )) ){
390 eind = start + (2 - 1) /* strlen("//") - 1 */;
391 memmove( start, eind, strlen(eind)+1 );
396 void BLI_cleanup_dir(const char *relabase, char *dir)
398 BLI_cleanup_path(relabase, dir);
403 void BLI_cleanup_file(const char *relabase, char *dir)
405 BLI_cleanup_path(relabase, dir);
409 void BLI_path_rel(char *file, const char *relfile)
412 char temp[FILE_MAXDIR+FILE_MAXFILE];
413 char res[FILE_MAXDIR+FILE_MAXFILE];
415 /* if file is already relative, bail out */
416 if(file[0]=='/' && file[1]=='/') return;
418 /* also bail out if relative path is not set */
419 if (relfile[0] == 0) return;
422 if (BLI_strnlen(relfile, 3) > 2 && relfile[1] != ':') {
424 /* fix missing volume name in relative base,
425 can happen with old recent-files.txt files */
426 get_default_root(temp);
428 if (relfile[0] != '\\' && relfile[0] != '/') {
431 BLI_strncpy(ptemp, relfile, FILE_MAXDIR + FILE_MAXFILE-3);
433 BLI_strncpy(temp, relfile, FILE_MAXDIR + FILE_MAXFILE);
436 if (BLI_strnlen(file, 3) > 2) {
437 if ( temp[1] == ':' && file[1] == ':' && temp[0] != file[0] )
441 BLI_strncpy(temp, relfile, FILE_MAX);
444 BLI_char_switch(temp, '\\', '/');
445 BLI_char_switch(file, '\\', '/');
447 /* remove /./ which confuse the following slash counting... */
448 BLI_cleanup_path(NULL, file);
449 BLI_cleanup_path(NULL, temp);
451 /* the last slash in the file indicates where the path part ends */
452 lslash = BLI_last_slash(temp);
456 /* find the prefix of the filename that is equal for both filenames.
457 This is replaced by the two slashes at the beginning */
462 while (tolower(*p) == tolower(*q))
468 /* dont search beyond the end of the string
469 * in the rare case they match */
470 if ((*p=='\0') || (*q=='\0')) {
475 /* we might have passed the slash when the beginning of a dir matches
476 so we rewind. Only check on the actual filename
479 while ( (q >= file) && (*q != '/') ) { --q; --p; }
481 else if (*p != '/') {
482 while ( (p >= temp) && (*p != '/') ) { --p; --q; }
487 /* p now points to the slash that is at the beginning of the part
488 where the path is different from the relative path.
489 We count the number of directories we need to go up in the
490 hierarchy to arrive at the common 'prefix' of the path
492 while (p && p < lslash) {
498 strcat(res, q+1); /* don't copy the slash at the beginning */
501 BLI_char_switch(res+2, '/', '\\');
507 int BLI_has_parent(char *path)
512 len = BLI_add_slash(path) - 1;
515 if ((path[len] == '\\') || (path[len] == '/'))
522 int BLI_parent_dir(char *path)
524 static char parent_dir[]= {'.', '.', SEP, '\0'}; /* "../" or "..\\" */
525 char tmp[FILE_MAXDIR+FILE_MAXFILE+4];
526 BLI_strncpy(tmp, path, sizeof(tmp)-4);
528 strcat(tmp, parent_dir);
529 BLI_cleanup_dir(NULL, tmp);
531 if (!BLI_testextensie(tmp, parent_dir)) {
532 BLI_strncpy(path, tmp, sizeof(tmp));
539 static int stringframe_chars(char *path, int *char_start, int *char_end)
541 int ch_sta, ch_end, i;
542 /* Insert current frame: file### -> file001 */
544 for (i = 0; path[i] != '\0'; i++) {
545 if (path[i] == '\\' || path[i] == '/') {
546 ch_end = 0; /* this is a directory name, dont use any hashes we found */
547 } else if (path[i] == '#') {
550 while (path[ch_end] == '#') {
553 i = ch_end-1; /* keep searching */
555 /* dont break, there may be a slash after this that invalidates the previous #'s */
571 static void ensure_digits(char *path, int digits)
573 char *file= BLI_last_slash(path);
578 if(strrchr(file, '#') == NULL) {
579 int len= strlen(file);
588 int BLI_path_frame(char *path, int frame, int digits)
593 ensure_digits(path, digits);
595 if (stringframe_chars(path, &ch_sta, &ch_end)) { /* warning, ch_end is the last # +1 */
597 sprintf(tmp, "%.*s%.*d%s", ch_sta, path, ch_end-ch_sta, frame, path+ch_end);
604 int BLI_path_frame_range(char *path, int sta, int end, int digits)
609 ensure_digits(path, digits);
611 if (stringframe_chars(path, &ch_sta, &ch_end)) { /* warning, ch_end is the last # +1 */
613 sprintf(tmp, "%.*s%.*d-%.*d%s", ch_sta, path, ch_end-ch_sta, sta, ch_end-ch_sta, end, path+ch_end);
620 int BLI_path_abs(char *path, const char *basepath)
622 int wasrelative = (strncmp(path, "//", 2)==0);
626 char vol[3] = {'\0', '\0', '\0'};
628 BLI_strncpy(vol, path, 3);
629 /* we are checking here if we have an absolute path that is not in the current
630 blend file as a lib main - we are basically checking for the case that a
631 UNIX root '/' is passed.
633 if (!wasrelative && (vol[1] != ':' && (vol[0] == '\0' || vol[0] == '/' || vol[0] == '\\'))) {
635 get_default_root(tmp);
636 // get rid of the slashes at the beginning of the path
637 while (*p == '\\' || *p == '/') {
643 BLI_strncpy(tmp, path, FILE_MAX);
646 BLI_strncpy(tmp, path, sizeof(tmp));
648 /* Check for loading a windows path on a posix system
649 * in this case, there is no use in trying C:/ since it
650 * will never exist on a unix os.
652 * Add a / prefix and lowercase the driveletter, remove the :
653 * C:\foo.JPG -> /c/foo.JPG */
655 if (isalpha(tmp[0]) && tmp[1] == ':' && (tmp[2]=='\\' || tmp[2]=='/') ) {
656 tmp[1] = tolower(tmp[0]); /* replace ':' with driveletter */
658 /* '\' the slash will be converted later */
663 BLI_strncpy(base, basepath, sizeof(base));
665 /* file component is ignored, so dont bother with the trailing slash */
666 BLI_cleanup_path(NULL, base);
668 /* push slashes into unix mode - strings entering this part are
669 potentially messed up: having both back- and forward slashes.
670 Here we push into one conform direction, and at the end we
671 push them into the system specific dir. This ensures uniformity
672 of paths and solving some problems (and prevent potential future
673 ones) -jesterKing. */
674 BLI_char_switch(tmp, '\\', '/');
675 BLI_char_switch(base, '\\', '/');
677 /* Paths starting with // will get the blend file as their base,
678 * this isnt standard in any os but is uesed in blender all over the place */
680 char *lslash= BLI_last_slash(base);
682 int baselen= (int) (lslash-base) + 1;
683 /* use path for temp storage here, we copy back over it right away */
684 BLI_strncpy(path, tmp+2, FILE_MAX);
686 memcpy(tmp, base, baselen);
687 BLI_strncpy(tmp+baselen, path, sizeof(tmp)-baselen);
688 BLI_strncpy(path, tmp, FILE_MAX);
690 BLI_strncpy(path, tmp+2, FILE_MAX);
693 BLI_strncpy(path, tmp, FILE_MAX);
696 BLI_cleanup_path(NULL, path);
699 /* skip first two chars, which in case of
700 absolute path will be drive:/blabla and
701 in case of relpath //blabla/. So relpath
702 // will be retained, rest will be nice and
703 shiny win32 backward slashes :) -jesterKing
705 BLI_char_switch(path+2, '/', '\\');
713 * Should only be done with command line paths.
714 * this is NOT somthing blenders internal paths support like the // prefix
716 int BLI_path_cwd(char *path)
719 int filelen = strlen(path);
722 if (filelen >= 3 && path[1] == ':' && (path[2] == '\\' || path[2] == '/'))
725 if (filelen >= 2 && path[0] == '/')
729 if (wasrelative==1) {
730 char cwd[FILE_MAXDIR + FILE_MAXFILE]= "";
731 BLI_getwdN(cwd, sizeof(cwd)); /* incase the full path to the blend isnt used */
733 if (cwd[0] == '\0') {
734 printf( "Could not get the current working directory - $PWD for an unknown reason.");
736 /* uses the blend path relative to cwd important for loading relative linked files.
738 * cwd should contain c:\ etc on win32 so the relbase can be NULL
739 * relbase being NULL also prevents // being misunderstood as relative to the current
740 * blend file which isnt a feature we want to use in this case since were dealing
741 * with a path from the command line, rather than from inside Blender */
743 char origpath[FILE_MAXDIR + FILE_MAXFILE];
744 BLI_strncpy(origpath, path, FILE_MAXDIR + FILE_MAXFILE);
746 BLI_make_file_string(NULL, path, cwd, origpath);
754 /* 'di's filename component is moved into 'fi', di is made a dir path */
755 void BLI_splitdirstring(char *di, char *fi)
757 char *lslash= BLI_last_slash(di);
760 BLI_strncpy(fi, lslash+1, FILE_MAXFILE);
763 BLI_strncpy(fi, di, FILE_MAXFILE);
768 void BLI_getlastdir(const char* dir, char *last, const size_t maxlen)
771 const char *lslash = NULL;
772 const char *prevslash = NULL;
774 if ((*s == '\\') || (*s == '/')) {
781 BLI_strncpy(last, prevslash+1, maxlen);
783 BLI_strncpy(last, dir, maxlen);
787 /* This is now only used to really get the user's default document folder */
788 /* On Windows I chose the 'Users/<MyUserName>/Documents' since it's used
789 as default location to save documents */
790 const char *BLI_getDefaultDocumentFolder(void)
793 return getenv("HOME");
797 static char documentfolder[MAXPATHLEN];
800 /* Check for %HOME% env var */
802 ret = getenv("HOME");
804 if (BLI_is_dir(ret)) return ret;
807 /* add user profile support for WIN 2K / NT.
808 * This is %APPDATA%, which translates to either
809 * %USERPROFILE%\Application Data or since Vista
810 * to %USERPROFILE%\AppData\Roaming
812 hResult = SHGetFolderPath(NULL, CSIDL_PERSONAL, NULL, SHGFP_TYPE_CURRENT, documentfolder);
816 if (BLI_is_dir(documentfolder)) return documentfolder;
823 /* NEW stuff, to be cleaned up when fully migrated */
824 /* ************************************************************* */
825 /* ************************************************************* */
827 // #define PATH_DEBUG2
829 static char *blender_version_decimal(const int ver)
831 static char version_str[5];
832 sprintf(version_str, "%d.%02d", ver/100, ver%100);
836 static int test_path(char *targetpath, const char *path_base, const char *path_sep, const char *folder_name)
838 char tmppath[FILE_MAX];
840 if(path_sep) BLI_join_dirfile(tmppath, sizeof(tmppath), path_base, path_sep);
841 else BLI_strncpy(tmppath, path_base, sizeof(tmppath));
843 /* rare cases folder_name is omitted (when looking for ~/.blender/2.xx dir only) */
845 BLI_make_file_string("/", targetpath, tmppath, folder_name);
847 BLI_strncpy(targetpath, tmppath, sizeof(tmppath));
849 if (BLI_is_dir(targetpath)) {
851 printf("\tpath found: %s\n", targetpath);
857 printf("\tpath missing: %s\n", targetpath);
859 //targetpath[0] = '\0';
864 static int test_env_path(char *path, const char *envvar)
866 const char *env = envvar?getenv(envvar):NULL;
869 if (BLI_is_dir(env)) {
870 BLI_strncpy(path, env, FILE_MAX);
878 static int get_path_local(char *targetpath, const char *folder_name, const char *subfolder_name, const int ver)
880 char relfolder[FILE_MAX];
883 printf("get_path_local...\n");
887 if (subfolder_name) {
888 BLI_join_dirfile(relfolder, sizeof(relfolder), folder_name, subfolder_name);
890 BLI_strncpy(relfolder, folder_name, sizeof(relfolder));
897 /* try EXECUTABLE_DIR/2.5x/folder_name - new default directory for local blender installed files */
898 if(test_path(targetpath, bprogdir, blender_version_decimal(ver), relfolder))
904 static int is_portable_install(void)
906 /* detect portable install by the existance of config folder */
907 const int ver= BLENDER_VERSION;
910 return get_path_local(path, "config", NULL, ver);
913 static int get_path_user(char *targetpath, const char *folder_name, const char *subfolder_name, const char *envvar, const int ver)
915 char user_path[FILE_MAX];
916 const char *user_base_path;
918 /* for portable install, user path is always local */
919 if (is_portable_install())
920 return get_path_local(targetpath, folder_name, subfolder_name, ver);
924 if (test_env_path(user_path, envvar)) {
925 if (subfolder_name) {
926 return test_path(targetpath, user_path, NULL, subfolder_name);
928 BLI_strncpy(targetpath, user_path, FILE_MAX);
933 user_base_path = (const char *)GHOST_getUserDir();
934 if (user_base_path) {
935 BLI_snprintf(user_path, FILE_MAX, BLENDER_USER_FORMAT, user_base_path, blender_version_decimal(ver));
942 printf("get_path_user: %s\n", user_path);
945 if (subfolder_name) {
946 /* try $HOME/folder_name/subfolder_name */
947 return test_path(targetpath, user_path, folder_name, subfolder_name);
949 /* try $HOME/folder_name */
950 return test_path(targetpath, user_path, NULL, folder_name);
954 static int get_path_system(char *targetpath, const char *folder_name, const char *subfolder_name, const char *envvar, const int ver)
956 char system_path[FILE_MAX];
957 const char *system_base_path;
960 /* first allow developer only overrides to the system path
961 * these are only used when running blender from source */
963 char relfolder[FILE_MAX];
966 if (subfolder_name) {
967 BLI_join_dirfile(relfolder, sizeof(relfolder), folder_name, subfolder_name);
969 BLI_strncpy(relfolder, folder_name, sizeof(relfolder));
976 /* try CWD/release/folder_name */
977 if(BLI_getwdN(cwd, sizeof(cwd))) {
978 if(test_path(targetpath, cwd, "release", relfolder)) {
983 /* try EXECUTABLE_DIR/release/folder_name */
984 if(test_path(targetpath, bprogdir, "release", relfolder))
986 /* end developer overrides */
990 system_path[0] = '\0';
992 if (test_env_path(system_path, envvar)) {
993 if (subfolder_name) {
994 return test_path(targetpath, system_path, NULL, subfolder_name);
996 BLI_strncpy(targetpath, system_path, FILE_MAX);
1001 system_base_path = (const char *)GHOST_getSystemDir();
1002 if (system_base_path) {
1003 BLI_snprintf(system_path, FILE_MAX, BLENDER_SYSTEM_FORMAT, system_base_path, blender_version_decimal(ver));
1010 printf("get_path_system: %s\n", system_path);
1013 if (subfolder_name) {
1014 /* try $BLENDERPATH/folder_name/subfolder_name */
1015 return test_path(targetpath, system_path, folder_name, subfolder_name);
1017 /* try $BLENDERPATH/folder_name */
1018 return test_path(targetpath, system_path, NULL, folder_name);
1022 /* get a folder out of the 'folder_id' presets for paths */
1023 /* returns the path if found, NULL string if not */
1024 char *BLI_get_folder(int folder_id, const char *subfolder)
1026 const int ver= BLENDER_VERSION;
1027 static char path[FILE_MAX] = "";
1029 switch (folder_id) {
1030 case BLENDER_DATAFILES: /* general case */
1031 if (get_path_user(path, "datafiles", subfolder, "BLENDER_USER_DATAFILES", ver)) break;
1032 if (get_path_local(path, "datafiles", subfolder, ver)) break;
1033 if (get_path_system(path, "datafiles", subfolder, "BLENDER_SYSTEM_DATAFILES", ver)) break;
1036 case BLENDER_USER_DATAFILES:
1037 if (get_path_user(path, "datafiles", subfolder, "BLENDER_USER_DATAFILES", ver)) break;
1040 case BLENDER_SYSTEM_DATAFILES:
1041 if (get_path_local(path, "datafiles", subfolder, ver)) break;
1042 if (get_path_system(path, "datafiles", subfolder, "BLENDER_SYSTEM_DATAFILES", ver)) break;
1045 case BLENDER_USER_AUTOSAVE:
1046 if (get_path_user(path, "autosave", subfolder, "BLENDER_USER_DATAFILES", ver)) break;
1049 case BLENDER_USER_CONFIG:
1050 if (get_path_user(path, "config", subfolder, "BLENDER_USER_CONFIG", ver)) break;
1053 case BLENDER_USER_SCRIPTS:
1054 if (get_path_user(path, "scripts", subfolder, "BLENDER_USER_SCRIPTS", ver)) break;
1057 case BLENDER_SYSTEM_SCRIPTS:
1058 if (get_path_local(path, "scripts", subfolder, ver)) break;
1059 if (get_path_system(path, "scripts", subfolder, "BLENDER_SYSTEM_SCRIPTS", ver)) break;
1062 case BLENDER_SYSTEM_PYTHON:
1063 if (get_path_local(path, "python", subfolder, ver)) break;
1064 if (get_path_system(path, "python", subfolder, "BLENDER_SYSTEM_PYTHON", ver)) break;
1071 char *BLI_get_user_folder_notest(int folder_id, const char *subfolder)
1073 const int ver= BLENDER_VERSION;
1074 static char path[FILE_MAX] = "";
1076 switch (folder_id) {
1077 case BLENDER_USER_DATAFILES:
1078 get_path_user(path, "datafiles", subfolder, "BLENDER_USER_DATAFILES", ver);
1080 case BLENDER_USER_CONFIG:
1081 get_path_user(path, "config", subfolder, "BLENDER_USER_CONFIG", ver);
1083 case BLENDER_USER_AUTOSAVE:
1084 get_path_user(path, "autosave", subfolder, "BLENDER_USER_AUTOSAVE", ver);
1086 case BLENDER_USER_SCRIPTS:
1087 get_path_user(path, "scripts", subfolder, "BLENDER_USER_SCRIPTS", ver);
1090 if ('\0' == path[0]) {
1096 char *BLI_get_folder_create(int folder_id, const char *subfolder)
1100 /* only for user folders */
1101 if (!ELEM4(folder_id, BLENDER_USER_DATAFILES, BLENDER_USER_CONFIG, BLENDER_USER_SCRIPTS, BLENDER_USER_AUTOSAVE))
1104 path = BLI_get_folder(folder_id, subfolder);
1107 path = BLI_get_user_folder_notest(folder_id, subfolder);
1108 if (path) BLI_recurdir_fileops(path);
1114 char *BLI_get_folder_version(const int id, const int ver, const int do_check)
1116 static char path[FILE_MAX] = "";
1119 case BLENDER_RESOURCE_PATH_USER:
1120 ok= get_path_user(path, NULL, NULL, NULL, ver);
1122 case BLENDER_RESOURCE_PATH_LOCAL:
1123 ok= get_path_local(path, NULL, NULL, ver);
1125 case BLENDER_RESOURCE_PATH_SYSTEM:
1126 ok= get_path_system(path, NULL, NULL, NULL, ver);
1129 path[0]= '\0'; /* incase do_check is false */
1131 BLI_assert(!"incorrect ID");
1134 if((ok == FALSE) && do_check) {
1142 /* ************************************************************* */
1143 /* ************************************************************* */
1151 void BLI_setenv(const char *env, const char*val)
1154 #if (defined(WIN32) || defined(WIN64)) && defined(FREE_WINDOWS)
1155 char *envstr= MEM_mallocN(sizeof(char) * (strlen(env) + strlen(val) + 2), "envstr"); /* one for = another for \0 */
1157 sprintf(envstr, "%s=%s", env, val);
1161 /* non-free windows */
1162 #elif (defined(WIN32) || defined(WIN64)) /* not free windows */
1163 _putenv_s(env, val);
1166 setenv(env, val, 1);
1172 Only set an env var if already not there.
1173 Like Unix setenv(env, val, 0);
1175 void BLI_setenv_if_new(const char *env, const char* val)
1177 if(getenv(env) == NULL)
1178 BLI_setenv(env, val);
1182 void BLI_clean(char *path)
1184 if(path==NULL) return;
1187 if(path && BLI_strnlen(path, 3) > 2) {
1188 BLI_char_switch(path+2, '/', '\\');
1191 BLI_char_switch(path, '\\', '/');
1195 void BLI_char_switch(char *string, char from, char to)
1197 if(string==NULL) return;
1198 while (*string != 0) {
1199 if (*string == from) *string = to;
1204 void BLI_make_exist(char *dir)
1208 BLI_char_switch(dir, ALTSEP, SEP);
1212 while(BLI_is_dir(dir) == 0){
1214 while(dir[a] != SEP){
1223 get_default_root(dir);
1232 void BLI_make_existing_file(const char *name)
1234 char di[FILE_MAXDIR+FILE_MAXFILE], fi[FILE_MAXFILE];
1236 BLI_strncpy(di, name, sizeof(di));
1237 BLI_splitdirstring(di, fi);
1240 if (BLI_exists(di) == 0) {
1241 BLI_recurdir_fileops(di);
1246 void BLI_make_file_string(const char *relabase, char *string, const char *dir, const char *file)
1250 if (!string || !dir || !file) return; /* We don't want any NULLs */
1252 string[0]= 0; /* ton */
1254 /* we first push all slashes into unix mode, just to make sure we don't get
1255 any mess with slashes later on. -jesterKing */
1256 /* constant strings can be passed for those parameters - don't change them - elubie */
1258 BLI_char_switch(relabase, '\\', '/');
1259 BLI_char_switch(dir, '\\', '/');
1260 BLI_char_switch(file, '\\', '/');
1263 /* Resolve relative references */
1264 if (relabase && dir[0] == '/' && dir[1] == '/') {
1267 /* Get the file name, chop everything past the last slash (ie. the filename) */
1268 strcpy(string, relabase);
1270 lslash= BLI_last_slash(string);
1271 if(lslash) *(lslash+1)= 0;
1273 dir+=2; /* Skip over the relative reference */
1277 if (BLI_strnlen(dir, 3) >= 2 && dir[1] == ':' ) {
1278 BLI_strncpy(string, dir, 3);
1281 else { /* no drive specified */
1282 /* first option: get the drive from the relabase if it has one */
1283 if (relabase && strlen(relabase) >= 2 && relabase[1] == ':' ) {
1284 BLI_strncpy(string, relabase, 3);
1288 else { /* we're out of luck here, guessing the first valid drive, usually c:\ */
1289 get_default_root(string);
1292 /* ignore leading slashes */
1293 while (*dir == '/' || *dir == '\\') dir++;
1298 strcat(string, dir);
1300 /* Make sure string ends in one (and only one) slash */
1301 /* first trim all slashes from the end of the string */
1302 sl = strlen(string);
1303 while (sl>0 && ( string[sl-1] == '/' || string[sl-1] == '\\') ) {
1304 string[sl-1] = '\0';
1307 /* since we've now removed all slashes, put back one slash at the end. */
1308 strcat(string, "/");
1310 while (*file && (*file == '/' || *file == '\\')) /* Trim slashes from the front of file */
1313 strcat (string, file);
1315 /* Push all slashes to the system preferred direction */
1319 int BLI_testextensie(const char *str, const char *ext)
1327 if(a==0 || b==0 || b>=a) {
1329 } else if (BLI_strcasecmp(ext, str + a - b)) {
1338 int BLI_testextensie_array(const char *str, const char **ext_array)
1341 while(ext_array[i]) {
1342 if(BLI_testextensie(str, ext_array[i])) {
1351 /* semicolon separated wildcards, eg:
1352 * '*.zip;*.py;*.exe' */
1353 int BLI_testextensie_glob(const char *str, const char *ext_fnmatch)
1355 const char *ext_step= ext_fnmatch;
1358 while(ext_step[0]) {
1362 if((ext_next=strchr(ext_step, ';'))) {
1363 len_ext= (int)(ext_next - ext_step) + 1;
1366 len_ext= sizeof(pattern);
1369 BLI_strncpy(pattern, ext_step, len_ext);
1371 if(fnmatch(pattern, str, FNM_CASEFOLD)==0) {
1374 ext_step += len_ext;
1381 int BLI_replace_extension(char *path, size_t maxlen, const char *ext)
1385 for(a=strlen(path); a>0; a--) {
1386 if(path[a-1] == '.' || path[a-1] == '/' || path[a-1] == '\\') {
1395 if(a + strlen(ext) >= maxlen)
1398 strcpy(path+a, ext);
1402 /* Converts "/foo/bar.txt" to "/foo/" and "bar.txt"
1403 * - wont change 'string'
1404 * - wont create any directories
1405 * - dosnt use CWD, or deal with relative paths.
1406 * - Only fill's in *dir and *file when they are non NULL
1408 void BLI_split_dirfile(const char *string, char *dir, char *file, const size_t dirlen, const size_t filelen)
1410 char *lslash_str = BLI_last_slash(string);
1411 size_t lslash= lslash_str ? (size_t)(lslash_str - string) + 1 : 0;
1415 BLI_strncpy( dir, string, MIN2(dirlen, lslash + 1)); /* +1 to include the slash and the last char */
1423 BLI_strncpy(file, string+lslash, filelen);
1427 void BLI_split_dir_part(const char *string, char *dir, const size_t dirlen)
1429 BLI_split_dirfile(string, dir, NULL, dirlen, 0);
1432 void BLI_split_file_part(const char *string, char *file, const size_t filelen)
1434 BLI_split_dirfile(string, NULL, file, 0, filelen);
1437 /* simple appending of filename to dir, does not check for valid path! */
1438 void BLI_join_dirfile(char *dst, const size_t maxlen, const char *dir, const char *file)
1440 size_t dirlen= BLI_strnlen(dir, maxlen);
1443 if(dirlen == maxlen) {
1444 memcpy(dst, dir, dirlen);
1445 dst[dirlen - 1]= '\0';
1446 return; /* dir fills the path */
1449 memcpy(dst, dir, dirlen + 1);
1453 if (dirlen + 1 >= maxlen) {
1454 return; /* fills the path */
1457 /* inline BLI_add_slash */
1458 if (dst[dirlen - 1] != SEP) {
1463 if (dirlen >= maxlen) {
1464 return; /* fills the path */
1471 BLI_strncpy(dst + dirlen, file, maxlen - dirlen);
1474 /* like pythons os.path.basename( ) */
1475 char *BLI_path_basename(char *path)
1477 char *filename= BLI_last_slash(path);
1478 return filename ? filename + 1 : path;
1482 Produce image export path.
1484 Fails returning 0 if image filename is empty or if destination path
1485 matches image path (i.e. both are the same file).
1487 Trailing slash in dest_dir is optional.
1491 - if an image is "below" current .blend file directory, rebuild the
1492 same dir structure in dest_dir
1494 For example //textures/foo/bar.png becomes
1495 [dest_dir]/textures/foo/bar.png.
1497 - if an image is not "below" current .blend file directory,
1498 disregard it's path and copy it in the same directory where 3D file
1501 For example //../foo/bar.png becomes [dest_dir]/bar.png.
1503 This logic will help ensure that all image paths are relative and
1504 that a user gets his images in one place. It'll also provide
1505 consistent behaviour across exporters.
1507 int BKE_rebase_path(char *abs, size_t abs_len, char *rel, size_t rel_len, const char *base_dir, const char *src_dir, const char *dest_dir)
1509 char path[FILE_MAX];
1511 char base[FILE_MAX];
1512 char blend_dir[FILE_MAX]; /* directory, where current .blend file resides */
1513 char dest_path[FILE_MAX];
1514 char rel_dir[FILE_MAX];
1523 BLI_split_dir_part(base_dir, blend_dir, sizeof(blend_dir));
1525 if (src_dir[0]=='\0')
1528 BLI_strncpy(path, src_dir, sizeof(path));
1530 /* expand "//" in filename and get absolute path */
1531 BLI_path_abs(path, base_dir);
1533 /* get the directory part */
1534 BLI_split_dirfile(path, dir, base, sizeof(dir), sizeof(base));
1536 len= strlen(blend_dir);
1540 /* if image is "below" current .blend file directory */
1541 if (!strncmp(path, blend_dir, len)) {
1543 /* if image is _in_ current .blend file directory */
1544 if (BLI_path_cmp(dir, blend_dir) == 0) {
1545 BLI_join_dirfile(dest_path, sizeof(dest_path), dest_dir, base);
1549 /* rel = image_path_dir - blend_dir */
1550 BLI_strncpy(rel_dir, dir + len, sizeof(rel_dir));
1552 BLI_join_dirfile(dest_path, sizeof(dest_path), dest_dir, rel_dir);
1553 BLI_join_dirfile(dest_path, sizeof(dest_path), dest_path, base);
1557 /* image is out of current directory */
1559 BLI_join_dirfile(dest_path, sizeof(dest_path), dest_dir, base);
1563 BLI_strncpy(abs, dest_path, abs_len);
1566 strncat(rel, rel_dir, rel_len);
1567 strncat(rel, base, rel_len);
1570 /* return 2 if src=dest */
1571 if (BLI_path_cmp(path, dest_path) == 0) {
1572 // if (G.f & G_DEBUG) printf("%s and %s are the same file\n", path, dest_path);
1579 char *BLI_first_slash(char *string)
1581 char *ffslash, *fbslash;
1583 ffslash= strchr(string, '/');
1584 fbslash= strchr(string, '\\');
1586 if (!ffslash) return fbslash;
1587 else if (!fbslash) return ffslash;
1589 if ((intptr_t)ffslash < (intptr_t)fbslash) return ffslash;
1590 else return fbslash;
1593 char *BLI_last_slash(const char *string)
1595 char *lfslash, *lbslash;
1597 lfslash= strrchr(string, '/');
1598 lbslash= strrchr(string, '\\');
1600 if (!lfslash) return lbslash;
1601 else if (!lbslash) return lfslash;
1603 if ((intptr_t)lfslash < (intptr_t)lbslash) return lbslash;
1604 else return lfslash;
1607 /* adds a slash if there isnt one there already */
1608 int BLI_add_slash(char *string)
1610 int len = strlen(string);
1611 if (len==0 || string[len-1] != SEP) {
1613 string[len+1] = '\0';
1619 /* removes a slash if there is one */
1620 void BLI_del_slash(char *string)
1622 int len = strlen(string);
1624 if (string[len-1] == SEP) {
1625 string[len-1] = '\0';
1633 static int add_win32_extension(char *name)
1638 type = BLI_exist(name);
1639 if ((type == 0) || S_ISDIR(type)) {
1641 char filename[FILE_MAXDIR+FILE_MAXFILE];
1642 char ext[FILE_MAXDIR+FILE_MAXFILE];
1643 const char *extensions = getenv("PATHEXT");
1647 strcpy(filename, name);
1648 temp = strstr(extensions, ";");
1650 strncpy(ext, extensions, temp - extensions);
1651 ext[temp - extensions] = 0;
1652 extensions = temp + 1;
1653 strcat(filename, ext);
1655 strcat(filename, extensions);
1658 type = BLI_exist(filename);
1659 if (type && (! S_ISDIR(type))) {
1661 strcpy(name, filename);
1675 * Checks if name is a fully qualified filename to an executable.
1676 * If not it searches $PATH for the file. On Windows it also
1677 * adds the correct extension (.com .exe etc) from
1678 * $PATHEXT if necessary. Also on Windows it translates
1679 * the name to its 8.3 version to prevent problems with
1680 * spaces and stuff. Final result is returned in fullname.
1682 * @param fullname The full path and full name of the executable
1683 * (must be FILE_MAX minimum)
1684 * @param name The name of the executable (usually argv[0]) to be checked
1686 static void bli_where_am_i(char *fullname, const size_t maxlen, const char *name)
1688 char filename[FILE_MAXDIR+FILE_MAXFILE];
1689 const char *path = NULL, *temp;
1692 const char *separator = ";";
1694 const char *separator = ":";
1698 #ifdef WITH_BINRELOC
1699 /* linux uses binreloc since argv[0] is not reliable, call br_init( NULL ) first */
1700 path = br_find_exe( NULL );
1702 BLI_strncpy(fullname, path, maxlen);
1709 if(GetModuleFileName(0, fullname, maxlen)) {
1710 if(!BLI_exists(fullname)) {
1711 printf("path can't be found: \"%.*s\"\n", maxlen, fullname);
1712 MessageBox(NULL, "path contains invalid characters or is too long (see console)", "Error", MB_OK);
1718 /* unix and non linux */
1719 if (name && name[0]) {
1720 BLI_strncpy(fullname, name, maxlen);
1721 if (name[0] == '.') {
1722 char wdir[FILE_MAX]= "";
1723 BLI_getwdN(wdir, sizeof(wdir)); /* backup cwd to restore after */
1725 // not needed but avoids annoying /./ in name
1727 BLI_join_dirfile(fullname, maxlen, wdir, name+2);
1729 BLI_join_dirfile(fullname, maxlen, wdir, name);
1731 add_win32_extension(fullname); /* XXX, doesnt respect length */
1733 else if (BLI_last_slash(name)) {
1735 BLI_strncpy(fullname, name, maxlen);
1736 add_win32_extension(fullname);
1738 // search for binary in $PATH
1739 path = getenv("PATH");
1742 temp = strstr(path, separator);
1744 strncpy(filename, path, temp - path);
1745 filename[temp - path] = 0;
1748 strncpy(filename, path, sizeof(filename));
1750 BLI_join_dirfile(fullname, maxlen, fullname, name);
1751 if (add_win32_extension(filename)) {
1752 BLI_strncpy(fullname, filename, maxlen);
1759 if (strcmp(name, fullname)) {
1760 printf("guessing '%s' == '%s'\n", name, fullname);
1766 void BLI_init_program_path(const char *argv0)
1768 bli_where_am_i(bprogname, sizeof(bprogname), argv0);
1769 BLI_split_dir_part(bprogname, bprogdir, sizeof(bprogdir));
1772 const char *BLI_program_path(void)
1777 const char *BLI_program_dir(void)
1783 * Gets the temp directory when blender first runs.
1784 * If the default path is not found, use try $TEMP
1786 * Also make sure the temp dir has a trailing slash
1788 * @param fullname The full path to the temp directory
1789 * @param userdir Directory specified in user preferences
1791 void BLI_where_is_temp(char *fullname, const size_t maxlen, char *userdir)
1795 if (userdir && BLI_is_dir(userdir)) {
1796 BLI_strncpy(fullname, userdir, maxlen);
1801 if (fullname[0] == '\0') {
1802 const char *tmp = getenv("TEMP"); /* Windows */
1803 if (tmp && BLI_is_dir(tmp)) {
1804 BLI_strncpy(fullname, tmp, maxlen);
1808 /* Other OS's - Try TMP and TMPDIR */
1809 if (fullname[0] == '\0') {
1810 const char *tmp = getenv("TMP");
1811 if (tmp && BLI_is_dir(tmp)) {
1812 BLI_strncpy(fullname, tmp, maxlen);
1816 if (fullname[0] == '\0') {
1817 const char *tmp = getenv("TMPDIR");
1818 if (tmp && BLI_is_dir(tmp)) {
1819 BLI_strncpy(fullname, tmp, maxlen);
1824 if (fullname[0] == '\0') {
1825 BLI_strncpy(fullname, "/tmp/", maxlen);
1827 /* add a trailing slash if needed */
1828 BLI_add_slash(fullname);
1830 if(userdir != fullname) {
1831 BLI_strncpy(userdir, fullname, maxlen); /* also set user pref to show %TEMP%. /tmp/ is just plain confusing for Windows users. */
1837 void BLI_init_temporary_dir(char *userdir)
1839 BLI_where_is_temp(btempdir, FILE_MAX, userdir);
1842 const char *BLI_temporary_dir(void)
1847 void BLI_system_temporary_dir(char *dir)
1849 BLI_where_is_temp(dir, FILE_MAX, NULL);
1854 void BLI_string_to_utf8(char *original, char *utf_8, const char *code)
1856 size_t inbytesleft=strlen(original);
1857 size_t outbytesleft=512;
1862 code = locale_charset();
1864 cd=iconv_open("UTF-8", code);
1866 if (cd == (iconv_t)(-1)) {
1867 printf("iconv_open Error");
1871 rv=iconv(cd, &original, &inbytesleft, &utf_8, &outbytesleft);
1872 if (rv == (size_t) -1) {
1873 printf("iconv Error\n");
1879 #endif // WITH_ICONV