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