]> git.ipfire.org Git - thirdparty/util-linux.git/blame - sys-utils/losetup.c
swapon: default to --show if nothing is requested
[thirdparty/util-linux.git] / sys-utils / losetup.c
CommitLineData
6dbe3af9 1/*
39fde137
KZ
2 * Copyright (C) 2011 Karel Zak <kzak@redhat.com>
3 * Originally from Ted's losetup.c
4 *
6dbe3af9
KZ
5 * losetup.c - setup and control loop devices
6 */
896352d3 7#include <assert.h>
6dbe3af9
KZ
8#include <stdio.h>
9#include <string.h>
fd6b7a7f 10#include <errno.h>
6dbe3af9
KZ
11#include <stdlib.h>
12#include <unistd.h>
13#include <sys/ioctl.h>
fd6b7a7f 14#include <sys/stat.h>
7711bc17 15#include <inttypes.h>
65329058 16#include <getopt.h>
6dbe3af9 17
934df30d 18#include "c.h"
896352d3 19#include "tt.h"
7eda085c 20#include "nls.h"
934df30d 21#include "strutils.h"
de4acb05 22#include "loopdev.h"
efb8854f 23#include "closestream.h"
96801c48 24#include "optutils.h"
896352d3 25#include "xalloc.h"
96801c48 26
39fde137 27enum {
c7e0925d 28 A_CREATE = 1, /* setup a new device */
c654c4f0
KZ
29 A_DELETE, /* delete given device(s) */
30 A_DELETE_ALL, /* delete all devices */
39fde137 31 A_SHOW, /* list devices */
09ec0c0a 32 A_SHOW_ONE, /* print info about one device */
39fde137
KZ
33 A_FIND_FREE, /* find first unused */
34 A_SET_CAPACITY, /* set device capacity */
35};
36
896352d3
OO
37enum {
38 COL_NAME = 0,
39 COL_AUTOCLR,
40 COL_BACK_FILE,
41 COL_BACK_INO,
42 COL_BACK_MAJMIN,
43 COL_MAJMIN,
44 COL_OFFSET,
45 COL_PARTSCAN,
46 COL_RO,
4ad996d7 47 COL_SIZELIMIT,
896352d3
OO
48};
49
50struct tt *tt;
51
52struct colinfo {
53 const char *name;
54 double whint;
55 int flags;
56 const char *help;
57};
58
59static struct colinfo infos[] = {
60 [COL_AUTOCLR] = { "AUTOCLEAR", 1, TT_FL_RIGHT, N_("autoclear flag set")},
61 [COL_BACK_FILE] = { "BACK-FILE", 0.3, 0, N_("device backing file")},
62 [COL_BACK_INO] = { "BACK-INO", 4, TT_FL_RIGHT, N_("backing file inode number")},
63 [COL_BACK_MAJMIN] = { "BACK-MAJ:MIN", 6, 0, N_("backing file major:minor device number")},
64 [COL_NAME] = { "NAME", 0.25, 0, N_("loop device name")},
65 [COL_OFFSET] = { "OFFSET", 5, TT_FL_RIGHT, N_("offset from the beginning")},
66 [COL_PARTSCAN] = { "PARTSCAN", 1, TT_FL_RIGHT, N_("partscan flag set")},
67 [COL_RO] = { "RO", 1, TT_FL_RIGHT, N_("read-only device")},
4ad996d7 68 [COL_SIZELIMIT] = { "SIZELIMIT", 5, TT_FL_RIGHT, N_("size limit of the file in bytes")},
896352d3
OO
69 [COL_MAJMIN] = { "MAJ:MIN", 3, 0, N_("loop device major:minor number")},
70};
71
72#define NCOLS ARRAY_SIZE(infos)
73
74static int columns[NCOLS] = {-1};
75static int ncolumns;
0a719a7c 76static int verbose;
6dbe3af9 77
896352d3
OO
78static int get_column_id(int num)
79{
80 assert(ARRAY_SIZE(columns) == NCOLS);
81 assert(num < ncolumns);
82 assert(columns[num] < (int) NCOLS);
83 return columns[num];
84}
85
86static struct colinfo *get_column_info(int num)
87{
88 return &infos[ get_column_id(num) ];
89}
90
91static int column_name_to_id(const char *name, size_t namesz)
92{
93 size_t i;
94
95 for (i = 0; i < NCOLS; i++) {
96 const char *cn = infos[i].name;
97
98 if (!strncasecmp(name, cn, namesz) && !*(cn + namesz))
99 return i;
100 }
101 warnx(_("unknown column: %s"), name);
102 return -1;
103}
d03dd608 104
39fde137
KZ
105static int printf_loopdev(struct loopdev_cxt *lc)
106{
107 uint64_t x;
108 dev_t dev = 0;
109 ino_t ino = 0;
110 char *fname = NULL;
a3b421df 111 uint32_t type;
39fde137
KZ
112
113 fname = loopcxt_get_backing_file(lc);
114 if (!fname)
115 return -EINVAL;
116
117 if (loopcxt_get_backing_devno(lc, &dev) == 0)
118 loopcxt_get_backing_inode(lc, &ino);
119
120 if (!dev && !ino) {
121 /*
122 * Probably non-root user (no permissions to
123 * call LOOP_GET_STATUS ioctls).
124 */
125 printf("%s: []: (%s)",
126 loopcxt_get_device(lc), fname);
127
128 if (loopcxt_get_offset(lc, &x) == 0 && x)
129 printf(_(", offset %ju"), x);
130
131 if (loopcxt_get_sizelimit(lc, &x) == 0 && x)
132 printf(_(", sizelimit %ju"), x);
133 printf("\n");
134 return 0;
135 }
136
137 printf("%s: [%04d]:%" PRIu64 " (%s)",
a3b421df 138 loopcxt_get_device(lc), (int) dev, ino, fname);
39fde137
KZ
139
140 if (loopcxt_get_offset(lc, &x) == 0 && x)
141 printf(_(", offset %ju"), x);
142
143 if (loopcxt_get_sizelimit(lc, &x) == 0 && x)
144 printf(_(", sizelimit %ju"), x);
145
146 if (loopcxt_get_encrypt_type(lc, &type) == 0) {
147 const char *e = loopcxt_get_crypt_name(lc);
148
149 if ((!e || !*e) && type == 1)
150 e = "XOR";
151 if (e && *e)
a3b421df 152 printf(_(", encryption %s (type %u)"), e, type);
39fde137
KZ
153 }
154 printf("\n");
155 return 0;
156}
157
bc0ac075
KZ
158static int show_all_loops(struct loopdev_cxt *lc, const char *file,
159 uint64_t offset, int flags)
39fde137 160{
bc0ac075
KZ
161 struct stat sbuf, *st = &sbuf;
162
39fde137 163 if (loopcxt_init_iterator(lc, LOOPITER_FL_USED))
6e90a44c 164 return -1;
39fde137 165
bc0ac075
KZ
166 if (!file || stat(file, st))
167 st = NULL;
168
169 while (loopcxt_next(lc) == 0) {
39fde137 170
bc0ac075
KZ
171 if (file && !loopcxt_is_used(lc, st, file, offset, flags))
172 continue;
bc0ac075
KZ
173 printf_loopdev(lc);
174 }
c654c4f0 175 loopcxt_deinit_iterator(lc);
6e90a44c
KZ
176 return 0;
177}
178
179static int set_capacity(struct loopdev_cxt *lc)
180{
181 int fd = loopcxt_get_fd(lc);
182
183 if (fd < 0)
289dcc90 184 warn(_("cannot open %s"), loopcxt_get_device(lc));
6e90a44c
KZ
185 else if (ioctl(fd, LOOP_SET_CAPACITY) != 0)
186 warnx(_("%s: set capacity failed"), loopcxt_get_device(lc));
187 else
188 return 0;
189
c654c4f0
KZ
190 return -1;
191}
192
193static int delete_loop(struct loopdev_cxt *lc)
194{
195 if (loopcxt_delete_device(lc))
196 warn(_("%s: detach failed"), loopcxt_get_device(lc));
197 else
198 return 0;
199
200 return -1;
201}
202
203static int delete_all_loops(struct loopdev_cxt *lc)
204{
205 int res = 0;
206
207 if (loopcxt_init_iterator(lc, LOOPITER_FL_USED))
208 return -1;
209
210 while (loopcxt_next(lc) == 0)
211 res += delete_loop(lc);
212
213 loopcxt_deinit_iterator(lc);
214 return res;
39fde137
KZ
215}
216
896352d3
OO
217static int set_tt_data(struct loopdev_cxt *lc, struct tt_line *ln)
218{
219 int i;
220
221 for (i = 0; i < ncolumns; i++) {
222 const char *p = NULL;
223 char *np = NULL;
224 uint64_t x = 0;
225
226 switch(get_column_id(i)) {
227 case COL_NAME:
228 p = loopcxt_get_device(lc);
229 if (p)
230 tt_line_set_data(ln, i, xstrdup(p));
231 break;
232 case COL_BACK_FILE:
233 p = loopcxt_get_backing_file(lc);
234 if (p)
235 tt_line_set_data(ln, i, xstrdup(p));
236 break;
237 case COL_OFFSET:
238 if (loopcxt_get_offset(lc, &x) == 0)
239 xasprintf(&np, "%jd", x);
240 if (np)
241 tt_line_set_data(ln, i, np);
242 break;
4ad996d7 243 case COL_SIZELIMIT:
896352d3
OO
244 if (loopcxt_get_sizelimit(lc, &x) == 0)
245 xasprintf(&np, "%jd", x);
246 if (np)
247 tt_line_set_data(ln, i, np);
248 break;
249 case COL_BACK_MAJMIN:
250 {
251 dev_t dev = 0;
252 if (loopcxt_get_backing_devno(lc, &dev) == 0 && dev)
253 xasprintf(&np, "%8u:%-3u", major(dev), minor(dev));
254 if (np)
255 tt_line_set_data(ln, i, np);
256 break;
257 }
258 case COL_MAJMIN:
259 {
260 struct stat st;
261
262 if (loopcxt_get_device(lc)
263 && stat(loopcxt_get_device(lc), &st) == 0
264 && S_ISBLK(st.st_mode)
265 && major(st.st_rdev) == LOOPDEV_MAJOR)
266 xasprintf(&np, "%3u:%-3u", major(st.st_rdev),
267 minor(st.st_rdev));
268 if (np)
269 tt_line_set_data(ln, i, np);
270 break;
271 }
272 case COL_BACK_INO:
273 {
274 ino_t ino = 0;
275 if (loopcxt_get_backing_inode(lc, &ino) == 0 && ino)
276 xasprintf(&np, "%ju", ino);
277 if (np)
278 tt_line_set_data(ln, i, np);
279 break;
280 }
281 case COL_AUTOCLR:
282 tt_line_set_data(ln, i,
283 xstrdup(loopcxt_is_autoclear(lc) ? "1" : "0"));
284 break;
285 case COL_RO:
286 tt_line_set_data(ln, i,
287 xstrdup(loopcxt_is_readonly(lc) ? "1" : "0"));
288 break;
289 case COL_PARTSCAN:
290 tt_line_set_data(ln, i,
291 xstrdup(loopcxt_is_partscan(lc) ? "1" : "0"));
292 break;
293 default:
294 return -EINVAL;
295 }
296 }
297 return 0;
298}
299
300static int make_table(struct loopdev_cxt *lc, const char *file,
301 uint64_t offset, int flags)
302{
303 struct stat sbuf, *st = &sbuf;
304 struct tt_line *ln;
305
306 if (!(tt = tt_new_table(0)))
307 errx(EXIT_FAILURE, _("failed to initialize output table"));
308
309 for (int i = 0; i < ncolumns; i++) {
310 struct colinfo *ci = get_column_info(i);
311
312 if (!tt_define_column(tt, ci->name, ci->whint, ci->flags))
313 warn(_("failed to initialize output column"));
314 }
315
316 if (loopcxt_get_device(lc)) {
317 ln = tt_add_line(tt, NULL);
318 if (set_tt_data(lc, ln))
319 return -EINVAL;
320 return 0;
321 }
322
323 if (loopcxt_init_iterator(lc, LOOPITER_FL_USED))
324 return -1;
325 if (!file || stat(file, st))
326 st = NULL;
327
328 while (loopcxt_next(lc) == 0) {
329 if (file && !loopcxt_is_used(lc, st, file, offset, flags))
330 continue;
331
332
333 ln = tt_add_line(tt, NULL);
334 if (set_tt_data(lc, ln))
335 return -EINVAL;
336 }
337
338 loopcxt_deinit_iterator(lc);
339 return 0;
340}
341
aadb9303
KZ
342static void usage(FILE *out)
343{
344 fputs(USAGE_HEADER, out);
345
346 fprintf(out,
347 _(" %1$s [options] [<loopdev>]\n"
348 " %1$s [options] -f | <loopdev> <file>\n"),
349 program_invocation_short_name);
350
351 fputs(USAGE_OPTIONS, out);
352 fputs(_(" -a, --all list all used devices\n"
353 " -d, --detach <loopdev> [...] detach one or more devices\n"
354 " -D, --detach-all detach all used devices\n"
355 " -f, --find find first unused device\n"
356 " -c, --set-capacity <loopdev> resize device\n"
357 " -j, --associated <file> list all devices associated with <file>\n"), out);
358 fputs(USAGE_SEPARATOR, out);
359
896352d3
OO
360 fputs(_(" -l, --list list info about all or specified\n"
361 " -o, --offset <num> start at offset <num> into file\n"
362 " -O, --output <cols> specify columns to output for --list\n"
aadb9303 363 " --sizelimit <num> device limited to <num> bytes of the file\n"
916bf85e 364 " -P, --partscan create partitioned loop device\n"
aadb9303
KZ
365 " -r, --read-only setup read-only loop device\n"
366 " --show print device name after setup (with -f)\n"
367 " -v, --verbose verbose mode\n"), out);
368
369 fputs(USAGE_SEPARATOR, out);
370 fputs(USAGE_HELP, out);
371 fputs(USAGE_VERSION, out);
372
896352d3
OO
373 fputs(_("\nAvailable --list columns:\n"), out);
374 for (size_t i = 0; i < NCOLS; i++)
375 fprintf(out, " %12s %s\n", infos[i].name, _(infos[i].help));
376
aadb9303 377 fprintf(out, USAGE_MAN_TAIL("losetup(8)"));
6997468e
KZ
378
379 exit(out == stderr ? EXIT_FAILURE : EXIT_SUCCESS);
aadb9303 380}
22853e4a 381
35545456
KZ
382static void warn_size(const char *filename, uint64_t size)
383{
384 struct stat st;
385
386 if (!size) {
387 if (stat(filename, &st))
388 return;
389 size = st.st_size;
390 }
391
392 if (size < 512)
393 warnx(_("%s: warning: file smaller than 512 bytes, the loop device "
394 "maybe be useless or invisible for system tools."),
395 filename);
396 else if (size % 512)
397 warnx(_("%s: warning: file does not fit into a 512-byte sector "
398 "the end of the file will be ignored."),
399 filename);
400}
401
39fde137
KZ
402int main(int argc, char **argv)
403{
404 struct loopdev_cxt lc;
5cf05c71
LN
405 int act = 0, flags = 0, c;
406 char *file = NULL;
c7e0925d
KZ
407 uint64_t offset = 0, sizelimit = 0;
408 int res = 0, showdev = 0, lo_flags = 0;
896352d3
OO
409 char *outarg = NULL;
410 int list = 0;
6c7d5ae9 411
aadb9303
KZ
412 enum {
413 OPT_SIZELIMIT = CHAR_MAX + 1,
414 OPT_SHOW
415 };
416 static const struct option longopts[] = {
d99f0140 417 { "all", 0, 0, 'a' },
6e90a44c 418 { "set-capacity", 1, 0, 'c' },
c654c4f0 419 { "detach", 1, 0, 'd' },
34f9b684 420 { "detach-all", 0, 0, 'D' },
d99f0140
KZ
421 { "encryption", 1, 0, 'e' },
422 { "find", 0, 0, 'f' },
423 { "help", 0, 0, 'h' },
259fcc57 424 { "associated", 1, 0, 'j' },
896352d3 425 { "list", 0, 0, 'l' },
d99f0140 426 { "offset", 1, 0, 'o' },
896352d3 427 { "output", 1, 0, 'O' },
aadb9303 428 { "sizelimit", 1, 0, OPT_SIZELIMIT },
d99f0140 429 { "pass-fd", 1, 0, 'p' },
916bf85e 430 { "partscan", 0, 0, 'P' },
d99f0140 431 { "read-only", 0, 0, 'r' },
896352d3 432 { "show", 0, 0, OPT_SHOW },
d99f0140 433 { "verbose", 0, 0, 'v' },
aadb9303 434 { "version", 0, 0, 'V' },
d99f0140
KZ
435 { NULL, 0, 0, 0 }
436 };
22853e4a 437
c1ac3144
KZ
438 static const ul_excl_t excl[] = { /* rows and cols in ASCII order */
439 { 'D','a','c','d','f','j' },
896352d3 440 { 'D','c','d','f','l' },
65178cb3 441 { 'D','c','d','f','O' },
c1ac3144
KZ
442 { 0 }
443 };
444 int excl_st[ARRAY_SIZE(excl)] = UL_EXCL_STATUS_INIT;
445
22853e4a
KZ
446 setlocale(LC_ALL, "");
447 bindtextdomain(PACKAGE, LOCALEDIR);
448 textdomain(PACKAGE);
efb8854f 449 atexit(close_stdout);
22853e4a 450
defa0710
KZ
451 if (loopcxt_init(&lc, 0))
452 err(EXIT_FAILURE, _("failed to initialize loopcxt"));
453
896352d3 454 while ((c = getopt_long(argc, argv, "ac:d:De:E:fhj:lo:O:p:PrvV",
d99f0140 455 longopts, NULL)) != -1) {
c1ac3144
KZ
456
457 err_exclusive_options(c, longopts, excl, excl_st);
458
22853e4a 459 switch (c) {
8b125fae 460 case 'a':
39fde137 461 act = A_SHOW;
8b125fae 462 break;
d34ac93a 463 case 'c':
6e90a44c 464 act = A_SET_CAPACITY;
defa0710
KZ
465 if (loopcxt_set_device(&lc, optarg))
466 err(EXIT_FAILURE, _("%s: failed to use device"),
467 optarg);
d34ac93a 468 break;
faf142b6 469 case 'r':
c7e0925d 470 lo_flags |= LO_FLAGS_READ_ONLY;
faf142b6 471 break;
22853e4a 472 case 'd':
c654c4f0 473 act = A_DELETE;
defa0710
KZ
474 if (loopcxt_set_device(&lc, optarg))
475 err(EXIT_FAILURE, _("%s: failed to use device"),
476 optarg);
22853e4a 477 break;
34f9b684 478 case 'D':
c654c4f0 479 act = A_DELETE_ALL;
34f9b684 480 break;
d03dd608 481 case 'E':
22853e4a 482 case 'e':
5cf05c71 483 errx(EXIT_FAILURE, _("encryption not supported, use cryptsetup(8) instead"));
22853e4a 484 break;
d162fcb5 485 case 'f':
bcdbdc72 486 act = A_FIND_FREE;
d162fcb5 487 break;
108591d2
KZ
488 case 'h':
489 usage(stdout);
490 break;
259fcc57 491 case 'j':
bc0ac075
KZ
492 act = A_SHOW;
493 file = optarg;
259fcc57 494 break;
896352d3
OO
495 case 'l':
496 list = 1;
497 break;
22853e4a 498 case 'o':
e9e426eb 499 offset = strtosize_or_err(optarg, _("failed to parse offset"));
bc0ac075 500 flags |= LOOPDEV_FL_OFFSET;
22853e4a 501 break;
896352d3
OO
502 case 'O':
503 outarg = optarg;
65178cb3 504 list = 1;
896352d3 505 break;
d03dd608 506 case 'p':
5cf05c71 507 warn(_("--pass-fd is no longer supported"));
d03dd608 508 break;
916bf85e
KZ
509 case 'P':
510 lo_flags |= LO_FLAGS_PARTSCAN;
511 break;
aadb9303 512 case OPT_SHOW:
ba3809b0
KZ
513 showdev = 1;
514 break;
22853e4a
KZ
515 case 'v':
516 verbose = 1;
517 break;
aadb9303
KZ
518 case 'V':
519 printf(UTIL_LINUX_VERSION);
520 return EXIT_SUCCESS;
521 case OPT_SIZELIMIT: /* --sizelimit */
e9e426eb 522 sizelimit = strtosize_or_err(optarg, _("failed to parse size"));
c7e0925d 523 flags |= LOOPDEV_FL_SIZELIMIT;
7bcefc7f 524 break;
22853e4a 525 default:
108591d2 526 usage(stderr);
22853e4a
KZ
527 }
528 }
d162fcb5 529
896352d3
OO
530 /* default is --list --all */
531 if (argc == 1) {
532 act = A_SHOW;
533 list = 1;
534 }
535
536 /* default --list output columns */
537 if (list && !ncolumns) {
538 columns[ncolumns++] = COL_NAME;
4ad996d7 539 columns[ncolumns++] = COL_SIZELIMIT;
896352d3
OO
540 columns[ncolumns++] = COL_OFFSET;
541 columns[ncolumns++] = COL_AUTOCLR;
542 columns[ncolumns++] = COL_RO;
543 columns[ncolumns++] = COL_BACK_FILE;
544 }
39fde137 545
c7e0925d
KZ
546 if (act == A_FIND_FREE && optind < argc) {
547 /*
548 * losetup -f <backing_file>
549 */
550 act = A_CREATE;
551 file = argv[optind++];
552 }
896352d3
OO
553
554 if (list && !act && optind == argc)
555 /*
556 * losetup --list defaults to --all
557 */
558 act = A_SHOW;
559
09ec0c0a
KZ
560 if (!act && optind + 1 == argc) {
561 /*
896352d3 562 * losetup [--list] <device>
09ec0c0a
KZ
563 */
564 act = A_SHOW_ONE;
defa0710
KZ
565 if (loopcxt_set_device(&lc, argv[optind]))
566 err(EXIT_FAILURE, _("%s: failed to use device"),
567 argv[optind]);
568 optind++;
09ec0c0a 569 }
c7e0925d
KZ
570 if (!act) {
571 /*
572 * losetup <loopdev> <backing_file>
573 */
574 act = A_CREATE;
575
576 if (optind >= argc)
577 errx(EXIT_FAILURE, _("no loop device specified"));
defa0710 578 if (loopcxt_set_device(&lc, argv[optind]))
e9e7698e 579 err(EXIT_FAILURE, _("%s: failed to use device"),
defa0710
KZ
580 argv[optind]);
581 optind++;
c7e0925d
KZ
582
583 if (optind >= argc)
584 errx(EXIT_FAILURE, _("no file specified"));
585 file = argv[optind++];
586 }
587
588 if (act != A_CREATE &&
5cf05c71 589 (sizelimit || lo_flags || showdev))
c7e0925d
KZ
590 errx(EXIT_FAILURE,
591 _("the options %s are allowed to loop device setup only"),
5cf05c71 592 "--{sizelimit,read-only,show}");
c7e0925d 593
934df30d
KZ
594 if ((flags & LOOPDEV_FL_OFFSET) &&
595 act != A_CREATE && (act != A_SHOW || !file))
c7e0925d 596 errx(EXIT_FAILURE, _("the option --offset is not allowed in this context."));
c654c4f0 597
896352d3
OO
598 if (outarg && string_add_to_idarray(outarg, columns, ARRAY_SIZE(columns),
599 &ncolumns, column_name_to_id) < 0)
600 return EXIT_FAILURE;
601
39fde137 602 switch (act) {
c7e0925d
KZ
603 case A_CREATE:
604 {
c7e0925d
KZ
605 int hasdev = loopcxt_has_device(&lc);
606
c7e0925d
KZ
607 do {
608 /* Note that loopcxt_{find_unused,set_device}() resets
609 * loopcxt struct.
610 */
611 if (!hasdev && (res = loopcxt_find_unused(&lc))) {
612 warnx(_("not found unused device"));
613 break;
614 }
c7e0925d
KZ
615 if (flags & LOOPDEV_FL_OFFSET)
616 loopcxt_set_offset(&lc, offset);
617 if (flags & LOOPDEV_FL_SIZELIMIT)
ce65b29a 618 loopcxt_set_sizelimit(&lc, sizelimit);
c7e0925d
KZ
619 if (lo_flags)
620 loopcxt_set_flags(&lc, lo_flags);
621 if ((res = loopcxt_set_backing_file(&lc, file))) {
622 warn(_("%s: failed to use backing file"), file);
623 break;
624 }
625 errno = 0;
626 res = loopcxt_setup_device(&lc);
627 if (res == 0)
628 break; /* success */
629 if (errno != EBUSY) {
cda4f8f1
KZ
630 warn(_("%s: failed to setup loop device"),
631 hasdev && loopcxt_get_fd(&lc) < 0 ?
632 loopcxt_get_device(&lc) : file);
c7e0925d
KZ
633 break;
634 }
635 } while (hasdev == 0);
636
35545456
KZ
637 if (res == 0) {
638 if (showdev)
639 printf("%s\n", loopcxt_get_device(&lc));
640 warn_size(file, sizelimit);
641 }
c7e0925d
KZ
642 break;
643 }
c654c4f0
KZ
644 case A_DELETE:
645 res = delete_loop(&lc);
646 while (optind < argc) {
defa0710
KZ
647 if (loopcxt_set_device(&lc, argv[optind]))
648 warn(_("%s: failed to use device"),
649 argv[optind]);
650 optind++;
c654c4f0
KZ
651 res += delete_loop(&lc);
652 }
653 break;
654 case A_DELETE_ALL:
655 res = delete_all_loops(&lc);
656 break;
bcdbdc72
KZ
657 case A_FIND_FREE:
658 if (loopcxt_find_unused(&lc))
659 warn(_("find unused loop device failed"));
660 else
661 printf("%s\n", loopcxt_get_device(&lc));
662 break;
39fde137 663 case A_SHOW:
896352d3
OO
664 if (list)
665 res = make_table(&lc, file, offset, flags);
666 else
667 res = show_all_loops(&lc, file, offset, flags);
bc0ac075 668 break;
09ec0c0a 669 case A_SHOW_ONE:
896352d3
OO
670 if (list)
671 res = make_table( &lc, NULL, 0, 0);
672 else
673 res = printf_loopdev(&lc);
09ec0c0a
KZ
674 if (res)
675 warn(_("%s"), loopcxt_get_device(&lc));
676 break;
6e90a44c
KZ
677 case A_SET_CAPACITY:
678 res = set_capacity(&lc);
679 break;
39fde137 680 default:
c7e0925d 681 usage(stderr);
39fde137
KZ
682 break;
683 }
896352d3
OO
684 if (tt) {
685 if (!res)
686 tt_print_table(tt);
687 tt_free_table(tt);
688 }
39fde137
KZ
689
690 loopcxt_deinit(&lc);
c7e0925d 691 return res ? EXIT_FAILURE : EXIT_SUCCESS;
22853e4a
KZ
692}
693