44# define _WIN32_IE 0x0501
60#define STR_OR_FALLBACK(a) ((a) ? (a) : _str_null)
88# define ASSERT_IS_INIT() BLI_assert(is_appdir_init)
90# define ASSERT_IS_INIT() ((void)0)
125 static char version_str[5];
127 SNPRINTF(version_str,
"%d.%d", version / 100, version % 100);
145 return documentfolder;
166 if (path ==
nullptr) {
174 const char *home_dir =
nullptr;
180# if defined(__APPLE__)
183 if (home_dir ==
nullptr) {
185 if (home_dir ==
nullptr) {
186 if (
const passwd *pwuser = getpwuid(getuid())) {
187 home_dir = pwuser->pw_dir;
203 if (documents_path &&
BLI_is_dir(documents_path)) {
217 BLI_path_join(try_documents_path,
sizeof(try_documents_path), home_path,
N_(
"Documents"));
231 if (caches_root_path ==
nullptr || !
BLI_is_dir(caches_root_path)) {
234 if (caches_root_path ==
nullptr || !
BLI_is_dir(caches_root_path)) {
240 path, path_maxncpy, caches_root_path,
"Blender Foundation",
"Blender",
"Cache",
SEP_STR);
241#elif defined(__APPLE__)
256 wchar_t wpath[MAX_PATH];
257 if (SHGetSpecialFolderPathW(0, wpath, CSIDL_FONTS, 0)) {
260#elif defined(__APPLE__)
265 STRNCPY(test_dir,
"/usr/share/fonts");
297 size_t targetpath_maxncpy,
298 const bool check_is_dir,
299 const char *path_base,
300 const char *folder_name,
301 const char *subfolder_name)
306 BLI_assert(!(folder_name ==
nullptr && (subfolder_name !=
nullptr)));
307 const char *path_array[] = {path_base, folder_name, subfolder_name};
308 const int path_array_num = (folder_name ? (subfolder_name ? 3 : 2) : 1);
310 if (check_is_dir ==
false) {
311 CLOG_INFO(&
LOG, 3,
"using without test: '%s'", targetpath);
324 targetpath[0] =
'\0';
336static bool test_env_path(
char *path,
const char *envvar,
const bool check_is_dir)
340 const char *env_path = envvar ?
BLI_getenv(envvar) :
nullptr;
347 if (check_is_dir ==
false) {
348 CLOG_INFO(&
LOG, 3,
"using env '%s' without test: '%s'", envvar, env_path);
353 CLOG_INFO(&
LOG, 3,
"env '%s' found: %s", envvar, env_path);
357 CLOG_INFO(&
LOG, 3,
"env '%s' missing: %s", envvar, env_path);
378 size_t targetpath_maxncpy,
379 const char *folder_name,
380 const char *subfolder_name,
382 const bool check_is_dir)
388 "folder='%s', subfolder='%s'",
393 const char *path_array[] = {folder_name, subfolder_name};
394 const int path_array_num = subfolder_name ? 2 : 1;
403 const char *path_base =
g_app.program_dirname;
404#if defined(__APPLE__) && !defined(WITH_PYTHON_MODULE)
408 char osx_resourses[
FILE_MAX + 4 + 9];
409 BLI_path_join(osx_resourses,
sizeof(osx_resourses),
g_app.program_dirname,
"..",
"Resources");
412 path_base = osx_resourses;
419 (version) ? relfolder :
nullptr);
422 size_t targetpath_maxncpy,
423 const char *folder_name,
424 const char *subfolder_name)
427 const bool check_is_dir =
true;
429 targetpath, targetpath_maxncpy, folder_name, subfolder_name, version, check_is_dir);
442 size_t targetpath_maxncpy,
443 const char *subfolder_name,
445 const bool check_is_dir)
452 targetpath, targetpath_maxncpy, check_is_dir, user_path, subfolder_name,
nullptr);
457 size_t targetpath_maxncpy,
458 const char *subfolder_name,
461 const bool check_is_dir =
true;
463 targetpath, targetpath_maxncpy, subfolder_name, envvar, check_is_dir);
477 size_t targetpath_maxncpy,
478 const char *folder_name,
479 const char *subfolder_name,
481 const bool check_is_dir)
486 if (
test_env_path(user_path,
"BLENDER_USER_RESOURCES", check_is_dir)) {
490 else if (
get_path_local_ex(user_path,
sizeof(user_path),
"portable",
nullptr, 0,
true)) {
497 if (user_base_path) {
498 STRNCPY(user_path, user_base_path);
508 "'%s', folder='%s', subfolder='%s'",
515 targetpath, targetpath_maxncpy, check_is_dir, user_path, folder_name, subfolder_name);
518 size_t targetpath_maxncpy,
519 const char *folder_name,
520 const char *subfolder_name)
523 const bool check_is_dir =
true;
525 targetpath, targetpath_maxncpy, folder_name, subfolder_name, version, check_is_dir);
539 size_t targetpath_maxncpy,
540 const char *folder_name,
541 const char *subfolder_name,
543 const bool check_is_dir)
547 if (
test_env_path(system_path,
"BLENDER_SYSTEM_RESOURCES", check_is_dir)) {
551 system_path[0] =
'\0';
553 if (system_base_path) {
554 STRNCPY(system_path, system_base_path);
558 if (!system_path[0]) {
564 "'%s', folder='%s', subfolder='%s'",
571 targetpath, targetpath_maxncpy, check_is_dir, system_path, folder_name, subfolder_name);
575 size_t targetpath_maxncpy,
576 const char *folder_name,
577 const char *subfolder_name)
580 const bool check_is_dir =
true;
582 targetpath, targetpath_maxncpy, folder_name, subfolder_name, version, check_is_dir);
592 const char *subfolder,
601 if (
get_path_user(path, path_maxncpy,
"datafiles", subfolder)) {
619 if (
get_path_user(path, path_maxncpy,
"datafiles", subfolder)) {
640 if (
get_path_user(path, path_maxncpy,
"config", subfolder)) {
649 if (
get_path_user(path, path_maxncpy,
"scripts", subfolder)) {
667 if (
get_path_user(path, path_maxncpy,
"extensions", subfolder)) {
679 if (
get_path_local(path, path_maxncpy,
"extensions", subfolder)) {
714 const char *subfolder)
718 const bool check_is_dir =
false;
723 path,
sizeof(path), subfolder,
"BLENDER_USER_DATAFILES", check_is_dir))
727 get_path_user_ex(path,
sizeof(path),
"datafiles", subfolder, version, check_is_dir);
731 path,
sizeof(path), subfolder,
"BLENDER_USER_CONFIG", check_is_dir))
735 get_path_user_ex(path,
sizeof(path),
"config", subfolder, version, check_is_dir);
739 path,
sizeof(path), subfolder,
"BLENDER_USER_SCRIPTS", check_is_dir))
743 get_path_user_ex(path,
sizeof(path),
"scripts", subfolder, version, check_is_dir);
747 path,
sizeof(path), subfolder,
"BLENDER_USER_EXTENSIONS", check_is_dir))
751 get_path_user_ex(path,
sizeof(path),
"extensions", subfolder, version, check_is_dir);
758 if (
'\0' == path[0]) {
779 if (!path.has_value()) {
781 if (path.has_value()) {
790 const bool check_is_dir,
797 ok =
get_path_user_ex(path,
sizeof(path),
nullptr,
nullptr, version, check_is_dir);
800 ok =
get_path_local_ex(path,
sizeof(path),
nullptr,
nullptr, version, check_is_dir);
818 const bool check_is_dir)
831#ifndef WITH_PYTHON_MODULE
845 const size_t program_filepath_maxncpy,
846 const char *program_name)
851 const char *path =
nullptr;
852 path = br_find_exe(
nullptr);
863 wchar_t *fullname_16 =
static_cast<wchar_t *
>(
864 MEM_mallocN(program_filepath_maxncpy *
sizeof(
wchar_t),
"ProgramPath"));
865 if (GetModuleFileNameW(0, fullname_16, program_filepath_maxncpy)) {
869 "path can't be found: \"%.*s\"",
870 int(program_filepath_maxncpy),
873 "path contains invalid characters or is too long (see console)",
886 if (program_name && program_name[0]) {
889 if (program_name[0] ==
'.') {
892 BLI_path_program_extensions_add_win32(
program_filepath, program_filepath_maxncpy);
899 BLI_path_program_extensions_add_win32(
program_filepath, program_filepath_maxncpy);
919#ifdef WITH_PYTHON_MODULE
926 if (
g_app.program_dirname[0] ==
'\0') {
930 g_app.program_filepath,
g_app.program_dirname,
sizeof(
g_app.program_dirname));
931 g_app.program_filepath[0] =
'\0';
936 g_app.program_filepath,
g_app.program_dirname,
sizeof(
g_app.program_dirname));
942#ifndef WITH_PYTHON_MODULE
945 return g_app.program_filepath;
951 return g_app.program_dirname;
955 const size_t program_filepath_maxncpy,
956 const int version_major,
957 const int version_minor)
961#ifdef PYTHON_EXECUTABLE_NAME
963 const char *python_build_def =
STRINGIFY(PYTHON_EXECUTABLE_NAME);
965 const char *basename =
"python";
966#if defined(WIN32) && !defined(NDEBUG)
967 const char *basename_debug =
"python_d";
969 char python_version[16];
971 const char *python_names[] = {
972#ifdef PYTHON_EXECUTABLE_NAME
975#if defined(WIN32) && !defined(NDEBUG)
981 bool is_found =
false;
983 SNPRINTF(python_version,
"%s%d.%d", basename, version_major, version_minor);
988 if (python_bin_dir.has_value()) {
990 for (
int i = 0; i <
ARRAY_SIZE(python_names); i++) {
992 program_filepath, program_filepath_maxncpy, python_bin_dir->c_str(), python_names[i]);
996 BLI_path_program_extensions_add_win32(
program_filepath, program_filepath_maxncpy)
1009 if (is_found ==
false) {
1010 for (
int i = 0; i <
ARRAY_SIZE(python_names); i++) {
1018 if (is_found ==
false) {
1038 "startup" SEP_STR "bl_app_templates_user",
1042 directories.
append(temp_dir);
1048 "startup" SEP_STR "bl_app_templates_system",
1049 "BLENDER_SYSTEM_SCRIPTS"))
1051 directories.
append(temp_dir);
1056 "startup" SEP_STR "bl_app_templates_system",
1060 directories.
append(temp_dir);
1075 for (
const std::string &directory : directories) {
1095 app_template, app_template_path,
sizeof(app_template_path)))
1111 for (
const std::string &subdir : directories) {
1114 for (
int f = 0; f < dir_num; f++) {
1142static void where_is_temp(
char *tempdir,
const size_t tempdir_maxncpy,
const char *userdir)
1151 const size_t tempdir_session_maxncpy,
1152 const char *tempdir)
1154 tempdir_session[0] =
'\0';
1156 const int tempdir_len = strlen(tempdir);
1158 const char *session_name =
"blender_XXXXXX";
1159 const int session_name_len = strlen(session_name);
1163 const int tempdir_session_len_required = tempdir_len + session_name_len + 1;
1165 if (tempdir_session_len_required <= tempdir_session_maxncpy) {
1167 BLI_string_join(tempdir_session, tempdir_session_maxncpy, tempdir, session_name);
1169 const bool needs_create = (_mktemp_s(tempdir_session, tempdir_session_len_required) == 0);
1171 const bool needs_create = (mkdtemp(tempdir_session) ==
nullptr);
1184 "Could not generate a temp file name for '%s', falling back to '%s'",
1187 BLI_strncpy(tempdir_session, tempdir, tempdir_session_maxncpy);
1203 g_app.temp_dirname_session,
sizeof(
g_app.temp_dirname_session),
g_app.temp_dirname_base);
1213 return g_app.temp_dirname_base;
#define BLENDER_USERPREF_FILE
@ BLENDER_USER_EXTENSIONS
@ BLENDER_SYSTEM_DATAFILES
@ BLENDER_SYSTEM_EXTENSIONS
@ BLENDER_RESOURCE_PATH_SYSTEM
@ BLENDER_RESOURCE_PATH_LOCAL
@ BLENDER_RESOURCE_PATH_USER
#define BLI_assert_unreachable()
#define BLI_assert_msg(a, msg)
File and directory operations.
int BLI_exists(const char *path) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
bool BLI_dir_create_recursive(const char *dirname) ATTR_NONNULL()
unsigned int BLI_filelist_dir_contents(const char *dirname, struct direntry **r_filelist)
int BLI_delete(const char *path, bool dir, bool recursive) ATTR_NONNULL()
bool BLI_is_dir(const char *path) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
void BLI_filelist_free(struct direntry *filelist, unsigned int nrentries)
Some types for dealing with directories.
void BLI_kdtree_nd_ free(KDTree *tree)
BLI_INLINE void BLI_listbase_clear(struct ListBase *lb)
void BLI_addtail(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
struct LinkData * BLI_genericNodeN(void *data)
bool BLI_path_program_search(char *program_filepath, size_t program_filepath_maxncpy, const char *program_name) ATTR_NONNULL(1
#define BLI_path_join(...)
const char * BLI_getenv(const char *env) ATTR_NONNULL(1) ATTR_WARN_UNUSED_RESULT
#define FILENAME_IS_CURRPAR(_n)
int BLI_path_canonicalize_native(char *path, int path_maxncpy)
void void BLI_path_split_dir_part(const char *filepath, char *dir, size_t dir_maxncpy) ATTR_NONNULL(1
size_t BLI_path_join_array(char *__restrict dst, const size_t dst_maxncpy, const char *path_array[], const int path_array_num) ATTR_NONNULL(1
int BLI_path_slash_ensure(char *path, size_t path_maxncpy) ATTR_NONNULL(1)
bool BLI_path_abs_from_cwd(char *path, size_t path_maxncpy) ATTR_NONNULL(1)
const char * BLI_path_slash_rfind(const char *path) ATTR_NONNULL(1) ATTR_WARN_UNUSED_RESULT
int BLI_path_normalize_native(char *path) ATTR_NONNULL(1)
char * BLI_strdup(const char *str) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1) ATTR_MALLOC
#define STRNCPY(dst, src)
#define SNPRINTF(dst, format,...)
char * BLI_strncpy(char *__restrict dst, const char *__restrict src, size_t dst_maxncpy) ATTR_NONNULL(1
size_t BLI_strncpy_wchar_as_utf8(char *__restrict dst, const wchar_t *__restrict src, size_t dst_maxncpy) ATTR_NONNULL(1
#define BLI_string_join(...)
bool void BLI_temp_directory_path_get(char *tempdir, const size_t tempdir_maxncpy) ATTR_NONNULL(1)
bool BLI_temp_directory_path_copy_if_valid(char *tempdir, const size_t tempdir_maxncpy, const char *dirpath) ATTR_NONNULL(1
Compatibility-like things for windows.
void BLI_windows_get_default_root_dir(char root_dir[4])
#define CLOG_ERROR(clg_ref,...)
#define CLOG_WARN(clg_ref,...)
#define CLOG_INFO(clg_ref, level,...)
const char * GHOST_getUserSpecialDir(GHOST_TUserSpecialDirTypes type)
const char * GHOST_getSystemDir(int version, const char *versionstr)
GHOST_TSuccess GHOST_DisposeSystemPaths()
const char * GHOST_getUserDir(int version, const char *versionstr)
@ GHOST_kUserSpecialDirCaches
@ GHOST_kUserSpecialDirDocuments
Read Guarded memory(de)allocation.
static const char _str_null[]
void BKE_tempdir_init(const char *userdir)
static bool is_appdir_init
std::optional< std::string > BKE_appdir_folder_id_create(const int folder_id, const char *subfolder)
char program_dirname[FILE_MAX]
static bool get_path_user_ex(char *targetpath, size_t targetpath_maxncpy, const char *folder_name, const char *subfolder_name, const int version, const bool check_is_dir)
static bool get_path_environment(char *targetpath, size_t targetpath_maxncpy, const char *subfolder_name, const char *envvar)
std::optional< std::string > BKE_appdir_resource_path_id(const int folder_id, const bool check_is_dir)
const char * BKE_appdir_folder_root()
const char * BKE_tempdir_session()
static void tempdir_session_create(char *tempdir_session, const size_t tempdir_session_maxncpy, const char *tempdir)
static void where_is_temp(char *tempdir, const size_t tempdir_maxncpy, const char *userdir)
char temp_dirname_session[FILE_MAX]
std::optional< std::string > BKE_appdir_folder_id_user_notest(const int folder_id, const char *subfolder)
bool BKE_appdir_folder_documents(char *dir)
static bool test_env_path(char *path, const char *envvar, const bool check_is_dir)
bool BKE_appdir_app_template_has_userpref(const char *app_template)
const char * BKE_appdir_program_dir()
static bool test_path(char *targetpath, size_t targetpath_maxncpy, const bool check_is_dir, const char *path_base, const char *folder_name, const char *subfolder_name)
bool BKE_appdir_program_python_search(char *program_filepath, const size_t program_filepath_maxncpy, const int version_major, const int version_minor)
static bool get_path_system_ex(char *targetpath, size_t targetpath_maxncpy, const char *folder_name, const char *subfolder_name, const int version, const bool check_is_dir)
void BKE_appdir_program_path_init(const char *argv0)
std::optional< std::string > BKE_appdir_resource_path_id_with_version(const int folder_id, const bool check_is_dir, const int version)
const char * BKE_appdir_folder_default_or_root()
bool BKE_appdir_folder_id_ex(const int folder_id, const char *subfolder, char *path, size_t path_maxncpy)
static char * blender_version_decimal(const int version)
const char * BKE_appdir_folder_home()
static blender::Vector< std::string > appdir_app_template_directories()
#define STR_OR_FALLBACK(a)
static bool get_path_local(char *targetpath, size_t targetpath_maxncpy, const char *folder_name, const char *subfolder_name)
std::optional< std::string > BKE_appdir_folder_id(const int folder_id, const char *subfolder)
bool BKE_appdir_app_template_any()
void BKE_appdir_app_templates(ListBase *templates)
bool BKE_appdir_font_folder_default(char *dir, size_t dir_maxncpy)
bool BKE_appdir_app_template_id_search(const char *app_template, char *path, size_t path_maxncpy)
const char * BKE_appdir_folder_default()
static bool get_path_local_ex(char *targetpath, size_t targetpath_maxncpy, const char *folder_name, const char *subfolder_name, const int version, const bool check_is_dir)
const char * BKE_appdir_program_path()
char temp_dirname_base[FILE_MAX]
void BKE_tempdir_session_purge()
static void where_am_i(char *program_filepath, const size_t program_filepath_maxncpy, const char *program_name)
static bool get_path_system(char *targetpath, size_t targetpath_maxncpy, const char *folder_name, const char *subfolder_name)
static bool get_path_user(char *targetpath, size_t targetpath_maxncpy, const char *folder_name, const char *subfolder_name)
char program_filepath[FILE_MAX]
const char * BKE_tempdir_base()
static bool get_path_environment_ex(char *targetpath, size_t targetpath_maxncpy, const char *subfolder_name, const char *envvar, const bool check_is_dir)
bool BKE_appdir_folder_caches(char *path, const size_t path_maxncpy)
void append(const T &value)
void *(* MEM_mallocN)(size_t len, const char *str)
void MEM_freeN(void *vmemh)
const char * BLI_expand_tilde(const char *path_with_tilde)
int conv_utf_16_to_8(const wchar_t *in16, char *out8, size_t size8)