summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobert Haas <rhaas@postgresql.org>2022-10-21 08:21:55 -0400
committerRobert Haas <rhaas@postgresql.org>2022-10-21 09:11:47 -0400
commitba58266eb8dbe56f5dd48dc584816104343ffe85 (patch)
tree0c0e56b65b5b22103ad162cd8b884c03aad9762f
parent61838d2dd3c49a4616bfae0b54f72ba4f893b7e1 (diff)
downloadpostgresql-ba58266eb8dbe56f5dd48dc584816104343ffe85.tar.gz
pg_basebackup: Fix cross-platform tablespace relocation.
Specifically, when pg_basebackup is invoked with -Tx=y, don't error out if x could plausibly be an absolute path either on Windows or on non-Windows systems. We don't know whether the remote system is running the same OS as the local system, so it's not appropriate to assume that our local rule about absolute pathnames is the same as the rule on the remote system. Patch by me, reviewed by Tom Lane, Andrew Dunstan, and Davinder Singh. Discussion: http://postgr.es/m/CA+TgmoY+jC3YiskomvYKDPK3FbrmsDU7_8+wMHt02HOdJeRb0g@mail.gmail.com
-rw-r--r--src/bin/pg_basebackup/pg_basebackup.c20
-rw-r--r--src/include/port.h34
2 files changed, 34 insertions, 20 deletions
diff --git a/src/bin/pg_basebackup/pg_basebackup.c b/src/bin/pg_basebackup/pg_basebackup.c
index 9793a08cc0..21a3307ec4 100644
--- a/src/bin/pg_basebackup/pg_basebackup.c
+++ b/src/bin/pg_basebackup/pg_basebackup.c
@@ -276,12 +276,22 @@ tablespace_list_append(const char *arg)
}
/*
- * This check isn't absolutely necessary. But all tablespaces are created
- * with absolute directories, so specifying a non-absolute path here would
- * just never match, possibly confusing users. It's also good to be
- * consistent with the new_dir check.
+ * All tablespaces are created with absolute directories, so specifying a
+ * non-absolute path here would just never match, possibly confusing users.
+ * Since we don't know whether the remote side is Windows or not, and it
+ * might be different than the local side, permit any path that could be
+ * absolute under either set of rules.
+ *
+ * (There is little practical risk of confusion here, because someone
+ * running entirely on Linux isn't likely to have a relative path that
+ * begins with a backslash or something that looks like a drive
+ * specification. If they do, and they also incorrectly believe that
+ * a relative path is acceptable here, we'll silently fail to warn them
+ * of their mistake, and the -T option will just not get applied, same
+ * as if they'd specified -T for a nonexistent tablespace.)
*/
- if (!is_absolute_path(cell->old_dir))
+ if (!is_nonwindows_absolute_path(cell->old_dir) &&
+ !is_windows_absolute_path(cell->old_dir))
{
fprintf(stderr, _("%s: old directory is not an absolute path in tablespace mapping: %s\n"),
progname, cell->old_dir);
diff --git a/src/include/port.h b/src/include/port.h
index 74992715e4..6fe3d4c804 100644
--- a/src/include/port.h
+++ b/src/include/port.h
@@ -66,28 +66,32 @@ extern void get_parent_directory(char *path);
extern char **pgfnames(const char *path);
extern void pgfnames_cleanup(char **filenames);
-/*
- * is_absolute_path
- *
- * By making this a macro we avoid needing to include path.c in libpq.
- */
-#ifndef WIN32
-#define IS_DIR_SEP(ch) ((ch) == '/')
-
-#define is_absolute_path(filename) \
+#define IS_NONWINDOWS_DIR_SEP(ch) ((ch) == '/')
+#define is_nonwindows_absolute_path(filename) \
( \
- IS_DIR_SEP((filename)[0]) \
+ IS_NONWINDOWS_DIR_SEP((filename)[0]) \
)
-#else
-#define IS_DIR_SEP(ch) ((ch) == '/' || (ch) == '\\')
+#define IS_WINDOWS_DIR_SEP(ch) ((ch) == '/' || (ch) == '\\')
/* See path_is_relative_and_below_cwd() for how we handle 'E:abc'. */
-#define is_absolute_path(filename) \
+#define is_windows_absolute_path(filename) \
( \
- IS_DIR_SEP((filename)[0]) || \
+ IS_WINDOWS_DIR_SEP((filename)[0]) || \
(isalpha((unsigned char) ((filename)[0])) && (filename)[1] == ':' && \
- IS_DIR_SEP((filename)[2])) \
+ IS_WINDOWS_DIR_SEP((filename)[2])) \
)
+
+/*
+ * is_absolute_path and IS_DIR_SEP
+ *
+ * By using macros here we avoid needing to include path.c in libpq.
+ */
+#ifndef WIN32
+#define IS_DIR_SEP(ch) IS_NONWINDOWS_DIR_SEP(ch)
+#define is_absolute_path(filename) is_nonwindows_absolute_path(filename)
+#else
+#define IS_DIR_SEP(ch) IS_WINDOWS_DIR_SEP(ch)
+#define is_absolute_path(filename) is_windows_absolute_path(filename)
#endif
/* Portable locale initialization (in exec.c) */