]> git.ipfire.org Git - thirdparty/util-linux.git/blob - sys-utils/losetup.c
afeb5babbd8bc36cd7d28034737bb231d742ccd8
[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_BACK_MAJ,
49 COL_BACK_MIN,
50 COL_MAJMIN,
51 COL_MAJ,
52 COL_MIN,
53 COL_OFFSET,
54 COL_PARTSCAN,
55 COL_REF,
56 COL_RO,
57 COL_SIZELIMIT,
58 COL_DIO,
59 COL_LOGSEC,
60 };
61
62 /* basic output flags */
63 static int no_headings;
64 static int raw;
65 static int json;
66
67 struct colinfo {
68 const char * const name;
69 double whint;
70 int flags;
71 const char *help;
72
73 int json_type; /* default is string */
74 };
75
76 static const struct colinfo infos[] = {
77 [COL_AUTOCLR] = { "AUTOCLEAR", 1, SCOLS_FL_RIGHT, N_("autoclear flag set"), SCOLS_JSON_BOOLEAN},
78 [COL_BACK_FILE] = { "BACK-FILE", 0.3, SCOLS_FL_NOEXTREMES, N_("device backing file")},
79 [COL_BACK_INO] = { "BACK-INO", 4, SCOLS_FL_RIGHT, N_("backing file inode number"), SCOLS_JSON_NUMBER},
80 [COL_BACK_MAJMIN] = { "BACK-MAJ:MIN", 6, 0, N_("backing file major:minor device number")},
81 [COL_BACK_MAJ] = { "BACK-MAJ", 6, 0, N_("backing file major device number")},
82 [COL_BACK_MIN] = { "BACK-MIN", 6, 0, N_("backing file minor device number")},
83 [COL_NAME] = { "NAME", 0.25, 0, N_("loop device name")},
84 [COL_OFFSET] = { "OFFSET", 5, SCOLS_FL_RIGHT, N_("offset from the beginning"), SCOLS_JSON_NUMBER},
85 [COL_PARTSCAN] = { "PARTSCAN", 1, SCOLS_FL_RIGHT, N_("partscan flag set"), SCOLS_JSON_BOOLEAN},
86 [COL_REF] = { "REF", 0.1, 0, N_("loop device reference string")},
87 [COL_RO] = { "RO", 1, SCOLS_FL_RIGHT, N_("read-only device"), SCOLS_JSON_BOOLEAN},
88 [COL_SIZELIMIT] = { "SIZELIMIT", 5, SCOLS_FL_RIGHT, N_("size limit of the file in bytes"), SCOLS_JSON_NUMBER},
89 [COL_MAJMIN] = { "MAJ:MIN", 3, 0, N_("loop device major:minor number")},
90 [COL_MAJ] = { "MAJ", 1, SCOLS_FL_RIGHT, N_("loop device major number"), SCOLS_JSON_NUMBER},
91 [COL_MIN] = { "MIN", 1, SCOLS_FL_RIGHT, N_("loop device minor number"), SCOLS_JSON_NUMBER},
92 [COL_DIO] = { "DIO", 1, SCOLS_FL_RIGHT, N_("access backing file with direct-io"), SCOLS_JSON_BOOLEAN},
93 [COL_LOGSEC] = { "LOG-SEC", 4, SCOLS_FL_RIGHT, N_("logical sector size in bytes"), SCOLS_JSON_NUMBER},
94 };
95
96 static int columns[ARRAY_SIZE(infos) * 2] = {-1};
97 static size_t ncolumns;
98
99 static int get_column_id(int num)
100 {
101 assert(num >= 0);
102 assert((size_t) num < ncolumns);
103 assert(columns[num] < (int) ARRAY_SIZE(infos));
104 return columns[num];
105 }
106
107 static const struct colinfo *get_column_info(int num)
108 {
109 return &infos[ get_column_id(num) ];
110 }
111
112 static int column_name_to_id(const char *name, size_t namesz)
113 {
114 size_t i;
115
116 for (i = 0; i < ARRAY_SIZE(infos); i++) {
117 const char *cn = infos[i].name;
118
119 if (!strncasecmp(name, cn, namesz) && !*(cn + namesz))
120 return i;
121 }
122 warnx(_("unknown column: %s"), name);
123 return -1;
124 }
125
126 static int printf_loopdev(struct loopdev_cxt *lc)
127 {
128 uint64_t x;
129 dev_t dev = 0;
130 ino_t ino = 0;
131 char *fname;
132 uint32_t type;
133
134 fname = loopcxt_get_backing_file(lc);
135 if (!fname)
136 return -EINVAL;
137
138 if (loopcxt_get_backing_devno(lc, &dev) == 0)
139 loopcxt_get_backing_inode(lc, &ino);
140
141 if (!dev && !ino) {
142 /*
143 * Probably non-root user (no permissions to
144 * call LOOP_GET_STATUS ioctls).
145 */
146 printf("%s%s: []: (%s)",
147 loopcxt_get_device(lc),
148 loopcxt_is_lost(lc) ? " (lost)" : "",
149 fname);
150
151 if (loopcxt_get_offset(lc, &x) == 0 && x)
152 printf(_(", offset %ju"), x);
153 if (loopcxt_get_sizelimit(lc, &x) == 0 && x)
154 printf(_(", sizelimit %ju"), x);
155
156 goto done;
157 }
158
159 printf("%s%s: [%04jd]:%ju (%s)",
160 loopcxt_get_device(lc),
161 loopcxt_is_lost(lc) ? " (lost)" : "",
162 (intmax_t) dev, (uintmax_t) ino, fname);
163
164 if (loopcxt_get_offset(lc, &x) == 0 && x)
165 printf(_(", offset %ju"), x);
166 if (loopcxt_get_sizelimit(lc, &x) == 0 && x)
167 printf(_(", sizelimit %ju"), x);
168
169 if (loopcxt_get_encrypt_type(lc, &type) == 0) {
170 const char *e = loopcxt_get_crypt_name(lc);
171
172 if ((!e || !*e) && type == 1)
173 e = "XOR";
174 if (e && *e)
175 printf(_(", encryption %s (type %u)"), e, type);
176 }
177
178 done:
179 free(fname);
180 printf("\n");
181 return 0;
182 }
183
184 static int show_all_loops(struct loopdev_cxt *lc, const char *file,
185 uint64_t offset, int flags)
186 {
187 struct stat sbuf, *st = &sbuf;
188 char *cn_file = NULL;
189
190 if (loopcxt_init_iterator(lc, LOOPITER_FL_USED))
191 return -1;
192
193 if (!file || stat(file, st))
194 st = NULL;
195
196 while (loopcxt_next(lc) == 0) {
197 if (file) {
198 int used;
199 const char *bf = cn_file ? cn_file : file;
200
201 used = loopcxt_is_used(lc, st, bf, offset, 0, flags);
202 if (!used && !cn_file) {
203 bf = cn_file = canonicalize_path(file);
204 used = loopcxt_is_used(lc, st, bf, offset, 0, flags);
205 }
206 if (!used)
207 continue;
208 }
209 printf_loopdev(lc);
210 }
211 loopcxt_deinit_iterator(lc);
212 free(cn_file);
213 return 0;
214 }
215
216 static void warn_lost(struct loopdev_cxt *lc)
217 {
218 dev_t devno = loopcxt_get_devno(lc);
219
220 if (devno <= 0)
221 return;
222
223 warnx(("device node %s (%u:%u) is lost. You may use mknod(1) to recover it."),
224 loopcxt_get_device(lc), major(devno), minor(devno));
225 }
226
227 static int delete_loop(struct loopdev_cxt *lc)
228 {
229 if (loopcxt_delete_device(lc)) {
230 warn(_("%s: detach failed"), loopcxt_get_device(lc));
231 if (loopcxt_is_lost(lc))
232 warn_lost(lc);
233 } else
234 return 0;
235
236 return -1;
237 }
238
239 static int delete_all_loops(struct loopdev_cxt *lc)
240 {
241 int res = 0;
242
243 if (loopcxt_init_iterator(lc, LOOPITER_FL_USED))
244 return -1;
245
246 while (loopcxt_next(lc) == 0)
247 res += delete_loop(lc);
248
249 loopcxt_deinit_iterator(lc);
250 return res;
251 }
252
253 static int set_scols_data(struct loopdev_cxt *lc, struct libscols_line *ln)
254 {
255 size_t i;
256
257 for (i = 0; i < ncolumns; i++) {
258 const char *p = NULL; /* external data */
259 char *np = NULL; /* allocated here */
260 uint64_t x = 0;
261 int rc = 0;
262
263 switch(get_column_id(i)) {
264 case COL_NAME:
265 p = loopcxt_get_device(lc);
266 if (loopcxt_is_lost(lc)) {
267 xasprintf(&np, "%s (lost)", p);
268 p = NULL;
269 }
270 break;
271 case COL_BACK_FILE:
272 np = loopcxt_get_backing_file(lc);
273 break;
274 case COL_OFFSET:
275 if (loopcxt_get_offset(lc, &x) == 0)
276 xasprintf(&np, "%jd", x);
277 break;
278 case COL_SIZELIMIT:
279 if (loopcxt_get_sizelimit(lc, &x) == 0)
280 xasprintf(&np, "%jd", x);
281 break;
282 case COL_BACK_MAJMIN:
283 {
284 dev_t dev = 0;
285 if (loopcxt_get_backing_devno(lc, &dev) == 0 && dev)
286 xasprintf(&np, raw || json ? "%u:%u" : "%8u:%-3u",
287 major(dev), minor(dev));
288 break;
289 }
290 case COL_BACK_MAJ:
291 {
292 dev_t dev = 0;
293 if (loopcxt_get_backing_devno(lc, &dev) == 0 && dev)
294 xasprintf(&np, "%u", major(dev));
295 break;
296 }
297 case COL_BACK_MIN:
298 {
299 dev_t dev = 0;
300 if (loopcxt_get_backing_devno(lc, &dev) == 0 && dev)
301 xasprintf(&np, "%u", minor(dev));
302 break;
303 }
304 case COL_MAJMIN:
305 {
306 dev_t dev = loopcxt_get_devno(lc);
307 if (dev)
308 xasprintf(&np, raw || json ? "%u:%u" :"%3u:%-3u",
309 major(dev), minor(dev));
310 break;
311 }
312 case COL_MAJ: {
313 dev_t dev = loopcxt_get_devno(lc);
314 if (dev)
315 xasprintf(&np, "%u", major(dev));
316 break;
317 }
318 case COL_MIN: {
319 dev_t dev = loopcxt_get_devno(lc);
320 if (dev)
321 xasprintf(&np, "%u", minor(dev));
322 break;
323 }
324 case COL_BACK_INO:
325 {
326 ino_t ino = 0;
327 if (loopcxt_get_backing_inode(lc, &ino) == 0 && ino)
328 xasprintf(&np, "%ju", ino);
329 break;
330 }
331 case COL_AUTOCLR:
332 p = loopcxt_is_autoclear(lc) ? "1" : "0";
333 break;
334 case COL_RO:
335 p = loopcxt_is_readonly(lc) ? "1" : "0";
336 break;
337 case COL_DIO:
338 p = loopcxt_is_dio(lc) ? "1" : "0";
339 break;
340 case COL_PARTSCAN:
341 p = loopcxt_is_partscan(lc) ? "1" : "0";
342 break;
343 case COL_LOGSEC:
344 if (loopcxt_get_blocksize(lc, &x) == 0)
345 xasprintf(&np, "%jd", x);
346 break;
347 case COL_REF:
348 np = loopcxt_get_refname(lc);
349 break;
350 default:
351 return -EINVAL;
352 }
353
354
355 if (p)
356 rc = scols_line_set_data(ln, i, p); /* calls strdup() */
357 else if (np)
358 rc = scols_line_refer_data(ln, i, np); /* only refers */
359
360 if (rc)
361 err(EXIT_FAILURE, _("failed to add output data"));
362 }
363
364 return 0;
365 }
366
367 static int show_table(struct loopdev_cxt *lc,
368 const char *file,
369 uint64_t offset,
370 int flags)
371 {
372 struct stat sbuf, *st = &sbuf;
373 struct libscols_table *tb;
374 struct libscols_line *ln;
375 int rc = 0;
376 size_t i;
377
378 scols_init_debug(0);
379
380 if (!(tb = scols_new_table()))
381 err(EXIT_FAILURE, _("failed to allocate output table"));
382 scols_table_enable_raw(tb, raw);
383 scols_table_enable_json(tb, json);
384 scols_table_enable_noheadings(tb, no_headings);
385
386 if (json)
387 scols_table_set_name(tb, "loopdevices");
388
389 for (i = 0; i < ncolumns; i++) {
390 const struct colinfo *ci = get_column_info(i);
391 struct libscols_column *cl;
392
393 cl = scols_table_new_column(tb, ci->name, ci->whint, ci->flags);
394 if (!cl)
395 err(EXIT_FAILURE, _("failed to allocate output column"));
396 if (json)
397 scols_column_set_json_type(cl, ci->json_type);
398 }
399
400 /* only one loopdev requested (already assigned to loopdev_cxt) */
401 if (loopcxt_get_device(lc)) {
402 ln = scols_table_new_line(tb, NULL);
403 if (!ln)
404 err(EXIT_FAILURE, _("failed to allocate output line"));
405 rc = set_scols_data(lc, ln);
406
407 /* list all loopdevs */
408 } else {
409 char *cn_file = NULL;
410
411 rc = loopcxt_init_iterator(lc, LOOPITER_FL_USED);
412 if (rc)
413 goto done;
414 if (!file || stat(file, st))
415 st = NULL;
416
417 while (loopcxt_next(lc) == 0) {
418 if (file) {
419 int used;
420 const char *bf = cn_file ? cn_file : file;
421
422 used = loopcxt_is_used(lc, st, bf, offset, 0, flags);
423 if (!used && !cn_file) {
424 bf = cn_file = canonicalize_path(file);
425 used = loopcxt_is_used(lc, st, bf, offset, 0, flags);
426 }
427 if (!used)
428 continue;
429 }
430
431 ln = scols_table_new_line(tb, NULL);
432 if (!ln)
433 err(EXIT_FAILURE, _("failed to allocate output line"));
434 rc = set_scols_data(lc, ln);
435 if (rc)
436 break;
437 }
438
439 loopcxt_deinit_iterator(lc);
440 free(cn_file);
441 }
442 done:
443 if (rc == 0)
444 rc = scols_print_table(tb);
445 scols_unref_table(tb);
446 return rc;
447 }
448
449 static void __attribute__((__noreturn__)) usage(void)
450 {
451 FILE *out = stdout;
452 size_t i;
453
454 fputs(USAGE_HEADER, out);
455
456 fprintf(out,
457 _(" %1$s [options] [<loopdev>]\n"
458 " %1$s [options] -f | <loopdev> <file>\n"),
459 program_invocation_short_name);
460
461 fputs(USAGE_SEPARATOR, out);
462 fputs(_("Set up and control loop devices.\n"), out);
463
464 /* commands */
465 fputs(USAGE_OPTIONS, out);
466 fputs(_(" -a, --all list all used devices\n"), out);
467 fputs(_(" -d, --detach <loopdev>... detach one or more devices\n"), out);
468 fputs(_(" -D, --detach-all detach all used devices\n"), out);
469 fputs(_(" -f, --find find first unused device\n"), out);
470 fputs(_(" -c, --set-capacity <loopdev> resize the device\n"), out);
471 fputs(_(" -j, --associated <file> list all devices associated with <file>\n"), out);
472 fputs(_(" -L, --nooverlap avoid possible conflict between devices\n"), out);
473
474 /* commands options */
475 fputs(USAGE_SEPARATOR, out);
476 fputs(_(" -o, --offset <num> start at offset <num> into file\n"), out);
477 fputs(_(" --sizelimit <num> device is limited to <num> bytes of the file\n"), out);
478 fputs(_(" -b, --sector-size <num> set the logical sector size to <num>\n"), out);
479 fputs(_(" -P, --partscan create a partitioned loop device\n"), out);
480 fputs(_(" -r, --read-only set up a read-only loop device\n"), out);
481 fputs(_(" --direct-io[=<on|off>] open backing file with O_DIRECT\n"), out);
482 fputs(_(" --loop-ref <string> loop device reference\n"), out);
483 fputs(_(" --show print device name after setup (with -f)\n"), out);
484 fputs(_(" -v, --verbose verbose mode\n"), out);
485
486 /* output options */
487 fputs(USAGE_SEPARATOR, out);
488 fputs(_(" -J, --json use JSON --list output format\n"), out);
489 fputs(_(" -l, --list list info about all or specified (default)\n"), out);
490 fputs(_(" -n, --noheadings don't print headings for --list output\n"), out);
491 fputs(_(" -O, --output <cols> specify columns to output for --list\n"), out);
492 fputs(_(" --output-all output all columns\n"), out);
493 fputs(_(" --raw use raw --list output format\n"), out);
494
495 fputs(USAGE_SEPARATOR, out);
496 fprintf(out, USAGE_HELP_OPTIONS(31));
497
498 fputs(USAGE_COLUMNS, out);
499 for (i = 0; i < ARRAY_SIZE(infos); i++)
500 fprintf(out, " %12s %s\n", infos[i].name, _(infos[i].help));
501
502 fprintf(out, USAGE_MAN_TAIL("losetup(8)"));
503
504 exit(EXIT_SUCCESS);
505 }
506
507 static void warn_size(const char *filename, uint64_t size, uint64_t offset, int flags)
508 {
509 struct stat st;
510
511 if (!size) {
512 if (stat(filename, &st) || S_ISBLK(st.st_mode))
513 return;
514 size = st.st_size;
515
516 if (flags & LOOPDEV_FL_OFFSET)
517 size -= offset;
518 }
519
520 if (size < 512)
521 warnx(_("%s: Warning: file is smaller than 512 bytes; the loop device "
522 "may be useless or invisible for system tools."),
523 filename);
524 else if (size % 512)
525 warnx(_("%s: Warning: file does not fit into a 512-byte sector; "
526 "the end of the file will be ignored."),
527 filename);
528 }
529
530 static int find_unused(struct loopdev_cxt *lc)
531 {
532 int rc;
533
534 rc = loopcxt_find_unused(lc);
535 if (!rc)
536 return 0;
537
538 if (access(_PATH_DEV_LOOPCTL, F_OK) == 0 &&
539 access(_PATH_DEV_LOOPCTL, W_OK) != 0)
540 ;
541 else
542 errno = -rc;
543
544 warn(_("cannot find an unused loop device"));
545
546 return rc;
547 }
548
549 static int create_loop(struct loopdev_cxt *lc,
550 int nooverlap, int lo_flags, int flags,
551 const char *file, const char *refname,
552 uint64_t offset, uint64_t sizelimit,
553 uint64_t blocksize)
554 {
555 int hasdev = loopcxt_has_device(lc);
556 int rc = 0, ntries = 0;
557
558 /* losetup --find --noverlap file.img */
559 if (!hasdev && nooverlap) {
560 rc = loopcxt_find_overlap(lc, file, offset, sizelimit);
561 switch (rc) {
562 case 0: /* not found */
563 break;
564
565 case 1: /* overlap */
566 loopcxt_deinit(lc);
567 errx(EXIT_FAILURE, _("%s: overlapping loop device exists"), file);
568
569 case 2: /* overlap -- full size and offset match (reuse) */
570 {
571 uint32_t lc_encrypt_type;
572
573 /* Once a loop is initialized RO, there is no
574 * way to change its parameters. */
575 if (loopcxt_is_readonly(lc)
576 && !(lo_flags & LO_FLAGS_READ_ONLY)) {
577 loopcxt_deinit(lc);
578 errx(EXIT_FAILURE, _("%s: overlapping read-only loop device exists"), file);
579 }
580
581 /* This is no more supported, but check to be safe. */
582 if (loopcxt_get_encrypt_type(lc, &lc_encrypt_type) == 0
583 && lc_encrypt_type != LO_CRYPT_NONE) {
584 loopcxt_deinit(lc);
585 errx(EXIT_FAILURE, _("%s: overlapping encrypted loop device exists"), file);
586 }
587
588 lc->config.info.lo_flags &= ~LO_FLAGS_AUTOCLEAR;
589 if (loopcxt_ioctl_status(lc)) {
590 loopcxt_deinit(lc);
591 errx(EXIT_FAILURE, _("%s: failed to re-use loop device"), file);
592 }
593 return 0; /* success, re-use */
594 }
595 default: /* error */
596 loopcxt_deinit(lc);
597 errx(EXIT_FAILURE, _("failed to inspect loop devices"));
598 return -errno;
599 }
600 }
601
602 if (hasdev)
603 loopcxt_add_device(lc);
604
605 /* losetup --noverlap /dev/loopN file.img */
606 if (hasdev && nooverlap) {
607 struct loopdev_cxt lc2;
608
609 if (loopcxt_init(&lc2, 0)) {
610 loopcxt_deinit(lc);
611 err(EXIT_FAILURE, _("failed to initialize loopcxt"));
612 }
613 rc = loopcxt_find_overlap(&lc2, file, offset, sizelimit);
614 loopcxt_deinit(&lc2);
615
616 if (rc) {
617 loopcxt_deinit(lc);
618 if (rc > 0)
619 errx(EXIT_FAILURE, _("%s: overlapping loop device exists"), file);
620 err(EXIT_FAILURE, _("%s: failed to check for conflicting loop devices"), file);
621 }
622 }
623
624 /* Create a new device */
625 do {
626 const char *errpre;
627
628 /* Note that loopcxt_{find_unused,set_device}() resets
629 * loopcxt struct.
630 */
631 if (!hasdev && (rc = find_unused(lc)))
632 break;
633 if (flags & LOOPDEV_FL_OFFSET)
634 loopcxt_set_offset(lc, offset);
635 if (flags & LOOPDEV_FL_SIZELIMIT)
636 loopcxt_set_sizelimit(lc, sizelimit);
637 if (lo_flags)
638 loopcxt_set_flags(lc, lo_flags);
639 if (blocksize > 0)
640 loopcxt_set_blocksize(lc, blocksize);
641 if (refname && (rc = loopcxt_set_refname(lc, refname))) {
642 warnx(_("cannot set loop reference string"));
643 break;
644 }
645 if ((rc = loopcxt_set_backing_file(lc, file))) {
646 warn(_("%s: failed to use backing file"), file);
647 break;
648 }
649 errno = 0;
650 rc = loopcxt_setup_device(lc);
651 if (rc == 0)
652 break; /* success */
653
654 if ((errno == EBUSY || errno == EAGAIN) && !hasdev && ntries < 64) {
655 xusleep(200000);
656 ntries++;
657 continue;
658 }
659
660 /* errors */
661 errpre = hasdev && lc->fd < 0 ?
662 loopcxt_get_device(lc) : file;
663 warn(_("%s: failed to set up loop device"), errpre);
664 break;
665 } while (hasdev == 0);
666
667 return rc;
668 }
669
670 int main(int argc, char **argv)
671 {
672 struct loopdev_cxt lc;
673 int act = 0, flags = 0, no_overlap = 0, c;
674 char *file = NULL, *refname = NULL;
675 uint64_t offset = 0, sizelimit = 0, blocksize = 0;
676 int res = 0, showdev = 0, lo_flags = 0;
677 char *outarg = NULL;
678 int list = 0;
679 unsigned long use_dio = 0, set_dio = 0, set_blocksize = 0;
680
681 enum {
682 OPT_SIZELIMIT = CHAR_MAX + 1,
683 OPT_SHOW,
684 OPT_RAW,
685 OPT_REF,
686 OPT_DIO,
687 OPT_OUTPUT_ALL
688 };
689 static const struct option longopts[] = {
690 { "all", no_argument, NULL, 'a' },
691 { "set-capacity", required_argument, NULL, 'c' },
692 { "detach", required_argument, NULL, 'd' },
693 { "detach-all", no_argument, NULL, 'D' },
694 { "find", no_argument, NULL, 'f' },
695 { "nooverlap", no_argument, NULL, 'L' },
696 { "help", no_argument, NULL, 'h' },
697 { "associated", required_argument, NULL, 'j' },
698 { "json", no_argument, NULL, 'J' },
699 { "list", no_argument, NULL, 'l' },
700 { "sector-size", required_argument, NULL, 'b' },
701 { "noheadings", no_argument, NULL, 'n' },
702 { "offset", required_argument, NULL, 'o' },
703 { "output", required_argument, NULL, 'O' },
704 { "output-all", no_argument, NULL, OPT_OUTPUT_ALL },
705 { "sizelimit", required_argument, NULL, OPT_SIZELIMIT },
706 { "partscan", no_argument, NULL, 'P' },
707 { "read-only", no_argument, NULL, 'r' },
708 { "direct-io", optional_argument, NULL, OPT_DIO },
709 { "raw", no_argument, NULL, OPT_RAW },
710 { "loop-ref", required_argument, NULL, OPT_REF, },
711 { "show", no_argument, NULL, OPT_SHOW },
712 { "verbose", no_argument, NULL, 'v' },
713 { "version", no_argument, NULL, 'V' },
714 { NULL, 0, NULL, 0 }
715 };
716
717 static const ul_excl_t excl[] = { /* rows and cols in ASCII order */
718 { 'D','a','c','d','f','j' },
719 { 'D','c','d','f','l' },
720 { 'D','c','d','f','O' },
721 { 'J',OPT_RAW },
722 { 0 }
723 };
724 int excl_st[ARRAY_SIZE(excl)] = UL_EXCL_STATUS_INIT;
725
726 setlocale(LC_ALL, "");
727 bindtextdomain(PACKAGE, LOCALEDIR);
728 textdomain(PACKAGE);
729 close_stdout_atexit();
730
731 if (loopcxt_init(&lc, 0))
732 err(EXIT_FAILURE, _("failed to initialize loopcxt"));
733
734 while ((c = getopt_long(argc, argv, "ab:c:d:Dfhj:JlLno:O:PrvV",
735 longopts, NULL)) != -1) {
736
737 err_exclusive_options(c, longopts, excl, excl_st);
738
739 switch (c) {
740 case 'a':
741 act = A_SHOW;
742 break;
743 case 'b':
744 set_blocksize = 1;
745 blocksize = strtosize_or_err(optarg, _("failed to parse logical block size"));
746 break;
747 case 'c':
748 act = A_SET_CAPACITY;
749 if (loopcxt_set_device(&lc, optarg))
750 err(EXIT_FAILURE, _("%s: failed to use device"),
751 optarg);
752 break;
753 case 'r':
754 lo_flags |= LO_FLAGS_READ_ONLY;
755 break;
756 case OPT_REF:
757 refname = optarg;
758 break;
759 case 'd':
760 act = A_DELETE;
761 if (loopcxt_set_device(&lc, optarg))
762 err(EXIT_FAILURE, _("%s: failed to use device"),
763 optarg);
764 break;
765 case 'D':
766 act = A_DELETE_ALL;
767 break;
768 case 'f':
769 act = A_FIND_FREE;
770 break;
771 case 'J':
772 json = 1;
773 break;
774 case 'j':
775 act = A_SHOW;
776 file = optarg;
777 break;
778 case 'l':
779 list = 1;
780 break;
781 case 'L':
782 no_overlap = 1;
783 break;
784 case 'n':
785 no_headings = 1;
786 break;
787 case OPT_RAW:
788 raw = 1;
789 break;
790 case 'o':
791 offset = strtosize_or_err(optarg, _("failed to parse offset"));
792 flags |= LOOPDEV_FL_OFFSET;
793 break;
794 case 'O':
795 outarg = optarg;
796 list = 1;
797 break;
798 case OPT_OUTPUT_ALL:
799 list = 1;
800 for (ncolumns = 0; ncolumns < ARRAY_SIZE(infos); ncolumns++)
801 columns[ncolumns] = ncolumns;
802 break;
803 case 'P':
804 lo_flags |= LO_FLAGS_PARTSCAN;
805 break;
806 case OPT_SHOW:
807 showdev = 1;
808 break;
809 case OPT_DIO:
810 use_dio = set_dio = 1;
811 if (optarg)
812 use_dio = parse_switch(optarg, _("argument error"), "on", "off", NULL);
813 if (use_dio)
814 lo_flags |= LO_FLAGS_DIRECT_IO;
815 break;
816 case 'v':
817 break;
818 case OPT_SIZELIMIT: /* --sizelimit */
819 sizelimit = strtosize_or_err(optarg, _("failed to parse size"));
820 flags |= LOOPDEV_FL_SIZELIMIT;
821 break;
822
823 case 'h':
824 usage();
825 case 'V':
826 print_version(EXIT_SUCCESS);
827 default:
828 errtryhelp(EXIT_FAILURE);
829 }
830 }
831
832 ul_path_init_debug();
833 ul_sysfs_init_debug();
834
835 /* default is --list --all */
836 if (argc == 1) {
837 act = A_SHOW;
838 list = 1;
839 }
840
841 if (!act && argc == 2 && (raw || json)) {
842 act = A_SHOW;
843 list = 1;
844 }
845
846 /* default --list output columns */
847 if (list && !ncolumns) {
848 columns[ncolumns++] = COL_NAME;
849 columns[ncolumns++] = COL_SIZELIMIT;
850 columns[ncolumns++] = COL_OFFSET;
851 columns[ncolumns++] = COL_AUTOCLR;
852 columns[ncolumns++] = COL_RO;
853 columns[ncolumns++] = COL_BACK_FILE;
854 columns[ncolumns++] = COL_DIO;
855 columns[ncolumns++] = COL_LOGSEC;
856 }
857
858 if (act == A_FIND_FREE && optind < argc) {
859 /*
860 * losetup -f <backing_file>
861 */
862 act = A_CREATE;
863 file = argv[optind++];
864
865 if (optind < argc)
866 errx(EXIT_FAILURE, _("unexpected arguments"));
867 }
868
869 if (list && !act && optind == argc)
870 /*
871 * losetup --list defaults to --all
872 */
873 act = A_SHOW;
874
875 if (!act && optind + 1 == argc) {
876 /*
877 * losetup [--list] <device>
878 * OR
879 * losetup {--direct-io[=off]|--logical-blocksize=size}... <device>
880 */
881 if (set_dio) {
882 act = A_SET_DIRECT_IO;
883 lo_flags &= ~LO_FLAGS_DIRECT_IO;
884 } else if (set_blocksize)
885 act = A_SET_BLOCKSIZE;
886 else
887 act = A_SHOW_ONE;
888
889 if (loopcxt_set_device(&lc, argv[optind]))
890 err(EXIT_FAILURE, _("%s: failed to use device"),
891 argv[optind]);
892 optind++;
893 }
894 if (!act) {
895 /*
896 * losetup <loopdev> <backing_file>
897 */
898 act = A_CREATE;
899
900 if (optind >= argc)
901 errx(EXIT_FAILURE, _("no loop device specified"));
902 /* don't use is_loopdev() here, the device does not have exist yet */
903 if (loopcxt_set_device(&lc, argv[optind]))
904 err(EXIT_FAILURE, _("%s: failed to use device"),
905 argv[optind]);
906 optind++;
907
908 if (optind >= argc)
909 errx(EXIT_FAILURE, _("no file specified"));
910 file = argv[optind++];
911 }
912
913 if (act != A_CREATE &&
914 (sizelimit || lo_flags || showdev))
915 errx(EXIT_FAILURE,
916 _("the options %s are allowed during loop device setup only"),
917 "--{sizelimit,partscan,read-only,show}");
918
919 if ((flags & LOOPDEV_FL_OFFSET) &&
920 act != A_CREATE && (act != A_SHOW || !file))
921 errx(EXIT_FAILURE, _("the option --offset is not allowed in this context"));
922
923 if (outarg && string_add_to_idarray(outarg, columns, ARRAY_SIZE(columns),
924 &ncolumns, column_name_to_id) < 0)
925 return EXIT_FAILURE;
926
927 switch (act) {
928 case A_CREATE:
929 res = create_loop(&lc, no_overlap, lo_flags, flags, file, refname,
930 offset, sizelimit, blocksize);
931 if (res == 0) {
932 if (showdev)
933 printf("%s\n", loopcxt_get_device(&lc));
934 warn_size(file, sizelimit, offset, flags);
935 }
936 break;
937 case A_DELETE:
938 res = delete_loop(&lc);
939 while (optind < argc) {
940 if (loopcxt_set_device(&lc, argv[optind]))
941 warn(_("%s: failed to use device"),
942 argv[optind]);
943 optind++;
944 res += delete_loop(&lc);
945 }
946 break;
947 case A_DELETE_ALL:
948 res = delete_all_loops(&lc);
949 break;
950 case A_FIND_FREE:
951 res = find_unused(&lc);
952 if (!res)
953 printf("%s%s\n", loopcxt_get_device(&lc),
954 loopcxt_is_lost(&lc) ? " (lost)" : "");
955 break;
956 case A_SHOW:
957 if (list)
958 res = show_table(&lc, file, offset, flags);
959 else
960 res = show_all_loops(&lc, file, offset, flags);
961 break;
962 case A_SHOW_ONE:
963 if (list)
964 res = show_table(&lc, NULL, 0, 0);
965 else
966 res = printf_loopdev(&lc);
967 if (res)
968 warn("%s", loopcxt_get_device(&lc));
969 break;
970 case A_SET_CAPACITY:
971 res = loopcxt_ioctl_capacity(&lc);
972 if (res)
973 warn(_("%s: set capacity failed"),
974 loopcxt_get_device(&lc));
975 break;
976 case A_SET_DIRECT_IO:
977 res = loopcxt_ioctl_dio(&lc, use_dio);
978 if (res)
979 warn(_("%s: set direct io failed"),
980 loopcxt_get_device(&lc));
981 break;
982 case A_SET_BLOCKSIZE:
983 res = loopcxt_ioctl_blocksize(&lc, blocksize);
984 if (res)
985 warn(_("%s: set logical block size failed"),
986 loopcxt_get_device(&lc));
987 break;
988 default:
989 warnx(_("bad usage"));
990 errtryhelp(EXIT_FAILURE);
991 break;
992 }
993
994 if (res && (act == A_SET_CAPACITY
995 || act == A_CREATE
996 || act == A_SET_DIRECT_IO
997 || act == A_SET_BLOCKSIZE)
998 && loopcxt_is_lost(&lc))
999 warn_lost(&lc);
1000
1001 loopcxt_deinit(&lc);
1002 return res ? EXIT_FAILURE : EXIT_SUCCESS;
1003 }