Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCampbell Barton <ideasman42@gmail.com>2021-12-16 08:17:28 +0300
committerCampbell Barton <ideasman42@gmail.com>2021-12-16 08:27:35 +0300
commit8dbd406ea0f495b3d404a7433a32b4781953e55a (patch)
treec8056b188efa299986b7d936e0b578e9f1f43232
parent15c36170092d26b7d6106924270b6e590627fcb6 (diff)
WM: various changes to file writing behavior
Saving with only a filename (from Python) wasn't being prevented, while it would successfully write the file to the working-directory, path remapping and setting relative paths wouldn't work afterwards as `Main.filepath` would have no directory component. Disallow this since it's a corner case which only ever occurs when path names without any directories are used from Python, the overhead of expanding the working-directory for all data saving operations isn't worthwhile. The following changes have been made: - bpy.ops.wm.save_mainfile() without a filepath argument fails & reports and error when the file hasn't been saved. Previously it would write to "untitled.blend" and set the `G.main->filepath` to this as well. - bpy.ops.wm.save_mainfile(filepath="untitled.blend") fails & reports and error as the filename has no directory component. - `BLI_path_is_abs_from_cwd` was added to check if the path would attempt to expand to the CWD.
-rw-r--r--source/blender/blenlib/BLI_path_util.h8
-rw-r--r--source/blender/blenlib/intern/path_util.c30
-rw-r--r--source/blender/blenloader/intern/writefile.c1
-rw-r--r--source/blender/windowmanager/intern/wm_files.c26
4 files changed, 49 insertions, 16 deletions
diff --git a/source/blender/blenlib/BLI_path_util.h b/source/blender/blenlib/BLI_path_util.h
index 9e2970f6013..3cffecae187 100644
--- a/source/blender/blenlib/BLI_path_util.h
+++ b/source/blender/blenlib/BLI_path_util.h
@@ -324,8 +324,14 @@ void BLI_path_frame_strip(char *path, char *ext) ATTR_NONNULL();
*/
bool BLI_path_frame_check_chars(const char *path) ATTR_NONNULL();
/**
+ * Checks for a relative path (ignoring Blender's "//") prefix
+ * (unlike `!BLI_path_is_rel(path)`).
+ * When false, #BLI_path_abs_from_cwd would expand the absolute path.
+ */
+bool BLI_path_is_abs_from_cwd(const char *path) ATTR_NONNULL();
+/**
* Checks for relative path, expanding them relative to the current working directory.
- * Returns true if the expansion was performed.
+ * \returns true if the expansion was performed.
*
* \note Should only be called with command line paths.
* This is _not_ something Blender's internal paths support, instead they use the "//" prefix.
diff --git a/source/blender/blenlib/intern/path_util.c b/source/blender/blenlib/intern/path_util.c
index c40eed711f5..de71188abfe 100644
--- a/source/blender/blenlib/intern/path_util.c
+++ b/source/blender/blenlib/intern/path_util.c
@@ -1002,25 +1002,30 @@ bool BLI_path_abs(char *path, const char *basepath)
return wasrelative;
}
-bool BLI_path_abs_from_cwd(char *path, const size_t maxlen)
+bool BLI_path_is_abs_from_cwd(const char *path)
{
-#ifdef DEBUG_STRSIZE
- memset(path, 0xff, sizeof(*path) * maxlen);
-#endif
- bool wasrelative = true;
- const int filelen = strlen(path);
+ bool is_abs = false;
+ const int path_len_clamp = BLI_strnlen(path, 3);
#ifdef WIN32
- if ((filelen >= 3 && BLI_path_is_abs(path)) || BLI_path_is_unc(path)) {
- wasrelative = false;
+ if ((ppath_len_clamp >= 3 && BLI_path_is_abs(path)) || BLI_path_is_unc(path)) {
+ is_abs = true;
}
#else
- if (filelen >= 2 && path[0] == '/') {
- wasrelative = false;
+ if (path_len_clamp >= 2 && path[0] == '/') {
+ is_abs = true;
}
#endif
+ return is_abs;
+}
- if (wasrelative) {
+bool BLI_path_abs_from_cwd(char *path, const size_t maxlen)
+{
+#ifdef DEBUG_STRSIZE
+ memset(path, 0xff, sizeof(*path) * maxlen);
+#endif
+
+ if (!BLI_path_is_abs_from_cwd(path)) {
char cwd[FILE_MAX];
/* in case the full path to the blend isn't used */
if (BLI_current_working_dir(cwd, sizeof(cwd))) {
@@ -1031,9 +1036,10 @@ bool BLI_path_abs_from_cwd(char *path, const size_t maxlen)
else {
printf("Could not get the current working directory - $PWD for an unknown reason.\n");
}
+ return true;
}
- return wasrelative;
+ return false;
}
#ifdef _WIN32
diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c
index e0ff70d4b49..aa3eef4b475 100644
--- a/source/blender/blenloader/intern/writefile.c
+++ b/source/blender/blenloader/intern/writefile.c
@@ -1319,6 +1319,7 @@ bool BLO_write_file(Main *mainvar,
ReportList *reports)
{
BLI_assert(!BLI_path_is_rel(filepath));
+ BLI_assert(BLI_path_is_abs_from_cwd(filepath));
char tempname[FILE_MAX + 1];
WriteWrap ww;
diff --git a/source/blender/windowmanager/intern/wm_files.c b/source/blender/windowmanager/intern/wm_files.c
index 7ac9395e16c..1d3fa158ac1 100644
--- a/source/blender/windowmanager/intern/wm_files.c
+++ b/source/blender/windowmanager/intern/wm_files.c
@@ -3067,12 +3067,32 @@ static int wm_save_as_mainfile_exec(bContext *C, wmOperator *op)
BLO_WRITE_PATH_REMAP_NONE;
save_set_compress(op);
- if (RNA_struct_property_is_set(op->ptr, "filepath")) {
+ const bool is_filepath_set = RNA_struct_property_is_set(op->ptr, "filepath");
+ if (is_filepath_set) {
RNA_string_get(op->ptr, "filepath", path);
}
else {
- BLI_strncpy(path, BKE_main_blendfile_path(bmain), FILE_MAX);
- wm_filepath_default(bmain, path);
+ STRNCPY(path, BKE_main_blendfile_path(bmain));
+ }
+
+ if (path[0] == '\0') {
+ BKE_report(op->reports,
+ RPT_ERROR,
+ "Unable to save an unsaved file with an empty or unset \"filepath\" property");
+ return OPERATOR_CANCELLED;
+ }
+
+ /* NOTE(@campbellbarton): only check this for file-path properties so saving an already
+ * saved file never fails with an error.
+ * Even though this should never happen, there may be some corner case where a malformed
+ * path is stored in `G.main->filepath`: when the file path is initialized from recovering
+ * a blend file - for example, so in this case failing to save isn't ideal. */
+ if (is_filepath_set && !BLI_path_is_abs_from_cwd(path)) {
+ BKE_reportf(op->reports,
+ RPT_ERROR,
+ "The \"filepath\" property was not an absolute path: \"%s\"",
+ path);
+ return OPERATOR_CANCELLED;
}
const int fileflags_orig = G.fileflags;