Rename virStorageBackendUpdateVolTargetInfo to virStorageFileGetInfo() and move to util/storage_file.[ch] * src/storage/storage_backend.[ch]: move code from here ... * src/util/storage_file.[ch]: ... to here * src/libvirt_private.syms: export new functions * src/storage/storage_backend_fs.c, src/storage/storage_backend_mpath.c, src/storage/storage_backend_scsi.c: update from above changes * po/POTFILES.in: add storage_file.c --- po/POTFILES.in | 1 + src/libvirt_private.syms | 2 + src/storage/storage_backend.c | 148 ++------------------------------- src/storage/storage_backend.h | 9 -- src/storage/storage_backend_fs.c | 18 ++-- src/storage/storage_backend_mpath.c | 7 +- src/storage/storage_backend_scsi.c | 7 +- src/util/storage_file.c | 157 +++++++++++++++++++++++++++++++++++ src/util/storage_file.h | 13 +++ 9 files changed, 194 insertions(+), 168 deletions(-) diff --git a/po/POTFILES.in b/po/POTFILES.in index 9f21459..30c52f5 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -45,6 +45,7 @@ src/util/iptables.c src/util/logging.c src/util/pci.c src/util/storage_encryption.c +src/util/storage_file.c src/util/util.c src/util/uuid.c src/util/virterror.c diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 76a6e1b..9b6f4a7 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -393,6 +393,8 @@ virStorageGenerateQcowPassphrase; # storage_file.h virStorageFileFormatTypeToString; virStorageFileFormatTypeFromString; +virStorageFileGetInfo; +virStorageFileGetInfoFromFD; # threads.h virMutexInit; diff --git a/src/storage/storage_backend.c b/src/storage/storage_backend.c index 18a69be..e214c3f 100644 --- a/src/storage/storage_backend.c +++ b/src/storage/storage_backend.c @@ -73,10 +73,6 @@ #include "storage_backend_fs.h" #endif -#ifndef DEV_BSIZE -#define DEV_BSIZE 512 -#endif - #define VIR_FROM_THIS VIR_FROM_STORAGE static virStorageBackendPtr backends[] = { @@ -768,33 +764,6 @@ virStorageBackendForType(int type) { return NULL; } - -int -virStorageBackendUpdateVolTargetInfo(virConnectPtr conn, - virStorageVolTargetPtr target, - unsigned long long *allocation, - unsigned long long *capacity) -{ - int ret, fd; - - if ((fd = open(target->path, O_RDONLY)) < 0) { - virReportSystemError(conn, errno, - _("cannot open volume '%s'"), - target->path); - return -1; - } - - ret = virStorageBackendUpdateVolTargetInfoFD(conn, - target, - fd, - allocation, - capacity); - - close(fd); - - return ret; -} - int virStorageBackendUpdateVolInfo(virConnectPtr conn, virStorageVolDefPtr vol, @@ -802,122 +771,23 @@ virStorageBackendUpdateVolInfo(virConnectPtr conn, { int ret; - if ((ret = virStorageBackendUpdateVolTargetInfo(conn, - &vol->target, - &vol->allocation, - withCapacity ? &vol->capacity : NULL)) < 0) + if ((ret = virStorageFileGetInfo(conn, + vol->target.path, + &vol->target.perms, + &vol->allocation, + withCapacity ? &vol->capacity : NULL)) < 0) return ret; if (vol->backingStore.path && - (ret = virStorageBackendUpdateVolTargetInfo(conn, - &vol->backingStore, - NULL, NULL)) < 0) + (ret = virStorageFileGetInfo(conn, + vol->backingStore.path, + &vol->backingStore.perms, + NULL, NULL)) < 0) return ret; return 0; } -/* - * virStorageBackendUpdateVolTargetInfoFD: - * @conn: connection to report errors on - * @target: target definition ptr of volume to update - * @fd: fd of storage volume to update - * @allocation: If not NULL, updated allocation information will be stored - * @capacity: If not NULL, updated capacity info will be stored - * - * Returns 0 for success-1 on a legitimate error condition, - * -2 if passed FD isn't a regular, char, or block file. - */ -int -virStorageBackendUpdateVolTargetInfoFD(virConnectPtr conn, - virStorageVolTargetPtr target, - int fd, - unsigned long long *allocation, - unsigned long long *capacity) -{ - struct stat sb; -#if HAVE_SELINUX - security_context_t filecon = NULL; -#endif - - if (fstat(fd, &sb) < 0) { - virReportSystemError(conn, errno, - _("cannot stat file '%s'"), - target->path); - return -1; - } - - if (!S_ISREG(sb.st_mode) && - !S_ISCHR(sb.st_mode) && - !S_ISBLK(sb.st_mode)) - return -2; - - if (allocation) { - if (S_ISREG(sb.st_mode)) { -#ifndef __MINGW32__ - *allocation = (unsigned long long)sb.st_blocks * - (unsigned long long)DEV_BSIZE; -#else - *allocation = sb.st_size; -#endif - /* Regular files may be sparse, so logical size (capacity) is not same - * as actual allocation above - */ - if (capacity) - *capacity = sb.st_size; - } else { - off_t end; - /* XXX this is POSIX compliant, but doesn't work for for CHAR files, - * only BLOCK. There is a Linux specific ioctl() for getting - * size of both CHAR / BLOCK devices we should check for in - * configure - */ - end = lseek(fd, 0, SEEK_END); - if (end == (off_t)-1) { - virReportSystemError(conn, errno, - _("cannot seek to end of file '%s'"), - target->path); - return -1; - } - *allocation = end; - if (capacity) - *capacity = end; - } - } - - target->perms.mode = sb.st_mode & S_IRWXUGO; - target->perms.uid = sb.st_uid; - target->perms.gid = sb.st_gid; - - VIR_FREE(target->perms.label); - -#if HAVE_SELINUX - /* XXX: make this a security driver call */ - if (fgetfilecon(fd, &filecon) == -1) { - if (errno != ENODATA && errno != ENOTSUP) { - virReportSystemError(conn, errno, - _("cannot get file context of '%s'"), - target->path); - return -1; - } else { - target->perms.label = NULL; - } - } else { - target->perms.label = strdup(filecon); - if (target->perms.label == NULL) { - virReportOOMError(conn); - return -1; - } - freecon(filecon); - } -#else - target->perms.label = NULL; -#endif - - return 0; -} - - struct diskType { int part_table_type; unsigned short offset; diff --git a/src/storage/storage_backend.h b/src/storage/storage_backend.h index 88c6161..550bd32 100644 --- a/src/storage/storage_backend.h +++ b/src/storage/storage_backend.h @@ -82,15 +82,6 @@ int virStorageBackendUpdateVolInfo(virConnectPtr conn, virStorageVolDefPtr vol, int withCapacity); -int virStorageBackendUpdateVolTargetInfo(virConnectPtr conn, - virStorageVolTargetPtr target, - unsigned long long *allocation, - unsigned long long *capacity); -int virStorageBackendUpdateVolTargetInfoFD(virConnectPtr conn, - virStorageVolTargetPtr target, - int fd, - unsigned long long *allocation, - unsigned long long *capacity); int virStorageBackendUpdateVolTargetFormatFD(virConnectPtr conn, virStorageVolTargetPtr target, diff --git a/src/storage/storage_backend_fs.c b/src/storage/storage_backend_fs.c index e7a3ca9..49cfc6f 100644 --- a/src/storage/storage_backend_fs.c +++ b/src/storage/storage_backend_fs.c @@ -305,9 +305,9 @@ static int virStorageBackendProbeTarget(virConnectPtr conn, return -1; } - if ((ret = virStorageBackendUpdateVolTargetInfoFD(conn, target, fd, - allocation, - capacity)) < 0) { + if ((ret = virStorageFileGetInfoFromFD(conn, target->path, fd, + &target->perms, + allocation, capacity)) < 0) { close(fd); return ret; /* Take care to propagate ret, it is not always -1 */ } @@ -934,10 +934,8 @@ virStorageBackendFileSystemRefresh(virConnectPtr conn, memmove(backingStore, path, strlen(path) + 1); vol->backingStore.path = backingStore; - if (virStorageBackendUpdateVolTargetInfo(conn, - &vol->backingStore, - NULL, - NULL) < 0) + if (virStorageFileGetInfo(conn, vol->backingStore.path, + &vol->backingStore.perms, NULL, NULL) < 0) VIR_FREE(vol->backingStore); } } @@ -1167,9 +1165,9 @@ _virStorageBackendFileSystemVolBuild(virConnectPtr conn, } /* Refresh allocation / permissions info, but not capacity */ - if (virStorageBackendUpdateVolTargetInfoFD(conn, &vol->target, fd, - &vol->allocation, - NULL) < 0) { + if (virStorageFileGetInfoFromFD(conn, vol->target.path, fd, + &vol->target.perms, &vol->allocation, + NULL) < 0) { close(fd); return -1; } diff --git a/src/storage/storage_backend_mpath.c b/src/storage/storage_backend_mpath.c index fcc38ba..71e86d0 100644 --- a/src/storage/storage_backend_mpath.c +++ b/src/storage/storage_backend_mpath.c @@ -55,11 +55,8 @@ virStorageBackendMpathUpdateVolTargetInfo(virConnectPtr conn, goto out; } - if (virStorageBackendUpdateVolTargetInfoFD(conn, - target, - fd, - allocation, - capacity) < 0) { + if (virStorageFileGetInfoFromFD(conn, target->path, fd, &target->perms, + allocation, capacity) < 0) { virStorageReportError(conn, VIR_ERR_INTERNAL_ERROR, _("Failed to update volume target info for '%s'"), diff --git a/src/storage/storage_backend_scsi.c b/src/storage/storage_backend_scsi.c index c70b1ed..f9eb0ab 100644 --- a/src/storage/storage_backend_scsi.c +++ b/src/storage/storage_backend_scsi.c @@ -149,11 +149,8 @@ virStorageBackendSCSIUpdateVolTargetInfo(virConnectPtr conn, return -1; } - if (virStorageBackendUpdateVolTargetInfoFD(conn, - target, - fd, - allocation, - capacity) < 0) + if (virStorageFileGetInfoFromFD(conn, target->path, fd, &target->perms, + allocation, capacity) < 0) goto cleanup; /* make sure to set the target format "unknown" to begin with */ diff --git a/src/util/storage_file.c b/src/util/storage_file.c index e66ec8a..c1eec9b 100644 --- a/src/util/storage_file.c +++ b/src/util/storage_file.c @@ -24,8 +24,165 @@ #include <config.h> #include "storage_file.h" +#include <sys/statvfs.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <errno.h> +#include <fcntl.h> +#include <unistd.h> +#include <string.h> + +#if HAVE_SELINUX +#include <selinux/selinux.h> +#endif + +#include "memory.h" +#include "virterror_internal.h" + +#define VIR_FROM_THIS VIR_FROM_STORAGE + VIR_ENUM_IMPL(virStorageFileFormat, VIR_STORAGE_FILE_LAST, "raw", "dir", "bochs", "cloop", "cow", "dmg", "iso", "qcow", "qcow2", "vmdk", "vpc") + +#ifndef DEV_BSIZE +#define DEV_BSIZE 512 +#endif + +/* + * virStorageFileGetInfoFromFD: + * @conn: connection to report errors on + * @path: path of the file + * @fd: file description of the open file + * @permissions: If not NULL, file permsions info to update + * @allocation: If not NULL, updated allocation information will be stored + * @capacity: If not NULL, updated capacity info will be stored + * + * Returns 0 for success-1 on a legitimate error condition, + * -2 if passed FD isn't a regular, char, or block file. + */ +int +virStorageFileGetInfoFromFD(virConnectPtr conn, + const char *path, + int fd, + virStorageFilePermsPtr perms, + unsigned long long *allocation, + unsigned long long *capacity) +{ + struct stat sb; +#if HAVE_SELINUX + security_context_t filecon = NULL; +#endif + + if (fstat(fd, &sb) < 0) { + virReportSystemError(conn, errno, + _("cannot stat file '%s'"), path); + return -1; + } + + if (!S_ISREG(sb.st_mode) && + !S_ISCHR(sb.st_mode) && + !S_ISBLK(sb.st_mode)) + return -2; + + if (allocation) { + if (S_ISREG(sb.st_mode)) { +#ifndef __MINGW32__ + *allocation = (unsigned long long)sb.st_blocks * + (unsigned long long)DEV_BSIZE; +#else + *allocation = sb.st_size; +#endif + /* Regular files may be sparse, so logical size (capacity) is not same + * as actual allocation above + */ + if (capacity) + *capacity = sb.st_size; + } else { + off_t end; + /* XXX this is POSIX compliant, but doesn't work for for CHAR files, + * only BLOCK. There is a Linux specific ioctl() for getting + * size of both CHAR / BLOCK devices we should check for in + * configure + */ + end = lseek(fd, 0, SEEK_END); + if (end == (off_t)-1) { + virReportSystemError(conn, errno, + _("cannot seek to end of file '%s'"), path); + return -1; + } + *allocation = end; + if (capacity) + *capacity = end; + } + } + + if (!perms) + return 0; + + perms->mode = sb.st_mode & S_IRWXUGO; + perms->uid = sb.st_uid; + perms->gid = sb.st_gid; + + VIR_FREE(perms->label); + +#if HAVE_SELINUX + /* XXX: make this a security driver call */ + if (fgetfilecon(fd, &filecon) == -1) { + if (errno != ENODATA && errno != ENOTSUP) { + virReportSystemError(conn, errno, + _("cannot get file context of '%s'"), path); + return -1; + } else { + perms->label = NULL; + } + } else { + perms->label = strdup(filecon); + if (perms->label == NULL) { + virReportOOMError(conn); + return -1; + } + freecon(filecon); + } +#else + perms->label = NULL; +#endif + + return 0; +} + +/* + * virFileGetInfo: + * + * @path: path of the file + * @perms: If not NULL, file permissions information will be stored + * @allocation: If not NULL, file allocation information will be stored + * @capacity: If not NULL, file capacity info will be stored + * + * Returns 0 for success-1 on a legitimate error condition, + * -2 if passed FD isn't a regular, char, or block file. + */ +int +virStorageFileGetInfo(virConnectPtr conn, + const char *path, + virStorageFilePermsPtr perms, + unsigned long long *allocation, + unsigned long long *capacity) +{ + int ret, fd; + + if ((fd = open(path, O_RDONLY)) < 0) { + virReportSystemError(conn, errno, + _("cannot open volume '%s'"), path); + return -1; + } + + ret = virStorageFileGetInfoFromFD(conn, path, fd, perms, + allocation, capacity); + + close(fd); + + return ret; +} diff --git a/src/util/storage_file.h b/src/util/storage_file.h index e2f1478..efacc65 100644 --- a/src/util/storage_file.h +++ b/src/util/storage_file.h @@ -52,4 +52,17 @@ struct _virStorageFilePerms { char *label; }; +int virStorageFileGetInfo(virConnectPtr conn, + const char *path, + virStorageFilePermsPtr perms, + unsigned long long *allocation, + unsigned long long *capacity); + +int virStorageFileGetInfoFromFD(virConnectPtr conn, + const char *path, + int fd, + virStorageFilePermsPtr perms, + unsigned long long *allocation, + unsigned long long *capacity); + #endif /* __VIR_STORAGE_FILE_H__ */ -- 1.6.2.5 -- Libvir-list mailing list Libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list