From b4d601ba87ade7fa1a3a4f9c0c268659c15a35c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= Date: Mon, 23 Dec 2019 14:21:54 +0000 Subject: [PATCH] util: use realpath/g_canonicalize_filename MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The canonicalize_file_name(path) is equivalent to calling realpath(path, NULL). Passing NULL for the second arg of realpath is not standardized behaviour, however, Linux, FreeBSD > 6.4 and macOS > 10.5 all support this critical extension. This leaves Windows which doesn't provide realpath at all. The g_canonicalize_filename() function doesn't expand symlinks, so is not strictly equivalent to realpath() but is close enough for our Windows portability needs right now. Reviewed-by: Fabiano FidĂȘncio Signed-off-by: Daniel P. BerrangĂ© --- src/util/virfile.c | 9 ++++++++- tests/virfilemock.c | 12 +++++++----- 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/src/util/virfile.c b/src/util/virfile.c index 9787086f3d..4fc872ef1d 100644 --- a/src/util/virfile.c +++ b/src/util/virfile.c @@ -3256,7 +3256,14 @@ virFileSanitizePath(const char *path) char * virFileCanonicalizePath(const char *path) { - return canonicalize_file_name(path); /* exempt from syntax-check */ +#ifdef WIN32 + /* Does not resolve symlinks, only expands . & .. & repeated /. + * It will never fail, so sanitize errno to indicate success */ + errno = 0; + return g_canonicalize_filename(path, NULL); +#else + return realpath(path, NULL); /* exempt from syntax-check */ +#endif } /** diff --git a/tests/virfilemock.c b/tests/virfilemock.c index 65685c6d26..802ee9b5f9 100644 --- a/tests/virfilemock.c +++ b/tests/virfilemock.c @@ -24,6 +24,7 @@ #if HAVE_LINUX_MAGIC_H # include #endif +#include #include "virmock.h" #include "virstring.h" @@ -33,7 +34,7 @@ static FILE *(*real_setmntent)(const char *filename, const char *type); static int (*real_statfs)(const char *path, struct statfs *buf); -static char *(*real_canonicalize_file_name)(const char *path); +static char *(*real_realpath)(const char *path, char *resolved); static void @@ -44,7 +45,7 @@ init_syms(void) VIR_MOCK_REAL_INIT(setmntent); VIR_MOCK_REAL_INIT(statfs); - VIR_MOCK_REAL_INIT(canonicalize_file_name); + VIR_MOCK_REAL_INIT(realpath); } @@ -116,7 +117,7 @@ statfs_mock(const char *mtab, /* We don't need to do this in callers because real statfs(2) * does that for us. However, in mocked implementation we * need to do this. */ - if (!(canonPath = canonicalize_file_name(path))) + if (!(canonPath = realpath(path, NULL))) return -1; while (getmntent_r(f, &mb, mntbuf, sizeof(mntbuf))) { @@ -178,7 +179,7 @@ statfs(const char *path, struct statfs *buf) char * -canonicalize_file_name(const char *path) +realpath(const char *path, char *resolved) { init_syms(); @@ -187,6 +188,7 @@ canonicalize_file_name(const char *path) const char *p; char *ret; + assert(resolved == NULL); if ((p = STRSKIP(path, "/some/symlink"))) ret = g_strdup_printf("/gluster%s", p); else @@ -195,5 +197,5 @@ canonicalize_file_name(const char *path) return ret; } - return real_canonicalize_file_name(path); + return real_realpath(path, resolved); }