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); }
/* * 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; }
/* * Returns: 0 = success, < 0 error, 1 not found */ int loopcxt_find_by_backing_file(struct loopdev_cxt *lc, const char *filename, uint64_t offset, int flags) { int rc, hasst; struct stat st; if (!filename) return -EINVAL; hasst = !stat(filename, &st); rc = loopcxt_init_iterator(lc, LOOPITER_FL_USED); if (rc) return rc; while ((rc = loopcxt_next(lc)) == 0) { if (loopcxt_is_used(lc, hasst ? &st : NULL, filename, offset, flags)) break; } loopcxt_deinit_iterator(lc); return rc; }
/* * Note that LOOP_CTL_GET_FREE ioctl is supported since kernel 3.1. In older * kernels we have to check all loop devices to found unused one. * * See kernel commit 770fe30a46a12b6fb6b63fbe1737654d28e8484. */ int loopcxt_find_unused(struct loopdev_cxt *lc) { int rc = -1; DBG(lc, loopdev_debug("find_unused requested")); if (lc->flags & LOOPDEV_FL_CONTROL) { int ctl = open(_PATH_DEV_LOOPCTL, O_RDWR); if (ctl >= 0) rc = ioctl(ctl, LOOP_CTL_GET_FREE); if (rc >= 0) { char name[16]; snprintf(name, sizeof(name), "loop%d", rc); rc = loopiter_set_device(lc, name); } if (ctl >= 0) close(ctl); DBG(lc, loopdev_debug("find_unused by loop-control [rc=%d]", rc)); } if (rc < 0) { rc = loopcxt_init_iterator(lc, LOOPITER_FL_FREE); if (rc) return rc; rc = loopcxt_next(lc); loopcxt_deinit_iterator(lc); DBG(lc, loopdev_debug("find_unused by scan [rc=%d]", rc)); } return rc; }
static int delete_all_loops(struct loopdev_cxt *lc) { int res = 0; if (loopcxt_init_iterator(lc, LOOPITER_FL_USED)) return -1; while (loopcxt_next(lc) == 0) res += delete_loop(lc); loopcxt_deinit_iterator(lc); return res; }
static int show_all_loops(struct loopdev_cxt *lc, const char *file, uint64_t offset, int flags) { struct stat sbuf, *st = &sbuf; if (loopcxt_init_iterator(lc, LOOPITER_FL_USED)) return -1; if (!file || stat(file, st)) st = NULL; while (loopcxt_next(lc) == 0) { if (file && !loopcxt_is_used(lc, st, file, offset, flags)) continue; printf_loopdev(lc); } loopcxt_deinit_iterator(lc); return 0; }