Since directories can be used for <filesystem> passthrough, they are basically storage volumes. v2: Skip ., .., lost+found dirs v3: Use gnulib last_component Signed-off-by: Cole Robinson <crobinso@xxxxxxxxxx> --- src/storage/storage_backend.c | 45 ++++++++++++++++++++++++++++++++------ src/storage/storage_backend.h | 7 +++++- src/storage/storage_backend_fs.c | 14 ++++++++--- src/util/storage_file.c | 30 ++++++++++++++++++++++++- 4 files changed, 83 insertions(+), 13 deletions(-) diff --git a/src/storage/storage_backend.c b/src/storage/storage_backend.c index 02e455f..f23cf60 100644 --- a/src/storage/storage_backend.c +++ b/src/storage/storage_backend.c @@ -36,6 +36,7 @@ #include <sys/stat.h> #include <sys/param.h> #include <dirent.h> +#include <dirname.h> #ifdef __linux__ # include <sys/ioctl.h> # include <linux/fs.h> @@ -994,6 +995,7 @@ virStorageBackendVolOpenCheckMode(const char *path, unsigned int flags) { int fd, mode = 0; struct stat sb; + char *base = last_component(path); if ((fd = open(path, O_RDONLY|O_NONBLOCK|O_NOCTTY)) < 0) { if ((errno == ENOENT || errno == ELOOP) && @@ -1022,9 +1024,21 @@ virStorageBackendVolOpenCheckMode(const char *path, unsigned int flags) mode = VIR_STORAGE_VOL_OPEN_CHAR; else if (S_ISBLK(sb.st_mode)) mode = VIR_STORAGE_VOL_OPEN_BLOCK; + else if (S_ISDIR(sb.st_mode)) { + mode = VIR_STORAGE_VOL_OPEN_DIR; + + if (STREQ(base, ".") || + STREQ(base, "..") || + STREQ(base, "lost+found")) { + VIR_FORCE_CLOSE(fd); + VIR_INFO("Skipping special dir '%s'", base); + return -2; + } + } if (!(mode & flags)) { VIR_FORCE_CLOSE(fd); + VIR_INFO("Skipping volume '%s'", path); if (mode & VIR_STORAGE_VOL_OPEN_ERROR) { virStorageReportError(VIR_ERR_INTERNAL_ERROR, @@ -1047,11 +1061,13 @@ int virStorageBackendVolOpen(const char *path) int virStorageBackendUpdateVolTargetInfo(virStorageVolTargetPtr target, unsigned long long *allocation, - unsigned long long *capacity) + unsigned long long *capacity, + unsigned int openflags) { int ret, fd; - if ((ret = virStorageBackendVolOpen(target->path)) < 0) + if ((ret = virStorageBackendVolOpenCheckMode(target->path, + openflags)) < 0) return ret; fd = ret; @@ -1066,24 +1082,34 @@ virStorageBackendUpdateVolTargetInfo(virStorageVolTargetPtr target, } int -virStorageBackendUpdateVolInfo(virStorageVolDefPtr vol, - int withCapacity) +virStorageBackendUpdateVolInfoFlags(virStorageVolDefPtr vol, + int withCapacity, + unsigned int openflags) { int ret; if ((ret = virStorageBackendUpdateVolTargetInfo(&vol->target, - &vol->allocation, - withCapacity ? &vol->capacity : NULL)) < 0) + &vol->allocation, + withCapacity ? &vol->capacity : NULL, + openflags)) < 0) return ret; if (vol->backingStore.path && (ret = virStorageBackendUpdateVolTargetInfo(&vol->backingStore, - NULL, NULL)) < 0) + NULL, NULL, + VIR_STORAGE_VOL_OPEN_DEFAULT)) < 0) return ret; return 0; } +int virStorageBackendUpdateVolInfo(virStorageVolDefPtr vol, + int withCapacity) +{ + return virStorageBackendUpdateVolInfoFlags(vol, withCapacity, + VIR_STORAGE_VOL_OPEN_DEFAULT); +} + /* * virStorageBackendUpdateVolTargetInfoFD: * @conn: connection to report errors on @@ -1125,6 +1151,11 @@ virStorageBackendUpdateVolTargetInfoFD(virStorageVolTargetPtr target, */ if (capacity) *capacity = sb.st_size; + } else if (S_ISDIR(sb.st_mode)) { + *allocation = 0; + if (capacity) + *capacity = 0; + } else { off_t end; /* XXX this is POSIX compliant, but doesn't work for CHAR files, diff --git a/src/storage/storage_backend.h b/src/storage/storage_backend.h index fcfbed0..67ac32c 100644 --- a/src/storage/storage_backend.h +++ b/src/storage/storage_backend.h @@ -93,6 +93,7 @@ enum { VIR_STORAGE_VOL_OPEN_REG = 1 << 1, /* regular files okay */ VIR_STORAGE_VOL_OPEN_BLOCK = 1 << 2, /* block files okay */ VIR_STORAGE_VOL_OPEN_CHAR = 1 << 3, /* char files okay */ + VIR_STORAGE_VOL_OPEN_DIR = 1 << 4, /* directories okay */ }; # define VIR_STORAGE_VOL_OPEN_DEFAULT (VIR_STORAGE_VOL_OPEN_ERROR |\ @@ -107,9 +108,13 @@ ATTRIBUTE_NONNULL(1); int virStorageBackendUpdateVolInfo(virStorageVolDefPtr vol, int withCapacity); +int virStorageBackendUpdateVolInfoFlags(virStorageVolDefPtr vol, + int withCapacity, + unsigned int openflags); int virStorageBackendUpdateVolTargetInfo(virStorageVolTargetPtr target, unsigned long long *allocation, - unsigned long long *capacity); + unsigned long long *capacity, + unsigned int openflags); int virStorageBackendUpdateVolTargetInfoFD(virStorageVolTargetPtr target, int fd, unsigned long long *allocation, diff --git a/src/storage/storage_backend_fs.c b/src/storage/storage_backend_fs.c index b8d4d63..3f4d978 100644 --- a/src/storage/storage_backend_fs.c +++ b/src/storage/storage_backend_fs.c @@ -48,6 +48,11 @@ #define VIR_FROM_THIS VIR_FROM_STORAGE +#define VIR_STORAGE_VOL_FS_OPEN_FLAGS (VIR_STORAGE_VOL_OPEN_DEFAULT |\ + VIR_STORAGE_VOL_OPEN_DIR) +#define VIR_STORAGE_VOL_FS_REFRESH_FLAGS (VIR_STORAGE_VOL_FS_OPEN_FLAGS &\ + ~VIR_STORAGE_VOL_OPEN_ERROR) + static int ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3) virStorageBackendProbeTarget(virStorageVolTargetPtr target, char **backingStore, @@ -65,7 +70,7 @@ virStorageBackendProbeTarget(virStorageVolTargetPtr target, *encryption = NULL; if ((ret = virStorageBackendVolOpenCheckMode(target->path, - (VIR_STORAGE_VOL_OPEN_DEFAULT & ~VIR_STORAGE_VOL_OPEN_ERROR))) < 0) + VIR_STORAGE_VOL_FS_REFRESH_FLAGS)) < 0) return ret; /* Take care to propagate ret, it is not always -1 */ fd = ret; @@ -676,8 +681,8 @@ virStorageBackendFileSystemRefresh(virConnectPtr conn ATTRIBUTE_UNUSED, vol->backingStore.format = backingStoreFormat; if (virStorageBackendUpdateVolTargetInfo(&vol->backingStore, - NULL, - NULL) < 0) { + NULL, NULL, + VIR_STORAGE_VOL_OPEN_DEFAULT) < 0) { /* The backing file is currently unavailable, the capacity, * allocation, owner, group and mode are unknown. Just log the * error an continue. @@ -941,7 +946,8 @@ virStorageBackendFileSystemVolRefresh(virConnectPtr conn, int ret; /* Refresh allocation / permissions info in case its changed */ - ret = virStorageBackendUpdateVolInfo(vol, 0); + ret = virStorageBackendUpdateVolInfoFlags(vol, 0, + VIR_STORAGE_VOL_FS_OPEN_FLAGS); if (ret < 0) return ret; diff --git a/src/util/storage_file.c b/src/util/storage_file.c index ede79fa..8dbd933 100644 --- a/src/util/storage_file.c +++ b/src/util/storage_file.c @@ -24,6 +24,7 @@ #include <config.h> #include "storage_file.h" +#include <sys/stat.h> #include <unistd.h> #include <fcntl.h> #ifdef __linux__ @@ -736,6 +737,19 @@ virStorageFileProbeFormatFromFD(const char *path, int fd) unsigned char *head; ssize_t len = STORAGE_MAX_HEAD; int ret = -1; + struct stat sb; + + if (fstat(fd, &sb) < 0) { + virReportSystemError(errno, + _("cannot stat file '%s'"), + path); + return -1; + } + + /* No header to probe for directories */ + if (S_ISDIR(sb.st_mode)) { + return VIR_STORAGE_FILE_DIR; + } if (VIR_ALLOC_N(head, len) < 0) { virReportOOMError(); @@ -812,9 +826,10 @@ virStorageFileGetMetadataFromFD(const char *path, int format, virStorageFileMetadata *meta) { - unsigned char *head; + unsigned char *head = NULL; ssize_t len = STORAGE_MAX_HEAD; int ret = -1; + struct stat sb; if (VIR_ALLOC_N(head, len) < 0) { virReportOOMError(); @@ -823,6 +838,19 @@ virStorageFileGetMetadataFromFD(const char *path, memset(meta, 0, sizeof (*meta)); + if (fstat(fd, &sb) < 0) { + virReportSystemError(errno, + _("cannot stat file '%s'"), + path); + return -1; + } + + /* No header to probe for directories */ + if (S_ISDIR(sb.st_mode)) { + ret = 0; + goto cleanup; + } + if (lseek(fd, 0, SEEK_SET) == (off_t)-1) { virReportSystemError(errno, _("cannot seek to start of '%s'"), path); goto cleanup; -- 1.7.4.4 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list