static void test_loop_scan(int flags, int debug) { struct loopdev_cxt lc; int rc; loopcxt_init(&lc, 0); loopcxt_enable_debug(&lc, debug); if (loopcxt_init_iterator(&lc, flags)) err(EXIT_FAILURE, "iterator initlization failed"); while((rc = loopcxt_next(&lc)) == 0) { const char *device = loopcxt_get_device(&lc); if (flags & LOOPITER_FL_USED) { char *backing = loopcxt_get_backing_file(&lc); printf("\t%s: %s\n", device, backing); free(backing); } else printf("\t%s\n", device); } if (rc < 0) err(EXIT_FAILURE, "loopdevs scanning failed"); loopcxt_deinit(&lc); }
/** * mnt_pretty_path: * @path: any path * @cache: NULL or pointer to the cache * * Converts path: * - to the absolute path * - /dev/dm-N to /dev/mapper/name * - /dev/loopN to the loop backing filename * - empty path (NULL) to 'none' * * Returns: newly allocated string with path, result always has to be deallocated * by free(). */ char *mnt_pretty_path(const char *path, struct libmnt_cache *cache) { char *pretty = mnt_resolve_path(path, cache); if (!pretty) return strdup("none"); #ifdef __linux__ /* users assume backing file name rather than /dev/loopN in * output if the device has been initialized by mount(8). */ if (strncmp(pretty, "/dev/loop", 9) == 0) { struct loopdev_cxt lc; if (loopcxt_init(&lc, 0) || loopcxt_set_device(&lc, pretty)) goto done; if (loopcxt_is_autoclear(&lc)) { char *tmp = loopcxt_get_backing_file(&lc); if (tmp) { if (!cache) free(pretty); /* not cached, deallocate */ return tmp; /* return backing file */ } } loopcxt_deinit(&lc); } #endif done: /* don't return pointer to the cache, allocate a new string */ return cache ? strdup(pretty) : pretty; }
static void test_loop_info(const char *device, int flags, int debug) { struct loopdev_cxt lc; char *p; uint64_t u64; loopcxt_init(&lc, flags); loopcxt_enable_debug(&lc, debug); if (loopcxt_set_device(&lc, device)) err(EXIT_FAILURE, "failed to set device"); p = loopcxt_get_backing_file(&lc); printf("\tBACKING FILE: %s\n", p); free(p); if (loopcxt_get_offset(&lc, &u64) == 0) printf("\tOFFSET: %jd\n", u64); if (loopcxt_get_sizelimit(&lc, &u64) == 0) printf("\tSIZE LIMIT: %jd\n", u64); printf("\tAUTOCLEAR: %s\n", loopcxt_is_autoclear(&lc) ? "YES" : "NOT"); loopcxt_deinit(&lc); }
/* * Returns number of loop devices associated with @file, if only one loop * device is associeted with the given @filename and @loopdev is not NULL then * @loopdev returns name of the device. */ int loopdev_count_by_backing_file(const char *filename, char **loopdev) { struct loopdev_cxt lc; int count = 0; if (!filename) return -1; loopcxt_init(&lc, 0); if (loopcxt_init_iterator(&lc, LOOPITER_FL_USED)) return -1; while(loopcxt_next(&lc) == 0) { char *backing = loopcxt_get_backing_file(&lc); if (!backing || strcmp(backing, filename)) { free(backing); continue; } free(backing); if (loopdev && count == 0) *loopdev = loopcxt_strdup_device(&lc); count++; } loopcxt_deinit(&lc); if (loopdev && count > 1) { free(*loopdev); *loopdev = NULL; } return count; }
static int printf_loopdev(struct loopdev_cxt *lc) { uint64_t x; dev_t dev = 0; ino_t ino = 0; char *fname = NULL; uint32_t type; fname = loopcxt_get_backing_file(lc); if (!fname) return -EINVAL; if (loopcxt_get_backing_devno(lc, &dev) == 0) loopcxt_get_backing_inode(lc, &ino); if (!dev && !ino) { /* * Probably non-root user (no permissions to * call LOOP_GET_STATUS ioctls). */ printf("%s: []: (%s)", loopcxt_get_device(lc), fname); if (loopcxt_get_offset(lc, &x) == 0 && x) printf(_(", offset %ju"), x); if (loopcxt_get_sizelimit(lc, &x) == 0 && x) printf(_(", sizelimit %ju"), x); printf("\n"); return 0; } printf("%s: [%04d]:%" PRIu64 " (%s)", loopcxt_get_device(lc), (int) dev, ino, fname); if (loopcxt_get_offset(lc, &x) == 0 && x) printf(_(", offset %ju"), x); if (loopcxt_get_sizelimit(lc, &x) == 0 && x) printf(_(", sizelimit %ju"), x); if (loopcxt_get_encrypt_type(lc, &type) == 0) { const char *e = loopcxt_get_crypt_name(lc); if ((!e || !*e) && type == 1) e = "XOR"; if (e && *e) printf(_(", encryption %s (type %u)"), e, type); } printf("\n"); return 0; }
char *loopdev_get_backing_file(const char *device) { struct loopdev_cxt lc; char *res; if (!device) return NULL; loopcxt_init(&lc, 0); loopcxt_set_device(&lc, device); res = loopcxt_get_backing_file(&lc); loopcxt_deinit(&lc); return res; }
/* * @lc: context * @st: backing file stat or NULL * @backing_file: filename * @offset: offset * @flags: LOOPDEV_FL_OFFSET if @offset should not be ignored * * Returns 1 if the current @lc loopdev is associated with the given backing * file. Note that the preferred way is to use devno and inode number rather * than filename. The @backing_file filename is poor solution usable in case * that you don't have rights to call stat(). * * Don't forget that old kernels provide very restricted (in size) backing * filename by LOOP_GET_STAT64 ioctl only. */ int loopcxt_is_used(struct loopdev_cxt *lc, struct stat *st, const char *backing_file, uint64_t offset, int flags) { ino_t ino; dev_t dev; if (!lc) return 0; DBG(lc, loopdev_debug("checking %s vs. %s", loopcxt_get_device(lc), backing_file)); if (st && loopcxt_get_backing_inode(lc, &ino) == 0 && loopcxt_get_backing_devno(lc, &dev) == 0) { if (ino == st->st_ino && dev == st->st_dev) goto found; /* don't use filename if we have devno and inode */ return 0; } /* poor man's solution */ if (backing_file) { char *name = loopcxt_get_backing_file(lc); int rc = name && strcmp(name, backing_file) == 0; free(name); if (rc) goto found; } return 0; found: if (flags & LOOPDEV_FL_OFFSET) { uint64_t off; return loopcxt_get_offset(lc, &off) == 0 && off == offset; } return 1; }