ClangFormat: apply to source, most of intern
[blender.git] / source / blender / blenkernel / intern / appdir.c
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  */
16
17 /** \file
18  * \ingroup bke
19  *
20  * Access to application level directories.
21  */
22
23 #include <stdlib.h>
24 #include <string.h>
25 #include <stdio.h>
26
27 #include "BLI_utildefines.h"
28 #include "BLI_fileops.h"
29 #include "BLI_fileops_types.h"
30 #include "BLI_listbase.h"
31 #include "BLI_path_util.h"
32 #include "BLI_string.h"
33
34 #include "BKE_blender_version.h"
35 #include "BKE_appdir.h" /* own include */
36
37 #include "GHOST_Path-api.h"
38
39 #include "MEM_guardedalloc.h"
40
41 #include "CLG_log.h"
42
43 #ifdef WIN32
44 #  include "utf_winfunc.h"
45 #  include "utfconv.h"
46 #  include <io.h>
47 #  ifdef _WIN32_IE
48 #    undef _WIN32_IE
49 #  endif
50 #  define _WIN32_IE 0x0501
51 #  include <windows.h>
52 #  include <shlobj.h>
53 #  include "BLI_winstuff.h"
54 #else /* non windows */
55 #  ifdef WITH_BINRELOC
56 #    include "binreloc.h"
57 #  endif
58 #  include <unistd.h> /* mkdtemp on OSX (and probably all *BSD?), not worth making specific check for this OS. */
59 #endif                /* WIN32 */
60
61 /* local */
62 static CLG_LogRef LOG = {"bke.appdir"};
63 static char bprogname[FILE_MAX];     /* full path to program executable */
64 static char bprogdir[FILE_MAX];      /* full path to directory in which executable is located */
65 static char btempdir_base[FILE_MAX]; /* persistent temporary directory */
66 static char btempdir_session[FILE_MAX] = ""; /* volatile temporary directory */
67
68 /* This is now only used to really get the user's default document folder */
69 /* On Windows I chose the 'Users/<MyUserName>/Documents' since it's used
70  * as default location to save documents */
71 const char *BKE_appdir_folder_default(void)
72 {
73 #ifndef WIN32
74   const char *const xdg_documents_dir = BLI_getenv("XDG_DOCUMENTS_DIR");
75
76   if (xdg_documents_dir)
77     return xdg_documents_dir;
78
79   return BLI_getenv("HOME");
80 #else  /* Windows */
81   static char documentfolder[MAXPATHLEN];
82   HRESULT hResult;
83
84   /* Check for %HOME% env var */
85   if (uput_getenv("HOME", documentfolder, MAXPATHLEN)) {
86     if (BLI_is_dir(documentfolder))
87       return documentfolder;
88   }
89
90   /* add user profile support for WIN 2K / NT.
91    * This is %APPDATA%, which translates to either
92    * %USERPROFILE%\Application Data or since Vista
93    * to %USERPROFILE%\AppData\Roaming
94    */
95   hResult = SHGetFolderPath(NULL, CSIDL_PERSONAL, NULL, SHGFP_TYPE_CURRENT, documentfolder);
96
97   if (hResult == S_OK) {
98     if (BLI_is_dir(documentfolder))
99       return documentfolder;
100   }
101
102   return NULL;
103 #endif /* WIN32 */
104 }
105
106 // #define PATH_DEBUG
107
108 /* returns a formatted representation of the specified version number. Non-reentrant! */
109 static char *blender_version_decimal(const int ver)
110 {
111   static char version_str[5];
112   BLI_assert(ver < 1000);
113   BLI_snprintf(version_str, sizeof(version_str), "%d.%02d", ver / 100, ver % 100);
114   return version_str;
115 }
116
117 /**
118  * Concatenates path_base, (optional) path_sep and (optional) folder_name into targetpath,
119  * returning true if result points to a directory.
120  */
121 static bool test_path(char *targetpath,
122                       size_t targetpath_len,
123                       const char *path_base,
124                       const char *path_sep,
125                       const char *folder_name)
126 {
127   char tmppath[FILE_MAX];
128
129   if (path_sep) {
130     BLI_join_dirfile(tmppath, sizeof(tmppath), path_base, path_sep);
131   }
132   else {
133     BLI_strncpy(tmppath, path_base, sizeof(tmppath));
134   }
135
136   /* rare cases folder_name is omitted (when looking for ~/.config/blender/2.xx dir only) */
137   if (folder_name) {
138     BLI_join_dirfile(targetpath, targetpath_len, tmppath, folder_name);
139   }
140   else {
141     BLI_strncpy(targetpath, tmppath, targetpath_len);
142   }
143   /* FIXME: why is "//" on front of tmppath expanded to "/" (by BLI_join_dirfile)
144    * if folder_name is specified but not otherwise? */
145
146   if (BLI_is_dir(targetpath)) {
147 #ifdef PATH_DEBUG
148     printf("\t%s found: %s\n", __func__, targetpath);
149 #endif
150     return true;
151   }
152   else {
153 #ifdef PATH_DEBUG
154     printf("\t%s missing: %s\n", __func__, targetpath);
155 #endif
156     //targetpath[0] = '\0';
157     return false;
158   }
159 }
160
161 /**
162  * Puts the value of the specified environment variable into *path if it exists
163  * and points at a directory. Returns true if this was done.
164  */
165 static bool test_env_path(char *path, const char *envvar)
166 {
167   const char *env = envvar ? BLI_getenv(envvar) : NULL;
168   if (!env)
169     return false;
170
171   if (BLI_is_dir(env)) {
172     BLI_strncpy(path, env, FILE_MAX);
173 #ifdef PATH_DEBUG
174     printf("\t%s env %s found: %s\n", __func__, envvar, env);
175 #endif
176     return true;
177   }
178   else {
179     path[0] = '\0';
180 #ifdef PATH_DEBUG
181     printf("\t%s env %s missing: %s\n", __func__, envvar, env);
182 #endif
183     return false;
184   }
185 }
186
187 /**
188  * Constructs in \a targetpath the name of a directory relative to a version-specific
189  * subdirectory in the parent directory of the Blender executable.
190  *
191  * \param targetpath: String to return path
192  * \param folder_name: Optional folder name within version-specific directory
193  * \param subfolder_name: Optional subfolder name within folder_name
194  * \param ver: To construct name of version-specific directory within bprogdir
195  * \return true if such a directory exists.
196  */
197 static bool get_path_local(char *targetpath,
198                            size_t targetpath_len,
199                            const char *folder_name,
200                            const char *subfolder_name,
201                            const int ver)
202 {
203   char relfolder[FILE_MAX];
204
205 #ifdef PATH_DEBUG
206   printf("%s...\n", __func__);
207 #endif
208
209   if (folder_name) {
210     if (subfolder_name) {
211       BLI_join_dirfile(relfolder, sizeof(relfolder), folder_name, subfolder_name);
212     }
213     else {
214       BLI_strncpy(relfolder, folder_name, sizeof(relfolder));
215     }
216   }
217   else {
218     relfolder[0] = '\0';
219   }
220
221   /* try EXECUTABLE_DIR/2.5x/folder_name - new default directory for local blender installed files */
222 #ifdef __APPLE__
223   /* due new codesign situation in OSX > 10.9.5 we must move the blender_version dir with contents to Resources */
224   char osx_resourses[FILE_MAX];
225   BLI_snprintf(osx_resourses, sizeof(osx_resourses), "%s../Resources", bprogdir);
226   /* Remove the '/../' added above. */
227   BLI_cleanup_path(NULL, osx_resourses);
228   return test_path(
229       targetpath, targetpath_len, osx_resourses, blender_version_decimal(ver), relfolder);
230 #else
231   return test_path(targetpath, targetpath_len, bprogdir, blender_version_decimal(ver), relfolder);
232 #endif
233 }
234
235 /**
236  * Is this an install with user files kept together with the Blender executable and its
237  * installation files.
238  */
239 bool BKE_appdir_app_is_portable_install(void)
240 {
241   /* detect portable install by the existence of config folder */
242   const int ver = BLENDER_VERSION;
243   char path[FILE_MAX];
244
245   return get_path_local(path, sizeof(path), "config", NULL, ver);
246 }
247
248 /**
249  * Returns the path of a folder from environment variables
250  *
251  * \param targetpath: String to return path.
252  * \param subfolder_name: optional name of subfolder within folder.
253  * \param envvar: name of environment variable to check folder_name.
254  * \return true if it was able to construct such a path and the path exists.
255  */
256 static bool get_path_environment(char *targetpath,
257                                  size_t targetpath_len,
258                                  const char *subfolder_name,
259                                  const char *envvar)
260 {
261   char user_path[FILE_MAX];
262
263   if (test_env_path(user_path, envvar)) {
264     if (subfolder_name) {
265       return test_path(targetpath, targetpath_len, user_path, NULL, subfolder_name);
266     }
267     else {
268       BLI_strncpy(targetpath, user_path, FILE_MAX);
269       return true;
270     }
271   }
272   return false;
273 }
274
275 /**
276  * Returns the path of a folder from environment variables
277  *
278  * \param targetpath: String to return path.
279  * \param subfolder_name: optional name of subfolder within folder.
280  * \param envvar: name of environment variable to check folder_name.
281  * \return true if it was able to construct such a path.
282  */
283 static bool get_path_environment_notest(char *targetpath,
284                                         size_t targetpath_len,
285                                         const char *subfolder_name,
286                                         const char *envvar)
287 {
288   char user_path[FILE_MAX];
289
290   if (test_env_path(user_path, envvar)) {
291     if (subfolder_name) {
292       BLI_join_dirfile(targetpath, targetpath_len, user_path, subfolder_name);
293       return true;
294     }
295     else {
296       BLI_strncpy(targetpath, user_path, FILE_MAX);
297       return true;
298     }
299   }
300   return false;
301 }
302
303 /**
304  * Returns the path of a folder within the user-files area.
305  * \param targetpath: String to return path
306  * \param folder_name: default name of folder within user area
307  * \param subfolder_name: optional name of subfolder within folder
308  * \param ver: Blender version, used to construct a subdirectory name
309  * \return true if it was able to construct such a path.
310  */
311 static bool get_path_user(char *targetpath,
312                           size_t targetpath_len,
313                           const char *folder_name,
314                           const char *subfolder_name,
315                           const int ver)
316 {
317   char user_path[FILE_MAX];
318   const char *user_base_path;
319
320   /* for portable install, user path is always local */
321   if (BKE_appdir_app_is_portable_install()) {
322     return get_path_local(targetpath, targetpath_len, folder_name, subfolder_name, ver);
323   }
324   user_path[0] = '\0';
325
326   user_base_path = (const char *)GHOST_getUserDir(ver, blender_version_decimal(ver));
327   if (user_base_path)
328     BLI_strncpy(user_path, user_base_path, FILE_MAX);
329
330   if (!user_path[0])
331     return false;
332
333 #ifdef PATH_DEBUG
334   printf("%s: %s\n", __func__, user_path);
335 #endif
336
337   if (subfolder_name) {
338     return test_path(targetpath, targetpath_len, user_path, folder_name, subfolder_name);
339   }
340   else {
341     return test_path(targetpath, targetpath_len, user_path, NULL, folder_name);
342   }
343 }
344
345 /**
346  * Returns the path of a folder within the Blender installation directory.
347  *
348  * \param targetpath: String to return path
349  * \param folder_name: default name of folder within installation area
350  * \param subfolder_name: optional name of subfolder within folder
351  * \param ver: Blender version, used to construct a subdirectory name
352  * \return  true if it was able to construct such a path.
353  */
354 static bool get_path_system(char *targetpath,
355                             size_t targetpath_len,
356                             const char *folder_name,
357                             const char *subfolder_name,
358                             const int ver)
359 {
360   char system_path[FILE_MAX];
361   const char *system_base_path;
362   char relfolder[FILE_MAX];
363
364   if (folder_name) {
365     if (subfolder_name) {
366       BLI_join_dirfile(relfolder, sizeof(relfolder), folder_name, subfolder_name);
367     }
368     else {
369       BLI_strncpy(relfolder, folder_name, sizeof(relfolder));
370     }
371   }
372   else {
373     relfolder[0] = '\0';
374   }
375
376   system_path[0] = '\0';
377   system_base_path = (const char *)GHOST_getSystemDir(ver, blender_version_decimal(ver));
378   if (system_base_path)
379     BLI_strncpy(system_path, system_base_path, FILE_MAX);
380
381   if (!system_path[0])
382     return false;
383
384 #ifdef PATH_DEBUG
385   printf("%s: %s\n", __func__, system_path);
386 #endif
387
388   if (subfolder_name) {
389     /* try $BLENDERPATH/folder_name/subfolder_name */
390     return test_path(targetpath, targetpath_len, system_path, folder_name, subfolder_name);
391   }
392   else {
393     /* try $BLENDERPATH/folder_name */
394     return test_path(targetpath, targetpath_len, system_path, NULL, folder_name);
395   }
396 }
397
398 /**
399  * Get a folder out of the 'folder_id' presets for paths.
400  * returns the path if found, NULL string if not
401  *
402  * \param subfolder: The name of a directory to check for,
403  * this may contain path separators but must resolve to a directory, checked with #BLI_is_dir.
404  */
405 const char *BKE_appdir_folder_id_ex(const int folder_id,
406                                     const char *subfolder,
407                                     char *path,
408                                     size_t path_len)
409 {
410   const int ver = BLENDER_VERSION;
411
412   switch (folder_id) {
413     case BLENDER_DATAFILES: /* general case */
414       if (get_path_environment(path, path_len, subfolder, "BLENDER_USER_DATAFILES"))
415         break;
416       if (get_path_user(path, path_len, "datafiles", subfolder, ver))
417         break;
418       if (get_path_environment(path, path_len, subfolder, "BLENDER_SYSTEM_DATAFILES"))
419         break;
420       if (get_path_local(path, path_len, "datafiles", subfolder, ver))
421         break;
422       if (get_path_system(path, path_len, "datafiles", subfolder, ver))
423         break;
424       return NULL;
425
426     case BLENDER_USER_DATAFILES:
427       if (get_path_environment(path, path_len, subfolder, "BLENDER_USER_DATAFILES"))
428         break;
429       if (get_path_user(path, path_len, "datafiles", subfolder, ver))
430         break;
431       return NULL;
432
433     case BLENDER_SYSTEM_DATAFILES:
434       if (get_path_environment(path, path_len, subfolder, "BLENDER_SYSTEM_DATAFILES"))
435         break;
436       if (get_path_system(path, path_len, "datafiles", subfolder, ver))
437         break;
438       if (get_path_local(path, path_len, "datafiles", subfolder, ver))
439         break;
440       return NULL;
441
442     case BLENDER_USER_AUTOSAVE:
443       if (get_path_environment(path, path_len, subfolder, "BLENDER_USER_DATAFILES"))
444         break;
445       if (get_path_user(path, path_len, "autosave", subfolder, ver))
446         break;
447       return NULL;
448
449     case BLENDER_USER_CONFIG:
450       if (get_path_environment(path, path_len, subfolder, "BLENDER_USER_CONFIG"))
451         break;
452       if (get_path_user(path, path_len, "config", subfolder, ver))
453         break;
454       return NULL;
455
456     case BLENDER_USER_SCRIPTS:
457       if (get_path_environment(path, path_len, subfolder, "BLENDER_USER_SCRIPTS"))
458         break;
459       if (get_path_user(path, path_len, "scripts", subfolder, ver))
460         break;
461       return NULL;
462
463     case BLENDER_SYSTEM_SCRIPTS:
464       if (get_path_environment(path, path_len, subfolder, "BLENDER_SYSTEM_SCRIPTS"))
465         break;
466       if (get_path_system(path, path_len, "scripts", subfolder, ver))
467         break;
468       if (get_path_local(path, path_len, "scripts", subfolder, ver))
469         break;
470       return NULL;
471
472     case BLENDER_SYSTEM_PYTHON:
473       if (get_path_environment(path, path_len, subfolder, "BLENDER_SYSTEM_PYTHON"))
474         break;
475       if (get_path_system(path, path_len, "python", subfolder, ver))
476         break;
477       if (get_path_local(path, path_len, "python", subfolder, ver))
478         break;
479       return NULL;
480
481     default:
482       BLI_assert(0);
483       break;
484   }
485
486   return path;
487 }
488
489 const char *BKE_appdir_folder_id(const int folder_id, const char *subfolder)
490 {
491   static char path[FILE_MAX] = "";
492   return BKE_appdir_folder_id_ex(folder_id, subfolder, path, sizeof(path));
493 }
494
495 /**
496  * Returns the path to a folder in the user area without checking that it actually exists first.
497  */
498 const char *BKE_appdir_folder_id_user_notest(const int folder_id, const char *subfolder)
499 {
500   const int ver = BLENDER_VERSION;
501   static char path[FILE_MAX] = "";
502
503   switch (folder_id) {
504     case BLENDER_USER_DATAFILES:
505       if (get_path_environment_notest(path, sizeof(path), subfolder, "BLENDER_USER_DATAFILES"))
506         break;
507       get_path_user(path, sizeof(path), "datafiles", subfolder, ver);
508       break;
509     case BLENDER_USER_CONFIG:
510       if (get_path_environment_notest(path, sizeof(path), subfolder, "BLENDER_USER_CONFIG"))
511         break;
512       get_path_user(path, sizeof(path), "config", subfolder, ver);
513       break;
514     case BLENDER_USER_AUTOSAVE:
515       if (get_path_environment_notest(path, sizeof(path), subfolder, "BLENDER_USER_AUTOSAVE"))
516         break;
517       get_path_user(path, sizeof(path), "autosave", subfolder, ver);
518       break;
519     case BLENDER_USER_SCRIPTS:
520       if (get_path_environment_notest(path, sizeof(path), subfolder, "BLENDER_USER_SCRIPTS"))
521         break;
522       get_path_user(path, sizeof(path), "scripts", subfolder, ver);
523       break;
524     default:
525       BLI_assert(0);
526       break;
527   }
528
529   if ('\0' == path[0]) {
530     return NULL;
531   }
532   return path;
533 }
534
535 /**
536  * Returns the path to a folder in the user area, creating it if it doesn't exist.
537  */
538 const char *BKE_appdir_folder_id_create(const int folder_id, const char *subfolder)
539 {
540   const char *path;
541
542   /* only for user folders */
543   if (!ELEM(folder_id,
544             BLENDER_USER_DATAFILES,
545             BLENDER_USER_CONFIG,
546             BLENDER_USER_SCRIPTS,
547             BLENDER_USER_AUTOSAVE))
548     return NULL;
549
550   path = BKE_appdir_folder_id(folder_id, subfolder);
551
552   if (!path) {
553     path = BKE_appdir_folder_id_user_notest(folder_id, subfolder);
554     if (path)
555       BLI_dir_create_recursive(path);
556   }
557
558   return path;
559 }
560
561 /**
562  * Returns the path of the top-level version-specific local, user or system directory.
563  * If do_check, then the result will be NULL if the directory doesn't exist.
564  */
565 const char *BKE_appdir_folder_id_version(const int folder_id, const int ver, const bool do_check)
566 {
567   static char path[FILE_MAX] = "";
568   bool ok;
569   switch (folder_id) {
570     case BLENDER_RESOURCE_PATH_USER:
571       ok = get_path_user(path, sizeof(path), NULL, NULL, ver);
572       break;
573     case BLENDER_RESOURCE_PATH_LOCAL:
574       ok = get_path_local(path, sizeof(path), NULL, NULL, ver);
575       break;
576     case BLENDER_RESOURCE_PATH_SYSTEM:
577       ok = get_path_system(path, sizeof(path), NULL, NULL, ver);
578       break;
579     default:
580       path[0] = '\0'; /* in case do_check is false */
581       ok = false;
582       BLI_assert(!"incorrect ID");
583       break;
584   }
585
586   if (!ok && do_check) {
587     return NULL;
588   }
589
590   return path;
591 }
592
593 #ifdef PATH_DEBUG
594 #  undef PATH_DEBUG
595 #endif
596
597 /* -------------------------------------------------------------------- */
598 /* Preset paths */
599
600 /**
601  * Checks if name is a fully qualified filename to an executable.
602  * If not it searches $PATH for the file. On Windows it also
603  * adds the correct extension (.com .exe etc) from
604  * $PATHEXT if necessary. Also on Windows it translates
605  * the name to its 8.3 version to prevent problems with
606  * spaces and stuff. Final result is returned in fullname.
607  *
608  * \param fullname: The full path and full name of the executable
609  * (must be FILE_MAX minimum)
610  * \param name: The name of the executable (usually argv[0]) to be checked
611  */
612 static void where_am_i(char *fullname, const size_t maxlen, const char *name)
613 {
614 #ifdef WITH_BINRELOC
615   /* linux uses binreloc since argv[0] is not reliable, call br_init( NULL ) first */
616   {
617     const char *path = NULL;
618     path = br_find_exe(NULL);
619     if (path) {
620       BLI_strncpy(fullname, path, maxlen);
621       free((void *)path);
622       return;
623     }
624   }
625 #endif
626
627 #ifdef _WIN32
628   {
629     wchar_t *fullname_16 = MEM_mallocN(maxlen * sizeof(wchar_t), "ProgramPath");
630     if (GetModuleFileNameW(0, fullname_16, maxlen)) {
631       conv_utf_16_to_8(fullname_16, fullname, maxlen);
632       if (!BLI_exists(fullname)) {
633         CLOG_ERROR(&LOG, "path can't be found: \"%.*s\"", (int)maxlen, fullname);
634         MessageBox(
635             NULL, "path contains invalid characters or is too long (see console)", "Error", MB_OK);
636       }
637       MEM_freeN(fullname_16);
638       return;
639     }
640
641     MEM_freeN(fullname_16);
642   }
643 #endif
644
645   /* unix and non linux */
646   if (name && name[0]) {
647
648     BLI_strncpy(fullname, name, maxlen);
649     if (name[0] == '.') {
650       BLI_path_cwd(fullname, maxlen);
651 #ifdef _WIN32
652       BLI_path_program_extensions_add_win32(fullname, maxlen);
653 #endif
654     }
655     else if (BLI_last_slash(name)) {
656       // full path
657       BLI_strncpy(fullname, name, maxlen);
658 #ifdef _WIN32
659       BLI_path_program_extensions_add_win32(fullname, maxlen);
660 #endif
661     }
662     else {
663       BLI_path_program_search(fullname, maxlen, name);
664     }
665     /* Remove "/./" and "/../" so string comparisons can be used on the path. */
666     BLI_cleanup_path(NULL, fullname);
667
668 #if defined(DEBUG)
669     if (!STREQ(name, fullname)) {
670       CLOG_INFO(&LOG, 2, "guessing '%s' == '%s'", name, fullname);
671     }
672 #endif
673   }
674 }
675
676 void BKE_appdir_program_path_init(const char *argv0)
677 {
678   where_am_i(bprogname, sizeof(bprogname), argv0);
679   BLI_split_dir_part(bprogname, bprogdir, sizeof(bprogdir));
680 }
681
682 /**
683  * Path to executable
684  */
685 const char *BKE_appdir_program_path(void)
686 {
687   return bprogname;
688 }
689
690 /**
691  * Path to directory of executable
692  */
693 const char *BKE_appdir_program_dir(void)
694 {
695   return bprogdir;
696 }
697
698 bool BKE_appdir_program_python_search(char *fullpath,
699                                       const size_t fullpath_len,
700                                       const int version_major,
701                                       const int version_minor)
702 {
703 #ifdef PYTHON_EXECUTABLE_NAME
704   /* passed in from the build-systems 'PYTHON_EXECUTABLE' */
705   const char *python_build_def = STRINGIFY(PYTHON_EXECUTABLE_NAME);
706 #endif
707   const char *basename = "python";
708   char python_ver[16];
709   /* check both possible names */
710   const char *python_names[] = {
711 #ifdef PYTHON_EXECUTABLE_NAME
712       python_build_def,
713 #endif
714       python_ver,
715       basename,
716   };
717   int i;
718
719   bool is_found = false;
720
721   BLI_snprintf(python_ver, sizeof(python_ver), "%s%d.%d", basename, version_major, version_minor);
722
723   {
724     const char *python_bin_dir = BKE_appdir_folder_id(BLENDER_SYSTEM_PYTHON, "bin");
725     if (python_bin_dir) {
726
727       for (i = 0; i < ARRAY_SIZE(python_names); i++) {
728         BLI_join_dirfile(fullpath, fullpath_len, python_bin_dir, python_names[i]);
729
730         if (
731 #ifdef _WIN32
732             BLI_path_program_extensions_add_win32(fullpath, fullpath_len)
733 #else
734             BLI_exists(fullpath)
735 #endif
736         ) {
737           is_found = true;
738           break;
739         }
740       }
741     }
742   }
743
744   if (is_found == false) {
745     for (i = 0; i < ARRAY_SIZE(python_names); i++) {
746       if (BLI_path_program_search(fullpath, fullpath_len, python_names[i])) {
747         is_found = true;
748         break;
749       }
750     }
751   }
752
753   if (is_found == false) {
754     *fullpath = '\0';
755   }
756
757   return is_found;
758 }
759
760 /** Keep in sync with `bpy.utils.app_template_paths()` */
761 static const char *app_template_directory_search[2] = {
762     "startup" SEP_STR "bl_app_templates_user",
763     "startup" SEP_STR "bl_app_templates_system",
764 };
765
766 static const int app_template_directory_id[2] = {
767     /* Only 'USER' */
768     BLENDER_USER_SCRIPTS,
769     /* Covers 'LOCAL' & 'SYSTEM'. */
770     BLENDER_SYSTEM_SCRIPTS,
771 };
772
773 /**
774  * Return true if templates exist
775  */
776 bool BKE_appdir_app_template_any(void)
777 {
778   char temp_dir[FILE_MAX];
779   for (int i = 0; i < 2; i++) {
780     if (BKE_appdir_folder_id_ex(app_template_directory_id[i],
781                                 app_template_directory_search[i],
782                                 temp_dir,
783                                 sizeof(temp_dir))) {
784       return true;
785     }
786   }
787   return false;
788 }
789
790 bool BKE_appdir_app_template_id_search(const char *app_template, char *path, size_t path_len)
791 {
792   for (int i = 0; i < 2; i++) {
793     char subdir[FILE_MAX];
794     BLI_join_dirfile(subdir, sizeof(subdir), app_template_directory_search[i], app_template);
795     if (BKE_appdir_folder_id_ex(app_template_directory_id[i], subdir, path, path_len)) {
796       return true;
797     }
798   }
799   return false;
800 }
801
802 void BKE_appdir_app_templates(ListBase *templates)
803 {
804   BLI_listbase_clear(templates);
805
806   for (int i = 0; i < 2; i++) {
807     char subdir[FILE_MAX];
808     if (!BKE_appdir_folder_id_ex(app_template_directory_id[i],
809                                  app_template_directory_search[i],
810                                  subdir,
811                                  sizeof(subdir))) {
812       continue;
813     }
814
815     struct direntry *dir;
816     uint totfile = BLI_filelist_dir_contents(subdir, &dir);
817     for (int f = 0; f < totfile; f++) {
818       if (!FILENAME_IS_CURRPAR(dir[f].relname) && S_ISDIR(dir[f].type)) {
819         char *template = BLI_strdup(dir[f].relname);
820         BLI_addtail(templates, BLI_genericNodeN(template));
821       }
822     }
823
824     BLI_filelist_free(dir, totfile);
825   }
826 }
827
828 /**
829  * Gets the temp directory when blender first runs.
830  * If the default path is not found, use try $TEMP
831  *
832  * Also make sure the temp dir has a trailing slash
833  *
834  * \param fullname: The full path to the temporary temp directory
835  * \param basename: The full path to the persistent temp directory (may be NULL)
836  * \param maxlen: The size of the fullname buffer
837  * \param userdir: Directory specified in user preferences
838  */
839 static void where_is_temp(char *fullname, char *basename, const size_t maxlen, char *userdir)
840 {
841   /* Clear existing temp dir, if needed. */
842   BKE_tempdir_session_purge();
843
844   fullname[0] = '\0';
845   if (basename) {
846     basename[0] = '\0';
847   }
848
849   if (userdir && BLI_is_dir(userdir)) {
850     BLI_strncpy(fullname, userdir, maxlen);
851   }
852
853 #ifdef WIN32
854   if (fullname[0] == '\0') {
855     const char *tmp = BLI_getenv("TEMP"); /* Windows */
856     if (tmp && BLI_is_dir(tmp)) {
857       BLI_strncpy(fullname, tmp, maxlen);
858     }
859   }
860 #else
861   /* Other OS's - Try TMP and TMPDIR */
862   if (fullname[0] == '\0') {
863     const char *tmp = BLI_getenv("TMP");
864     if (tmp && BLI_is_dir(tmp)) {
865       BLI_strncpy(fullname, tmp, maxlen);
866     }
867   }
868
869   if (fullname[0] == '\0') {
870     const char *tmp = BLI_getenv("TMPDIR");
871     if (tmp && BLI_is_dir(tmp)) {
872       BLI_strncpy(fullname, tmp, maxlen);
873     }
874   }
875 #endif
876
877   if (fullname[0] == '\0') {
878     BLI_strncpy(fullname, "/tmp/", maxlen);
879   }
880   else {
881     /* add a trailing slash if needed */
882     BLI_add_slash(fullname);
883 #ifdef WIN32
884     if (userdir && userdir != fullname) {
885       /* also set user pref to show %TEMP%. /tmp/ is just plain confusing for Windows users. */
886       BLI_strncpy(userdir, fullname, maxlen);
887     }
888 #endif
889   }
890
891   /* Now that we have a valid temp dir, add system-generated unique sub-dir. */
892   if (basename) {
893     /* 'XXXXXX' is kind of tag to be replaced by mktemp-familly by an uuid. */
894     char *tmp_name = BLI_strdupcat(fullname, "blender_XXXXXX");
895     const size_t ln = strlen(tmp_name) + 1;
896     if (ln <= maxlen) {
897 #ifdef WIN32
898       if (_mktemp_s(tmp_name, ln) == 0) {
899         BLI_dir_create_recursive(tmp_name);
900       }
901 #else
902       if (mkdtemp(tmp_name) == NULL) {
903         BLI_dir_create_recursive(tmp_name);
904       }
905 #endif
906     }
907     if (BLI_is_dir(tmp_name)) {
908       BLI_strncpy(basename, fullname, maxlen);
909       BLI_strncpy(fullname, tmp_name, maxlen);
910       BLI_add_slash(fullname);
911     }
912     else {
913       CLOG_WARN(&LOG,
914                 "Could not generate a temp file name for '%s', falling back to '%s'",
915                 tmp_name,
916                 fullname);
917     }
918
919     MEM_freeN(tmp_name);
920   }
921 }
922
923 /**
924  * Sets btempdir_base to userdir if specified and is a valid directory, otherwise
925  * chooses a suitable OS-specific temporary directory.
926  * Sets btempdir_session to a mkdtemp-generated sub-dir of btempdir_base.
927  *
928  * \note On Window userdir will be set to the temporary directory!
929  */
930 void BKE_tempdir_init(char *userdir)
931 {
932   where_is_temp(btempdir_session, btempdir_base, FILE_MAX, userdir);
933 }
934
935 /**
936  * Path to temporary directory (with trailing slash)
937  */
938 const char *BKE_tempdir_session(void)
939 {
940   return btempdir_session[0] ? btempdir_session : BKE_tempdir_base();
941 }
942
943 /**
944  * Path to persistent temporary directory (with trailing slash)
945  */
946 const char *BKE_tempdir_base(void)
947 {
948   return btempdir_base;
949 }
950
951 /**
952  * Path to the system temporary directory (with trailing slash)
953  */
954 void BKE_tempdir_system_init(char *dir)
955 {
956   where_is_temp(dir, NULL, FILE_MAX, NULL);
957 }
958
959 /**
960  * Delete content of this instance's temp dir.
961  */
962 void BKE_tempdir_session_purge(void)
963 {
964   if (btempdir_session[0] && BLI_is_dir(btempdir_session)) {
965     BLI_delete(btempdir_session, true, true);
966   }
967 }