2 * SPDX-License-Identifier: GPL-2.0-or-later
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * Original implementation from Ted Ts'o; losetup was part of mount.
11 * Copyright (C) 2011-2023 Karel Zak <kzak@redhat.com>
13 * losetup.c - setup and control loop devices
21 #include <sys/ioctl.h>
26 #include <libsmartcols.h>
33 #include "closestream.h"
36 #include "canonicalize.h"
37 #include "pathnames.h"
40 A_CREATE
= 1, /* setup a new device */
41 A_DELETE
, /* delete given device(s) */
42 A_DELETE_ALL
, /* delete all devices */
43 A_SHOW
, /* list devices */
44 A_SHOW_ONE
, /* print info about one device */
45 A_FIND_FREE
, /* find first unused */
46 A_SET_CAPACITY
, /* set device capacity */
47 A_SET_DIRECT_IO
, /* set accessing backing file by direct io */
48 A_SET_BLOCKSIZE
, /* set logical block size of the loop device */
71 /* basic output flags */
72 static int no_headings
;
77 const char * const name
;
82 int json_type
; /* default is string */
85 static const struct colinfo infos
[] = {
86 [COL_AUTOCLR
] = { "AUTOCLEAR", 1, SCOLS_FL_RIGHT
, N_("autoclear flag set"), SCOLS_JSON_BOOLEAN
},
87 [COL_BACK_FILE
] = { "BACK-FILE", 0.3, SCOLS_FL_NOEXTREMES
, N_("device backing file")},
88 [COL_BACK_INO
] = { "BACK-INO", 4, SCOLS_FL_RIGHT
, N_("backing file inode number"), SCOLS_JSON_NUMBER
},
89 [COL_BACK_MAJMIN
] = { "BACK-MAJ:MIN", 6, 0, N_("backing file major:minor device number")},
90 [COL_BACK_MAJ
] = { "BACK-MAJ", 6, 0, N_("backing file major device number")},
91 [COL_BACK_MIN
] = { "BACK-MIN", 6, 0, N_("backing file minor device number")},
92 [COL_NAME
] = { "NAME", 0.25, 0, N_("loop device name")},
93 [COL_OFFSET
] = { "OFFSET", 5, SCOLS_FL_RIGHT
, N_("offset from the beginning"), SCOLS_JSON_NUMBER
},
94 [COL_PARTSCAN
] = { "PARTSCAN", 1, SCOLS_FL_RIGHT
, N_("partscan flag set"), SCOLS_JSON_BOOLEAN
},
95 [COL_REF
] = { "REF", 0.1, 0, N_("loop device reference string")},
96 [COL_RO
] = { "RO", 1, SCOLS_FL_RIGHT
, N_("read-only device"), SCOLS_JSON_BOOLEAN
},
97 [COL_SIZELIMIT
] = { "SIZELIMIT", 5, SCOLS_FL_RIGHT
, N_("size limit of the file in bytes"), SCOLS_JSON_NUMBER
},
98 [COL_MAJMIN
] = { "MAJ:MIN", 3, 0, N_("loop device major:minor number")},
99 [COL_MAJ
] = { "MAJ", 1, SCOLS_FL_RIGHT
, N_("loop device major number"), SCOLS_JSON_NUMBER
},
100 [COL_MIN
] = { "MIN", 1, SCOLS_FL_RIGHT
, N_("loop device minor number"), SCOLS_JSON_NUMBER
},
101 [COL_DIO
] = { "DIO", 1, SCOLS_FL_RIGHT
, N_("access backing file with direct-io"), SCOLS_JSON_BOOLEAN
},
102 [COL_LOGSEC
] = { "LOG-SEC", 4, SCOLS_FL_RIGHT
, N_("logical sector size in bytes"), SCOLS_JSON_NUMBER
},
105 static int columns
[ARRAY_SIZE(infos
) * 2] = {-1};
106 static size_t ncolumns
;
108 static int get_column_id(int num
)
111 assert((size_t) num
< ncolumns
);
112 assert(columns
[num
] < (int) ARRAY_SIZE(infos
));
116 static const struct colinfo
*get_column_info(int num
)
118 return &infos
[ get_column_id(num
) ];
121 static int column_name_to_id(const char *name
, size_t namesz
)
125 for (i
= 0; i
< ARRAY_SIZE(infos
); i
++) {
126 const char *cn
= infos
[i
].name
;
128 if (!c_strncasecmp(name
, cn
, namesz
) && !*(cn
+ namesz
))
131 warnx(_("unknown column: %s"), name
);
135 static int printf_loopdev(struct loopdev_cxt
*lc
)
143 fname
= loopcxt_get_backing_file(lc
);
147 if (loopcxt_get_backing_devno(lc
, &dev
) == 0)
148 loopcxt_get_backing_inode(lc
, &ino
);
152 * Probably non-root user (no permissions to
153 * call LOOP_GET_STATUS ioctls).
155 printf("%s%s: []: (%s)",
156 loopcxt_get_device(lc
),
157 loopcxt_is_lost(lc
) ? " (lost)" : "",
160 if (loopcxt_get_offset(lc
, &x
) == 0 && x
)
161 printf(_(", offset %ju"), x
);
162 if (loopcxt_get_sizelimit(lc
, &x
) == 0 && x
)
163 printf(_(", sizelimit %ju"), x
);
168 printf("%s%s: [%04jd]:%ju (%s)",
169 loopcxt_get_device(lc
),
170 loopcxt_is_lost(lc
) ? " (lost)" : "",
171 (intmax_t) dev
, (uintmax_t) ino
, fname
);
173 if (loopcxt_get_offset(lc
, &x
) == 0 && x
)
174 printf(_(", offset %ju"), x
);
175 if (loopcxt_get_sizelimit(lc
, &x
) == 0 && x
)
176 printf(_(", sizelimit %ju"), x
);
178 if (loopcxt_get_encrypt_type(lc
, &type
) == 0) {
179 const char *e
= loopcxt_get_crypt_name(lc
);
181 if ((!e
|| !*e
) && type
== 1)
184 printf(_(", encryption %s (type %u)"), e
, type
);
193 static int show_all_loops(struct loopdev_cxt
*lc
, const char *file
,
194 uint64_t offset
, int flags
)
196 struct stat sbuf
, *st
= &sbuf
;
197 char *cn_file
= NULL
;
199 if (loopcxt_init_iterator(lc
, LOOPITER_FL_USED
))
202 if (!file
|| stat(file
, st
))
205 while (loopcxt_next(lc
) == 0) {
208 const char *bf
= cn_file
? cn_file
: file
;
210 used
= loopcxt_is_used(lc
, st
, bf
, offset
, 0, flags
);
211 if (!used
&& !cn_file
) {
212 bf
= cn_file
= canonicalize_path(file
);
213 used
= loopcxt_is_used(lc
, st
, bf
, offset
, 0, flags
);
220 loopcxt_deinit_iterator(lc
);
225 static void warn_lost(struct loopdev_cxt
*lc
)
227 dev_t devno
= loopcxt_get_devno(lc
);
232 warnx(("device node %s (%u:%u) is lost. You may use mknod(1) to recover it."),
233 loopcxt_get_device(lc
), major(devno
), minor(devno
));
236 static int delete_loop(struct loopdev_cxt
*lc
)
238 if (loopcxt_delete_device(lc
)) {
239 warn(_("%s: detach failed"), loopcxt_get_device(lc
));
240 if (loopcxt_is_lost(lc
))
248 static int delete_all_loops(struct loopdev_cxt
*lc
)
252 if (loopcxt_init_iterator(lc
, LOOPITER_FL_USED
))
255 while (loopcxt_next(lc
) == 0)
256 res
+= delete_loop(lc
);
258 loopcxt_deinit_iterator(lc
);
262 static int set_scols_data(struct loopdev_cxt
*lc
, struct libscols_line
*ln
)
266 for (i
= 0; i
< ncolumns
; i
++) {
267 const char *p
= NULL
; /* external data */
268 char *np
= NULL
; /* allocated here */
272 switch(get_column_id(i
)) {
274 p
= loopcxt_get_device(lc
);
275 if (loopcxt_is_lost(lc
)) {
276 xasprintf(&np
, "%s (lost)", p
);
281 np
= loopcxt_get_backing_file(lc
);
284 if (loopcxt_get_offset(lc
, &x
) == 0)
285 xasprintf(&np
, "%jd", x
);
288 if (loopcxt_get_sizelimit(lc
, &x
) == 0)
289 xasprintf(&np
, "%jd", x
);
291 case COL_BACK_MAJMIN
:
294 if (loopcxt_get_backing_devno(lc
, &dev
) == 0 && dev
)
295 xasprintf(&np
, raw
|| json
? "%u:%u" : "%8u:%-3u",
296 major(dev
), minor(dev
));
302 if (loopcxt_get_backing_devno(lc
, &dev
) == 0 && dev
)
303 xasprintf(&np
, "%u", major(dev
));
309 if (loopcxt_get_backing_devno(lc
, &dev
) == 0 && dev
)
310 xasprintf(&np
, "%u", minor(dev
));
315 dev_t dev
= loopcxt_get_devno(lc
);
317 xasprintf(&np
, raw
|| json
? "%u:%u" :"%3u:%-3u",
318 major(dev
), minor(dev
));
322 dev_t dev
= loopcxt_get_devno(lc
);
324 xasprintf(&np
, "%u", major(dev
));
328 dev_t dev
= loopcxt_get_devno(lc
);
330 xasprintf(&np
, "%u", minor(dev
));
336 if (loopcxt_get_backing_inode(lc
, &ino
) == 0 && ino
)
337 xasprintf(&np
, "%ju", ino
);
341 p
= loopcxt_is_autoclear(lc
) ? "1" : "0";
344 p
= loopcxt_is_readonly(lc
) ? "1" : "0";
347 p
= loopcxt_is_dio(lc
) ? "1" : "0";
350 p
= loopcxt_is_partscan(lc
) ? "1" : "0";
353 if (loopcxt_get_blocksize(lc
, &x
) == 0)
354 xasprintf(&np
, "%jd", x
);
357 np
= loopcxt_get_refname(lc
);
365 rc
= scols_line_set_data(ln
, i
, p
); /* calls strdup() */
367 rc
= scols_line_refer_data(ln
, i
, np
); /* only refers */
370 err(EXIT_FAILURE
, _("failed to add output data"));
376 static int show_table(struct loopdev_cxt
*lc
,
381 struct stat sbuf
, *st
= &sbuf
;
382 struct libscols_table
*tb
;
383 struct libscols_line
*ln
;
389 if (!(tb
= scols_new_table()))
390 err(EXIT_FAILURE
, _("failed to allocate output table"));
391 scols_table_enable_raw(tb
, raw
);
392 scols_table_enable_json(tb
, json
);
393 scols_table_enable_noheadings(tb
, no_headings
);
396 scols_table_set_name(tb
, "loopdevices");
398 for (i
= 0; i
< ncolumns
; i
++) {
399 const struct colinfo
*ci
= get_column_info(i
);
400 struct libscols_column
*cl
;
402 cl
= scols_table_new_column(tb
, ci
->name
, ci
->whint
, ci
->flags
);
404 err(EXIT_FAILURE
, _("failed to allocate output column"));
406 scols_column_set_json_type(cl
, ci
->json_type
);
409 /* only one loopdev requested (already assigned to loopdev_cxt) */
410 if (loopcxt_get_device(lc
)) {
411 ln
= scols_table_new_line(tb
, NULL
);
413 err(EXIT_FAILURE
, _("failed to allocate output line"));
414 rc
= set_scols_data(lc
, ln
);
416 /* list all loopdevs */
418 char *cn_file
= NULL
;
420 rc
= loopcxt_init_iterator(lc
, LOOPITER_FL_USED
);
423 if (!file
|| stat(file
, st
))
426 while (loopcxt_next(lc
) == 0) {
429 const char *bf
= cn_file
? cn_file
: file
;
431 used
= loopcxt_is_used(lc
, st
, bf
, offset
, 0, flags
);
432 if (!used
&& !cn_file
) {
433 bf
= cn_file
= canonicalize_path(file
);
434 used
= loopcxt_is_used(lc
, st
, bf
, offset
, 0, flags
);
440 ln
= scols_table_new_line(tb
, NULL
);
442 err(EXIT_FAILURE
, _("failed to allocate output line"));
443 rc
= set_scols_data(lc
, ln
);
448 loopcxt_deinit_iterator(lc
);
453 rc
= scols_print_table(tb
);
454 scols_unref_table(tb
);
458 static void __attribute__((__noreturn__
)) usage(void)
463 fputs(USAGE_HEADER
, out
);
466 _(" %1$s [options] [<loopdev>]\n"
467 " %1$s [options] -f | <loopdev> <file>\n"),
468 program_invocation_short_name
);
470 fputs(USAGE_SEPARATOR
, out
);
471 fputs(_("Set up and control loop devices.\n"), out
);
474 fputs(USAGE_OPTIONS
, out
);
475 fputs(_(" -a, --all list all used devices\n"), out
);
476 fputs(_(" -d, --detach <loopdev>... detach one or more devices\n"), out
);
477 fputs(_(" -D, --detach-all detach all used devices\n"), out
);
478 fputs(_(" -f, --find find first unused device\n"), out
);
479 fputs(_(" -c, --set-capacity <loopdev> resize the device\n"), out
);
480 fputs(_(" -j, --associated <file> list all devices associated with <file>\n"), out
);
481 fputs(_(" -L, --nooverlap avoid possible conflict between devices\n"), out
);
483 /* commands options */
484 fputs(USAGE_SEPARATOR
, out
);
485 fputs(_(" -o, --offset <num> start at offset <num> into file\n"), out
);
486 fputs(_(" --sizelimit <num> device is limited to <num> bytes of the file\n"), out
);
487 fputs(_(" -b, --sector-size <num> set the logical sector size to <num>\n"), out
);
488 fputs(_(" -P, --partscan create a partitioned loop device\n"), out
);
489 fputs(_(" -r, --read-only set up a read-only loop device\n"), out
);
490 fputs(_(" --direct-io[=<on|off>] open backing file with O_DIRECT\n"), out
);
491 fputs(_(" --loop-ref <string> loop device reference\n"), out
);
492 fputs(_(" --show print device name after setup (with -f)\n"), out
);
493 fputs(_(" -v, --verbose verbose mode\n"), out
);
496 fputs(USAGE_SEPARATOR
, out
);
497 fputs(_(" -J, --json use JSON --list output format\n"), out
);
498 fputs(_(" -l, --list list info about all or specified (default)\n"), out
);
499 fputs(_(" -n, --noheadings don't print headings for --list output\n"), out
);
500 fputs(_(" -O, --output <cols> specify columns to output for --list\n"), out
);
501 fputs(_(" --output-all output all columns\n"), out
);
502 fputs(_(" --raw use raw --list output format\n"), out
);
504 fputs(USAGE_SEPARATOR
, out
);
505 fprintf(out
, USAGE_HELP_OPTIONS(31));
507 fputs(USAGE_COLUMNS
, out
);
508 for (i
= 0; i
< ARRAY_SIZE(infos
); i
++)
509 fprintf(out
, " %12s %s\n", infos
[i
].name
, _(infos
[i
].help
));
511 fprintf(out
, USAGE_MAN_TAIL("losetup(8)"));
516 static void warn_size(const char *filename
, uint64_t size
, uint64_t offset
, int flags
)
521 if (stat(filename
, &st
) || S_ISBLK(st
.st_mode
))
525 if (flags
& LOOPDEV_FL_OFFSET
)
530 warnx(_("%s: Warning: file is smaller than 512 bytes; the loop device "
531 "may be useless or invisible for system tools."),
534 warnx(_("%s: Warning: file does not end on a 512-byte sector boundary; "
535 "the remaining end of the file will be ignored."),
539 static int find_unused(struct loopdev_cxt
*lc
)
543 rc
= loopcxt_find_unused(lc
);
547 if (access(_PATH_DEV_LOOPCTL
, F_OK
) == 0 &&
548 access(_PATH_DEV_LOOPCTL
, W_OK
) != 0)
553 warn(_("cannot find an unused loop device"));
558 static int create_loop(struct loopdev_cxt
*lc
,
559 int nooverlap
, int lo_flags
, int flags
,
560 const char *file
, const char *refname
,
561 uint64_t offset
, uint64_t sizelimit
,
564 int hasdev
= loopcxt_has_device(lc
);
565 int rc
= 0, ntries
= 0;
567 /* losetup --find --noverlap file.img */
568 if (!hasdev
&& nooverlap
) {
569 rc
= loopcxt_find_overlap(lc
, file
, offset
, sizelimit
);
571 case 0: /* not found */
574 case 1: /* overlap */
576 errx(EXIT_FAILURE
, _("%s: overlapping loop device exists"), file
);
578 case 2: /* overlap -- full size and offset match (reuse) */
580 uint32_t lc_encrypt_type
;
582 /* Once a loop is initialized RO, there is no
583 * way to change its parameters. */
584 if (loopcxt_is_readonly(lc
)
585 && !(lo_flags
& LO_FLAGS_READ_ONLY
)) {
587 errx(EXIT_FAILURE
, _("%s: overlapping read-only loop device exists"), file
);
590 /* This is no more supported, but check to be safe. */
591 if (loopcxt_get_encrypt_type(lc
, &lc_encrypt_type
) == 0
592 && lc_encrypt_type
!= LO_CRYPT_NONE
) {
594 errx(EXIT_FAILURE
, _("%s: overlapping encrypted loop device exists"), file
);
597 lc
->config
.info
.lo_flags
&= ~LO_FLAGS_AUTOCLEAR
;
598 if (loopcxt_ioctl_status(lc
)) {
600 errx(EXIT_FAILURE
, _("%s: failed to re-use loop device"), file
);
602 return 0; /* success, re-use */
606 errx(EXIT_FAILURE
, _("failed to inspect loop devices"));
612 loopcxt_add_device(lc
);
614 /* losetup --noverlap /dev/loopN file.img */
615 if (hasdev
&& nooverlap
) {
616 struct loopdev_cxt lc2
;
618 if (loopcxt_init(&lc2
, 0)) {
620 err(EXIT_FAILURE
, _("failed to initialize loopcxt"));
622 rc
= loopcxt_find_overlap(&lc2
, file
, offset
, sizelimit
);
623 loopcxt_deinit(&lc2
);
628 errx(EXIT_FAILURE
, _("%s: overlapping loop device exists"), file
);
629 err(EXIT_FAILURE
, _("%s: failed to check for conflicting loop devices"), file
);
633 /* Create a new device */
637 /* Note that loopcxt_{find_unused,set_device}() resets
640 if (!hasdev
&& (rc
= find_unused(lc
)))
642 if (flags
& LOOPDEV_FL_OFFSET
)
643 loopcxt_set_offset(lc
, offset
);
644 if (flags
& LOOPDEV_FL_SIZELIMIT
)
645 loopcxt_set_sizelimit(lc
, sizelimit
);
647 loopcxt_set_flags(lc
, lo_flags
);
649 loopcxt_set_blocksize(lc
, blocksize
);
650 if (refname
&& (rc
= loopcxt_set_refname(lc
, refname
))) {
651 warnx(_("cannot set loop reference string"));
654 if ((rc
= loopcxt_set_backing_file(lc
, file
))) {
655 warn(_("%s: failed to use backing file"), file
);
659 rc
= loopcxt_setup_device(lc
);
663 if ((errno
== EBUSY
|| errno
== EAGAIN
) && !hasdev
&& ntries
< 64) {
670 errpre
= hasdev
&& lc
->fd
< 0 ?
671 loopcxt_get_device(lc
) : file
;
672 warn(_("%s: failed to set up loop device"), errpre
);
674 } while (hasdev
== 0);
679 int main(int argc
, char **argv
)
681 struct loopdev_cxt lc
;
682 int act
= 0, flags
= 0, no_overlap
= 0, c
;
683 char *file
= NULL
, *refname
= NULL
;
684 uint64_t offset
= 0, sizelimit
= 0, blocksize
= 0;
685 int res
= 0, showdev
= 0, lo_flags
= 0;
688 unsigned long use_dio
= 0, set_dio
= 0, set_blocksize
= 0;
691 OPT_SIZELIMIT
= CHAR_MAX
+ 1,
698 static const struct option longopts
[] = {
699 { "all", no_argument
, NULL
, 'a' },
700 { "set-capacity", required_argument
, NULL
, 'c' },
701 { "detach", required_argument
, NULL
, 'd' },
702 { "detach-all", no_argument
, NULL
, 'D' },
703 { "find", no_argument
, NULL
, 'f' },
704 { "nooverlap", no_argument
, NULL
, 'L' },
705 { "help", no_argument
, NULL
, 'h' },
706 { "associated", required_argument
, NULL
, 'j' },
707 { "json", no_argument
, NULL
, 'J' },
708 { "list", no_argument
, NULL
, 'l' },
709 { "sector-size", required_argument
, NULL
, 'b' },
710 { "noheadings", no_argument
, NULL
, 'n' },
711 { "offset", required_argument
, NULL
, 'o' },
712 { "output", required_argument
, NULL
, 'O' },
713 { "output-all", no_argument
, NULL
, OPT_OUTPUT_ALL
},
714 { "sizelimit", required_argument
, NULL
, OPT_SIZELIMIT
},
715 { "partscan", no_argument
, NULL
, 'P' },
716 { "read-only", no_argument
, NULL
, 'r' },
717 { "direct-io", optional_argument
, NULL
, OPT_DIO
},
718 { "raw", no_argument
, NULL
, OPT_RAW
},
719 { "loop-ref", required_argument
, NULL
, OPT_REF
, },
720 { "show", no_argument
, NULL
, OPT_SHOW
},
721 { "verbose", no_argument
, NULL
, 'v' },
722 { "version", no_argument
, NULL
, 'V' },
726 static const ul_excl_t excl
[] = { /* rows and cols in ASCII order */
727 { 'D','a','c','d','f','j' },
728 { 'D','c','d','f','l' },
729 { 'D','c','d','f','O' },
733 int excl_st
[ARRAY_SIZE(excl
)] = UL_EXCL_STATUS_INIT
;
735 setlocale(LC_ALL
, "");
736 bindtextdomain(PACKAGE
, LOCALEDIR
);
738 close_stdout_atexit();
740 if (loopcxt_init(&lc
, 0))
741 err(EXIT_FAILURE
, _("failed to initialize loopcxt"));
743 while ((c
= getopt_long(argc
, argv
, "ab:c:d:Dfhj:JlLno:O:PrvV",
744 longopts
, NULL
)) != -1) {
746 err_exclusive_options(c
, longopts
, excl
, excl_st
);
754 blocksize
= strtosize_or_err(optarg
, _("failed to parse logical block size"));
757 act
= A_SET_CAPACITY
;
758 if (loopcxt_set_device(&lc
, optarg
))
759 err(EXIT_FAILURE
, _("%s: failed to use device"),
763 lo_flags
|= LO_FLAGS_READ_ONLY
;
770 if (loopcxt_set_device(&lc
, optarg
))
771 err(EXIT_FAILURE
, _("%s: failed to use device"),
800 offset
= strtosize_or_err(optarg
, _("failed to parse offset"));
801 flags
|= LOOPDEV_FL_OFFSET
;
809 for (ncolumns
= 0; ncolumns
< ARRAY_SIZE(infos
); ncolumns
++)
810 columns
[ncolumns
] = ncolumns
;
813 lo_flags
|= LO_FLAGS_PARTSCAN
;
819 use_dio
= set_dio
= 1;
821 use_dio
= ul_parse_switch(optarg
, "on", "off", NULL
);
823 lo_flags
|= LO_FLAGS_DIRECT_IO
;
827 case OPT_SIZELIMIT
: /* --sizelimit */
828 sizelimit
= strtosize_or_err(optarg
, _("failed to parse size"));
829 flags
|= LOOPDEV_FL_SIZELIMIT
;
835 print_version(EXIT_SUCCESS
);
837 errtryhelp(EXIT_FAILURE
);
841 ul_path_init_debug();
842 ul_sysfs_init_debug();
844 /* default is --list --all */
850 if (!act
&& argc
== 2 && (raw
|| json
)) {
855 /* default --list output columns */
856 if (list
&& !ncolumns
) {
857 columns
[ncolumns
++] = COL_NAME
;
858 columns
[ncolumns
++] = COL_SIZELIMIT
;
859 columns
[ncolumns
++] = COL_OFFSET
;
860 columns
[ncolumns
++] = COL_AUTOCLR
;
861 columns
[ncolumns
++] = COL_RO
;
862 columns
[ncolumns
++] = COL_BACK_FILE
;
863 columns
[ncolumns
++] = COL_DIO
;
864 columns
[ncolumns
++] = COL_LOGSEC
;
867 if (act
== A_FIND_FREE
&& optind
< argc
) {
869 * losetup -f <backing_file>
872 file
= argv
[optind
++];
875 errx(EXIT_FAILURE
, _("unexpected arguments"));
878 if (list
&& !act
&& optind
== argc
)
880 * losetup --list defaults to --all
884 if (!act
&& optind
+ 1 == argc
) {
886 * losetup [--list] <device>
888 * losetup {--direct-io[=off]|--logical-blocksize=size}... <device>
891 act
= A_SET_DIRECT_IO
;
892 lo_flags
&= ~LO_FLAGS_DIRECT_IO
;
893 } else if (set_blocksize
)
894 act
= A_SET_BLOCKSIZE
;
898 if (loopcxt_set_device(&lc
, argv
[optind
]))
899 err(EXIT_FAILURE
, _("%s: failed to use device"),
905 * losetup <loopdev> <backing_file>
910 errx(EXIT_FAILURE
, _("no loop device specified"));
911 /* don't use is_loopdev() here, the device does not have exist yet */
912 if (loopcxt_set_device(&lc
, argv
[optind
]))
913 err(EXIT_FAILURE
, _("%s: failed to use device"),
918 errx(EXIT_FAILURE
, _("no file specified"));
919 file
= argv
[optind
++];
922 if (act
!= A_CREATE
&&
923 (sizelimit
|| lo_flags
|| showdev
))
925 _("the options %s are allowed during loop device setup only"),
926 "--{sizelimit,partscan,read-only,show}");
928 if ((flags
& LOOPDEV_FL_OFFSET
) &&
929 act
!= A_CREATE
&& (act
!= A_SHOW
|| !file
))
930 errx(EXIT_FAILURE
, _("the option --offset is not allowed in this context"));
932 if (outarg
&& string_add_to_idarray(outarg
, columns
, ARRAY_SIZE(columns
),
933 &ncolumns
, column_name_to_id
) < 0)
938 res
= create_loop(&lc
, no_overlap
, lo_flags
, flags
, file
, refname
,
939 offset
, sizelimit
, blocksize
);
942 printf("%s\n", loopcxt_get_device(&lc
));
943 warn_size(file
, sizelimit
, offset
, flags
);
947 res
= delete_loop(&lc
);
948 while (optind
< argc
) {
949 if (loopcxt_set_device(&lc
, argv
[optind
]))
950 warn(_("%s: failed to use device"),
953 res
+= delete_loop(&lc
);
957 res
= delete_all_loops(&lc
);
960 res
= find_unused(&lc
);
962 printf("%s%s\n", loopcxt_get_device(&lc
),
963 loopcxt_is_lost(&lc
) ? " (lost)" : "");
967 res
= show_table(&lc
, file
, offset
, flags
);
969 res
= show_all_loops(&lc
, file
, offset
, flags
);
973 res
= show_table(&lc
, NULL
, 0, 0);
975 res
= printf_loopdev(&lc
);
977 warn("%s", loopcxt_get_device(&lc
));
980 res
= loopcxt_ioctl_capacity(&lc
);
982 warn(_("%s: set capacity failed"),
983 loopcxt_get_device(&lc
));
985 case A_SET_DIRECT_IO
:
986 res
= loopcxt_ioctl_dio(&lc
, use_dio
);
988 warn(_("%s: set direct io failed"),
989 loopcxt_get_device(&lc
));
991 case A_SET_BLOCKSIZE
:
992 res
= loopcxt_ioctl_blocksize(&lc
, blocksize
);
994 warn(_("%s: set logical block size failed"),
995 loopcxt_get_device(&lc
));
998 warnx(_("bad usage"));
999 errtryhelp(EXIT_FAILURE
);
1003 if (res
&& (act
== A_SET_CAPACITY
1005 || act
== A_SET_DIRECT_IO
1006 || act
== A_SET_BLOCKSIZE
)
1007 && loopcxt_is_lost(&lc
))
1010 loopcxt_deinit(&lc
);
1011 return res
? EXIT_FAILURE
: EXIT_SUCCESS
;