]> git.ipfire.org Git - thirdparty/util-linux.git/blame - sys-utils/losetup.c
losetup: don't skip adding a new device if it already has a device node
[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
7e86cd54
OO
18#include <libsmartcols.h>
19
934df30d 20#include "c.h"
7eda085c 21#include "nls.h"
934df30d 22#include "strutils.h"
de4acb05 23#include "loopdev.h"
efb8854f 24#include "closestream.h"
96801c48 25#include "optutils.h"
896352d3 26#include "xalloc.h"
114ade3d 27#include "canonicalize.h"
362f5d20 28#include "pathnames.h"
96801c48 29
39fde137 30enum {
c7e0925d 31 A_CREATE = 1, /* setup a new device */
c654c4f0
KZ
32 A_DELETE, /* delete given device(s) */
33 A_DELETE_ALL, /* delete all devices */
39fde137 34 A_SHOW, /* list devices */
09ec0c0a 35 A_SHOW_ONE, /* print info about one device */
39fde137
KZ
36 A_FIND_FREE, /* find first unused */
37 A_SET_CAPACITY, /* set device capacity */
64c3bb3c 38 A_SET_DIRECT_IO, /* set accessing backing file by direct io */
a1a41597 39 A_SET_BLOCKSIZE, /* set logical block size of the loop device */
39fde137
KZ
40};
41
896352d3
OO
42enum {
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,
4ad996d7 52 COL_SIZELIMIT,
faeef4d2 53 COL_DIO,
76493ceb 54 COL_LOGSEC,
896352d3
OO
55};
56
7e86cd54
OO
57/* basic output flags */
58static int no_headings;
59static int raw;
4827093d 60static int json;
896352d3
OO
61
62struct colinfo {
63 const char *name;
64 double whint;
65 int flags;
66 const char *help;
46de0fe6
KZ
67
68 int json_type; /* default is string */
896352d3
OO
69};
70
71static struct colinfo infos[] = {
46de0fe6 72 [COL_AUTOCLR] = { "AUTOCLEAR", 1, SCOLS_FL_RIGHT, N_("autoclear flag set"), SCOLS_JSON_BOOLEAN},
896352d3 73 [COL_BACK_FILE] = { "BACK-FILE", 0.3, 0, N_("device backing file")},
46de0fe6 74 [COL_BACK_INO] = { "BACK-INO", 4, SCOLS_FL_RIGHT, N_("backing file inode number"), SCOLS_JSON_NUMBER},
896352d3
OO
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")},
46de0fe6
KZ
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},
896352d3 81 [COL_MAJMIN] = { "MAJ:MIN", 3, 0, N_("loop device major:minor number")},
46de0fe6
KZ
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},
896352d3
OO
84};
85
d78deddc 86static int columns[ARRAY_SIZE(infos) * 2] = {-1};
40b17508 87static size_t ncolumns;
6dbe3af9 88
896352d3
OO
89static int get_column_id(int num)
90{
40b17508
KZ
91 assert(num >= 0);
92 assert((size_t) num < ncolumns);
d78deddc 93 assert(columns[num] < (int) ARRAY_SIZE(infos));
896352d3
OO
94 return columns[num];
95}
96
97static struct colinfo *get_column_info(int num)
98{
99 return &infos[ get_column_id(num) ];
100}
101
102static int column_name_to_id(const char *name, size_t namesz)
103{
104 size_t i;
105
d78deddc 106 for (i = 0; i < ARRAY_SIZE(infos); i++) {
896352d3
OO
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}
d03dd608 115
39fde137
KZ
116static int printf_loopdev(struct loopdev_cxt *lc)
117{
118 uint64_t x;
119 dev_t dev = 0;
120 ino_t ino = 0;
1b504263 121 char *fname;
a3b421df 122 uint32_t type;
39fde137
KZ
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);
9c6af25c 144 goto done;
39fde137
KZ
145 }
146
cd3f22e6
MB
147 printf("%s: [%04jd]:%ju (%s)",
148 loopcxt_get_device(lc), (intmax_t) dev, (uintmax_t) ino, fname);
39fde137
KZ
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)
a3b421df 162 printf(_(", encryption %s (type %u)"), e, type);
39fde137 163 }
9c6af25c
KZ
164
165done:
166 free(fname);
39fde137
KZ
167 printf("\n");
168 return 0;
169}
170
bc0ac075
KZ
171static int show_all_loops(struct loopdev_cxt *lc, const char *file,
172 uint64_t offset, int flags)
39fde137 173{
bc0ac075 174 struct stat sbuf, *st = &sbuf;
6d62bc0f 175 char *cn_file = NULL;
bc0ac075 176
39fde137 177 if (loopcxt_init_iterator(lc, LOOPITER_FL_USED))
6e90a44c 178 return -1;
39fde137 179
bc0ac075
KZ
180 if (!file || stat(file, st))
181 st = NULL;
182
183 while (loopcxt_next(lc) == 0) {
6d62bc0f
KZ
184 if (file) {
185 int used;
186 const char *bf = cn_file ? cn_file : file;
187
74a4705a 188 used = loopcxt_is_used(lc, st, bf, offset, 0, flags);
6d62bc0f
KZ
189 if (!used && !cn_file) {
190 bf = cn_file = canonicalize_path(file);
74a4705a 191 used = loopcxt_is_used(lc, st, bf, offset, 0, flags);
6d62bc0f
KZ
192 }
193 if (!used)
114ade3d
SK
194 continue;
195 }
bc0ac075
KZ
196 printf_loopdev(lc);
197 }
c654c4f0 198 loopcxt_deinit_iterator(lc);
f614b73c 199 free(cn_file);
6e90a44c
KZ
200 return 0;
201}
202
c654c4f0
KZ
203static 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
213static 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;
39fde137
KZ
225}
226
7e86cd54 227static int set_scols_data(struct loopdev_cxt *lc, struct libscols_line *ln)
896352d3 228{
40b17508 229 size_t i;
896352d3
OO
230
231 for (i = 0; i < ncolumns; i++) {
48f1f38b
KZ
232 const char *p = NULL; /* external data */
233 char *np = NULL; /* allocated here */
896352d3 234 uint64_t x = 0;
a9e3ec19 235 int rc = 0;
896352d3
OO
236
237 switch(get_column_id(i)) {
238 case COL_NAME:
239 p = loopcxt_get_device(lc);
896352d3
OO
240 break;
241 case COL_BACK_FILE:
242 p = loopcxt_get_backing_file(lc);
896352d3
OO
243 break;
244 case COL_OFFSET:
245 if (loopcxt_get_offset(lc, &x) == 0)
246 xasprintf(&np, "%jd", x);
896352d3 247 break;
4ad996d7 248 case COL_SIZELIMIT:
896352d3
OO
249 if (loopcxt_get_sizelimit(lc, &x) == 0)
250 xasprintf(&np, "%jd", x);
896352d3
OO
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));
896352d3
OO
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));
896352d3
OO
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);
896352d3
OO
276 break;
277 }
278 case COL_AUTOCLR:
48f1f38b 279 p = loopcxt_is_autoclear(lc) ? "1" : "0";
896352d3
OO
280 break;
281 case COL_RO:
48f1f38b 282 p = loopcxt_is_readonly(lc) ? "1" : "0";
896352d3 283 break;
faeef4d2
ML
284 case COL_DIO:
285 p = loopcxt_is_dio(lc) ? "1" : "0";
286 break;
896352d3 287 case COL_PARTSCAN:
48f1f38b 288 p = loopcxt_is_partscan(lc) ? "1" : "0";
896352d3 289 break;
76493ceb 290 case COL_LOGSEC:
a1a41597
SB
291 if (loopcxt_get_blocksize(lc, &x) == 0)
292 xasprintf(&np, "%jd", x);
293 break;
896352d3
OO
294 default:
295 return -EINVAL;
296 }
48f1f38b
KZ
297
298
299 if (p)
780ce22c 300 rc = scols_line_set_data(ln, i, p); /* calls strdup() */
48f1f38b 301 else if (np)
780ce22c
KZ
302 rc = scols_line_refer_data(ln, i, np); /* only refers */
303
304 if (rc)
305 err(EXIT_FAILURE, _("failed to add output data"));
896352d3 306 }
48f1f38b 307
896352d3
OO
308 return 0;
309}
310
48f1f38b 311static int show_table(struct loopdev_cxt *lc,
9f56106d
KZ
312 const char *file,
313 uint64_t offset,
7e86cd54 314 int flags)
896352d3
OO
315{
316 struct stat sbuf, *st = &sbuf;
48f1f38b 317 struct libscols_table *tb;
7e86cd54 318 struct libscols_line *ln;
40b17508
KZ
319 int rc = 0;
320 size_t i;
896352d3 321
710ed55d
KZ
322 scols_init_debug(0);
323
0925a9dd 324 if (!(tb = scols_new_table()))
780ce22c 325 err(EXIT_FAILURE, _("failed to allocate output table"));
0925a9dd 326 scols_table_enable_raw(tb, raw);
4827093d 327 scols_table_enable_json(tb, json);
0925a9dd 328 scols_table_enable_noheadings(tb, no_headings);
896352d3 329
4827093d
KZ
330 if (json)
331 scols_table_set_name(tb, "loopdevices");
332
e0b06769 333 for (i = 0; i < ncolumns; i++) {
896352d3 334 struct colinfo *ci = get_column_info(i);
46de0fe6 335 struct libscols_column *cl;
896352d3 336
46de0fe6
KZ
337 cl = scols_table_new_column(tb, ci->name, ci->whint, ci->flags);
338 if (!cl)
780ce22c 339 err(EXIT_FAILURE, _("failed to allocate output column"));
46de0fe6
KZ
340 if (json)
341 scols_column_set_json_type(cl, ci->json_type);
896352d3
OO
342 }
343
9f56106d 344 /* only one loopdev requested (already assigned to loopdev_cxt) */
896352d3 345 if (loopcxt_get_device(lc)) {
48f1f38b 346 ln = scols_table_new_line(tb, NULL);
7e86cd54 347 if (!ln)
780ce22c 348 err(EXIT_FAILURE, _("failed to allocate output line"));
48f1f38b 349 rc = set_scols_data(lc, ln);
896352d3 350
9f56106d 351 /* list all loopdevs */
48f1f38b
KZ
352 } else {
353 char *cn_file = NULL;
896352d3 354
48f1f38b
KZ
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;
6d62bc0f 365
74a4705a 366 used = loopcxt_is_used(lc, st, bf, offset, 0, flags);
48f1f38b
KZ
367 if (!used && !cn_file) {
368 bf = cn_file = canonicalize_path(file);
74a4705a 369 used = loopcxt_is_used(lc, st, bf, offset, 0, flags);
48f1f38b
KZ
370 }
371 if (!used)
372 continue;
6d62bc0f 373 }
48f1f38b
KZ
374
375 ln = scols_table_new_line(tb, NULL);
376 if (!ln)
780ce22c 377 err(EXIT_FAILURE, _("failed to allocate output line"));
48f1f38b
KZ
378 rc = set_scols_data(lc, ln);
379 if (rc)
380 break;
6d62bc0f 381 }
896352d3 382
48f1f38b
KZ
383 loopcxt_deinit_iterator(lc);
384 free(cn_file);
896352d3 385 }
48f1f38b
KZ
386done:
387 if (rc == 0)
388 rc = scols_print_table(tb);
389 scols_unref_table(tb);
390 return rc;
896352d3
OO
391}
392
6e1eda6f 393static void __attribute__((__noreturn__)) usage(void)
aadb9303 394{
6e1eda6f 395 FILE *out = stdout;
e0b06769
SK
396 size_t i;
397
aadb9303
KZ
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
451dbcfa
BS
405 fputs(USAGE_SEPARATOR, out);
406 fputs(_("Set up and control loop devices.\n"), out);
407
ec3624aa 408 /* commands */
aadb9303 409 fputs(USAGE_OPTIONS, out);
9c47f25e 410 fputs(_(" -a, --all list all used devices\n"), out);
aa06617f 411 fputs(_(" -d, --detach <loopdev>... detach one or more devices\n"), out);
9c47f25e
BS
412 fputs(_(" -D, --detach-all detach all used devices\n"), out);
413 fputs(_(" -f, --find find first unused device\n"), out);
aa06617f 414 fputs(_(" -c, --set-capacity <loopdev> resize the device\n"), out);
9c47f25e 415 fputs(_(" -j, --associated <file> list all devices associated with <file>\n"), out);
9a94b634 416 fputs(_(" -L, --nooverlap avoid possible conflict between devices\n"), out);
9c47f25e 417
ec3624aa 418 /* commands options */
aadb9303 419 fputs(USAGE_SEPARATOR, out);
59a4ed11 420 fputs(_(" -o, --offset <num> start at offset <num> into file\n"), out);
aa06617f 421 fputs(_(" --sizelimit <num> device is limited to <num> bytes of the file\n"), out);
ec06412c 422 fputs(_(" -b, --sector-size <num> set the logical sector size to <num>\n"), out);
aa06617f
BS
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);
f98d9641 425 fputs(_(" --direct-io[=<on|off>] open backing file with O_DIRECT\n"), out);
59a4ed11
SK
426 fputs(_(" --show print device name after setup (with -f)\n"), out);
427 fputs(_(" -v, --verbose verbose mode\n"), out);
aadb9303 428
ec3624aa 429 /* output options */
9f56106d 430 fputs(USAGE_SEPARATOR, out);
ec3624aa 431 fputs(_(" -J, --json use JSON --list output format\n"), out);
14576644 432 fputs(_(" -l, --list list info about all or specified (default)\n"), out);
0d0d12ad 433 fputs(_(" -n, --noheadings don't print headings for --list output\n"), out);
ec3624aa 434 fputs(_(" -O, --output <cols> specify columns to output for --list\n"), out);
289673b1 435 fputs(_(" --output-all output all columns\n"), out);
9f56106d
KZ
436 fputs(_(" --raw use raw --list output format\n"), out);
437
aadb9303 438 fputs(USAGE_SEPARATOR, out);
f45f3ec3 439 printf(USAGE_HELP_OPTIONS(31));
aadb9303 440
c3a4cfc5 441 fputs(USAGE_COLUMNS, out);
d78deddc 442 for (i = 0; i < ARRAY_SIZE(infos); i++)
896352d3
OO
443 fprintf(out, " %12s %s\n", infos[i].name, _(infos[i].help));
444
f45f3ec3 445 printf(USAGE_MAN_TAIL("losetup(8)"));
6997468e 446
6e1eda6f 447 exit(EXIT_SUCCESS);
aadb9303 448}
22853e4a 449
6daf185c 450static void warn_size(const char *filename, uint64_t size, uint64_t offset, int flags)
35545456
KZ
451{
452 struct stat st;
453
454 if (!size) {
b048b8af 455 if (stat(filename, &st) || S_ISBLK(st.st_mode))
35545456
KZ
456 return;
457 size = st.st_size;
6daf185c
KZ
458
459 if (flags & LOOPDEV_FL_OFFSET)
460 size -= offset;
35545456
KZ
461 }
462
463 if (size < 512)
97b820bf
BS
464 warnx(_("%s: Warning: file is smaller than 512 bytes; the loop device "
465 "may be useless or invisible for system tools."),
35545456
KZ
466 filename);
467 else if (size % 512)
97b820bf 468 warnx(_("%s: Warning: file does not fit into a 512-byte sector; "
35545456
KZ
469 "the end of the file will be ignored."),
470 filename);
471}
472
9a94b634
KZ
473static int create_loop(struct loopdev_cxt *lc,
474 int nooverlap, int lo_flags, int flags,
422f0e9f
KZ
475 const char *file, uint64_t offset, uint64_t sizelimit,
476 uint64_t blocksize)
9a94b634
KZ
477{
478 int hasdev = loopcxt_has_device(lc);
3ff6fb80 479 int rc = 0, ntries = 0;
9a94b634 480
d8ba61fc 481 /* losetup --find --noverlap file.img */
9a94b634
KZ
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 }
f27d989c 510
d5fd456c 511 lc->config.info.lo_flags &= ~LO_FLAGS_AUTOCLEAR;
9fcc8936 512 if (loopcxt_ioctl_status(lc)) {
f27d989c
SB
513 loopcxt_deinit(lc);
514 errx(EXIT_FAILURE, _("%s: failed to re-use loop device"), file);
515 }
9a94b634
KZ
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
dfa92ef1 525 if (hasdev)
9a94b634
KZ
526 loopcxt_add_device(lc);
527
d8ba61fc
KZ
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
9a94b634
KZ
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);
422f0e9f
KZ
564 if (blocksize > 0)
565 loopcxt_set_blocksize(lc, blocksize);
566
9a94b634
KZ
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 */
3ff6fb80 575
3e03cb68 576 if ((errno == EBUSY || errno == EAGAIN) && !hasdev && ntries < 64) {
3ff6fb80
KZ
577 xusleep(200000);
578 ntries++;
9a94b634 579 continue;
3ff6fb80 580 }
9a94b634
KZ
581
582 /* errors */
583 errpre = hasdev && loopcxt_get_fd(lc) < 0 ?
584 loopcxt_get_device(lc) : file;
585 warn(_("%s: failed to set up loop device"), errpre);
586 break;
587 } while (hasdev == 0);
588
589 return rc;
590}
591
39fde137
KZ
592int main(int argc, char **argv)
593{
594 struct loopdev_cxt lc;
9a94b634 595 int act = 0, flags = 0, no_overlap = 0, c;
5cf05c71 596 char *file = NULL;
a1a41597 597 uint64_t offset = 0, sizelimit = 0, blocksize = 0;
7e86cd54 598 int res = 0, showdev = 0, lo_flags = 0;
896352d3
OO
599 char *outarg = NULL;
600 int list = 0;
a1a41597 601 unsigned long use_dio = 0, set_dio = 0, set_blocksize = 0;
6c7d5ae9 602
aadb9303
KZ
603 enum {
604 OPT_SIZELIMIT = CHAR_MAX + 1,
9f56106d 605 OPT_SHOW,
64c3bb3c 606 OPT_RAW,
289673b1
SK
607 OPT_DIO,
608 OPT_OUTPUT_ALL
aadb9303
KZ
609 };
610 static const struct option longopts[] = {
87918040
SK
611 { "all", no_argument, NULL, 'a' },
612 { "set-capacity", required_argument, NULL, 'c' },
613 { "detach", required_argument, NULL, 'd' },
614 { "detach-all", no_argument, NULL, 'D' },
615 { "find", no_argument, NULL, 'f' },
616 { "nooverlap", no_argument, NULL, 'L' },
617 { "help", no_argument, NULL, 'h' },
618 { "associated", required_argument, NULL, 'j' },
619 { "json", no_argument, NULL, 'J' },
620 { "list", no_argument, NULL, 'l' },
76493ceb 621 { "sector-size", required_argument, NULL, 'b' },
87918040
SK
622 { "noheadings", no_argument, NULL, 'n' },
623 { "offset", required_argument, NULL, 'o' },
624 { "output", required_argument, NULL, 'O' },
289673b1 625 { "output-all", no_argument, NULL, OPT_OUTPUT_ALL },
87918040
SK
626 { "sizelimit", required_argument, NULL, OPT_SIZELIMIT },
627 { "partscan", no_argument, NULL, 'P' },
628 { "read-only", no_argument, NULL, 'r' },
629 { "direct-io", optional_argument, NULL, OPT_DIO },
630 { "raw", no_argument, NULL, OPT_RAW },
631 { "show", no_argument, NULL, OPT_SHOW },
632 { "verbose", no_argument, NULL, 'v' },
633 { "version", no_argument, NULL, 'V' },
634 { NULL, 0, NULL, 0 }
d99f0140 635 };
22853e4a 636
c1ac3144
KZ
637 static const ul_excl_t excl[] = { /* rows and cols in ASCII order */
638 { 'D','a','c','d','f','j' },
896352d3 639 { 'D','c','d','f','l' },
65178cb3 640 { 'D','c','d','f','O' },
4827093d 641 { 'J',OPT_RAW },
c1ac3144
KZ
642 { 0 }
643 };
644 int excl_st[ARRAY_SIZE(excl)] = UL_EXCL_STATUS_INIT;
645
22853e4a
KZ
646 setlocale(LC_ALL, "");
647 bindtextdomain(PACKAGE, LOCALEDIR);
648 textdomain(PACKAGE);
25b7045e 649 close_stdout_atexit();
22853e4a 650
defa0710
KZ
651 if (loopcxt_init(&lc, 0))
652 err(EXIT_FAILURE, _("failed to initialize loopcxt"));
653
a1a41597 654 while ((c = getopt_long(argc, argv, "ab:c:d:Dfhj:JlLno:O:PrvV",
d99f0140 655 longopts, NULL)) != -1) {
c1ac3144
KZ
656
657 err_exclusive_options(c, longopts, excl, excl_st);
658
22853e4a 659 switch (c) {
8b125fae 660 case 'a':
39fde137 661 act = A_SHOW;
8b125fae 662 break;
a1a41597
SB
663 case 'b':
664 set_blocksize = 1;
665 blocksize = strtosize_or_err(optarg, _("failed to parse logical block size"));
666 break;
d34ac93a 667 case 'c':
6e90a44c 668 act = A_SET_CAPACITY;
21ce3f3a
KZ
669 if (!is_loopdev(optarg) ||
670 loopcxt_set_device(&lc, optarg))
defa0710
KZ
671 err(EXIT_FAILURE, _("%s: failed to use device"),
672 optarg);
d34ac93a 673 break;
faf142b6 674 case 'r':
c7e0925d 675 lo_flags |= LO_FLAGS_READ_ONLY;
faf142b6 676 break;
22853e4a 677 case 'd':
c654c4f0 678 act = A_DELETE;
21ce3f3a
KZ
679 if (!is_loopdev(optarg) ||
680 loopcxt_set_device(&lc, optarg))
defa0710
KZ
681 err(EXIT_FAILURE, _("%s: failed to use device"),
682 optarg);
22853e4a 683 break;
34f9b684 684 case 'D':
c654c4f0 685 act = A_DELETE_ALL;
34f9b684 686 break;
d162fcb5 687 case 'f':
bcdbdc72 688 act = A_FIND_FREE;
d162fcb5 689 break;
4827093d
KZ
690 case 'J':
691 json = 1;
692 break;
259fcc57 693 case 'j':
bc0ac075
KZ
694 act = A_SHOW;
695 file = optarg;
259fcc57 696 break;
896352d3
OO
697 case 'l':
698 list = 1;
699 break;
9a94b634
KZ
700 case 'L':
701 no_overlap = 1;
702 break;
9f56106d 703 case 'n':
7e86cd54 704 no_headings = 1;
9f56106d
KZ
705 break;
706 case OPT_RAW:
7e86cd54 707 raw = 1;
9f56106d 708 break;
22853e4a 709 case 'o':
e9e426eb 710 offset = strtosize_or_err(optarg, _("failed to parse offset"));
bc0ac075 711 flags |= LOOPDEV_FL_OFFSET;
22853e4a 712 break;
896352d3
OO
713 case 'O':
714 outarg = optarg;
65178cb3 715 list = 1;
896352d3 716 break;
289673b1
SK
717 case OPT_OUTPUT_ALL:
718 for (ncolumns = 0; ncolumns < ARRAY_SIZE(infos); ncolumns++)
719 columns[ncolumns] = ncolumns;
720 break;
916bf85e
KZ
721 case 'P':
722 lo_flags |= LO_FLAGS_PARTSCAN;
723 break;
aadb9303 724 case OPT_SHOW:
ba3809b0
KZ
725 showdev = 1;
726 break;
64c3bb3c 727 case OPT_DIO:
f98d9641
KZ
728 use_dio = set_dio = 1;
729 if (optarg)
730 use_dio = parse_switch(optarg, _("argument error"), "on", "off", NULL);
d53346ed
AXH
731 if (use_dio)
732 lo_flags |= LO_FLAGS_DIRECT_IO;
64c3bb3c 733 break;
22853e4a 734 case 'v':
22853e4a 735 break;
aadb9303 736 case OPT_SIZELIMIT: /* --sizelimit */
e9e426eb 737 sizelimit = strtosize_or_err(optarg, _("failed to parse size"));
c7e0925d 738 flags |= LOOPDEV_FL_SIZELIMIT;
7bcefc7f 739 break;
2c308875
KZ
740
741 case 'h':
742 usage();
743 case 'V':
744 print_version(EXIT_SUCCESS);
22853e4a 745 default:
677ec86c 746 errtryhelp(EXIT_FAILURE);
22853e4a
KZ
747 }
748 }
d162fcb5 749
bcf445fd
KZ
750 ul_path_init_debug();
751 ul_sysfs_init_debug();
752
896352d3
OO
753 /* default is --list --all */
754 if (argc == 1) {
755 act = A_SHOW;
756 list = 1;
757 }
758
4827093d
KZ
759 if (!act && argc == 2 && (raw || json)) {
760 act = A_SHOW;
761 list = 1;
762 }
763
896352d3
OO
764 /* default --list output columns */
765 if (list && !ncolumns) {
766 columns[ncolumns++] = COL_NAME;
4ad996d7 767 columns[ncolumns++] = COL_SIZELIMIT;
896352d3
OO
768 columns[ncolumns++] = COL_OFFSET;
769 columns[ncolumns++] = COL_AUTOCLR;
770 columns[ncolumns++] = COL_RO;
771 columns[ncolumns++] = COL_BACK_FILE;
faeef4d2 772 columns[ncolumns++] = COL_DIO;
76493ceb 773 columns[ncolumns++] = COL_LOGSEC;
896352d3 774 }
39fde137 775
c7e0925d
KZ
776 if (act == A_FIND_FREE && optind < argc) {
777 /*
778 * losetup -f <backing_file>
779 */
780 act = A_CREATE;
781 file = argv[optind++];
c3f5a0f1
KZ
782
783 if (optind < argc)
784 errx(EXIT_FAILURE, _("unexpected arguments"));
c7e0925d 785 }
896352d3
OO
786
787 if (list && !act && optind == argc)
788 /*
789 * losetup --list defaults to --all
790 */
791 act = A_SHOW;
792
09ec0c0a
KZ
793 if (!act && optind + 1 == argc) {
794 /*
896352d3 795 * losetup [--list] <device>
64c3bb3c 796 * OR
a1a41597 797 * losetup {--direct-io[=off]|--logical-blocksize=size}... <device>
09ec0c0a 798 */
a1a41597 799 if (!(set_dio || set_blocksize))
64c3bb3c 800 act = A_SHOW_ONE;
a1a41597 801 if (set_dio)
64c3bb3c 802 act = A_SET_DIRECT_IO;
a1a41597
SB
803 if (set_blocksize)
804 act = A_SET_BLOCKSIZE;
21ce3f3a
KZ
805 if (!is_loopdev(argv[optind]) ||
806 loopcxt_set_device(&lc, argv[optind]))
defa0710
KZ
807 err(EXIT_FAILURE, _("%s: failed to use device"),
808 argv[optind]);
809 optind++;
09ec0c0a 810 }
c7e0925d
KZ
811 if (!act) {
812 /*
813 * losetup <loopdev> <backing_file>
814 */
815 act = A_CREATE;
816
817 if (optind >= argc)
818 errx(EXIT_FAILURE, _("no loop device specified"));
21ce3f3a 819 /* don't use is_loopdev() here, the device does not have exist yet */
defa0710 820 if (loopcxt_set_device(&lc, argv[optind]))
e9e7698e 821 err(EXIT_FAILURE, _("%s: failed to use device"),
defa0710
KZ
822 argv[optind]);
823 optind++;
c7e0925d
KZ
824
825 if (optind >= argc)
826 errx(EXIT_FAILURE, _("no file specified"));
827 file = argv[optind++];
828 }
829
830 if (act != A_CREATE &&
5cf05c71 831 (sizelimit || lo_flags || showdev))
c7e0925d 832 errx(EXIT_FAILURE,
136b23ef 833 _("the options %s are allowed during loop device setup only"),
014e7eb3 834 "--{sizelimit,partscan,read-only,show}");
c7e0925d 835
934df30d
KZ
836 if ((flags & LOOPDEV_FL_OFFSET) &&
837 act != A_CREATE && (act != A_SHOW || !file))
136b23ef 838 errx(EXIT_FAILURE, _("the option --offset is not allowed in this context"));
c654c4f0 839
896352d3
OO
840 if (outarg && string_add_to_idarray(outarg, columns, ARRAY_SIZE(columns),
841 &ncolumns, column_name_to_id) < 0)
842 return EXIT_FAILURE;
843
39fde137 844 switch (act) {
c7e0925d 845 case A_CREATE:
422f0e9f
KZ
846 res = create_loop(&lc, no_overlap, lo_flags, flags, file,
847 offset, sizelimit, blocksize);
35545456
KZ
848 if (res == 0) {
849 if (showdev)
850 printf("%s\n", loopcxt_get_device(&lc));
6daf185c 851 warn_size(file, sizelimit, offset, flags);
35545456 852 }
c7e0925d 853 break;
c654c4f0
KZ
854 case A_DELETE:
855 res = delete_loop(&lc);
856 while (optind < argc) {
21ce3f3a
KZ
857 if (!is_loopdev(argv[optind]) ||
858 loopcxt_set_device(&lc, argv[optind]))
defa0710
KZ
859 warn(_("%s: failed to use device"),
860 argv[optind]);
861 optind++;
c654c4f0
KZ
862 res += delete_loop(&lc);
863 }
864 break;
865 case A_DELETE_ALL:
866 res = delete_all_loops(&lc);
867 break;
bcdbdc72 868 case A_FIND_FREE:
3e55659f 869 res = loopcxt_find_unused(&lc);
362f5d20
KZ
870 if (res) {
871 int errsv = errno;
872
873 if (access(_PATH_DEV_LOOPCTL, F_OK) == 0 &&
874 access(_PATH_DEV_LOOPCTL, W_OK) != 0)
875 ;
876 else
877 errno = errsv;
878
136b23ef 879 warn(_("cannot find an unused loop device"));
362f5d20 880 } else
bcdbdc72
KZ
881 printf("%s\n", loopcxt_get_device(&lc));
882 break;
39fde137 883 case A_SHOW:
896352d3 884 if (list)
48f1f38b 885 res = show_table(&lc, file, offset, flags);
896352d3
OO
886 else
887 res = show_all_loops(&lc, file, offset, flags);
bc0ac075 888 break;
09ec0c0a 889 case A_SHOW_ONE:
896352d3 890 if (list)
48f1f38b 891 res = show_table(&lc, NULL, 0, 0);
896352d3
OO
892 else
893 res = printf_loopdev(&lc);
09ec0c0a 894 if (res)
136b23ef 895 warn("%s", loopcxt_get_device(&lc));
09ec0c0a 896 break;
6e90a44c 897 case A_SET_CAPACITY:
9fcc8936 898 res = loopcxt_ioctl_capacity(&lc);
293714c0
JM
899 if (res)
900 warn(_("%s: set capacity failed"),
901 loopcxt_get_device(&lc));
6e90a44c 902 break;
64c3bb3c 903 case A_SET_DIRECT_IO:
422f0e9f
KZ
904 res = loopcxt_ioctl_dio(&lc, use_dio);
905 if (res)
906 warn(_("%s: set direct io failed"),
907 loopcxt_get_device(&lc));
908 break;
a1a41597 909 case A_SET_BLOCKSIZE:
422f0e9f
KZ
910 res = loopcxt_ioctl_blocksize(&lc, blocksize);
911 if (res)
912 warn(_("%s: set logical block size failed"),
913 loopcxt_get_device(&lc));
64c3bb3c 914 break;
39fde137 915 default:
6e1eda6f
RM
916 warnx(_("bad usage"));
917 errtryhelp(EXIT_FAILURE);
39fde137
KZ
918 break;
919 }
920
921 loopcxt_deinit(&lc);
c7e0925d 922 return res ? EXIT_FAILURE : EXIT_SUCCESS;
22853e4a
KZ
923}
924