BLI_path: add native path canonicalize function
This function handles cleaning valid system paths that are functional when passed to `open(..)` but may be relative to the current working directory or have redundant slashers that can be normalized.
This commit is contained in:
@@ -120,7 +120,18 @@ enum {
|
||||
|
||||
typedef struct Main {
|
||||
struct Main *next, *prev;
|
||||
/** The file-path of this blend file, an empty string indicates an unsaved file. */
|
||||
/**
|
||||
* The file-path of this blend file, an empty string indicates an unsaved file.
|
||||
*
|
||||
* \note For the current loaded blend file this path should be absolute & normalized
|
||||
* to prevent redundant leading slashes or current-working-directory relative paths
|
||||
* from causing problems with absolute/relative patch conversion that relies on this being
|
||||
* an absolute path. See #BLI_path_canonicalize_native.
|
||||
*
|
||||
* This rule is not strictly enforced as in some cases loading a #Main is performed
|
||||
* to read data temporarily (preferences & startup) for e.g.
|
||||
* where the `filepath` is not persistent or used as a basis for other paths.
|
||||
*/
|
||||
char filepath[1024]; /* 1024 = FILE_MAX */
|
||||
short versionfile, subversionfile; /* see BLENDER_FILE_VERSION, BLENDER_FILE_SUBVERSION */
|
||||
short minversionfile, minsubversionfile;
|
||||
|
||||
@@ -897,8 +897,7 @@ void BKE_appdir_program_path_init(const char *argv0)
|
||||
* Otherwise other methods of detecting the binary that override this argument
|
||||
* which must point to the Python module for data-files to be detected. */
|
||||
STRNCPY(g_app.program_filepath, argv0);
|
||||
BLI_path_abs_from_cwd(g_app.program_filepath, sizeof(g_app.program_filepath));
|
||||
BLI_path_normalize_native(g_app.program_filepath);
|
||||
BLI_path_canonicalize_native(g_app.program_filepath, sizeof(g_app.program_filepath));
|
||||
|
||||
if (g_app.program_dirname[0] == '\0') {
|
||||
/* First time initializing, the file binary path isn't valid from a Python module.
|
||||
|
||||
@@ -185,6 +185,28 @@ void BLI_path_normalize_unc(char *path, int path_maxncpy);
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Path Canonicalize
|
||||
* \{ */
|
||||
|
||||
/**
|
||||
* Convert `path` to a canonical representation.
|
||||
* This is intended for system paths (passed in as command-line arguments of via scripts)
|
||||
* which are valid in that they resolve to a file/directory and but could be `CWD` relative or
|
||||
* contain redundant slashes that cause absolute/relative conversion to fail.
|
||||
* (specifically the "//" prefix used by Blender).
|
||||
*
|
||||
* Perform the following operations:
|
||||
*
|
||||
* - Make absolute (relative to the current working directory).
|
||||
* - Convert slash direction (WIN32 only, as other systems may use back-slashes in filenames).
|
||||
* - Normalize redundant slashes.
|
||||
* - Strip trailing slashes.
|
||||
*/
|
||||
int BLI_path_canonicalize_native(char *path, int path_maxncpy);
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Path FileName Manipulation
|
||||
* \{ */
|
||||
|
||||
@@ -43,6 +43,7 @@ static int BLI_path_unc_prefix_len(const char *path);
|
||||
|
||||
#ifdef WIN32
|
||||
static bool BLI_path_is_abs_win32(const char *path);
|
||||
static int BLI_path_win32_prefix_len(const char *path);
|
||||
#endif /* WIN32 */
|
||||
|
||||
/**
|
||||
@@ -384,6 +385,29 @@ int BLI_path_normalize_dir(char *dir, size_t dir_maxncpy)
|
||||
return BLI_path_slash_ensure_ex(dir, dir_maxncpy, dir_len);
|
||||
}
|
||||
|
||||
int BLI_path_canonicalize_native(char *path, int path_maxncpy)
|
||||
{
|
||||
BLI_path_abs_from_cwd(path, path_maxncpy);
|
||||
/* As these are system level paths, only convert slashes
|
||||
* if the alternate direction is accepted as a slash. */
|
||||
if (BLI_path_slash_is_native_compat(ALTSEP)) {
|
||||
BLI_path_slash_native(path);
|
||||
}
|
||||
int path_len = BLI_path_normalize_native(path);
|
||||
/* Strip trailing slash but don't strip `/` away to nothing. */
|
||||
if (path_len > 1 && path[path_len - 1] == SEP) {
|
||||
#ifdef WIN32
|
||||
/* Don't strip `C:\` -> `C:` as this is no longer a valid directory. */
|
||||
if (BLI_path_win32_prefix_len(path) + 1 < path_len)
|
||||
#endif
|
||||
{
|
||||
path_len -= 1;
|
||||
path[path_len] = '\0';
|
||||
}
|
||||
}
|
||||
return path_len;
|
||||
}
|
||||
|
||||
bool BLI_path_make_safe_filename_ex(char *fname, bool allow_tokens)
|
||||
{
|
||||
#define INVALID_CHARS \
|
||||
@@ -529,6 +553,16 @@ static int BLI_path_unc_prefix_len(const char *path)
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef WIN32
|
||||
static int BLI_path_win32_prefix_len(const char *path)
|
||||
{
|
||||
if (BLI_path_is_win32_drive(path)) {
|
||||
return 2;
|
||||
}
|
||||
return BLI_path_unc_prefix_len(path);
|
||||
}
|
||||
#endif
|
||||
|
||||
bool BLI_path_is_win32_drive(const char *path)
|
||||
{
|
||||
return isalpha(path[0]) && (path[1] == ':');
|
||||
|
||||
@@ -2797,8 +2797,7 @@ static int wm_open_mainfile__open(bContext *C, wmOperator *op)
|
||||
bool success;
|
||||
|
||||
RNA_string_get(op->ptr, "filepath", filepath);
|
||||
BLI_path_abs_from_cwd(filepath, sizeof(filepath));
|
||||
BLI_path_normalize_native(filepath);
|
||||
BLI_path_canonicalize_native(filepath, sizeof(filepath));
|
||||
|
||||
/* re-use last loaded setting so we can reload a file without changing */
|
||||
wm_open_init_load_ui(op, false);
|
||||
@@ -3103,8 +3102,7 @@ static int wm_recover_auto_save_exec(bContext *C, wmOperator *op)
|
||||
bool success;
|
||||
|
||||
RNA_string_get(op->ptr, "filepath", filepath);
|
||||
BLI_path_abs_from_cwd(filepath, sizeof(filepath));
|
||||
BLI_path_normalize_native(filepath);
|
||||
BLI_path_canonicalize_native(filepath, sizeof(filepath));
|
||||
|
||||
wm_open_init_use_scripts(op, true);
|
||||
SET_FLAG_FROM_TEST(G.f, RNA_boolean_get(op->ptr, "use_scripts"), G_FLAG_SCRIPT_AUTOEXEC);
|
||||
@@ -3246,8 +3244,7 @@ static int wm_save_as_mainfile_exec(bContext *C, wmOperator *op)
|
||||
const bool is_filepath_set = RNA_struct_property_is_set(op->ptr, "filepath");
|
||||
if (is_filepath_set) {
|
||||
RNA_string_get(op->ptr, "filepath", filepath);
|
||||
BLI_path_abs_from_cwd(filepath, sizeof(filepath));
|
||||
BLI_path_normalize_native(filepath);
|
||||
BLI_path_canonicalize_native(filepath, sizeof(filepath));
|
||||
}
|
||||
else {
|
||||
STRNCPY(filepath, BKE_main_blendfile_path(bmain));
|
||||
|
||||
@@ -1866,7 +1866,7 @@ static int arg_handle_python_file_run(int argc, const char **argv, void *data)
|
||||
/* Make the path absolute because its needed for relative linked blends to be found */
|
||||
char filepath[FILE_MAX];
|
||||
STRNCPY(filepath, argv[1]);
|
||||
BLI_path_abs_from_cwd(filepath, sizeof(filepath));
|
||||
BLI_path_canonicalize_native(filepath, sizeof(filepath));
|
||||
|
||||
bool ok;
|
||||
BPY_CTX_SETUP(ok = BPY_run_filepath(C, filepath, NULL));
|
||||
@@ -2063,9 +2063,7 @@ static int arg_handle_load_file(int UNUSED(argc), const char **argv, void *data)
|
||||
}
|
||||
|
||||
STRNCPY(filepath, argv[0]);
|
||||
BLI_path_slash_native(filepath);
|
||||
BLI_path_abs_from_cwd(filepath, sizeof(filepath));
|
||||
BLI_path_normalize_native(filepath);
|
||||
BLI_path_canonicalize_native(filepath, sizeof(filepath));
|
||||
|
||||
/* load the file */
|
||||
BKE_reports_init(&reports, RPT_PRINT);
|
||||
|
||||
Reference in New Issue
Block a user