]> git.ipfire.org Git - thirdparty/util-linux.git/blob - sys-utils/losetup.c
losetup: rewrite -a
[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 <stdio.h>
8 #include <string.h>
9 #include <ctype.h>
10 #include <fcntl.h>
11 #include <errno.h>
12 #include <stdlib.h>
13 #include <unistd.h>
14 #include <sys/ioctl.h>
15 #include <sys/stat.h>
16 #include <sys/mman.h>
17 #include <sys/sysmacros.h>
18 #include <inttypes.h>
19 #include <dirent.h>
20 #include <getopt.h>
21 #include <stdarg.h>
22
23 #include "strutils.h"
24 #include "nls.h"
25 #include "pathnames.h"
26 #include "loopdev.h"
27 #include "xalloc.h"
28 #include "canonicalize.h"
29
30 enum {
31 A_CREATE, /* setup a new device */
32 A_DELETE, /* delete one or all devices */
33 A_SHOW, /* list devices */
34 A_FIND_FREE, /* find first unused */
35 A_SET_CAPACITY, /* set device capacity */
36 };
37
38 static int verbose;
39
40 static int is_associated(int dev, struct stat *file, unsigned long long offset, int isoff);
41
42 #define LOOPMAJOR 7
43 #define NLOOPS_DEFAULT 8 /* /dev/loop[0-7] */
44
45 struct looplist {
46 int flag; /* scanning options */
47 FILE *proc; /* /proc/partitions */
48 int ncur; /* current position */
49 int *minors; /* ary of minor numbers (when scan whole /dev) */
50 int nminors; /* number of items in *minors */
51 char name[128]; /* device name */
52 int ct_perm; /* count permission problems */
53 int ct_succ; /* count number of successfully
54 detected devices */
55 };
56
57 #define LLFLG_USEDONLY (1 << 1) /* return used devices only */
58 #define LLFLG_FREEONLY (1 << 2) /* return non-used devices */
59 #define LLFLG_DONE (1 << 3) /* all is done */
60 #define LLFLG_PROCFS (1 << 4) /* try to found used devices in /proc/partitions */
61 #define LLFLG_SUBDIR (1 << 5) /* /dev/loop/N */
62 #define LLFLG_DFLT (1 << 6) /* directly try to check default loops */
63
64 #define SETLOOP_RDONLY (1<<0) /* Open loop read-only */
65 #define SETLOOP_AUTOCLEAR (1<<1) /* Automatically detach loop on close (2.6.25?) */
66
67 static int del_loop (const char *device);
68
69 /* TODO: move to lib/sysfs.c */
70 static char *loopfile_from_sysfs(const char *device)
71 {
72 FILE *f;
73 struct stat st;
74 char buf[PATH_MAX], *res = NULL;
75
76 if (stat(device, &st) || !S_ISBLK(st.st_mode))
77 return NULL;
78
79 snprintf(buf, sizeof(buf), _PATH_SYS_DEVBLOCK "/%d:%d/loop/backing_file",
80 major(st.st_rdev), minor(st.st_rdev));
81
82 f = fopen(buf, "r");
83 if (!f)
84 return NULL;
85
86 if (fgets(buf, sizeof(buf), f)) {
87 size_t sz = strlen(buf);
88 if (sz) {
89 buf[sz - 1] = '\0';
90 res = xstrdup(buf);
91 }
92 }
93
94 fclose(f);
95 return res;
96 }
97
98 char *loopdev_get_loopfile(const char *device)
99 {
100 char *res = loopfile_from_sysfs(device);
101
102 if (!res) {
103 struct loop_info64 lo64;
104 int fd;
105
106 if ((fd = open(device, O_RDONLY)) < 0)
107 return NULL;
108
109 if (ioctl(fd, LOOP_GET_STATUS64, &lo64) == 0) {
110 lo64.lo_file_name[LO_NAME_SIZE-2] = '*';
111 lo64.lo_file_name[LO_NAME_SIZE-1] = 0;
112 res = xstrdup((char *) lo64.lo_file_name);
113
114 }
115 close(fd);
116 }
117 return res;
118 }
119
120 int
121 is_loop_device (const char *device) {
122 struct stat st;
123
124 return (stat(device, &st) == 0 &&
125 S_ISBLK(st.st_mode) &&
126 major(st.st_rdev) == LOOPMAJOR);
127 }
128
129 static int
130 is_loop_used(int fd)
131 {
132 struct loop_info64 li;
133
134 errno = 0;
135 if (ioctl (fd, LOOP_GET_STATUS64, &li) < 0 && errno == ENXIO)
136 return 0;
137 return 1;
138 }
139
140 static int
141 is_loopfd_autoclear(int fd)
142 {
143 struct loop_info64 lo64;
144
145 if (ioctl(fd, LOOP_GET_STATUS64, &lo64) == 0) {
146 if (lo64.lo_flags & LO_FLAGS_AUTOCLEAR)
147 return 1;
148
149 }
150 return 0;
151 }
152
153 int
154 is_loop_autoclear(const char *device)
155 {
156 int fd, rc;
157
158 if ((fd = open(device, O_RDONLY)) < 0)
159 return 0;
160 rc = is_loopfd_autoclear(fd);
161
162 close(fd);
163 return rc;
164 }
165
166 static int
167 looplist_open(struct looplist *ll, int flag)
168 {
169 struct stat st;
170
171 memset(ll, 0, sizeof(*ll));
172 ll->flag = flag;
173 ll->ncur = -1;
174
175 if (stat(_PATH_DEV, &st) == -1 || (!S_ISDIR(st.st_mode)))
176 return -1; /* /dev doesn't exist */
177
178 if (stat(_PATH_DEV_LOOP, &st) == 0 && S_ISDIR(st.st_mode))
179 ll->flag |= LLFLG_SUBDIR; /* /dev/loop/ exists */
180
181 if ((ll->flag & LLFLG_USEDONLY) &&
182 stat(_PATH_PROC_PARTITIONS, &st) == 0)
183 ll->flag |= LLFLG_PROCFS; /* try /proc/partitions */
184
185 ll->flag |= LLFLG_DFLT; /* required! */
186 return 0;
187 }
188
189 static void
190 looplist_close(struct looplist *ll)
191 {
192 free(ll->minors);
193 if (ll->proc)
194 fclose(ll->proc);
195 ll->minors = NULL;
196 ll->proc = NULL;
197 ll->ncur = -1;
198 ll->flag |= LLFLG_DONE;
199 }
200
201 static int
202 looplist_open_dev(struct looplist *ll, int lnum)
203 {
204 struct stat st;
205 int used;
206 int fd;
207
208 /* create a full device path */
209 snprintf(ll->name, sizeof(ll->name),
210 ll->flag & LLFLG_SUBDIR ?
211 _PATH_DEV_LOOP "/%d" :
212 _PATH_DEV "loop%d",
213 lnum);
214
215 fd = open(ll->name, O_RDONLY);
216 if (fd == -1) {
217 if (errno == EACCES)
218 ll->ct_perm++;
219 return -1;
220 }
221 if (fstat(fd, &st) == -1)
222 goto error;
223 if (!S_ISBLK(st.st_mode) || major(st.st_rdev) != LOOPMAJOR)
224 goto error;
225
226 ll->ct_succ++;
227
228 /* check if the device is wanted */
229 if (!(ll->flag & (LLFLG_USEDONLY | LLFLG_FREEONLY)))
230 return fd;
231
232 used = is_loop_used(fd);
233
234 if ((ll->flag & LLFLG_USEDONLY) && used)
235 return fd;
236 if ((ll->flag & LLFLG_FREEONLY) && !used)
237 return fd;
238 error:
239 close(fd);
240 return -1;
241 }
242
243 /* returns <N> from "loop<N>" */
244 static int
245 name2minor(int hasprefix, const char *name)
246 {
247 int n;
248 char *end;
249
250 if (hasprefix) {
251 if (strncmp(name, "loop", 4))
252 return -1;
253 name += 4;
254 }
255 n = strtol(name, &end, 10);
256 if (end && end != name && *end == '\0' && n >= 0)
257 return n;
258 return -1;
259 }
260
261 static int
262 cmpnum(const void *p1, const void *p2)
263 {
264 return (*(int *) p1 > *(int *) p2) - (*(int *) p1 < *(int *) p2);
265 }
266
267 /*
268 * The classic scandir() is more expensive and less portable.
269 * We needn't full loop device names -- minor numbers (loop<N>)
270 * are enough.
271 */
272 static int
273 loop_scandir(const char *dirname, int **ary, int hasprefix)
274 {
275 DIR *dir;
276 struct dirent *d;
277 int n, count = 0, arylen = 0;
278
279 if (!dirname || !ary)
280 return -1;
281 dir = opendir(dirname);
282 if (!dir)
283 return -1;
284
285 *ary = NULL;
286
287 while((d = readdir(dir))) {
288 if (d->d_type != DT_BLK && d->d_type != DT_UNKNOWN && d->d_type != DT_LNK)
289 continue;
290 n = name2minor(hasprefix, d->d_name);
291 if (n == -1 || n < NLOOPS_DEFAULT)
292 continue;
293 if (count + 1 > arylen) {
294 int *tmp;
295
296 arylen += 1;
297
298 tmp = realloc(*ary, arylen * sizeof(int));
299 if (!tmp) {
300 free(*ary);
301 return -1;
302 }
303 *ary = tmp;
304 }
305 (*ary)[count++] = n;
306 }
307 if (count)
308 qsort(*ary, count, sizeof(int), cmpnum);
309
310 closedir(dir);
311 return count;
312 }
313
314 static int
315 looplist_next(struct looplist *ll)
316 {
317 int fd, n;
318
319 if (ll->flag & LLFLG_DONE)
320 return -1;
321
322 /* A) Look for used loop devices in /proc/partitions ("losetup -a" only)
323 */
324 if (ll->flag & LLFLG_PROCFS) {
325 char buf[BUFSIZ];
326
327 if (!ll->proc)
328 ll->proc = fopen(_PATH_PROC_PARTITIONS, "r");
329
330 while (ll->proc && fgets(buf, sizeof(buf), ll->proc)) {
331 int m;
332 unsigned long long sz;
333 char name[128];
334
335 if (sscanf(buf, " %d %d %llu %128[^\n ]",
336 &m, &n, &sz, name) != 4)
337 continue;
338 if (m != LOOPMAJOR)
339 continue;
340 /* unfortunately, real minor numbers needn't to match
341 * loop<N> device name. We have to follow device name.
342 */
343 n = name2minor(1, name);
344 fd = looplist_open_dev(ll, n);
345 if (fd != -1)
346 return fd;
347 }
348 goto done;
349 }
350
351
352 /* B) Classic way, try first eight loop devices (default number
353 * of loop devices). This is enough for 99% of all cases.
354 */
355 if (ll->flag & LLFLG_DFLT) {
356 for (++ll->ncur; ll->ncur < NLOOPS_DEFAULT; ll->ncur++) {
357 fd = looplist_open_dev(ll, ll->ncur);
358 if (fd != -1)
359 return fd;
360 }
361 ll->flag &= ~LLFLG_DFLT;
362 }
363
364 /* C) the worst possibility, scan all /dev or /dev/loop
365 */
366 if (!ll->minors) {
367 ll->nminors = (ll->flag & LLFLG_SUBDIR) ?
368 loop_scandir(_PATH_DEV_LOOP, &ll->minors, 0) :
369 loop_scandir(_PATH_DEV, &ll->minors, 1);
370 ll->ncur = -1;
371 }
372 for (++ll->ncur; ll->ncur < ll->nminors; ll->ncur++) {
373 fd = looplist_open_dev(ll, ll->minors[ll->ncur]);
374 if (fd != -1)
375 return fd;
376 }
377
378 done:
379 looplist_close(ll);
380 return -1;
381 }
382
383 /* Find loop device associated with given @filename. Used for unmounting loop
384 * device specified by associated backing file.
385 *
386 * returns: 1 no such device/error
387 * 2 more than one loop device associated with @filename
388 * 0 exactly one loop device associated with @filename
389 * (@loopdev points to string containing full device name)
390 */
391 int
392 find_loopdev_by_backing_file(const char *filename, char **loopdev)
393 {
394 struct looplist ll;
395 struct stat filestat;
396 int fd;
397 int devs_n = 0; /* number of loop devices found */
398 char* devname = NULL;
399
400 if (stat(filename, &filestat) == -1) {
401 perror(filename);
402 return 1;
403 }
404
405 if (looplist_open(&ll, LLFLG_USEDONLY) == -1) {
406 warnx(_("/dev directory does not exist."));
407 return 1;
408 }
409
410 while((devs_n < 2) && (fd = looplist_next(&ll)) != -1) {
411 if (is_associated(fd, &filestat, 0, 0) == 1) {
412 if (!devname)
413 devname = xstrdup(ll.name);
414 devs_n++;
415 }
416 close(fd);
417 }
418 looplist_close(&ll);
419
420 if (devs_n == 1) {
421 *loopdev = devname;
422 return 0; /* exactly one loopdev */
423 }
424 free(devname);
425 return devs_n ? 2 : 1; /* more loopdevs or error */
426 }
427
428 static int
429 set_capacity(const char *device)
430 {
431 int errsv;
432 int fd = open(device, O_RDONLY);
433
434 if (fd == -1)
435 goto err;
436
437 if (ioctl(fd, LOOP_SET_CAPACITY) != 0)
438 goto err;
439
440 return 0;
441 err:
442 errsv = errno;
443 fprintf(stderr, _("loop: can't set capacity on device %s: %s\n"),
444 device, strerror (errsv));
445 if (fd != -1)
446 close(fd);
447 return 2;
448 }
449
450 static int
451 show_loop_fd(int fd, char *device) {
452 struct loop_info64 loopinfo64;
453 int errsv;
454
455 if (ioctl(fd, LOOP_GET_STATUS64, &loopinfo64) == 0) {
456
457 char *lofile = NULL;
458
459 loopinfo64.lo_file_name[LO_NAME_SIZE-2] = '*';
460 loopinfo64.lo_file_name[LO_NAME_SIZE-1] = 0;
461 loopinfo64.lo_crypt_name[LO_NAME_SIZE-1] = 0;
462
463 /* ioctl has limited buffer for backing file name, since
464 * kernel 2.6.37 the filename is available in sysfs too
465 */
466 if (strlen((char *) loopinfo64.lo_file_name) == LO_NAME_SIZE - 1)
467 lofile = loopfile_from_sysfs(device);
468 if (!lofile)
469 lofile = (char *) loopinfo64.lo_file_name;
470
471 printf("%s: [%04" PRIx64 "]:%" PRIu64 " (%s)",
472 device, loopinfo64.lo_device, loopinfo64.lo_inode,
473 lofile);
474
475 if (lofile != (char *) loopinfo64.lo_file_name)
476 free(lofile);
477
478 if (loopinfo64.lo_offset)
479 printf(_(", offset %" PRIu64 ), loopinfo64.lo_offset);
480
481 if (loopinfo64.lo_sizelimit)
482 printf(_(", sizelimit %" PRIu64 ), loopinfo64.lo_sizelimit);
483
484 if (loopinfo64.lo_encrypt_type ||
485 loopinfo64.lo_crypt_name[0]) {
486 char *e = (char *)loopinfo64.lo_crypt_name;
487
488 if (*e == 0 && loopinfo64.lo_encrypt_type == 1)
489 e = "XOR";
490 printf(_(", encryption %s (type %" PRIu32 ")"),
491 e, loopinfo64.lo_encrypt_type);
492 }
493 printf("\n");
494 return 0;
495 }
496
497 errsv = errno;
498 fprintf(stderr, _("loop: can't get info on device %s: %s\n"),
499 device, strerror (errsv));
500 return 1;
501 }
502
503 static int
504 show_loop(char *device) {
505 int ret, fd;
506
507 if ((fd = open(device, O_RDONLY)) < 0) {
508 int errsv = errno;
509 fprintf(stderr, _("loop: can't open device %s: %s\n"),
510 device, strerror (errsv));
511 return 2;
512 }
513 ret = show_loop_fd(fd, device);
514 close(fd);
515 return ret;
516 }
517
518
519 static int
520 show_used_loop_devices (void) {
521 struct looplist ll;
522 int fd;
523
524 if (looplist_open(&ll, LLFLG_USEDONLY) == -1) {
525 warnx(_("/dev directory does not exist."));
526 return 1;
527 }
528
529 while((fd = looplist_next(&ll)) != -1) {
530 show_loop_fd(fd, ll.name);
531 close(fd);
532 }
533 looplist_close(&ll);
534
535 if (!ll.ct_succ && ll.ct_perm) {
536 warnx(_("no permission to look at /dev/loop%s<N>"),
537 (ll.flag & LLFLG_SUBDIR) ? "/" : "");
538 return 1;
539 }
540 return 0;
541 }
542
543 /* list all associated loop devices */
544 static int
545 show_associated_loop_devices(char *filename, unsigned long long offset, int isoff)
546 {
547 struct looplist ll;
548 struct stat filestat;
549 int fd;
550
551 if (stat(filename, &filestat) == -1) {
552 perror(filename);
553 return 1;
554 }
555
556 if (looplist_open(&ll, LLFLG_USEDONLY) == -1) {
557 warnx(_("/dev directory does not exist."));
558 return 1;
559 }
560
561 while((fd = looplist_next(&ll)) != -1) {
562 if (is_associated(fd, &filestat, offset, isoff) == 1)
563 show_loop_fd(fd, ll.name);
564 close(fd);
565 }
566 looplist_close(&ll);
567
568 return 0;
569 }
570
571 /* check if the loopfile is already associated with the same given
572 * parameters.
573 *
574 * returns: 0 unused / error
575 * 1 loop device already used
576 */
577 static int
578 is_associated(int dev, struct stat *file, unsigned long long offset, int isoff)
579 {
580 struct loop_info64 linfo64;
581 int ret = 0;
582
583 if (ioctl(dev, LOOP_GET_STATUS64, &linfo64) == 0) {
584 if (file->st_dev == linfo64.lo_device &&
585 file->st_ino == linfo64.lo_inode &&
586 (isoff == 0 || offset == linfo64.lo_offset))
587 ret = 1;
588
589 }
590
591 return ret;
592 }
593
594 /* check if the loop file is already used with the same given
595 * parameters. We check for device no, inode and offset.
596 * returns: associated devname or NULL
597 */
598 char *
599 loopfile_used (const char *filename, unsigned long long offset) {
600 struct looplist ll;
601 char *devname = NULL;
602 struct stat filestat;
603 int fd;
604
605 if (stat(filename, &filestat) == -1) {
606 perror(filename);
607 return NULL;
608 }
609
610 if (looplist_open(&ll, LLFLG_USEDONLY) == -1) {
611 warnx(_("/dev directory does not exist."));
612 return NULL;
613 }
614
615 while((fd = looplist_next(&ll)) != -1) {
616 int res = is_associated(fd, &filestat, offset, 1);
617 close(fd);
618 if (res == 1) {
619 devname = xstrdup(ll.name);
620 break;
621 }
622 }
623 looplist_close(&ll);
624
625 return devname;
626 }
627
628 int
629 loopfile_used_with(char *devname, const char *filename, unsigned long long offset)
630 {
631 struct stat statbuf;
632 int fd, ret;
633
634 if (!is_loop_device(devname))
635 return 0;
636
637 if (stat(filename, &statbuf) == -1)
638 return 0;
639
640 fd = open(devname, O_RDONLY);
641 if (fd == -1)
642 return 0;
643
644 ret = is_associated(fd, &statbuf, offset, 1);
645 close(fd);
646 return ret;
647 }
648
649 char *
650 find_unused_loop_device (void) {
651 struct looplist ll;
652 char *devname = NULL;
653 int fd;
654
655 if (looplist_open(&ll, LLFLG_FREEONLY) == -1) {
656 warnx(_("/dev directory does not exist."));
657 return NULL;
658 }
659
660 if ((fd = looplist_next(&ll)) != -1) {
661 close(fd);
662 devname = xstrdup(ll.name);
663 }
664 looplist_close(&ll);
665 if (devname)
666 return devname;
667
668 if (!ll.ct_succ && ll.ct_perm)
669 warnx(_("no permission to look at /dev/loop%s<N>"),
670 (ll.flag & LLFLG_SUBDIR) ? "/" : "");
671 else if (ll.ct_succ)
672 warnx(_("could not find any free loop device"));
673 else
674 warnx(_(
675 "Could not find any loop device. Maybe this kernel "
676 "does not know\n"
677 " about the loop device? (If so, recompile or "
678 "`modprobe loop'.)"));
679 return NULL;
680 }
681
682 /*
683 * A function to read the passphrase either from the terminal or from
684 * an open file descriptor.
685 */
686 static char *
687 xgetpass(int pfd, const char *prompt) {
688 char *pass;
689 int buflen, i;
690
691 if (pfd < 0) /* terminal */
692 return getpass(prompt);
693
694 pass = NULL;
695 buflen = 0;
696 for (i=0; ; i++) {
697 if (i >= buflen-1) {
698 /* we're running out of space in the buffer.
699 * Make it bigger: */
700 char *tmppass = pass;
701 buflen += 128;
702 pass = realloc(tmppass, buflen);
703 if (pass == NULL) {
704 /* realloc failed. Stop reading. */
705 warn(_("Out of memory while reading passphrase"));
706 pass = tmppass; /* the old buffer hasn't changed */
707 break;
708 }
709 }
710 if (read(pfd, pass+i, 1) != 1 ||
711 pass[i] == '\n' || pass[i] == 0)
712 break;
713 }
714
715 if (pass == NULL)
716 return "";
717
718 pass[i] = 0;
719 return pass;
720 }
721
722 static int
723 digits_only(const char *s) {
724 while (*s)
725 if (!isdigit(*s++))
726 return 0;
727 return 1;
728 }
729
730 /*
731 * return codes:
732 * 0 - success
733 * 1 - error
734 * 2 - error (EBUSY)
735 */
736 int
737 set_loop(const char *device, const char *file, unsigned long long offset,
738 unsigned long long sizelimit, const char *encryption, int pfd, int *options) {
739 struct loop_info64 loopinfo64;
740 int fd, ffd, mode, i;
741 char *pass;
742 char *filename;
743
744 if (verbose) {
745 char *xdev = loopfile_used(file, offset);
746
747 if (xdev) {
748 printf(_("warning: %s is already associated with %s\n"),
749 file, xdev);
750 free(xdev);
751 }
752 }
753
754 mode = (*options & SETLOOP_RDONLY) ? O_RDONLY : O_RDWR;
755 if ((ffd = open(file, mode)) < 0) {
756 if (!(*options & SETLOOP_RDONLY) &&
757 (errno == EROFS || errno == EACCES))
758 ffd = open(file, mode = O_RDONLY);
759 if (ffd < 0) {
760 perror(file);
761 return 1;
762 }
763 if (verbose)
764 printf(_("warning: %s: is write-protected, using read-only.\n"),
765 file);
766 *options |= SETLOOP_RDONLY;
767 }
768 if ((fd = open(device, mode)) < 0) {
769 perror (device);
770 close(ffd);
771 return 1;
772 }
773 memset(&loopinfo64, 0, sizeof(loopinfo64));
774
775 if (!(filename = canonicalize_path(file)))
776 filename = (char *) file;
777 xstrncpy((char *)loopinfo64.lo_file_name, filename, LO_NAME_SIZE);
778
779 if (encryption && *encryption) {
780 if (digits_only(encryption)) {
781 loopinfo64.lo_encrypt_type = atoi(encryption);
782 } else {
783 loopinfo64.lo_encrypt_type = LO_CRYPT_CRYPTOAPI;
784 snprintf((char *)loopinfo64.lo_crypt_name, LO_NAME_SIZE,
785 "%s", encryption);
786 }
787 }
788
789 loopinfo64.lo_offset = offset;
790 loopinfo64.lo_sizelimit = sizelimit;
791
792 #ifdef MCL_FUTURE
793 /*
794 * Oh-oh, sensitive data coming up. Better lock into memory to prevent
795 * passwd etc being swapped out and left somewhere on disk.
796 */
797 if (loopinfo64.lo_encrypt_type != LO_CRYPT_NONE) {
798 if(mlockall(MCL_CURRENT | MCL_FUTURE)) {
799 perror("memlock");
800 fprintf(stderr, _("Couldn't lock into memory, exiting.\n"));
801 exit(1);
802 }
803 }
804 #endif
805
806 switch (loopinfo64.lo_encrypt_type) {
807 case LO_CRYPT_NONE:
808 loopinfo64.lo_encrypt_key_size = 0;
809 break;
810 case LO_CRYPT_XOR:
811 pass = getpass(_("Password: "));
812 goto gotpass;
813 default:
814 pass = xgetpass(pfd, _("Password: "));
815 gotpass:
816 memset(loopinfo64.lo_encrypt_key, 0, LO_KEY_SIZE);
817 xstrncpy((char *)loopinfo64.lo_encrypt_key, pass, LO_KEY_SIZE);
818 memset(pass, 0, strlen(pass));
819 loopinfo64.lo_encrypt_key_size = LO_KEY_SIZE;
820 }
821
822 if (ioctl(fd, LOOP_SET_FD, ffd) < 0) {
823 int rc = 1;
824
825 if (errno == EBUSY) {
826 if (verbose)
827 printf(_("ioctl LOOP_SET_FD failed: %m\n"));
828 rc = 2;
829 } else
830 perror("ioctl: LOOP_SET_FD");
831
832 close(fd);
833 close(ffd);
834 if (file != filename)
835 free(filename);
836 return rc;
837 }
838 close (ffd);
839
840 if (*options & SETLOOP_AUTOCLEAR)
841 loopinfo64.lo_flags = LO_FLAGS_AUTOCLEAR;
842
843 i = ioctl(fd, LOOP_SET_STATUS64, &loopinfo64);
844 if (i)
845 perror("ioctl: LOOP_SET_STATUS64");
846
847 if ((*options & SETLOOP_AUTOCLEAR) && !is_loopfd_autoclear(fd))
848 /* kernel doesn't support loop auto-destruction */
849 *options &= ~SETLOOP_AUTOCLEAR;
850
851 memset(&loopinfo64, 0, sizeof(loopinfo64));
852
853 if (i) {
854 ioctl (fd, LOOP_CLR_FD, 0);
855 close (fd);
856 if (file != filename)
857 free(filename);
858 return 1;
859 }
860
861 /*
862 * HACK: here we're leaking a file descriptor,
863 * but mount is a short-lived process anyway.
864 */
865 if (!(*options & SETLOOP_AUTOCLEAR))
866 close (fd);
867
868 if (verbose)
869 printf(_("set_loop(%s,%s,%llu,%llu): success\n"),
870 device, filename, offset, sizelimit);
871 if (file != filename)
872 free(filename);
873 return 0;
874 }
875
876 static int
877 delete_all_devices (void)
878 {
879 struct looplist ll;
880 int fd;
881 int ok = 0;
882
883 if (looplist_open(&ll, LLFLG_USEDONLY) == -1) {
884 warnx(_("/dev directory does not exist."));
885 return 1;
886 }
887
888 while((fd = looplist_next(&ll)) != -1) {
889 close(fd);
890 ok |= del_loop(ll.name);
891 }
892 looplist_close(&ll);
893
894 if (!ll.ct_succ && ll.ct_perm) {
895 warnx(_("no permission to look at /dev/loop%s<N>"),
896 (ll.flag & LLFLG_SUBDIR) ? "/" : "");
897 return 1;
898 }
899 return ok;
900 }
901
902 static int
903 del_loop (const char *device) {
904 int fd, errsv;
905
906 if ((fd = open (device, O_RDONLY)) < 0) {
907 errsv = errno;
908 goto error;
909 }
910 if (ioctl (fd, LOOP_CLR_FD, 0) < 0) {
911 errsv = errno;
912 goto error;
913 }
914 close (fd);
915 if (verbose)
916 printf(_("del_loop(%s): success\n"), device);
917 return 0;
918
919 error:
920 fprintf(stderr, _("loop: can't delete device %s: %s\n"),
921 device, strerror(errsv));
922 if (fd >= 0)
923 close(fd);
924 return 1;
925 }
926
927
928 static int printf_loopdev(struct loopdev_cxt *lc)
929 {
930 uint64_t x;
931 dev_t dev = 0;
932 ino_t ino = 0;
933 char *fname = NULL;
934 int type;
935
936 fname = loopcxt_get_backing_file(lc);
937 if (!fname)
938 return -EINVAL;
939
940 if (loopcxt_get_backing_devno(lc, &dev) == 0)
941 loopcxt_get_backing_inode(lc, &ino);
942
943 if (!dev && !ino) {
944 /*
945 * Probably non-root user (no permissions to
946 * call LOOP_GET_STATUS ioctls).
947 */
948 printf("%s: []: (%s)",
949 loopcxt_get_device(lc), fname);
950
951 if (loopcxt_get_offset(lc, &x) == 0 && x)
952 printf(_(", offset %ju"), x);
953
954 if (loopcxt_get_sizelimit(lc, &x) == 0 && x)
955 printf(_(", sizelimit %ju"), x);
956 printf("\n");
957 return 0;
958 }
959
960 printf("%s: [%04d]:%" PRIu64 " (%s)",
961 loopcxt_get_device(lc), dev, ino, fname);
962
963 if (loopcxt_get_offset(lc, &x) == 0 && x)
964 printf(_(", offset %ju"), x);
965
966 if (loopcxt_get_sizelimit(lc, &x) == 0 && x)
967 printf(_(", sizelimit %ju"), x);
968
969 if (loopcxt_get_encrypt_type(lc, &type) == 0) {
970 const char *e = loopcxt_get_crypt_name(lc);
971
972 if ((!e || !*e) && type == 1)
973 e = "XOR";
974 if (e && *e)
975 printf(_(", encryption %s (type %ju)"), e, type);
976 }
977 printf("\n");
978 return 0;
979 }
980
981 static int show_all_loops(struct loopdev_cxt *lc)
982 {
983 if (loopcxt_init_iterator(lc, LOOPITER_FL_USED))
984 return EXIT_FAILURE;
985
986 while (loopcxt_next(lc) == 0)
987 printf_loopdev(lc);
988
989 return EXIT_SUCCESS;
990 }
991
992 static void
993 usage(FILE *out) {
994
995 fputs(_("\nUsage:\n"), out);
996 fprintf(out,
997 _(" %1$s loop_device give info\n"
998 " %1$s -a | --all list all used\n"
999 " %1$s -d | --detach <loopdev> [<loopdev> ...] delete\n"
1000 " %1$s -D | --detach-all delete all used\n"
1001 " %1$s -f | --find find unused\n"
1002 " %1$s -c | --set-capacity <loopdev> resize\n"
1003 " %1$s -j | --associated <file> [-o <num>] list all associated with <file>\n"
1004 " %1$s [options] {-f|--find|loopdev} <file> setup\n"),
1005 program_invocation_short_name);
1006
1007 fputs(_("\nOptions:\n"), out);
1008 fputs(_(" -e, --encryption <type> enable data encryption with specified <name/num>\n"
1009 " -h, --help this help\n"
1010 " -o, --offset <num> start at offset <num> into file\n"
1011 " --sizelimit <num> loop limited to only <num> bytes of the file\n"
1012 " -p, --pass-fd <num> read passphrase from file descriptor <num>\n"
1013 " -r, --read-only setup read-only loop device\n"
1014 " --show print device name (with -f <file>)\n"
1015 " -v, --verbose verbose mode\n\n"), out);
1016
1017 exit(out == stderr ? EXIT_FAILURE : EXIT_SUCCESS);
1018 }
1019
1020 int main(int argc, char **argv)
1021 {
1022 struct loopdev_cxt lc;
1023 int act = 0;
1024
1025 char *p, *offset, *sizelimit, *encryption, *passfd, *device, *file, *assoc;
1026 int delete, delete_all, find, c, capacity;
1027 int res = 0;
1028 int showdev = 0;
1029 int ro = 0;
1030 int pfd = -1;
1031 uintmax_t off = 0, slimit = 0;
1032
1033 loopcxt_init(&lc, 0);
1034 /*loopcxt_enable_debug(&lc, TRUE);*/
1035
1036 static const struct option longopts[] = {
1037 { "all", 0, 0, 'a' },
1038 { "set-capacity", 0, 0, 'c' },
1039 { "detach", 0, 0, 'd' },
1040 { "detach-all", 0, 0, 'D' },
1041 { "encryption", 1, 0, 'e' },
1042 { "find", 0, 0, 'f' },
1043 { "help", 0, 0, 'h' },
1044 { "associated", 1, 0, 'j' },
1045 { "offset", 1, 0, 'o' },
1046 { "sizelimit", 1, 0, 128 },
1047 { "pass-fd", 1, 0, 'p' },
1048 { "read-only", 0, 0, 'r' },
1049 { "show", 0, 0, 's' },
1050 { "verbose", 0, 0, 'v' },
1051 { NULL, 0, 0, 0 }
1052 };
1053
1054 setlocale(LC_ALL, "");
1055 bindtextdomain(PACKAGE, LOCALEDIR);
1056 textdomain(PACKAGE);
1057
1058 capacity = delete = delete_all = find = 0;
1059 assoc = offset = sizelimit = encryption = passfd = NULL;
1060
1061 while ((c = getopt_long(argc, argv, "acdDe:E:fhj:o:p:rsv",
1062 longopts, NULL)) != -1) {
1063
1064 if (act && strchr("acdDf", c))
1065 errx(EXIT_FAILURE,
1066 _("the options %s are mutually exclusive"),
1067 "--{all,set-capacity,detach,detach-all,find}");
1068
1069 switch (c) {
1070 case 'a':
1071 act = A_SHOW;
1072 break;
1073 case 'c':
1074 capacity = 1;
1075 break;
1076 case 'r':
1077 ro = 1;
1078 break;
1079 case 'd':
1080 delete = 1;
1081 break;
1082 case 'D':
1083 delete_all = 1;
1084 break;
1085 case 'E':
1086 case 'e':
1087 encryption = optarg;
1088 break;
1089 case 'f':
1090 find = 1;
1091 break;
1092 case 'h':
1093 usage(stdout);
1094 break;
1095 case 'j':
1096 assoc = optarg;
1097 break;
1098 case 'o':
1099 offset = optarg;
1100 break;
1101 case 'p':
1102 passfd = optarg;
1103 break;
1104 case 's':
1105 showdev = 1;
1106 break;
1107 case 'v':
1108 verbose = 1;
1109 break;
1110
1111 case 128: /* --sizelimit */
1112 sizelimit = optarg;
1113 break;
1114
1115 default:
1116 usage(stderr);
1117 }
1118 }
1119
1120 if (argc == 1)
1121 usage(stderr);
1122
1123 switch (act) {
1124 case A_SHOW:
1125 /* only -v is allowed */
1126 if ((argc == 3 && verbose == 0) || argc > 3)
1127 usage(stderr);
1128
1129 res = show_all_loops(&lc);
1130 default:
1131 break;
1132 }
1133
1134 loopcxt_deinit(&lc);
1135
1136 if (act)
1137 return res;
1138
1139 if (delete) {
1140 if (argc < optind+1 || encryption || offset || sizelimit ||
1141 capacity || find || showdev || assoc || ro)
1142 usage(stderr);
1143 } else if (delete_all) {
1144 if (argc > optind || encryption || offset || sizelimit ||
1145 capacity || find || showdev || assoc || ro)
1146 usage(stderr);
1147 } else if (find) {
1148 if (capacity || assoc || argc < optind || argc > optind+1)
1149 usage(stderr);
1150 } else if (delete_all) {
1151 } else if (assoc) {
1152 if (capacity || encryption || showdev || passfd || ro)
1153 usage(stderr);
1154 } else if (capacity) {
1155 if (argc != optind + 1 || encryption || offset || sizelimit ||
1156 showdev || ro)
1157 usage(stderr);
1158 } else {
1159 if (argc < optind+1 || argc > optind+2)
1160 usage(stderr);
1161 }
1162
1163 if (offset && strtosize(offset, &off)) {
1164 warnx(_("invalid offset '%s' specified"), offset);
1165 usage(stderr);
1166 }
1167 if (sizelimit && strtosize(sizelimit, &slimit)) {
1168 warnx(_("invalid sizelimit '%s' specified"), sizelimit);
1169 usage(stderr);
1170 }
1171
1172 if (delete_all)
1173 return delete_all_devices();
1174 else if (assoc)
1175 return show_associated_loop_devices(assoc, off, offset ? 1 : 0);
1176 else if (find) {
1177 device = find_unused_loop_device();
1178 if (device == NULL)
1179 return -1;
1180 if (argc == optind) {
1181 if (verbose)
1182 printf(_("Loop device is %s\n"), device);
1183 printf("%s\n", device);
1184 return 0;
1185 }
1186 file = argv[optind];
1187 } else if (!delete) {
1188 device = argv[optind];
1189 if (argc == optind+1)
1190 file = NULL;
1191 else
1192 file = argv[optind+1];
1193 }
1194
1195 if (delete) {
1196 while (optind < argc)
1197 res += del_loop(argv[optind++]);
1198 } else if (capacity) {
1199 res = set_capacity(device);
1200 } else if (file == NULL)
1201 res = show_loop(device);
1202 else {
1203 if (passfd && sscanf(passfd, "%d", &pfd) != 1)
1204 usage(stderr);
1205 do {
1206 res = set_loop(device, file, off, slimit, encryption, pfd, &ro);
1207 if (res == 2 && find) {
1208 if (verbose)
1209 printf(_("stolen loop=%s...trying again\n"),
1210 device);
1211 free(device);
1212 if (!(device = find_unused_loop_device()))
1213 return -1;
1214 }
1215 } while (find && res == 2);
1216
1217 if (device) {
1218 if (res == 2)
1219 warnx(_("%s: device is busy"), device);
1220 else if (res == 0) {
1221 if (verbose)
1222 printf(_("Loop device is %s\n"), device);
1223 if (showdev && find)
1224 printf("%s\n", device);
1225 }
1226 }
1227 }
1228 return res;
1229 }
1230