2 * Copyright (C) 2011 Karel Zak <kzak@redhat.com>
3 * Originally from Ted's losetup.c
5 * losetup.c - setup and control loop devices
13 #include <sys/ioctl.h>
18 #include <libsmartcols.h>
24 #include "closestream.h"
27 #include "canonicalize.h"
28 #include "pathnames.h"
31 A_CREATE
= 1, /* setup a new device */
32 A_DELETE
, /* delete given device(s) */
33 A_DELETE_ALL
, /* delete all devices */
34 A_SHOW
, /* list devices */
35 A_SHOW_ONE
, /* print info about one device */
36 A_FIND_FREE
, /* find first unused */
37 A_SET_CAPACITY
, /* set device capacity */
38 A_SET_DIRECT_IO
, /* set accessing backing file by direct io */
39 A_SET_BLOCKSIZE
, /* set logical block size of the loop device */
57 /* basic output flags */
58 static int no_headings
;
68 int json_type
; /* default is string */
71 static struct colinfo infos
[] = {
72 [COL_AUTOCLR
] = { "AUTOCLEAR", 1, SCOLS_FL_RIGHT
, N_("autoclear flag set"), SCOLS_JSON_BOOLEAN
},
73 [COL_BACK_FILE
] = { "BACK-FILE", 0.3, 0, N_("device backing file")},
74 [COL_BACK_INO
] = { "BACK-INO", 4, SCOLS_FL_RIGHT
, N_("backing file inode number"), SCOLS_JSON_NUMBER
},
75 [COL_BACK_MAJMIN
] = { "BACK-MAJ:MIN", 6, 0, N_("backing file major:minor device number")},
76 [COL_NAME
] = { "NAME", 0.25, 0, N_("loop device name")},
77 [COL_OFFSET
] = { "OFFSET", 5, SCOLS_FL_RIGHT
, N_("offset from the beginning"), SCOLS_JSON_NUMBER
},
78 [COL_PARTSCAN
] = { "PARTSCAN", 1, SCOLS_FL_RIGHT
, N_("partscan flag set"), SCOLS_JSON_BOOLEAN
},
79 [COL_RO
] = { "RO", 1, SCOLS_FL_RIGHT
, N_("read-only device"), SCOLS_JSON_BOOLEAN
},
80 [COL_SIZELIMIT
] = { "SIZELIMIT", 5, SCOLS_FL_RIGHT
, N_("size limit of the file in bytes"), SCOLS_JSON_NUMBER
},
81 [COL_MAJMIN
] = { "MAJ:MIN", 3, 0, N_("loop device major:minor number")},
82 [COL_DIO
] = { "DIO", 1, SCOLS_FL_RIGHT
, N_("access backing file with direct-io"), SCOLS_JSON_BOOLEAN
},
83 [COL_LOGSEC
] = { "LOG-SEC", 4, SCOLS_FL_RIGHT
, N_("logical sector size in bytes"), SCOLS_JSON_NUMBER
},
86 static int columns
[ARRAY_SIZE(infos
) * 2] = {-1};
87 static size_t ncolumns
;
89 static int get_column_id(int num
)
92 assert((size_t) num
< ncolumns
);
93 assert(columns
[num
] < (int) ARRAY_SIZE(infos
));
97 static struct colinfo
*get_column_info(int num
)
99 return &infos
[ get_column_id(num
) ];
102 static int column_name_to_id(const char *name
, size_t namesz
)
106 for (i
= 0; i
< ARRAY_SIZE(infos
); i
++) {
107 const char *cn
= infos
[i
].name
;
109 if (!strncasecmp(name
, cn
, namesz
) && !*(cn
+ namesz
))
112 warnx(_("unknown column: %s"), name
);
116 static int printf_loopdev(struct loopdev_cxt
*lc
)
124 fname
= loopcxt_get_backing_file(lc
);
128 if (loopcxt_get_backing_devno(lc
, &dev
) == 0)
129 loopcxt_get_backing_inode(lc
, &ino
);
133 * Probably non-root user (no permissions to
134 * call LOOP_GET_STATUS ioctls).
136 printf("%s: []: (%s)",
137 loopcxt_get_device(lc
), fname
);
139 if (loopcxt_get_offset(lc
, &x
) == 0 && x
)
140 printf(_(", offset %ju"), x
);
142 if (loopcxt_get_sizelimit(lc
, &x
) == 0 && x
)
143 printf(_(", sizelimit %ju"), x
);
147 printf("%s: [%04d]:%" PRIu64
" (%s)",
148 loopcxt_get_device(lc
), (int) dev
, ino
, fname
);
150 if (loopcxt_get_offset(lc
, &x
) == 0 && x
)
151 printf(_(", offset %ju"), x
);
153 if (loopcxt_get_sizelimit(lc
, &x
) == 0 && x
)
154 printf(_(", sizelimit %ju"), x
);
156 if (loopcxt_get_encrypt_type(lc
, &type
) == 0) {
157 const char *e
= loopcxt_get_crypt_name(lc
);
159 if ((!e
|| !*e
) && type
== 1)
162 printf(_(", encryption %s (type %u)"), e
, type
);
171 static int show_all_loops(struct loopdev_cxt
*lc
, const char *file
,
172 uint64_t offset
, int flags
)
174 struct stat sbuf
, *st
= &sbuf
;
175 char *cn_file
= NULL
;
177 if (loopcxt_init_iterator(lc
, LOOPITER_FL_USED
))
180 if (!file
|| stat(file
, st
))
183 while (loopcxt_next(lc
) == 0) {
186 const char *bf
= cn_file
? cn_file
: file
;
188 used
= loopcxt_is_used(lc
, st
, bf
, offset
, 0, flags
);
189 if (!used
&& !cn_file
) {
190 bf
= cn_file
= canonicalize_path(file
);
191 used
= loopcxt_is_used(lc
, st
, bf
, offset
, 0, flags
);
198 loopcxt_deinit_iterator(lc
);
203 static int delete_loop(struct loopdev_cxt
*lc
)
205 if (loopcxt_delete_device(lc
))
206 warn(_("%s: detach failed"), loopcxt_get_device(lc
));
213 static int delete_all_loops(struct loopdev_cxt
*lc
)
217 if (loopcxt_init_iterator(lc
, LOOPITER_FL_USED
))
220 while (loopcxt_next(lc
) == 0)
221 res
+= delete_loop(lc
);
223 loopcxt_deinit_iterator(lc
);
227 static int set_scols_data(struct loopdev_cxt
*lc
, struct libscols_line
*ln
)
231 for (i
= 0; i
< ncolumns
; i
++) {
232 const char *p
= NULL
; /* external data */
233 char *np
= NULL
; /* allocated here */
237 switch(get_column_id(i
)) {
239 p
= loopcxt_get_device(lc
);
242 p
= loopcxt_get_backing_file(lc
);
245 if (loopcxt_get_offset(lc
, &x
) == 0)
246 xasprintf(&np
, "%jd", x
);
249 if (loopcxt_get_sizelimit(lc
, &x
) == 0)
250 xasprintf(&np
, "%jd", x
);
252 case COL_BACK_MAJMIN
:
255 if (loopcxt_get_backing_devno(lc
, &dev
) == 0 && dev
)
256 xasprintf(&np
, "%8u:%-3u", major(dev
), minor(dev
));
263 if (loopcxt_get_device(lc
)
264 && stat(loopcxt_get_device(lc
), &st
) == 0
265 && S_ISBLK(st
.st_mode
)
266 && major(st
.st_rdev
) == LOOPDEV_MAJOR
)
267 xasprintf(&np
, "%3u:%-3u", major(st
.st_rdev
),
274 if (loopcxt_get_backing_inode(lc
, &ino
) == 0 && ino
)
275 xasprintf(&np
, "%ju", ino
);
279 p
= loopcxt_is_autoclear(lc
) ? "1" : "0";
282 p
= loopcxt_is_readonly(lc
) ? "1" : "0";
285 p
= loopcxt_is_dio(lc
) ? "1" : "0";
288 p
= loopcxt_is_partscan(lc
) ? "1" : "0";
291 if (loopcxt_get_blocksize(lc
, &x
) == 0)
292 xasprintf(&np
, "%jd", x
);
300 rc
= scols_line_set_data(ln
, i
, p
); /* calls strdup() */
302 rc
= scols_line_refer_data(ln
, i
, np
); /* only refers */
305 err(EXIT_FAILURE
, _("failed to add output data"));
311 static int show_table(struct loopdev_cxt
*lc
,
316 struct stat sbuf
, *st
= &sbuf
;
317 struct libscols_table
*tb
;
318 struct libscols_line
*ln
;
324 if (!(tb
= scols_new_table()))
325 err(EXIT_FAILURE
, _("failed to allocate output table"));
326 scols_table_enable_raw(tb
, raw
);
327 scols_table_enable_json(tb
, json
);
328 scols_table_enable_noheadings(tb
, no_headings
);
331 scols_table_set_name(tb
, "loopdevices");
333 for (i
= 0; i
< ncolumns
; i
++) {
334 struct colinfo
*ci
= get_column_info(i
);
335 struct libscols_column
*cl
;
337 cl
= scols_table_new_column(tb
, ci
->name
, ci
->whint
, ci
->flags
);
339 err(EXIT_FAILURE
, _("failed to allocate output column"));
341 scols_column_set_json_type(cl
, ci
->json_type
);
344 /* only one loopdev requested (already assigned to loopdev_cxt) */
345 if (loopcxt_get_device(lc
)) {
346 ln
= scols_table_new_line(tb
, NULL
);
348 err(EXIT_FAILURE
, _("failed to allocate output line"));
349 rc
= set_scols_data(lc
, ln
);
351 /* list all loopdevs */
353 char *cn_file
= NULL
;
355 rc
= loopcxt_init_iterator(lc
, LOOPITER_FL_USED
);
358 if (!file
|| stat(file
, st
))
361 while (loopcxt_next(lc
) == 0) {
364 const char *bf
= cn_file
? cn_file
: file
;
366 used
= loopcxt_is_used(lc
, st
, bf
, offset
, 0, flags
);
367 if (!used
&& !cn_file
) {
368 bf
= cn_file
= canonicalize_path(file
);
369 used
= loopcxt_is_used(lc
, st
, bf
, offset
, 0, flags
);
375 ln
= scols_table_new_line(tb
, NULL
);
377 err(EXIT_FAILURE
, _("failed to allocate output line"));
378 rc
= set_scols_data(lc
, ln
);
383 loopcxt_deinit_iterator(lc
);
388 rc
= scols_print_table(tb
);
389 scols_unref_table(tb
);
393 static void __attribute__((__noreturn__
)) usage(void)
398 fputs(USAGE_HEADER
, out
);
401 _(" %1$s [options] [<loopdev>]\n"
402 " %1$s [options] -f | <loopdev> <file>\n"),
403 program_invocation_short_name
);
405 fputs(USAGE_SEPARATOR
, out
);
406 fputs(_("Set up and control loop devices.\n"), out
);
409 fputs(USAGE_OPTIONS
, out
);
410 fputs(_(" -a, --all list all used devices\n"), out
);
411 fputs(_(" -d, --detach <loopdev>... detach one or more devices\n"), out
);
412 fputs(_(" -D, --detach-all detach all used devices\n"), out
);
413 fputs(_(" -f, --find find first unused device\n"), out
);
414 fputs(_(" -c, --set-capacity <loopdev> resize the device\n"), out
);
415 fputs(_(" -j, --associated <file> list all devices associated with <file>\n"), out
);
416 fputs(_(" -L, --nooverlap avoid possible conflict between devices\n"), out
);
418 /* commands options */
419 fputs(USAGE_SEPARATOR
, out
);
420 fputs(_(" -o, --offset <num> start at offset <num> into file\n"), out
);
421 fputs(_(" --sizelimit <num> device is limited to <num> bytes of the file\n"), out
);
422 fputs(_(" -b --sector-size <num> set the logical sector size to <num>\n"), out
);
423 fputs(_(" -P, --partscan create a partitioned loop device\n"), out
);
424 fputs(_(" -r, --read-only set up a read-only loop device\n"), out
);
425 fputs(_(" --direct-io[=<on|off>] open backing file with O_DIRECT\n"), out
);
426 fputs(_(" --show print device name after setup (with -f)\n"), out
);
427 fputs(_(" -v, --verbose verbose mode\n"), out
);
430 fputs(USAGE_SEPARATOR
, out
);
431 fputs(_(" -J, --json use JSON --list output format\n"), out
);
432 fputs(_(" -l, --list list info about all or specified (default)\n"), out
);
433 fputs(_(" -n, --noheadings don't print headings for --list output\n"), out
);
434 fputs(_(" -O, --output <cols> specify columns to output for --list\n"), out
);
435 fputs(_(" --output-all output all columns\n"), out
);
436 fputs(_(" --raw use raw --list output format\n"), out
);
438 fputs(USAGE_SEPARATOR
, out
);
439 printf(USAGE_HELP_OPTIONS(31));
441 fputs(USAGE_COLUMNS
, out
);
442 for (i
= 0; i
< ARRAY_SIZE(infos
); i
++)
443 fprintf(out
, " %12s %s\n", infos
[i
].name
, _(infos
[i
].help
));
445 printf(USAGE_MAN_TAIL("losetup(8)"));
450 static void warn_size(const char *filename
, uint64_t size
, uint64_t offset
, int flags
)
455 if (stat(filename
, &st
) || S_ISBLK(st
.st_mode
))
459 if (flags
& LOOPDEV_FL_OFFSET
)
464 warnx(_("%s: Warning: file is smaller than 512 bytes; the loop device "
465 "may be useless or invisible for system tools."),
468 warnx(_("%s: Warning: file does not fit into a 512-byte sector; "
469 "the end of the file will be ignored."),
473 static int create_loop(struct loopdev_cxt
*lc
,
474 int nooverlap
, int lo_flags
, int flags
,
475 const char *file
, uint64_t offset
, uint64_t sizelimit
)
477 int hasdev
= loopcxt_has_device(lc
);
480 /* losetup --find --noverlap file.img */
481 if (!hasdev
&& nooverlap
) {
482 rc
= loopcxt_find_overlap(lc
, file
, offset
, sizelimit
);
484 case 0: /* not found */
487 case 1: /* overlap */
489 errx(EXIT_FAILURE
, _("%s: overlapping loop device exists"), file
);
491 case 2: /* overlap -- full size and offset match (reuse) */
493 uint32_t lc_encrypt_type
;
495 /* Once a loop is initialized RO, there is no
496 * way to change its parameters. */
497 if (loopcxt_is_readonly(lc
)
498 && !(lo_flags
& LO_FLAGS_READ_ONLY
)) {
500 errx(EXIT_FAILURE
, _("%s: overlapping read-only loop device exists"), file
);
503 /* This is no more supported, but check to be safe. */
504 if (loopcxt_get_encrypt_type(lc
, &lc_encrypt_type
) == 0
505 && lc_encrypt_type
!= LO_CRYPT_NONE
) {
507 errx(EXIT_FAILURE
, _("%s: overlapping encrypted loop device exists"), file
);
510 lc
->info
.lo_flags
&= ~LO_FLAGS_AUTOCLEAR
;
511 if (loopcxt_ioctl_status(lc
)) {
513 errx(EXIT_FAILURE
, _("%s: failed to re-use loop device"), file
);
515 return 0; /* success, re-use */
519 errx(EXIT_FAILURE
, _("failed to inspect loop devices"));
524 if (hasdev
&& !is_loopdev(loopcxt_get_device(lc
)))
525 loopcxt_add_device(lc
);
527 /* losetup --noverlap /dev/loopN file.img */
528 if (hasdev
&& nooverlap
) {
529 struct loopdev_cxt lc2
;
531 if (loopcxt_init(&lc2
, 0)) {
533 err(EXIT_FAILURE
, _("failed to initialize loopcxt"));
535 rc
= loopcxt_find_overlap(&lc2
, file
, offset
, sizelimit
);
536 loopcxt_deinit(&lc2
);
541 errx(EXIT_FAILURE
, _("%s: overlapping loop device exists"), file
);
542 err(EXIT_FAILURE
, _("%s: failed to check for conflicting loop devices"), file
);
546 /* Create a new device */
550 /* Note that loopcxt_{find_unused,set_device}() resets
553 if (!hasdev
&& (rc
= loopcxt_find_unused(lc
))) {
554 warnx(_("cannot find an unused loop device"));
557 if (flags
& LOOPDEV_FL_OFFSET
)
558 loopcxt_set_offset(lc
, offset
);
559 if (flags
& LOOPDEV_FL_SIZELIMIT
)
560 loopcxt_set_sizelimit(lc
, sizelimit
);
562 loopcxt_set_flags(lc
, lo_flags
);
563 if ((rc
= loopcxt_set_backing_file(lc
, file
))) {
564 warn(_("%s: failed to use backing file"), file
);
568 rc
= loopcxt_setup_device(lc
);
571 if (errno
== EBUSY
&& !hasdev
)
575 errpre
= hasdev
&& loopcxt_get_fd(lc
) < 0 ?
576 loopcxt_get_device(lc
) : file
;
577 warn(_("%s: failed to set up loop device"), errpre
);
579 } while (hasdev
== 0);
584 int main(int argc
, char **argv
)
586 struct loopdev_cxt lc
;
587 int act
= 0, flags
= 0, no_overlap
= 0, c
;
589 uint64_t offset
= 0, sizelimit
= 0, blocksize
= 0;
590 int res
= 0, showdev
= 0, lo_flags
= 0;
593 unsigned long use_dio
= 0, set_dio
= 0, set_blocksize
= 0;
596 OPT_SIZELIMIT
= CHAR_MAX
+ 1,
602 static const struct option longopts
[] = {
603 { "all", no_argument
, NULL
, 'a' },
604 { "set-capacity", required_argument
, NULL
, 'c' },
605 { "detach", required_argument
, NULL
, 'd' },
606 { "detach-all", no_argument
, NULL
, 'D' },
607 { "find", no_argument
, NULL
, 'f' },
608 { "nooverlap", no_argument
, NULL
, 'L' },
609 { "help", no_argument
, NULL
, 'h' },
610 { "associated", required_argument
, NULL
, 'j' },
611 { "json", no_argument
, NULL
, 'J' },
612 { "list", no_argument
, NULL
, 'l' },
613 { "sector-size", required_argument
, NULL
, 'b' },
614 { "noheadings", no_argument
, NULL
, 'n' },
615 { "offset", required_argument
, NULL
, 'o' },
616 { "output", required_argument
, NULL
, 'O' },
617 { "output-all", no_argument
, NULL
, OPT_OUTPUT_ALL
},
618 { "sizelimit", required_argument
, NULL
, OPT_SIZELIMIT
},
619 { "partscan", no_argument
, NULL
, 'P' },
620 { "read-only", no_argument
, NULL
, 'r' },
621 { "direct-io", optional_argument
, NULL
, OPT_DIO
},
622 { "raw", no_argument
, NULL
, OPT_RAW
},
623 { "show", no_argument
, NULL
, OPT_SHOW
},
624 { "verbose", no_argument
, NULL
, 'v' },
625 { "version", no_argument
, NULL
, 'V' },
629 static const ul_excl_t excl
[] = { /* rows and cols in ASCII order */
630 { 'D','a','c','d','f','j' },
631 { 'D','c','d','f','l' },
632 { 'D','c','d','f','O' },
636 int excl_st
[ARRAY_SIZE(excl
)] = UL_EXCL_STATUS_INIT
;
638 setlocale(LC_ALL
, "");
639 bindtextdomain(PACKAGE
, LOCALEDIR
);
641 atexit(close_stdout
);
643 if (loopcxt_init(&lc
, 0))
644 err(EXIT_FAILURE
, _("failed to initialize loopcxt"));
646 while ((c
= getopt_long(argc
, argv
, "ab:c:d:Dfhj:JlLno:O:PrvV",
647 longopts
, NULL
)) != -1) {
649 err_exclusive_options(c
, longopts
, excl
, excl_st
);
657 blocksize
= strtosize_or_err(optarg
, _("failed to parse logical block size"));
660 act
= A_SET_CAPACITY
;
661 if (!is_loopdev(optarg
) ||
662 loopcxt_set_device(&lc
, optarg
))
663 err(EXIT_FAILURE
, _("%s: failed to use device"),
667 lo_flags
|= LO_FLAGS_READ_ONLY
;
671 if (!is_loopdev(optarg
) ||
672 loopcxt_set_device(&lc
, optarg
))
673 err(EXIT_FAILURE
, _("%s: failed to use device"),
705 offset
= strtosize_or_err(optarg
, _("failed to parse offset"));
706 flags
|= LOOPDEV_FL_OFFSET
;
713 for (ncolumns
= 0; ncolumns
< ARRAY_SIZE(infos
); ncolumns
++)
714 columns
[ncolumns
] = ncolumns
;
717 lo_flags
|= LO_FLAGS_PARTSCAN
;
723 use_dio
= set_dio
= 1;
725 use_dio
= parse_switch(optarg
, _("argument error"), "on", "off", NULL
);
730 printf(UTIL_LINUX_VERSION
);
732 case OPT_SIZELIMIT
: /* --sizelimit */
733 sizelimit
= strtosize_or_err(optarg
, _("failed to parse size"));
734 flags
|= LOOPDEV_FL_SIZELIMIT
;
737 errtryhelp(EXIT_FAILURE
);
741 ul_path_init_debug();
742 ul_sysfs_init_debug();
744 /* default is --list --all */
750 if (!act
&& argc
== 2 && (raw
|| json
)) {
755 /* default --list output columns */
756 if (list
&& !ncolumns
) {
757 columns
[ncolumns
++] = COL_NAME
;
758 columns
[ncolumns
++] = COL_SIZELIMIT
;
759 columns
[ncolumns
++] = COL_OFFSET
;
760 columns
[ncolumns
++] = COL_AUTOCLR
;
761 columns
[ncolumns
++] = COL_RO
;
762 columns
[ncolumns
++] = COL_BACK_FILE
;
763 columns
[ncolumns
++] = COL_DIO
;
764 columns
[ncolumns
++] = COL_LOGSEC
;
767 if (act
== A_FIND_FREE
&& optind
< argc
) {
769 * losetup -f <backing_file>
772 file
= argv
[optind
++];
775 errx(EXIT_FAILURE
, _("unexpected arguments"));
778 if (list
&& !act
&& optind
== argc
)
780 * losetup --list defaults to --all
784 if (!act
&& optind
+ 1 == argc
) {
786 * losetup [--list] <device>
788 * losetup {--direct-io[=off]|--logical-blocksize=size}... <device>
790 if (!(set_dio
|| set_blocksize
))
793 act
= A_SET_DIRECT_IO
;
795 act
= A_SET_BLOCKSIZE
;
796 if (!is_loopdev(argv
[optind
]) ||
797 loopcxt_set_device(&lc
, argv
[optind
]))
798 err(EXIT_FAILURE
, _("%s: failed to use device"),
804 * losetup <loopdev> <backing_file>
809 errx(EXIT_FAILURE
, _("no loop device specified"));
810 /* don't use is_loopdev() here, the device does not have exist yet */
811 if (loopcxt_set_device(&lc
, argv
[optind
]))
812 err(EXIT_FAILURE
, _("%s: failed to use device"),
817 errx(EXIT_FAILURE
, _("no file specified"));
818 file
= argv
[optind
++];
821 if (act
!= A_CREATE
&&
822 (sizelimit
|| lo_flags
|| showdev
))
824 _("the options %s are allowed during loop device setup only"),
825 "--{sizelimit,read-only,show}");
827 if ((flags
& LOOPDEV_FL_OFFSET
) &&
828 act
!= A_CREATE
&& (act
!= A_SHOW
|| !file
))
829 errx(EXIT_FAILURE
, _("the option --offset is not allowed in this context"));
831 if (outarg
&& string_add_to_idarray(outarg
, columns
, ARRAY_SIZE(columns
),
832 &ncolumns
, column_name_to_id
) < 0)
837 res
= create_loop(&lc
, no_overlap
, lo_flags
, flags
, file
, offset
, sizelimit
);
840 printf("%s\n", loopcxt_get_device(&lc
));
841 warn_size(file
, sizelimit
, offset
, flags
);
842 if (set_dio
|| set_blocksize
)
847 res
= delete_loop(&lc
);
848 while (optind
< argc
) {
849 if (!is_loopdev(argv
[optind
]) ||
850 loopcxt_set_device(&lc
, argv
[optind
]))
851 warn(_("%s: failed to use device"),
854 res
+= delete_loop(&lc
);
858 res
= delete_all_loops(&lc
);
861 res
= loopcxt_find_unused(&lc
);
865 if (access(_PATH_DEV_LOOPCTL
, F_OK
) == 0 &&
866 access(_PATH_DEV_LOOPCTL
, W_OK
) != 0)
871 warn(_("cannot find an unused loop device"));
873 printf("%s\n", loopcxt_get_device(&lc
));
877 res
= show_table(&lc
, file
, offset
, flags
);
879 res
= show_all_loops(&lc
, file
, offset
, flags
);
883 res
= show_table(&lc
, NULL
, 0, 0);
885 res
= printf_loopdev(&lc
);
887 warn("%s", loopcxt_get_device(&lc
));
890 res
= loopcxt_ioctl_capacity(&lc
);
892 warn(_("%s: set capacity failed"),
893 loopcxt_get_device(&lc
));
895 case A_SET_DIRECT_IO
:
896 case A_SET_BLOCKSIZE
:
899 res
= loopcxt_ioctl_dio(&lc
, use_dio
);
901 warn(_("%s: set direct io failed"),
902 loopcxt_get_device(&lc
));
905 res
= loopcxt_ioctl_blocksize(&lc
, blocksize
);
907 warn(_("%s: set logical block size failed"),
908 loopcxt_get_device(&lc
));
912 warnx(_("bad usage"));
913 errtryhelp(EXIT_FAILURE
);
918 return res
? EXIT_FAILURE
: EXIT_SUCCESS
;