From: Jiri Denemark Date: Tue, 3 Jun 2025 08:33:03 +0000 (+0200) Subject: util: Avoid statfs in virFileGetExistingParent X-Git-Tag: v11.5.0-rc1~114 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=74c591b7847d55a91030c373533c5c6d4abb1d20;p=thirdparty%2Flibvirt.git util: Avoid statfs in virFileGetExistingParent The code was separated from virFileIsSharedFSType which is Linux-only, but virFileGetExistingParent is also called from virFileIsSharedFSOverride which is OS independent. Thus we can't use statfs. Let's use virFileExists (access) instead, we were not interested in anything but success/failure from statfs anyway. Signed-off-by: Jiri Denemark Reviewed-by: Martin Kletzander --- diff --git a/src/util/virfile.c b/src/util/virfile.c index 06e8e08ddc..795f0218b4 100644 --- a/src/util/virfile.c +++ b/src/util/virfile.c @@ -3561,14 +3561,13 @@ static char * virFileGetExistingParent(const char *path) { g_autofree char *dirpath = g_strdup(path); - struct statfs sb; char *p = NULL; - /* Try less and less of the path until we get to a directory we can stat. + /* Try less and less of the path until we get to a directory we can access. * Even if we don't have 'x' permission on any directory in the path on the * NFS server (assuming it's NFS), we will be able to stat the mount point. */ - while (statfs(dirpath, &sb) < 0 && p != dirpath) { + while (!virFileExists(dirpath) && p != dirpath) { if (!(p = strrchr(dirpath, '/'))) { virReportSystemError(EINVAL, _("Invalid relative path '%1$s'"), path); diff --git a/tests/virfilemock.c b/tests/virfilemock.c index 4f1b8aecd7..5a09cce855 100644 --- a/tests/virfilemock.c +++ b/tests/virfilemock.c @@ -21,6 +21,7 @@ #include #include #include +#include #ifdef __linux__ # include #endif @@ -32,6 +33,7 @@ static FILE *(*real_setmntent)(const char *filename, const char *type); static int (*real_statfs)(const char *path, struct statfs *buf); static char *(*real_realpath)(const char *path, char *resolved); +static int (*real_access)(const char *path, int mode); static void @@ -43,6 +45,7 @@ init_syms(void) VIR_MOCK_REAL_INIT(setmntent); VIR_MOCK_REAL_INIT(statfs); VIR_MOCK_REAL_INIT(realpath); + VIR_MOCK_REAL_INIT(access); } @@ -200,3 +203,28 @@ realpath(const char *path, char *resolved) return real_realpath(path, resolved); } + + +int +access(const char *path, int mode) +{ + const char *mtab = getenv("LIBVIRT_MTAB"); + + init_syms(); + + if (mtab && mode == F_OK) { + struct statfs buf; + + /* The real statfs works on any existing file on a filesystem, while + * our mocked version only works on the mount point. Thus we have to + * pretend no files on the filesystem exist to make sure + * virFileGetExistingParent returns the mount point which can later be + * checked by statfs. Instead of checking we were called for a mount + * point by walking through the mtab, we just call our mocked statfs + * that does it for us. + */ + return statfs_mock(mtab, path, &buf); + } + + return real_access(path, mode); +}