2 * Copyright (C) 2011 Karel Zak <kzak@redhat.com>
3 * Originally from Ted's losetup.c
5 * losetup.c - setup and control loop devices
14 #include <sys/ioctl.h>
17 #include <sys/sysmacros.h>
25 #include "pathnames.h"
28 #include "canonicalize.h"
31 A_CREATE
, /* setup a new device */
32 A_DELETE
, /* delete one or all devices */
33 A_SHOW
, /* list devices */
34 A_FIND_FREE
, /* find first unused */
35 A_SET_CAPACITY
, /* set device capacity */
40 static int is_associated(int dev
, struct stat
*file
, unsigned long long offset
, int isoff
);
43 #define NLOOPS_DEFAULT 8 /* /dev/loop[0-7] */
46 int flag
; /* scanning options */
47 FILE *proc
; /* /proc/partitions */
48 int ncur
; /* current position */
49 int *minors
; /* ary of minor numbers (when scan whole /dev) */
50 int nminors
; /* number of items in *minors */
51 char name
[128]; /* device name */
52 int ct_perm
; /* count permission problems */
53 int ct_succ
; /* count number of successfully
57 #define LLFLG_USEDONLY (1 << 1) /* return used devices only */
58 #define LLFLG_FREEONLY (1 << 2) /* return non-used devices */
59 #define LLFLG_DONE (1 << 3) /* all is done */
60 #define LLFLG_PROCFS (1 << 4) /* try to found used devices in /proc/partitions */
61 #define LLFLG_SUBDIR (1 << 5) /* /dev/loop/N */
62 #define LLFLG_DFLT (1 << 6) /* directly try to check default loops */
64 #define SETLOOP_RDONLY (1<<0) /* Open loop read-only */
65 #define SETLOOP_AUTOCLEAR (1<<1) /* Automatically detach loop on close (2.6.25?) */
67 static int del_loop (const char *device
);
69 /* TODO: move to lib/sysfs.c */
70 static char *loopfile_from_sysfs(const char *device
)
74 char buf
[PATH_MAX
], *res
= NULL
;
76 if (stat(device
, &st
) || !S_ISBLK(st
.st_mode
))
79 snprintf(buf
, sizeof(buf
), _PATH_SYS_DEVBLOCK
"/%d:%d/loop/backing_file",
80 major(st
.st_rdev
), minor(st
.st_rdev
));
86 if (fgets(buf
, sizeof(buf
), f
)) {
87 size_t sz
= strlen(buf
);
98 char *loopdev_get_loopfile(const char *device
)
100 char *res
= loopfile_from_sysfs(device
);
103 struct loop_info64 lo64
;
106 if ((fd
= open(device
, O_RDONLY
)) < 0)
109 if (ioctl(fd
, LOOP_GET_STATUS64
, &lo64
) == 0) {
110 lo64
.lo_file_name
[LO_NAME_SIZE
-2] = '*';
111 lo64
.lo_file_name
[LO_NAME_SIZE
-1] = 0;
112 res
= xstrdup((char *) lo64
.lo_file_name
);
121 is_loop_device (const char *device
) {
124 return (stat(device
, &st
) == 0 &&
125 S_ISBLK(st
.st_mode
) &&
126 major(st
.st_rdev
) == LOOPMAJOR
);
132 struct loop_info64 li
;
135 if (ioctl (fd
, LOOP_GET_STATUS64
, &li
) < 0 && errno
== ENXIO
)
141 is_loopfd_autoclear(int fd
)
143 struct loop_info64 lo64
;
145 if (ioctl(fd
, LOOP_GET_STATUS64
, &lo64
) == 0) {
146 if (lo64
.lo_flags
& LO_FLAGS_AUTOCLEAR
)
154 is_loop_autoclear(const char *device
)
158 if ((fd
= open(device
, O_RDONLY
)) < 0)
160 rc
= is_loopfd_autoclear(fd
);
167 looplist_open(struct looplist
*ll
, int flag
)
171 memset(ll
, 0, sizeof(*ll
));
175 if (stat(_PATH_DEV
, &st
) == -1 || (!S_ISDIR(st
.st_mode
)))
176 return -1; /* /dev doesn't exist */
178 if (stat(_PATH_DEV_LOOP
, &st
) == 0 && S_ISDIR(st
.st_mode
))
179 ll
->flag
|= LLFLG_SUBDIR
; /* /dev/loop/ exists */
181 if ((ll
->flag
& LLFLG_USEDONLY
) &&
182 stat(_PATH_PROC_PARTITIONS
, &st
) == 0)
183 ll
->flag
|= LLFLG_PROCFS
; /* try /proc/partitions */
185 ll
->flag
|= LLFLG_DFLT
; /* required! */
190 looplist_close(struct looplist
*ll
)
198 ll
->flag
|= LLFLG_DONE
;
202 looplist_open_dev(struct looplist
*ll
, int lnum
)
208 /* create a full device path */
209 snprintf(ll
->name
, sizeof(ll
->name
),
210 ll
->flag
& LLFLG_SUBDIR
?
211 _PATH_DEV_LOOP
"/%d" :
215 fd
= open(ll
->name
, O_RDONLY
);
221 if (fstat(fd
, &st
) == -1)
223 if (!S_ISBLK(st
.st_mode
) || major(st
.st_rdev
) != LOOPMAJOR
)
228 /* check if the device is wanted */
229 if (!(ll
->flag
& (LLFLG_USEDONLY
| LLFLG_FREEONLY
)))
232 used
= is_loop_used(fd
);
234 if ((ll
->flag
& LLFLG_USEDONLY
) && used
)
236 if ((ll
->flag
& LLFLG_FREEONLY
) && !used
)
243 /* returns <N> from "loop<N>" */
245 name2minor(int hasprefix
, const char *name
)
251 if (strncmp(name
, "loop", 4))
255 n
= strtol(name
, &end
, 10);
256 if (end
&& end
!= name
&& *end
== '\0' && n
>= 0)
262 cmpnum(const void *p1
, const void *p2
)
264 return (*(int *) p1
> *(int *) p2
) - (*(int *) p1
< *(int *) p2
);
268 * The classic scandir() is more expensive and less portable.
269 * We needn't full loop device names -- minor numbers (loop<N>)
273 loop_scandir(const char *dirname
, int **ary
, int hasprefix
)
277 int n
, count
= 0, arylen
= 0;
279 if (!dirname
|| !ary
)
281 dir
= opendir(dirname
);
287 while((d
= readdir(dir
))) {
288 if (d
->d_type
!= DT_BLK
&& d
->d_type
!= DT_UNKNOWN
&& d
->d_type
!= DT_LNK
)
290 n
= name2minor(hasprefix
, d
->d_name
);
291 if (n
== -1 || n
< NLOOPS_DEFAULT
)
293 if (count
+ 1 > arylen
) {
298 tmp
= realloc(*ary
, arylen
* sizeof(int));
308 qsort(*ary
, count
, sizeof(int), cmpnum
);
315 looplist_next(struct looplist
*ll
)
319 if (ll
->flag
& LLFLG_DONE
)
322 /* A) Look for used loop devices in /proc/partitions ("losetup -a" only)
324 if (ll
->flag
& LLFLG_PROCFS
) {
328 ll
->proc
= fopen(_PATH_PROC_PARTITIONS
, "r");
330 while (ll
->proc
&& fgets(buf
, sizeof(buf
), ll
->proc
)) {
332 unsigned long long sz
;
335 if (sscanf(buf
, " %d %d %llu %128[^\n ]",
336 &m
, &n
, &sz
, name
) != 4)
340 /* unfortunately, real minor numbers needn't to match
341 * loop<N> device name. We have to follow device name.
343 n
= name2minor(1, name
);
344 fd
= looplist_open_dev(ll
, n
);
352 /* B) Classic way, try first eight loop devices (default number
353 * of loop devices). This is enough for 99% of all cases.
355 if (ll
->flag
& LLFLG_DFLT
) {
356 for (++ll
->ncur
; ll
->ncur
< NLOOPS_DEFAULT
; ll
->ncur
++) {
357 fd
= looplist_open_dev(ll
, ll
->ncur
);
361 ll
->flag
&= ~LLFLG_DFLT
;
364 /* C) the worst possibility, scan all /dev or /dev/loop
367 ll
->nminors
= (ll
->flag
& LLFLG_SUBDIR
) ?
368 loop_scandir(_PATH_DEV_LOOP
, &ll
->minors
, 0) :
369 loop_scandir(_PATH_DEV
, &ll
->minors
, 1);
372 for (++ll
->ncur
; ll
->ncur
< ll
->nminors
; ll
->ncur
++) {
373 fd
= looplist_open_dev(ll
, ll
->minors
[ll
->ncur
]);
383 /* Find loop device associated with given @filename. Used for unmounting loop
384 * device specified by associated backing file.
386 * returns: 1 no such device/error
387 * 2 more than one loop device associated with @filename
388 * 0 exactly one loop device associated with @filename
389 * (@loopdev points to string containing full device name)
392 find_loopdev_by_backing_file(const char *filename
, char **loopdev
)
395 struct stat filestat
;
397 int devs_n
= 0; /* number of loop devices found */
398 char* devname
= NULL
;
400 if (stat(filename
, &filestat
) == -1) {
405 if (looplist_open(&ll
, LLFLG_USEDONLY
) == -1) {
406 warnx(_("/dev directory does not exist."));
410 while((devs_n
< 2) && (fd
= looplist_next(&ll
)) != -1) {
411 if (is_associated(fd
, &filestat
, 0, 0) == 1) {
413 devname
= xstrdup(ll
.name
);
422 return 0; /* exactly one loopdev */
425 return devs_n
? 2 : 1; /* more loopdevs or error */
429 set_capacity(const char *device
)
432 int fd
= open(device
, O_RDONLY
);
437 if (ioctl(fd
, LOOP_SET_CAPACITY
) != 0)
443 fprintf(stderr
, _("loop: can't set capacity on device %s: %s\n"),
444 device
, strerror (errsv
));
451 show_loop_fd(int fd
, char *device
) {
452 struct loop_info64 loopinfo64
;
455 if (ioctl(fd
, LOOP_GET_STATUS64
, &loopinfo64
) == 0) {
459 loopinfo64
.lo_file_name
[LO_NAME_SIZE
-2] = '*';
460 loopinfo64
.lo_file_name
[LO_NAME_SIZE
-1] = 0;
461 loopinfo64
.lo_crypt_name
[LO_NAME_SIZE
-1] = 0;
463 /* ioctl has limited buffer for backing file name, since
464 * kernel 2.6.37 the filename is available in sysfs too
466 if (strlen((char *) loopinfo64
.lo_file_name
) == LO_NAME_SIZE
- 1)
467 lofile
= loopfile_from_sysfs(device
);
469 lofile
= (char *) loopinfo64
.lo_file_name
;
471 printf("%s: [%04" PRIx64
"]:%" PRIu64
" (%s)",
472 device
, loopinfo64
.lo_device
, loopinfo64
.lo_inode
,
475 if (lofile
!= (char *) loopinfo64
.lo_file_name
)
478 if (loopinfo64
.lo_offset
)
479 printf(_(", offset %" PRIu64
), loopinfo64
.lo_offset
);
481 if (loopinfo64
.lo_sizelimit
)
482 printf(_(", sizelimit %" PRIu64
), loopinfo64
.lo_sizelimit
);
484 if (loopinfo64
.lo_encrypt_type
||
485 loopinfo64
.lo_crypt_name
[0]) {
486 char *e
= (char *)loopinfo64
.lo_crypt_name
;
488 if (*e
== 0 && loopinfo64
.lo_encrypt_type
== 1)
490 printf(_(", encryption %s (type %" PRIu32
")"),
491 e
, loopinfo64
.lo_encrypt_type
);
498 fprintf(stderr
, _("loop: can't get info on device %s: %s\n"),
499 device
, strerror (errsv
));
504 show_loop(char *device
) {
507 if ((fd
= open(device
, O_RDONLY
)) < 0) {
509 fprintf(stderr
, _("loop: can't open device %s: %s\n"),
510 device
, strerror (errsv
));
513 ret
= show_loop_fd(fd
, device
);
520 show_used_loop_devices (void) {
524 if (looplist_open(&ll
, LLFLG_USEDONLY
) == -1) {
525 warnx(_("/dev directory does not exist."));
529 while((fd
= looplist_next(&ll
)) != -1) {
530 show_loop_fd(fd
, ll
.name
);
535 if (!ll
.ct_succ
&& ll
.ct_perm
) {
536 warnx(_("no permission to look at /dev/loop%s<N>"),
537 (ll
.flag
& LLFLG_SUBDIR
) ? "/" : "");
543 /* list all associated loop devices */
545 show_associated_loop_devices(char *filename
, unsigned long long offset
, int isoff
)
548 struct stat filestat
;
551 if (stat(filename
, &filestat
) == -1) {
556 if (looplist_open(&ll
, LLFLG_USEDONLY
) == -1) {
557 warnx(_("/dev directory does not exist."));
561 while((fd
= looplist_next(&ll
)) != -1) {
562 if (is_associated(fd
, &filestat
, offset
, isoff
) == 1)
563 show_loop_fd(fd
, ll
.name
);
571 /* check if the loopfile is already associated with the same given
574 * returns: 0 unused / error
575 * 1 loop device already used
578 is_associated(int dev
, struct stat
*file
, unsigned long long offset
, int isoff
)
580 struct loop_info64 linfo64
;
583 if (ioctl(dev
, LOOP_GET_STATUS64
, &linfo64
) == 0) {
584 if (file
->st_dev
== linfo64
.lo_device
&&
585 file
->st_ino
== linfo64
.lo_inode
&&
586 (isoff
== 0 || offset
== linfo64
.lo_offset
))
594 /* check if the loop file is already used with the same given
595 * parameters. We check for device no, inode and offset.
596 * returns: associated devname or NULL
599 loopfile_used (const char *filename
, unsigned long long offset
) {
601 char *devname
= NULL
;
602 struct stat filestat
;
605 if (stat(filename
, &filestat
) == -1) {
610 if (looplist_open(&ll
, LLFLG_USEDONLY
) == -1) {
611 warnx(_("/dev directory does not exist."));
615 while((fd
= looplist_next(&ll
)) != -1) {
616 int res
= is_associated(fd
, &filestat
, offset
, 1);
619 devname
= xstrdup(ll
.name
);
629 loopfile_used_with(char *devname
, const char *filename
, unsigned long long offset
)
634 if (!is_loop_device(devname
))
637 if (stat(filename
, &statbuf
) == -1)
640 fd
= open(devname
, O_RDONLY
);
644 ret
= is_associated(fd
, &statbuf
, offset
, 1);
650 find_unused_loop_device (void) {
652 char *devname
= NULL
;
655 if (looplist_open(&ll
, LLFLG_FREEONLY
) == -1) {
656 warnx(_("/dev directory does not exist."));
660 if ((fd
= looplist_next(&ll
)) != -1) {
662 devname
= xstrdup(ll
.name
);
668 if (!ll
.ct_succ
&& ll
.ct_perm
)
669 warnx(_("no permission to look at /dev/loop%s<N>"),
670 (ll
.flag
& LLFLG_SUBDIR
) ? "/" : "");
672 warnx(_("could not find any free loop device"));
675 "Could not find any loop device. Maybe this kernel "
677 " about the loop device? (If so, recompile or "
678 "`modprobe loop'.)"));
683 * A function to read the passphrase either from the terminal or from
684 * an open file descriptor.
687 xgetpass(int pfd
, const char *prompt
) {
691 if (pfd
< 0) /* terminal */
692 return getpass(prompt
);
698 /* we're running out of space in the buffer.
700 char *tmppass
= pass
;
702 pass
= realloc(tmppass
, buflen
);
704 /* realloc failed. Stop reading. */
705 warn(_("Out of memory while reading passphrase"));
706 pass
= tmppass
; /* the old buffer hasn't changed */
710 if (read(pfd
, pass
+i
, 1) != 1 ||
711 pass
[i
] == '\n' || pass
[i
] == 0)
723 digits_only(const char *s
) {
737 set_loop(const char *device
, const char *file
, unsigned long long offset
,
738 unsigned long long sizelimit
, const char *encryption
, int pfd
, int *options
) {
739 struct loop_info64 loopinfo64
;
740 int fd
, ffd
, mode
, i
;
745 char *xdev
= loopfile_used(file
, offset
);
748 printf(_("warning: %s is already associated with %s\n"),
754 mode
= (*options
& SETLOOP_RDONLY
) ? O_RDONLY
: O_RDWR
;
755 if ((ffd
= open(file
, mode
)) < 0) {
756 if (!(*options
& SETLOOP_RDONLY
) &&
757 (errno
== EROFS
|| errno
== EACCES
))
758 ffd
= open(file
, mode
= O_RDONLY
);
764 printf(_("warning: %s: is write-protected, using read-only.\n"),
766 *options
|= SETLOOP_RDONLY
;
768 if ((fd
= open(device
, mode
)) < 0) {
773 memset(&loopinfo64
, 0, sizeof(loopinfo64
));
775 if (!(filename
= canonicalize_path(file
)))
776 filename
= (char *) file
;
777 xstrncpy((char *)loopinfo64
.lo_file_name
, filename
, LO_NAME_SIZE
);
779 if (encryption
&& *encryption
) {
780 if (digits_only(encryption
)) {
781 loopinfo64
.lo_encrypt_type
= atoi(encryption
);
783 loopinfo64
.lo_encrypt_type
= LO_CRYPT_CRYPTOAPI
;
784 snprintf((char *)loopinfo64
.lo_crypt_name
, LO_NAME_SIZE
,
789 loopinfo64
.lo_offset
= offset
;
790 loopinfo64
.lo_sizelimit
= sizelimit
;
794 * Oh-oh, sensitive data coming up. Better lock into memory to prevent
795 * passwd etc being swapped out and left somewhere on disk.
797 if (loopinfo64
.lo_encrypt_type
!= LO_CRYPT_NONE
) {
798 if(mlockall(MCL_CURRENT
| MCL_FUTURE
)) {
800 fprintf(stderr
, _("Couldn't lock into memory, exiting.\n"));
806 switch (loopinfo64
.lo_encrypt_type
) {
808 loopinfo64
.lo_encrypt_key_size
= 0;
811 pass
= getpass(_("Password: "));
814 pass
= xgetpass(pfd
, _("Password: "));
816 memset(loopinfo64
.lo_encrypt_key
, 0, LO_KEY_SIZE
);
817 xstrncpy((char *)loopinfo64
.lo_encrypt_key
, pass
, LO_KEY_SIZE
);
818 memset(pass
, 0, strlen(pass
));
819 loopinfo64
.lo_encrypt_key_size
= LO_KEY_SIZE
;
822 if (ioctl(fd
, LOOP_SET_FD
, ffd
) < 0) {
825 if (errno
== EBUSY
) {
827 printf(_("ioctl LOOP_SET_FD failed: %m\n"));
830 perror("ioctl: LOOP_SET_FD");
834 if (file
!= filename
)
840 if (*options
& SETLOOP_AUTOCLEAR
)
841 loopinfo64
.lo_flags
= LO_FLAGS_AUTOCLEAR
;
843 i
= ioctl(fd
, LOOP_SET_STATUS64
, &loopinfo64
);
845 perror("ioctl: LOOP_SET_STATUS64");
847 if ((*options
& SETLOOP_AUTOCLEAR
) && !is_loopfd_autoclear(fd
))
848 /* kernel doesn't support loop auto-destruction */
849 *options
&= ~SETLOOP_AUTOCLEAR
;
851 memset(&loopinfo64
, 0, sizeof(loopinfo64
));
854 ioctl (fd
, LOOP_CLR_FD
, 0);
856 if (file
!= filename
)
862 * HACK: here we're leaking a file descriptor,
863 * but mount is a short-lived process anyway.
865 if (!(*options
& SETLOOP_AUTOCLEAR
))
869 printf(_("set_loop(%s,%s,%llu,%llu): success\n"),
870 device
, filename
, offset
, sizelimit
);
871 if (file
!= filename
)
877 delete_all_devices (void)
883 if (looplist_open(&ll
, LLFLG_USEDONLY
) == -1) {
884 warnx(_("/dev directory does not exist."));
888 while((fd
= looplist_next(&ll
)) != -1) {
890 ok
|= del_loop(ll
.name
);
894 if (!ll
.ct_succ
&& ll
.ct_perm
) {
895 warnx(_("no permission to look at /dev/loop%s<N>"),
896 (ll
.flag
& LLFLG_SUBDIR
) ? "/" : "");
903 del_loop (const char *device
) {
906 if ((fd
= open (device
, O_RDONLY
)) < 0) {
910 if (ioctl (fd
, LOOP_CLR_FD
, 0) < 0) {
916 printf(_("del_loop(%s): success\n"), device
);
920 fprintf(stderr
, _("loop: can't delete device %s: %s\n"),
921 device
, strerror(errsv
));
928 static int printf_loopdev(struct loopdev_cxt
*lc
)
936 fname
= loopcxt_get_backing_file(lc
);
940 if (loopcxt_get_backing_devno(lc
, &dev
) == 0)
941 loopcxt_get_backing_inode(lc
, &ino
);
945 * Probably non-root user (no permissions to
946 * call LOOP_GET_STATUS ioctls).
948 printf("%s: []: (%s)",
949 loopcxt_get_device(lc
), fname
);
951 if (loopcxt_get_offset(lc
, &x
) == 0 && x
)
952 printf(_(", offset %ju"), x
);
954 if (loopcxt_get_sizelimit(lc
, &x
) == 0 && x
)
955 printf(_(", sizelimit %ju"), x
);
960 printf("%s: [%04d]:%" PRIu64
" (%s)",
961 loopcxt_get_device(lc
), dev
, ino
, fname
);
963 if (loopcxt_get_offset(lc
, &x
) == 0 && x
)
964 printf(_(", offset %ju"), x
);
966 if (loopcxt_get_sizelimit(lc
, &x
) == 0 && x
)
967 printf(_(", sizelimit %ju"), x
);
969 if (loopcxt_get_encrypt_type(lc
, &type
) == 0) {
970 const char *e
= loopcxt_get_crypt_name(lc
);
972 if ((!e
|| !*e
) && type
== 1)
975 printf(_(", encryption %s (type %ju)"), e
, type
);
981 static int show_all_loops(struct loopdev_cxt
*lc
)
983 if (loopcxt_init_iterator(lc
, LOOPITER_FL_USED
))
986 while (loopcxt_next(lc
) == 0)
995 fputs(_("\nUsage:\n"), out
);
997 _(" %1$s loop_device give info\n"
998 " %1$s -a | --all list all used\n"
999 " %1$s -d | --detach <loopdev> [<loopdev> ...] delete\n"
1000 " %1$s -D | --detach-all delete all used\n"
1001 " %1$s -f | --find find unused\n"
1002 " %1$s -c | --set-capacity <loopdev> resize\n"
1003 " %1$s -j | --associated <file> [-o <num>] list all associated with <file>\n"
1004 " %1$s [options] {-f|--find|loopdev} <file> setup\n"),
1005 program_invocation_short_name
);
1007 fputs(_("\nOptions:\n"), out
);
1008 fputs(_(" -e, --encryption <type> enable data encryption with specified <name/num>\n"
1009 " -h, --help this help\n"
1010 " -o, --offset <num> start at offset <num> into file\n"
1011 " --sizelimit <num> loop limited to only <num> bytes of the file\n"
1012 " -p, --pass-fd <num> read passphrase from file descriptor <num>\n"
1013 " -r, --read-only setup read-only loop device\n"
1014 " --show print device name (with -f <file>)\n"
1015 " -v, --verbose verbose mode\n\n"), out
);
1017 exit(out
== stderr
? EXIT_FAILURE
: EXIT_SUCCESS
);
1020 int main(int argc
, char **argv
)
1022 struct loopdev_cxt lc
;
1025 char *p
, *offset
, *sizelimit
, *encryption
, *passfd
, *device
, *file
, *assoc
;
1026 int delete, delete_all
, find
, c
, capacity
;
1031 uintmax_t off
= 0, slimit
= 0;
1033 loopcxt_init(&lc
, 0);
1034 /*loopcxt_enable_debug(&lc, TRUE);*/
1036 static const struct option longopts
[] = {
1037 { "all", 0, 0, 'a' },
1038 { "set-capacity", 0, 0, 'c' },
1039 { "detach", 0, 0, 'd' },
1040 { "detach-all", 0, 0, 'D' },
1041 { "encryption", 1, 0, 'e' },
1042 { "find", 0, 0, 'f' },
1043 { "help", 0, 0, 'h' },
1044 { "associated", 1, 0, 'j' },
1045 { "offset", 1, 0, 'o' },
1046 { "sizelimit", 1, 0, 128 },
1047 { "pass-fd", 1, 0, 'p' },
1048 { "read-only", 0, 0, 'r' },
1049 { "show", 0, 0, 's' },
1050 { "verbose", 0, 0, 'v' },
1054 setlocale(LC_ALL
, "");
1055 bindtextdomain(PACKAGE
, LOCALEDIR
);
1056 textdomain(PACKAGE
);
1058 capacity
= delete = delete_all
= find
= 0;
1059 assoc
= offset
= sizelimit
= encryption
= passfd
= NULL
;
1061 while ((c
= getopt_long(argc
, argv
, "acdDe:E:fhj:o:p:rsv",
1062 longopts
, NULL
)) != -1) {
1064 if (act
&& strchr("acdDf", c
))
1066 _("the options %s are mutually exclusive"),
1067 "--{all,set-capacity,detach,detach-all,find}");
1087 encryption
= optarg
;
1111 case 128: /* --sizelimit */
1125 /* only -v is allowed */
1126 if ((argc
== 3 && verbose
== 0) || argc
> 3)
1129 res
= show_all_loops(&lc
);
1134 loopcxt_deinit(&lc
);
1140 if (argc
< optind
+1 || encryption
|| offset
|| sizelimit
||
1141 capacity
|| find
|| showdev
|| assoc
|| ro
)
1143 } else if (delete_all
) {
1144 if (argc
> optind
|| encryption
|| offset
|| sizelimit
||
1145 capacity
|| find
|| showdev
|| assoc
|| ro
)
1148 if (capacity
|| assoc
|| argc
< optind
|| argc
> optind
+1)
1150 } else if (delete_all
) {
1152 if (capacity
|| encryption
|| showdev
|| passfd
|| ro
)
1154 } else if (capacity
) {
1155 if (argc
!= optind
+ 1 || encryption
|| offset
|| sizelimit
||
1159 if (argc
< optind
+1 || argc
> optind
+2)
1163 if (offset
&& strtosize(offset
, &off
)) {
1164 warnx(_("invalid offset '%s' specified"), offset
);
1167 if (sizelimit
&& strtosize(sizelimit
, &slimit
)) {
1168 warnx(_("invalid sizelimit '%s' specified"), sizelimit
);
1173 return delete_all_devices();
1175 return show_associated_loop_devices(assoc
, off
, offset
? 1 : 0);
1177 device
= find_unused_loop_device();
1180 if (argc
== optind
) {
1182 printf(_("Loop device is %s\n"), device
);
1183 printf("%s\n", device
);
1186 file
= argv
[optind
];
1187 } else if (!delete) {
1188 device
= argv
[optind
];
1189 if (argc
== optind
+1)
1192 file
= argv
[optind
+1];
1196 while (optind
< argc
)
1197 res
+= del_loop(argv
[optind
++]);
1198 } else if (capacity
) {
1199 res
= set_capacity(device
);
1200 } else if (file
== NULL
)
1201 res
= show_loop(device
);
1203 if (passfd
&& sscanf(passfd
, "%d", &pfd
) != 1)
1206 res
= set_loop(device
, file
, off
, slimit
, encryption
, pfd
, &ro
);
1207 if (res
== 2 && find
) {
1209 printf(_("stolen loop=%s...trying again\n"),
1212 if (!(device
= find_unused_loop_device()))
1215 } while (find
&& res
== 2);
1219 warnx(_("%s: device is busy"), device
);
1220 else if (res
== 0) {
1222 printf(_("Loop device is %s\n"), device
);
1223 if (showdev
&& find
)
1224 printf("%s\n", device
);