diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/loopdev.c | 97 |
1 files changed, 97 insertions, 0 deletions
diff --git a/lib/loopdev.c b/lib/loopdev.c index 99a093926..ac46f5312 100644 --- a/lib/loopdev.c +++ b/lib/loopdev.c @@ -665,6 +665,9 @@ struct loop_info64 *loopcxt_get_info(struct loopdev_cxt *lc) if (fd < 0) return NULL; + /* indicate that file format support is implemented in sys-utils */ + lc->info.lo_flags |= LO_FLAGS_FILE_FMT; + if (ioctl(fd, LOOP_GET_STATUS64, &lc->info) == 0) { lc->has_info = 1; lc->info_failed = 0; @@ -824,6 +827,75 @@ int loopcxt_get_encrypt_type(struct loopdev_cxt *lc, uint32_t *type) } /* + * @file_fmt_type_str: file format type string. + * @file_fmt_type: returns file format type from the given file format string. + * + * Returns: <0 on error, 0 on success + */ +int parse_file_fmt_type(const char *file_fmt_type_str, uint32_t *file_fmt_type) +{ + int rc = 0; + + if (!strcmp(file_fmt_type_str, "RAW")) + *file_fmt_type = LO_FILE_FMT_RAW; + else if (!strcmp(file_fmt_type_str, "QCOW")) + *file_fmt_type = LO_FILE_FMT_QCOW; + else if (!strcmp(file_fmt_type_str, "VDI")) + *file_fmt_type = LO_FILE_FMT_VDI; + else if (!strcmp(file_fmt_type_str, "VMDK")) + *file_fmt_type = LO_FILE_FMT_VMDK; + else + rc = -EINVAL; + + return rc; +} + +/* + * @lc: context + * @file_fmt_type: returns file format type of the given device + * + * Returns: <0 on error, 0 on success + */ +int loopcxt_get_file_fmt_type(struct loopdev_cxt *lc, uint32_t* file_fmt_type) +{ + struct path_cxt *sysfs = loopcxt_get_sysfs(lc); + int rc = 0; + + if (sysfs) { + /* check if file_fmt_type is accessible and supported by the kernel module */ + char* file_fmt_str = NULL; + if (ul_path_read_string(sysfs, &file_fmt_str, "loop/file_fmt_type") == 0) + rc = parse_file_fmt_type(file_fmt_str, file_fmt_type); + } else + rc = -errno; + + if (rc != 0 && loopcxt_ioctl_enabled(lc)) { + struct loop_info64 *lo = loopcxt_get_info(lc); + if (lo) + *file_fmt_type = lo->lo_file_fmt_type; + } + + return 0; +} + +/* + * @lc: context + * + * Returns (allocated) string with file format type of the current loop device. + */ +char *loopcxt_get_file_fmt_type_string(struct loopdev_cxt *lc) +{ + struct path_cxt *sysfs = loopcxt_get_sysfs(lc); + char *res = NULL; + + if (sysfs) + ul_path_read_string(sysfs, &res, "loop/file_fmt_type"); + + DBG(CXT, ul_debugobj(lc, "loopcxt_get_file_fmt_type_string [%s]", res)); + return res; +} + +/* * @lc: context * @devno: returns crypt name * @@ -1124,6 +1196,23 @@ int loopcxt_set_blocksize(struct loopdev_cxt *lc, uint64_t blocksize) /* * @lc: context + * @file_fmt_type: kernel LO_FILE_FMT_{RAW,QCOW,VDI,VMDK} flags + * + * The setting is removed by loopcxt_set_device() loopcxt_next()! + * + * Returns: 0 on success, <0 on error. + */ +int loopcxt_set_file_fmt_type(struct loopdev_cxt *lc, uint32_t file_fmt_type) { + if (!lc) + return -EINVAL; + lc->info.lo_file_fmt_type = file_fmt_type; + + DBG(CXT, ul_debugobj(lc, "set file_fmt_type=%u", (unsigned) file_fmt_type)); + return 0; +} + +/* + * @lc: context * @flags: kernel LO_FLAGS_{READ_ONLY,USE_AOPS,AUTOCLEAR} flags * * The setting is removed by loopcxt_set_device() loopcxt_next()! @@ -1353,6 +1442,10 @@ int loopcxt_setup_device(struct loopdev_cxt *lc) } do { + /* indicate that file format support is implemented in + * sys-utils */ + lc->info.lo_flags |= LO_FLAGS_FILE_FMT; + err = ioctl(dev_fd, LOOP_SET_STATUS64, &lc->info); again = err && errno == EAGAIN; if (again) @@ -1415,6 +1508,10 @@ int loopcxt_ioctl_status(struct loopdev_cxt *lc) DBG(SETUP, ul_debugobj(lc, "device open: OK")); do { + /* indicate that file format support is implemented in + * sys-utils */ + lc->info.lo_flags |= LO_FLAGS_FILE_FMT; + err = ioctl(dev_fd, LOOP_SET_STATUS64, &lc->info); again = err && errno == EAGAIN; if (again) |