]> git.ipfire.org Git - thirdparty/util-linux.git/blob - sys-utils/losetup.c
misc: replaces atexit(close_stdout) with new close_stdout_atexit()
[thirdparty/util-linux.git] / sys-utils / losetup.c
1 /*
2 * Copyright (C) 2011 Karel Zak <kzak@redhat.com>
3 * Originally from Ted's losetup.c
4 *
5 * losetup.c - setup and control loop devices
6 */
7 #include <assert.h>
8 #include <stdio.h>
9 #include <string.h>
10 #include <errno.h>
11 #include <stdlib.h>
12 #include <unistd.h>
13 #include <sys/ioctl.h>
14 #include <sys/stat.h>
15 #include <inttypes.h>
16 #include <getopt.h>
17
18 #include <libsmartcols.h>
19
20 #include "c.h"
21 #include "nls.h"
22 #include "strutils.h"
23 #include "loopdev.h"
24 #include "closestream.h"
25 #include "optutils.h"
26 #include "xalloc.h"
27 #include "canonicalize.h"
28 #include "pathnames.h"
29
30 enum {
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 */
40 };
41
42 enum {
43 COL_NAME = 0,
44 COL_AUTOCLR,
45 COL_BACK_FILE,
46 COL_BACK_INO,
47 COL_BACK_MAJMIN,
48 COL_MAJMIN,
49 COL_OFFSET,
50 COL_PARTSCAN,
51 COL_RO,
52 COL_SIZELIMIT,
53 COL_DIO,
54 COL_LOGSEC,
55 };
56
57 /* basic output flags */
58 static int no_headings;
59 static int raw;
60 static int json;
61
62 struct colinfo {
63 const char *name;
64 double whint;
65 int flags;
66 const char *help;
67
68 int json_type; /* default is string */
69 };
70
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},
84 };
85
86 static int columns[ARRAY_SIZE(infos) * 2] = {-1};
87 static size_t ncolumns;
88
89 static int get_column_id(int num)
90 {
91 assert(num >= 0);
92 assert((size_t) num < ncolumns);
93 assert(columns[num] < (int) ARRAY_SIZE(infos));
94 return columns[num];
95 }
96
97 static struct colinfo *get_column_info(int num)
98 {
99 return &infos[ get_column_id(num) ];
100 }
101
102 static int column_name_to_id(const char *name, size_t namesz)
103 {
104 size_t i;
105
106 for (i = 0; i < ARRAY_SIZE(infos); i++) {
107 const char *cn = infos[i].name;
108
109 if (!strncasecmp(name, cn, namesz) && !*(cn + namesz))
110 return i;
111 }
112 warnx(_("unknown column: %s"), name);
113 return -1;
114 }
115
116 static int printf_loopdev(struct loopdev_cxt *lc)
117 {
118 uint64_t x;
119 dev_t dev = 0;
120 ino_t ino = 0;
121 char *fname;
122 uint32_t type;
123
124 fname = loopcxt_get_backing_file(lc);
125 if (!fname)
126 return -EINVAL;
127
128 if (loopcxt_get_backing_devno(lc, &dev) == 0)
129 loopcxt_get_backing_inode(lc, &ino);
130
131 if (!dev && !ino) {
132 /*
133 * Probably non-root user (no permissions to
134 * call LOOP_GET_STATUS ioctls).
135 */
136 printf("%s: []: (%s)",
137 loopcxt_get_device(lc), fname);
138
139 if (loopcxt_get_offset(lc, &x) == 0 && x)
140 printf(_(", offset %ju"), x);
141
142 if (loopcxt_get_sizelimit(lc, &x) == 0 && x)
143 printf(_(", sizelimit %ju"), x);
144 goto done;
145 }
146
147 printf("%s: [%04d]:%" PRIu64 " (%s)",
148 loopcxt_get_device(lc), (int) dev, ino, fname);
149
150 if (loopcxt_get_offset(lc, &x) == 0 && x)
151 printf(_(", offset %ju"), x);
152
153 if (loopcxt_get_sizelimit(lc, &x) == 0 && x)
154 printf(_(", sizelimit %ju"), x);
155
156 if (loopcxt_get_encrypt_type(lc, &type) == 0) {
157 const char *e = loopcxt_get_crypt_name(lc);
158
159 if ((!e || !*e) && type == 1)
160 e = "XOR";
161 if (e && *e)
162 printf(_(", encryption %s (type %u)"), e, type);
163 }
164
165 done:
166 free(fname);
167 printf("\n");
168 return 0;
169 }
170
171 static int show_all_loops(struct loopdev_cxt *lc, const char *file,
172 uint64_t offset, int flags)
173 {
174 struct stat sbuf, *st = &sbuf;
175 char *cn_file = NULL;
176
177 if (loopcxt_init_iterator(lc, LOOPITER_FL_USED))
178 return -1;
179
180 if (!file || stat(file, st))
181 st = NULL;
182
183 while (loopcxt_next(lc) == 0) {
184 if (file) {
185 int used;
186 const char *bf = cn_file ? cn_file : file;
187
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);
192 }
193 if (!used)
194 continue;
195 }
196 printf_loopdev(lc);
197 }
198 loopcxt_deinit_iterator(lc);
199 free(cn_file);
200 return 0;
201 }
202
203 static int delete_loop(struct loopdev_cxt *lc)
204 {
205 if (loopcxt_delete_device(lc))
206 warn(_("%s: detach failed"), loopcxt_get_device(lc));
207 else
208 return 0;
209
210 return -1;
211 }
212
213 static int delete_all_loops(struct loopdev_cxt *lc)
214 {
215 int res = 0;
216
217 if (loopcxt_init_iterator(lc, LOOPITER_FL_USED))
218 return -1;
219
220 while (loopcxt_next(lc) == 0)
221 res += delete_loop(lc);
222
223 loopcxt_deinit_iterator(lc);
224 return res;
225 }
226
227 static int set_scols_data(struct loopdev_cxt *lc, struct libscols_line *ln)
228 {
229 size_t i;
230
231 for (i = 0; i < ncolumns; i++) {
232 const char *p = NULL; /* external data */
233 char *np = NULL; /* allocated here */
234 uint64_t x = 0;
235 int rc = 0;
236
237 switch(get_column_id(i)) {
238 case COL_NAME:
239 p = loopcxt_get_device(lc);
240 break;
241 case COL_BACK_FILE:
242 p = loopcxt_get_backing_file(lc);
243 break;
244 case COL_OFFSET:
245 if (loopcxt_get_offset(lc, &x) == 0)
246 xasprintf(&np, "%jd", x);
247 break;
248 case COL_SIZELIMIT:
249 if (loopcxt_get_sizelimit(lc, &x) == 0)
250 xasprintf(&np, "%jd", x);
251 break;
252 case COL_BACK_MAJMIN:
253 {
254 dev_t dev = 0;
255 if (loopcxt_get_backing_devno(lc, &dev) == 0 && dev)
256 xasprintf(&np, "%8u:%-3u", major(dev), minor(dev));
257 break;
258 }
259 case COL_MAJMIN:
260 {
261 struct stat st;
262
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),
268 minor(st.st_rdev));
269 break;
270 }
271 case COL_BACK_INO:
272 {
273 ino_t ino = 0;
274 if (loopcxt_get_backing_inode(lc, &ino) == 0 && ino)
275 xasprintf(&np, "%ju", ino);
276 break;
277 }
278 case COL_AUTOCLR:
279 p = loopcxt_is_autoclear(lc) ? "1" : "0";
280 break;
281 case COL_RO:
282 p = loopcxt_is_readonly(lc) ? "1" : "0";
283 break;
284 case COL_DIO:
285 p = loopcxt_is_dio(lc) ? "1" : "0";
286 break;
287 case COL_PARTSCAN:
288 p = loopcxt_is_partscan(lc) ? "1" : "0";
289 break;
290 case COL_LOGSEC:
291 if (loopcxt_get_blocksize(lc, &x) == 0)
292 xasprintf(&np, "%jd", x);
293 break;
294 default:
295 return -EINVAL;
296 }
297
298
299 if (p)
300 rc = scols_line_set_data(ln, i, p); /* calls strdup() */
301 else if (np)
302 rc = scols_line_refer_data(ln, i, np); /* only refers */
303
304 if (rc)
305 err(EXIT_FAILURE, _("failed to add output data"));
306 }
307
308 return 0;
309 }
310
311 static int show_table(struct loopdev_cxt *lc,
312 const char *file,
313 uint64_t offset,
314 int flags)
315 {
316 struct stat sbuf, *st = &sbuf;
317 struct libscols_table *tb;
318 struct libscols_line *ln;
319 int rc = 0;
320 size_t i;
321
322 scols_init_debug(0);
323
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);
329
330 if (json)
331 scols_table_set_name(tb, "loopdevices");
332
333 for (i = 0; i < ncolumns; i++) {
334 struct colinfo *ci = get_column_info(i);
335 struct libscols_column *cl;
336
337 cl = scols_table_new_column(tb, ci->name, ci->whint, ci->flags);
338 if (!cl)
339 err(EXIT_FAILURE, _("failed to allocate output column"));
340 if (json)
341 scols_column_set_json_type(cl, ci->json_type);
342 }
343
344 /* only one loopdev requested (already assigned to loopdev_cxt) */
345 if (loopcxt_get_device(lc)) {
346 ln = scols_table_new_line(tb, NULL);
347 if (!ln)
348 err(EXIT_FAILURE, _("failed to allocate output line"));
349 rc = set_scols_data(lc, ln);
350
351 /* list all loopdevs */
352 } else {
353 char *cn_file = NULL;
354
355 rc = loopcxt_init_iterator(lc, LOOPITER_FL_USED);
356 if (rc)
357 goto done;
358 if (!file || stat(file, st))
359 st = NULL;
360
361 while (loopcxt_next(lc) == 0) {
362 if (file) {
363 int used;
364 const char *bf = cn_file ? cn_file : file;
365
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);
370 }
371 if (!used)
372 continue;
373 }
374
375 ln = scols_table_new_line(tb, NULL);
376 if (!ln)
377 err(EXIT_FAILURE, _("failed to allocate output line"));
378 rc = set_scols_data(lc, ln);
379 if (rc)
380 break;
381 }
382
383 loopcxt_deinit_iterator(lc);
384 free(cn_file);
385 }
386 done:
387 if (rc == 0)
388 rc = scols_print_table(tb);
389 scols_unref_table(tb);
390 return rc;
391 }
392
393 static void __attribute__((__noreturn__)) usage(void)
394 {
395 FILE *out = stdout;
396 size_t i;
397
398 fputs(USAGE_HEADER, out);
399
400 fprintf(out,
401 _(" %1$s [options] [<loopdev>]\n"
402 " %1$s [options] -f | <loopdev> <file>\n"),
403 program_invocation_short_name);
404
405 fputs(USAGE_SEPARATOR, out);
406 fputs(_("Set up and control loop devices.\n"), out);
407
408 /* commands */
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);
417
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);
428
429 /* output options */
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);
437
438 fputs(USAGE_SEPARATOR, out);
439 printf(USAGE_HELP_OPTIONS(31));
440
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));
444
445 printf(USAGE_MAN_TAIL("losetup(8)"));
446
447 exit(EXIT_SUCCESS);
448 }
449
450 static void warn_size(const char *filename, uint64_t size, uint64_t offset, int flags)
451 {
452 struct stat st;
453
454 if (!size) {
455 if (stat(filename, &st) || S_ISBLK(st.st_mode))
456 return;
457 size = st.st_size;
458
459 if (flags & LOOPDEV_FL_OFFSET)
460 size -= offset;
461 }
462
463 if (size < 512)
464 warnx(_("%s: Warning: file is smaller than 512 bytes; the loop device "
465 "may be useless or invisible for system tools."),
466 filename);
467 else if (size % 512)
468 warnx(_("%s: Warning: file does not fit into a 512-byte sector; "
469 "the end of the file will be ignored."),
470 filename);
471 }
472
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,
476 uint64_t blocksize)
477 {
478 int hasdev = loopcxt_has_device(lc);
479 int rc = 0;
480
481 /* losetup --find --noverlap file.img */
482 if (!hasdev && nooverlap) {
483 rc = loopcxt_find_overlap(lc, file, offset, sizelimit);
484 switch (rc) {
485 case 0: /* not found */
486 break;
487
488 case 1: /* overlap */
489 loopcxt_deinit(lc);
490 errx(EXIT_FAILURE, _("%s: overlapping loop device exists"), file);
491
492 case 2: /* overlap -- full size and offset match (reuse) */
493 {
494 uint32_t lc_encrypt_type;
495
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)) {
500 loopcxt_deinit(lc);
501 errx(EXIT_FAILURE, _("%s: overlapping read-only loop device exists"), file);
502 }
503
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) {
507 loopcxt_deinit(lc);
508 errx(EXIT_FAILURE, _("%s: overlapping encrypted loop device exists"), file);
509 }
510
511 lc->info.lo_flags &= ~LO_FLAGS_AUTOCLEAR;
512 if (loopcxt_ioctl_status(lc)) {
513 loopcxt_deinit(lc);
514 errx(EXIT_FAILURE, _("%s: failed to re-use loop device"), file);
515 }
516 return 0; /* success, re-use */
517 }
518 default: /* error */
519 loopcxt_deinit(lc);
520 errx(EXIT_FAILURE, _("failed to inspect loop devices"));
521 return -errno;
522 }
523 }
524
525 if (hasdev && !is_loopdev(loopcxt_get_device(lc)))
526 loopcxt_add_device(lc);
527
528 /* losetup --noverlap /dev/loopN file.img */
529 if (hasdev && nooverlap) {
530 struct loopdev_cxt lc2;
531
532 if (loopcxt_init(&lc2, 0)) {
533 loopcxt_deinit(lc);
534 err(EXIT_FAILURE, _("failed to initialize loopcxt"));
535 }
536 rc = loopcxt_find_overlap(&lc2, file, offset, sizelimit);
537 loopcxt_deinit(&lc2);
538
539 if (rc) {
540 loopcxt_deinit(lc);
541 if (rc > 0)
542 errx(EXIT_FAILURE, _("%s: overlapping loop device exists"), file);
543 err(EXIT_FAILURE, _("%s: failed to check for conflicting loop devices"), file);
544 }
545 }
546
547 /* Create a new device */
548 do {
549 const char *errpre;
550
551 /* Note that loopcxt_{find_unused,set_device}() resets
552 * loopcxt struct.
553 */
554 if (!hasdev && (rc = loopcxt_find_unused(lc))) {
555 warnx(_("cannot find an unused loop device"));
556 break;
557 }
558 if (flags & LOOPDEV_FL_OFFSET)
559 loopcxt_set_offset(lc, offset);
560 if (flags & LOOPDEV_FL_SIZELIMIT)
561 loopcxt_set_sizelimit(lc, sizelimit);
562 if (lo_flags)
563 loopcxt_set_flags(lc, lo_flags);
564 if (blocksize > 0)
565 loopcxt_set_blocksize(lc, blocksize);
566
567 if ((rc = loopcxt_set_backing_file(lc, file))) {
568 warn(_("%s: failed to use backing file"), file);
569 break;
570 }
571 errno = 0;
572 rc = loopcxt_setup_device(lc);
573 if (rc == 0)
574 break; /* success */
575 if (errno == EBUSY && !hasdev)
576 continue;
577
578 /* errors */
579 errpre = hasdev && loopcxt_get_fd(lc) < 0 ?
580 loopcxt_get_device(lc) : file;
581 warn(_("%s: failed to set up loop device"), errpre);
582 break;
583 } while (hasdev == 0);
584
585 return rc;
586 }
587
588 int main(int argc, char **argv)
589 {
590 struct loopdev_cxt lc;
591 int act = 0, flags = 0, no_overlap = 0, c;
592 char *file = NULL;
593 uint64_t offset = 0, sizelimit = 0, blocksize = 0;
594 int res = 0, showdev = 0, lo_flags = 0;
595 char *outarg = NULL;
596 int list = 0;
597 unsigned long use_dio = 0, set_dio = 0, set_blocksize = 0;
598
599 enum {
600 OPT_SIZELIMIT = CHAR_MAX + 1,
601 OPT_SHOW,
602 OPT_RAW,
603 OPT_DIO,
604 OPT_OUTPUT_ALL
605 };
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' },
630 { NULL, 0, NULL, 0 }
631 };
632
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' },
637 { 'J',OPT_RAW },
638 { 0 }
639 };
640 int excl_st[ARRAY_SIZE(excl)] = UL_EXCL_STATUS_INIT;
641
642 setlocale(LC_ALL, "");
643 bindtextdomain(PACKAGE, LOCALEDIR);
644 textdomain(PACKAGE);
645 close_stdout_atexit();
646
647 if (loopcxt_init(&lc, 0))
648 err(EXIT_FAILURE, _("failed to initialize loopcxt"));
649
650 while ((c = getopt_long(argc, argv, "ab:c:d:Dfhj:JlLno:O:PrvV",
651 longopts, NULL)) != -1) {
652
653 err_exclusive_options(c, longopts, excl, excl_st);
654
655 switch (c) {
656 case 'a':
657 act = A_SHOW;
658 break;
659 case 'b':
660 set_blocksize = 1;
661 blocksize = strtosize_or_err(optarg, _("failed to parse logical block size"));
662 break;
663 case 'c':
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"),
668 optarg);
669 break;
670 case 'r':
671 lo_flags |= LO_FLAGS_READ_ONLY;
672 break;
673 case 'd':
674 act = A_DELETE;
675 if (!is_loopdev(optarg) ||
676 loopcxt_set_device(&lc, optarg))
677 err(EXIT_FAILURE, _("%s: failed to use device"),
678 optarg);
679 break;
680 case 'D':
681 act = A_DELETE_ALL;
682 break;
683 case 'f':
684 act = A_FIND_FREE;
685 break;
686 case 'J':
687 json = 1;
688 break;
689 case 'j':
690 act = A_SHOW;
691 file = optarg;
692 break;
693 case 'l':
694 list = 1;
695 break;
696 case 'L':
697 no_overlap = 1;
698 break;
699 case 'n':
700 no_headings = 1;
701 break;
702 case OPT_RAW:
703 raw = 1;
704 break;
705 case 'o':
706 offset = strtosize_or_err(optarg, _("failed to parse offset"));
707 flags |= LOOPDEV_FL_OFFSET;
708 break;
709 case 'O':
710 outarg = optarg;
711 list = 1;
712 break;
713 case OPT_OUTPUT_ALL:
714 for (ncolumns = 0; ncolumns < ARRAY_SIZE(infos); ncolumns++)
715 columns[ncolumns] = ncolumns;
716 break;
717 case 'P':
718 lo_flags |= LO_FLAGS_PARTSCAN;
719 break;
720 case OPT_SHOW:
721 showdev = 1;
722 break;
723 case OPT_DIO:
724 use_dio = set_dio = 1;
725 if (optarg)
726 use_dio = parse_switch(optarg, _("argument error"), "on", "off", NULL);
727 break;
728 case 'v':
729 break;
730 case OPT_SIZELIMIT: /* --sizelimit */
731 sizelimit = strtosize_or_err(optarg, _("failed to parse size"));
732 flags |= LOOPDEV_FL_SIZELIMIT;
733 break;
734
735 case 'h':
736 usage();
737 case 'V':
738 print_version(EXIT_SUCCESS);
739 default:
740 errtryhelp(EXIT_FAILURE);
741 }
742 }
743
744 ul_path_init_debug();
745 ul_sysfs_init_debug();
746
747 /* default is --list --all */
748 if (argc == 1) {
749 act = A_SHOW;
750 list = 1;
751 }
752
753 if (!act && argc == 2 && (raw || json)) {
754 act = A_SHOW;
755 list = 1;
756 }
757
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;
768 }
769
770 if (act == A_FIND_FREE && optind < argc) {
771 /*
772 * losetup -f <backing_file>
773 */
774 act = A_CREATE;
775 file = argv[optind++];
776
777 if (optind < argc)
778 errx(EXIT_FAILURE, _("unexpected arguments"));
779 }
780
781 if (list && !act && optind == argc)
782 /*
783 * losetup --list defaults to --all
784 */
785 act = A_SHOW;
786
787 if (!act && optind + 1 == argc) {
788 /*
789 * losetup [--list] <device>
790 * OR
791 * losetup {--direct-io[=off]|--logical-blocksize=size}... <device>
792 */
793 if (!(set_dio || set_blocksize))
794 act = A_SHOW_ONE;
795 if (set_dio)
796 act = A_SET_DIRECT_IO;
797 if (set_blocksize)
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"),
802 argv[optind]);
803 optind++;
804 }
805 if (!act) {
806 /*
807 * losetup <loopdev> <backing_file>
808 */
809 act = A_CREATE;
810
811 if (optind >= argc)
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"),
816 argv[optind]);
817 optind++;
818
819 if (optind >= argc)
820 errx(EXIT_FAILURE, _("no file specified"));
821 file = argv[optind++];
822 }
823
824 if (act != A_CREATE &&
825 (sizelimit || lo_flags || showdev))
826 errx(EXIT_FAILURE,
827 _("the options %s are allowed during loop device setup only"),
828 "--{sizelimit,partscan,read-only,show}");
829
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"));
833
834 if (outarg && string_add_to_idarray(outarg, columns, ARRAY_SIZE(columns),
835 &ncolumns, column_name_to_id) < 0)
836 return EXIT_FAILURE;
837
838 switch (act) {
839 case A_CREATE:
840 res = create_loop(&lc, no_overlap, lo_flags, flags, file,
841 offset, sizelimit, blocksize);
842 if (res == 0) {
843 if (showdev)
844 printf("%s\n", loopcxt_get_device(&lc));
845 warn_size(file, sizelimit, offset, flags);
846 if (set_dio)
847 goto lo_set_dio;
848 }
849 break;
850 case A_DELETE:
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"),
856 argv[optind]);
857 optind++;
858 res += delete_loop(&lc);
859 }
860 break;
861 case A_DELETE_ALL:
862 res = delete_all_loops(&lc);
863 break;
864 case A_FIND_FREE:
865 res = loopcxt_find_unused(&lc);
866 if (res) {
867 int errsv = errno;
868
869 if (access(_PATH_DEV_LOOPCTL, F_OK) == 0 &&
870 access(_PATH_DEV_LOOPCTL, W_OK) != 0)
871 ;
872 else
873 errno = errsv;
874
875 warn(_("cannot find an unused loop device"));
876 } else
877 printf("%s\n", loopcxt_get_device(&lc));
878 break;
879 case A_SHOW:
880 if (list)
881 res = show_table(&lc, file, offset, flags);
882 else
883 res = show_all_loops(&lc, file, offset, flags);
884 break;
885 case A_SHOW_ONE:
886 if (list)
887 res = show_table(&lc, NULL, 0, 0);
888 else
889 res = printf_loopdev(&lc);
890 if (res)
891 warn("%s", loopcxt_get_device(&lc));
892 break;
893 case A_SET_CAPACITY:
894 res = loopcxt_ioctl_capacity(&lc);
895 if (res)
896 warn(_("%s: set capacity failed"),
897 loopcxt_get_device(&lc));
898 break;
899 case A_SET_DIRECT_IO:
900 lo_set_dio:
901 res = loopcxt_ioctl_dio(&lc, use_dio);
902 if (res)
903 warn(_("%s: set direct io failed"),
904 loopcxt_get_device(&lc));
905 break;
906 case A_SET_BLOCKSIZE:
907 res = loopcxt_ioctl_blocksize(&lc, blocksize);
908 if (res)
909 warn(_("%s: set logical block size failed"),
910 loopcxt_get_device(&lc));
911 break;
912 default:
913 warnx(_("bad usage"));
914 errtryhelp(EXIT_FAILURE);
915 break;
916 }
917
918 loopcxt_deinit(&lc);
919 return res ? EXIT_FAILURE : EXIT_SUCCESS;
920 }
921