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);
#include <stdio.h>
#include <mntent.h>
#include <sys/vfs.h>
+#include <unistd.h>
#ifdef __linux__
# include <linux/magic.h>
#endif
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
VIR_MOCK_REAL_INIT(setmntent);
VIR_MOCK_REAL_INIT(statfs);
VIR_MOCK_REAL_INIT(realpath);
+ VIR_MOCK_REAL_INIT(access);
}
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);
+}