summaryrefslogtreecommitdiffstats
path: root/mount
diff options
context:
space:
mode:
authorKarel Zak2007-11-26 11:13:37 +0100
committerKarel Zak2008-02-08 01:31:45 +0100
commit259fcc57346f863e65800c8671e8c34a8f1cbd30 (patch)
treee730d5742cd35d3f7e10c2e0d042d38e8208776d /mount
parentlosetup: support unlimited number of loops (diff)
downloadkernel-qcow2-util-linux-259fcc57346f863e65800c8671e8c34a8f1cbd30.tar.gz
kernel-qcow2-util-linux-259fcc57346f863e65800c8671e8c34a8f1cbd30.tar.xz
kernel-qcow2-util-linux-259fcc57346f863e65800c8671e8c34a8f1cbd30.zip
losetup: add --associated option
losetup -j | --associated <file> [-o <num>] This new option lists all loop devices associated with given file (and optionally file offset). Examples: # losetup -a /dev/loop0: [0807]:21921808 (/foo/vfat-mbr.img) /dev/loop1: [0807]:21921808 (/foo/vfat-mbr.img), offset 100 /dev/loop2: [0807]:21921802 (/bar/ext3.img) # losetup -j /foo/vfat-mbr.img /dev/loop0: [0807]:21921808 (/foo/vfat-mbr.img) /dev/loop1: [0807]:21921808 (/foo/vfat-mbr.img), offset 100 # losetup -j /foo/vfat-mbr.img -o 100 /dev/loop1: [0807]:21921808 (/foo/vfat-mbr.img), offset 100 Signed-off-by: Karel Zak <kzak@redhat.com>
Diffstat (limited to 'mount')
-rw-r--r--mount/lomount.c76
-rw-r--r--mount/losetup.813
2 files changed, 68 insertions, 21 deletions
diff --git a/mount/lomount.c b/mount/lomount.c
index 43c33516b..c5d03c48b 100644
--- a/mount/lomount.c
+++ b/mount/lomount.c
@@ -29,6 +29,8 @@
#ifdef LOOP_SET_FD
+static int is_associated(int dev, struct stat *file, unsigned long long offset, int isoff);
+
static int
loop_info64_to_old(const struct loop_info64 *info64, struct loop_info *info)
{
@@ -404,6 +406,34 @@ show_used_loop_devices (void) {
return 0;
}
+/* list all associated loop devices */
+static int
+show_associated_loop_devices(char *filename, unsigned long long offset, int isoff)
+{
+ struct looplist ll;
+ struct stat filestat;
+ int fd;
+
+ if (stat(filename, &filestat) == -1) {
+ perror(filename);
+ return 1;
+ }
+
+ if (looplist_open(&ll, LLFLG_USEDONLY) == -1) {
+ error(_("%s: /dev directory does not exist."), progname);
+ return 1;
+ }
+
+ while((fd = looplist_next(&ll)) != -1) {
+ if (is_associated(fd, &filestat, offset, isoff) == 1)
+ show_loop_fd(fd, ll.name);
+ close(fd);
+ }
+ looplist_close(&ll);
+
+ return 0;
+}
+
#endif /* MAIN */
/* check if the loopfile is already associated with the same given
@@ -414,7 +444,7 @@ show_used_loop_devices (void) {
* 1 loop device already used
*/
static int
-is_associated(int dev, struct stat *file, unsigned long long offset)
+is_associated(int dev, struct stat *file, unsigned long long offset, int isoff)
{
struct loop_info64 linfo64;
struct loop_info64 linfo;
@@ -423,14 +453,14 @@ is_associated(int dev, struct stat *file, unsigned long long offset)
if (ioctl(dev, LOOP_GET_STATUS64, &linfo64) == 0) {
if (file->st_dev == linfo64.lo_device &&
file->st_ino == linfo64.lo_inode &&
- offset == linfo64.lo_offset)
+ (isoff == 0 || offset == linfo64.lo_offset))
ret = 1;
return ret;
}
if (ioctl(dev, LOOP_GET_STATUS, &linfo) == 0) {
if (file->st_dev == linfo.lo_device &&
file->st_ino == linfo.lo_inode &&
- offset == linfo.lo_offset)
+ (isoff == 0 || offset == linfo.lo_offset))
ret = 1;
return ret;
}
@@ -460,7 +490,7 @@ loopfile_used (const char *filename, unsigned long long offset) {
}
while((fd = looplist_next(&ll)) != -1) {
- int res = is_associated(fd, &filestat, offset);
+ int res = is_associated(fd, &filestat, offset, 1);
close(fd);
if (res == 1) {
devname = xstrdup(ll.name);
@@ -491,7 +521,7 @@ loopfile_used_with(char *devname, const char *filename, unsigned long long offse
perror(devname);
return -1;
}
- ret = is_associated(fd, &statbuf, offset);
+ ret = is_associated(fd, &statbuf, offset, 1);
close(fd);
return ret;
@@ -773,11 +803,12 @@ find_unused_loop_device (void) {
static void
usage(void) {
fprintf(stderr, _("\nUsage:\n"
- " %1$s loop_device # give info\n"
- " %1$s -a | --all # list all used\n"
- " %1$s -d | --detach loop_device # delete\n"
- " %1$s -f | --find # find unused\n"
- " %1$s [ options ] {-f|--find|loop_device} file # setup\n"
+ " %1$s loop_device give info\n"
+ " %1$s -a | --all list all used\n"
+ " %1$s -d | --detach <loopdev> delete\n"
+ " %1$s -f | --find find unused\n"
+ " %1$s -j | --associated <file> [-o <num>] list all associated with <file>\n"
+ " %1$s [ options ] {-f|--find|loopdev} <file> setup\n"
"\nOptions:\n"
" -e | --encryption <type> enable data encryption with specified <name/num>\n"
" -h | --help this help\n"
@@ -792,7 +823,7 @@ usage(void) {
int
main(int argc, char **argv) {
- char *p, *offset, *encryption, *passfd, *device, *file;
+ char *p, *offset, *encryption, *passfd, *device, *file, *assoc;
int delete, find, c, all;
int res = 0;
int showdev = 0;
@@ -805,6 +836,7 @@ main(int argc, char **argv) {
{ "encryption", 1, 0, 'e' },
{ "find", 0, 0, 'f' },
{ "help", 0, 0, 'h' },
+ { "associated", 1, 0, 'j' },
{ "offset", 1, 0, 'o' },
{ "pass-fd", 1, 0, 'p' },
{ "read-only", 0, 0, 'r' },
@@ -819,13 +851,13 @@ main(int argc, char **argv) {
delete = find = all = 0;
off = 0;
- offset = encryption = passfd = NULL;
+ assoc = offset = encryption = passfd = NULL;
progname = argv[0];
if ((p = strrchr(progname, '/')) != NULL)
progname = p+1;
- while ((c = getopt_long(argc, argv, "ade:E:fho:p:rsv",
+ while ((c = getopt_long(argc, argv, "ade:E:fhj:o:p:rsv",
longopts, NULL)) != -1) {
switch (c) {
case 'a':
@@ -844,6 +876,9 @@ main(int argc, char **argv) {
case 'f':
find = 1;
break;
+ case 'j':
+ assoc = optarg;
+ break;
case 'o':
offset = optarg;
break;
@@ -864,21 +899,30 @@ main(int argc, char **argv) {
if (argc == 1) {
usage();
} else if (delete) {
- if (argc != optind+1 || encryption || offset || find || all || showdev)
+ if (argc != optind+1 || encryption || offset ||
+ find || all || showdev || assoc || ro)
usage();
} else if (find) {
- if (all || argc < optind || argc > optind+1)
+ if (all || assoc || argc < optind || argc > optind+1)
usage();
} else if (all) {
if (argc > 2)
usage();
+ } else if (assoc) {
+ if (encryption || showdev || passfd || ro)
+ usage();
} else {
if (argc < optind+1 || argc > optind+2)
usage();
}
+ if (offset && sscanf(offset, "%llu", &off) != 1)
+ usage();
+
if (all)
return show_used_loop_devices();
+ else if (assoc)
+ return show_associated_loop_devices(assoc, off, offset ? 1 : 0);
else if (find) {
device = find_unused_loop_device();
if (device == NULL)
@@ -903,8 +947,6 @@ main(int argc, char **argv) {
else if (file == NULL)
res = show_loop(device);
else {
- if (offset && sscanf(offset, "%llu", &off) != 1)
- usage();
if (passfd && sscanf(passfd, "%d", &pfd) != 1)
usage();
do {
diff --git a/mount/losetup.8 b/mount/losetup.8
index db2929f48..400ec2cab 100644
--- a/mount/losetup.8
+++ b/mount/losetup.8
@@ -11,6 +11,8 @@ Get info:
.sp
.B losetup -a
.sp
+.B losetup -j <file> [-o offset]
+.sp
.in -5
Delete loop:
.sp
@@ -73,14 +75,17 @@ enable data encryption with specified name or number
.IP "\fB\-f, \-\-find\fP"
find the first unused loop device. If a
.I file
-argument is present, use this device. Otherwise, print its name.
+argument is present, use this device. Otherwise, print its name
.IP "\fB\-h, \-\-help\fP"
print help
+.IP "\fB\-j, \-\-associated \fIfile\fP"
+show status of all loop devices associated with given
+.I file
.IP "\fB\-o, \-\-offset \fIoffset\fP"
-The data start is moved \fIoffset\fP bytes into the specified file or
-device.
+the data start is moved \fIoffset\fP bytes into the specified file or
+device
.IP "\fB\-p, \-\-pass-fd \fInum\fP"
-Read the passphrase from file descriptor with number
+read the passphrase from file descriptor with number
.I num
instead of from the terminal
.IP "\fB\-r, \-\-read-only\fP"