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
,
478 int hasdev
= loopcxt_has_device(lc
);
481 /* losetup --find --noverlap file.img */
482 if (!hasdev
&& nooverlap
) {
483 rc
= loopcxt_find_overlap(lc
, file
, offset
, sizelimit
);
485 case 0: /* not found */
488 case 1: /* overlap */
490 errx(EXIT_FAILURE
, _("%s: overlapping loop device exists"), file
);
492 case 2: /* overlap -- full size and offset match (reuse) */
494 uint32_t lc_encrypt_type
;
496 /* Once a loop is initialized RO, there is no
497 * way to change its parameters. */
498 if (loopcxt_is_readonly(lc
)
499 && !(lo_flags
& LO_FLAGS_READ_ONLY
)) {
501 errx(EXIT_FAILURE
, _("%s: overlapping read-only loop device exists"), file
);
504 /* This is no more supported, but check to be safe. */
505 if (loopcxt_get_encrypt_type(lc
, &lc_encrypt_type
) == 0
506 && lc_encrypt_type
!= LO_CRYPT_NONE
) {
508 errx(EXIT_FAILURE
, _("%s: overlapping encrypted loop device exists"), file
);
511 lc
->info
.lo_flags
&= ~LO_FLAGS_AUTOCLEAR
;
512 if (loopcxt_ioctl_status(lc
)) {
514 errx(EXIT_FAILURE
, _("%s: failed to re-use loop device"), file
);
516 return 0; /* success, re-use */
520 errx(EXIT_FAILURE
, _("failed to inspect loop devices"));
525 if (hasdev
&& !is_loopdev(loopcxt_get_device(lc
)))
526 loopcxt_add_device(lc
);
528 /* losetup --noverlap /dev/loopN file.img */
529 if (hasdev
&& nooverlap
) {
530 struct loopdev_cxt lc2
;
532 if (loopcxt_init(&lc2
, 0)) {
534 err(EXIT_FAILURE
, _("failed to initialize loopcxt"));
536 rc
= loopcxt_find_overlap(&lc2
, file
, offset
, sizelimit
);
537 loopcxt_deinit(&lc2
);
542 errx(EXIT_FAILURE
, _("%s: overlapping loop device exists"), file
);
543 err(EXIT_FAILURE
, _("%s: failed to check for conflicting loop devices"), file
);
547 /* Create a new device */
551 /* Note that loopcxt_{find_unused,set_device}() resets
554 if (!hasdev
&& (rc
= loopcxt_find_unused(lc
))) {
555 warnx(_("cannot find an unused loop device"));
558 if (flags
& LOOPDEV_FL_OFFSET
)
559 loopcxt_set_offset(lc
, offset
);
560 if (flags
& LOOPDEV_FL_SIZELIMIT
)
561 loopcxt_set_sizelimit(lc
, sizelimit
);
563 loopcxt_set_flags(lc
, lo_flags
);
565 loopcxt_set_blocksize(lc
, blocksize
);
567 if ((rc
= loopcxt_set_backing_file(lc
, file
))) {
568 warn(_("%s: failed to use backing file"), file
);
572 rc
= loopcxt_setup_device(lc
);
575 if (errno
== EBUSY
&& !hasdev
)
579 errpre
= hasdev
&& loopcxt_get_fd(lc
) < 0 ?
580 loopcxt_get_device(lc
) : file
;
581 warn(_("%s: failed to set up loop device"), errpre
);
583 } while (hasdev
== 0);
588 int main(int argc
, char **argv
)
590 struct loopdev_cxt lc
;
591 int act
= 0, flags
= 0, no_overlap
= 0, c
;
593 uint64_t offset
= 0, sizelimit
= 0, blocksize
= 0;
594 int res
= 0, showdev
= 0, lo_flags
= 0;
597 unsigned long use_dio
= 0, set_dio
= 0, set_blocksize
= 0;
600 OPT_SIZELIMIT
= CHAR_MAX
+ 1,
606 static const struct option longopts
[] = {
607 { "all", no_argument
, NULL
, 'a' },
608 { "set-capacity", required_argument
, NULL
, 'c' },
609 { "detach", required_argument
, NULL
, 'd' },
610 { "detach-all", no_argument
, NULL
, 'D' },
611 { "find", no_argument
, NULL
, 'f' },
612 { "nooverlap", no_argument
, NULL
, 'L' },
613 { "help", no_argument
, NULL
, 'h' },
614 { "associated", required_argument
, NULL
, 'j' },
615 { "json", no_argument
, NULL
, 'J' },
616 { "list", no_argument
, NULL
, 'l' },
617 { "sector-size", required_argument
, NULL
, 'b' },
618 { "noheadings", no_argument
, NULL
, 'n' },
619 { "offset", required_argument
, NULL
, 'o' },
620 { "output", required_argument
, NULL
, 'O' },
621 { "output-all", no_argument
, NULL
, OPT_OUTPUT_ALL
},
622 { "sizelimit", required_argument
, NULL
, OPT_SIZELIMIT
},
623 { "partscan", no_argument
, NULL
, 'P' },
624 { "read-only", no_argument
, NULL
, 'r' },
625 { "direct-io", optional_argument
, NULL
, OPT_DIO
},
626 { "raw", no_argument
, NULL
, OPT_RAW
},
627 { "show", no_argument
, NULL
, OPT_SHOW
},
628 { "verbose", no_argument
, NULL
, 'v' },
629 { "version", no_argument
, NULL
, 'V' },
633 static const ul_excl_t excl
[] = { /* rows and cols in ASCII order */
634 { 'D','a','c','d','f','j' },
635 { 'D','c','d','f','l' },
636 { 'D','c','d','f','O' },
640 int excl_st
[ARRAY_SIZE(excl
)] = UL_EXCL_STATUS_INIT
;
642 setlocale(LC_ALL
, "");
643 bindtextdomain(PACKAGE
, LOCALEDIR
);
645 close_stdout_atexit();
647 if (loopcxt_init(&lc
, 0))
648 err(EXIT_FAILURE
, _("failed to initialize loopcxt"));
650 while ((c
= getopt_long(argc
, argv
, "ab:c:d:Dfhj:JlLno:O:PrvV",
651 longopts
, NULL
)) != -1) {
653 err_exclusive_options(c
, longopts
, excl
, excl_st
);
661 blocksize
= strtosize_or_err(optarg
, _("failed to parse logical block size"));
664 act
= A_SET_CAPACITY
;
665 if (!is_loopdev(optarg
) ||
666 loopcxt_set_device(&lc
, optarg
))
667 err(EXIT_FAILURE
, _("%s: failed to use device"),
671 lo_flags
|= LO_FLAGS_READ_ONLY
;
675 if (!is_loopdev(optarg
) ||
676 loopcxt_set_device(&lc
, optarg
))
677 err(EXIT_FAILURE
, _("%s: failed to use device"),
706 offset
= strtosize_or_err(optarg
, _("failed to parse offset"));
707 flags
|= LOOPDEV_FL_OFFSET
;
714 for (ncolumns
= 0; ncolumns
< ARRAY_SIZE(infos
); ncolumns
++)
715 columns
[ncolumns
] = ncolumns
;
718 lo_flags
|= LO_FLAGS_PARTSCAN
;
724 use_dio
= set_dio
= 1;
726 use_dio
= parse_switch(optarg
, _("argument error"), "on", "off", NULL
);
730 case OPT_SIZELIMIT
: /* --sizelimit */
731 sizelimit
= strtosize_or_err(optarg
, _("failed to parse size"));
732 flags
|= LOOPDEV_FL_SIZELIMIT
;
738 print_version(EXIT_SUCCESS
);
740 errtryhelp(EXIT_FAILURE
);
744 ul_path_init_debug();
745 ul_sysfs_init_debug();
747 /* default is --list --all */
753 if (!act
&& argc
== 2 && (raw
|| json
)) {
758 /* default --list output columns */
759 if (list
&& !ncolumns
) {
760 columns
[ncolumns
++] = COL_NAME
;
761 columns
[ncolumns
++] = COL_SIZELIMIT
;
762 columns
[ncolumns
++] = COL_OFFSET
;
763 columns
[ncolumns
++] = COL_AUTOCLR
;
764 columns
[ncolumns
++] = COL_RO
;
765 columns
[ncolumns
++] = COL_BACK_FILE
;
766 columns
[ncolumns
++] = COL_DIO
;
767 columns
[ncolumns
++] = COL_LOGSEC
;
770 if (act
== A_FIND_FREE
&& optind
< argc
) {
772 * losetup -f <backing_file>
775 file
= argv
[optind
++];
778 errx(EXIT_FAILURE
, _("unexpected arguments"));
781 if (list
&& !act
&& optind
== argc
)
783 * losetup --list defaults to --all
787 if (!act
&& optind
+ 1 == argc
) {
789 * losetup [--list] <device>
791 * losetup {--direct-io[=off]|--logical-blocksize=size}... <device>
793 if (!(set_dio
|| set_blocksize
))
796 act
= A_SET_DIRECT_IO
;
798 act
= A_SET_BLOCKSIZE
;
799 if (!is_loopdev(argv
[optind
]) ||
800 loopcxt_set_device(&lc
, argv
[optind
]))
801 err(EXIT_FAILURE
, _("%s: failed to use device"),
807 * losetup <loopdev> <backing_file>
812 errx(EXIT_FAILURE
, _("no loop device specified"));
813 /* don't use is_loopdev() here, the device does not have exist yet */
814 if (loopcxt_set_device(&lc
, argv
[optind
]))
815 err(EXIT_FAILURE
, _("%s: failed to use device"),
820 errx(EXIT_FAILURE
, _("no file specified"));
821 file
= argv
[optind
++];
824 if (act
!= A_CREATE
&&
825 (sizelimit
|| lo_flags
|| showdev
))
827 _("the options %s are allowed during loop device setup only"),
828 "--{sizelimit,partscan,read-only,show}");
830 if ((flags
& LOOPDEV_FL_OFFSET
) &&
831 act
!= A_CREATE
&& (act
!= A_SHOW
|| !file
))
832 errx(EXIT_FAILURE
, _("the option --offset is not allowed in this context"));
834 if (outarg
&& string_add_to_idarray(outarg
, columns
, ARRAY_SIZE(columns
),
835 &ncolumns
, column_name_to_id
) < 0)
840 res
= create_loop(&lc
, no_overlap
, lo_flags
, flags
, file
,
841 offset
, sizelimit
, blocksize
);
844 printf("%s\n", loopcxt_get_device(&lc
));
845 warn_size(file
, sizelimit
, offset
, flags
);
851 res
= delete_loop(&lc
);
852 while (optind
< argc
) {
853 if (!is_loopdev(argv
[optind
]) ||
854 loopcxt_set_device(&lc
, argv
[optind
]))
855 warn(_("%s: failed to use device"),
858 res
+= delete_loop(&lc
);
862 res
= delete_all_loops(&lc
);
865 res
= loopcxt_find_unused(&lc
);
869 if (access(_PATH_DEV_LOOPCTL
, F_OK
) == 0 &&
870 access(_PATH_DEV_LOOPCTL
, W_OK
) != 0)
875 warn(_("cannot find an unused loop device"));
877 printf("%s\n", loopcxt_get_device(&lc
));
881 res
= show_table(&lc
, file
, offset
, flags
);
883 res
= show_all_loops(&lc
, file
, offset
, flags
);
887 res
= show_table(&lc
, NULL
, 0, 0);
889 res
= printf_loopdev(&lc
);
891 warn("%s", loopcxt_get_device(&lc
));
894 res
= loopcxt_ioctl_capacity(&lc
);
896 warn(_("%s: set capacity failed"),
897 loopcxt_get_device(&lc
));
899 case A_SET_DIRECT_IO
:
901 res
= loopcxt_ioctl_dio(&lc
, use_dio
);
903 warn(_("%s: set direct io failed"),
904 loopcxt_get_device(&lc
));
906 case A_SET_BLOCKSIZE
:
907 res
= loopcxt_ioctl_blocksize(&lc
, blocksize
);
909 warn(_("%s: set logical block size failed"),
910 loopcxt_get_device(&lc
));
913 warnx(_("bad usage"));
914 errtryhelp(EXIT_FAILURE
);
919 return res
? EXIT_FAILURE
: EXIT_SUCCESS
;