]> git.ipfire.org Git - thirdparty/util-linux.git/blame - lib/loopdev.c
lib/sysfs: fix possible fd leak on error
[thirdparty/util-linux.git] / lib / loopdev.c
CommitLineData
10ee5932
KZ
1/*
2 * Copyright (C) 2011 Karel Zak <kzak@redhat.com>
3 *
4 * -- based on mount/losetup.c
5 *
6 * Simple library for work with loop devices.
7 *
8 * - requires kernel 2.6.x
9 * - reads info from /sys/block/loop<N>/loop/<attr> (new kernels)
10 * - reads info by ioctl
11 * - supports *unlimited* number of loop devices
12 * - supports /dev/loop<N> as well as /dev/loop/<N>
13 * - minimize overhead (fd, loopinfo, ... are shared for all operations)
14 * - setup (associate device and backing file)
15 * - delete (dis-associate file)
16 * - old LOOP_{SET,GET}_STATUS (32bit) ioctls are unsupported
17 * - extendible
18 */
19#include <stdio.h>
20#include <stdint.h>
21#include <string.h>
22#include <ctype.h>
23#include <fcntl.h>
10ee5932
KZ
24#include <stdlib.h>
25#include <unistd.h>
26#include <sys/ioctl.h>
27#include <sys/stat.h>
28#include <sys/mman.h>
29#include <sys/sysmacros.h>
30#include <inttypes.h>
31#include <dirent.h>
32#include <linux/posix_types.h>
33
34#include "linux_version.h"
35#include "c.h"
36#include "sysfs.h"
37#include "pathnames.h"
38#include "loopdev.h"
39#include "canonicalize.h"
40
aee31ddc
KZ
41#define CONFIG_LOOPDEV_DEBUG
42
43#ifdef CONFIG_LOOPDEV_DEBUG
aee31ddc
KZ
44# include <stdarg.h>
45
46# define DBG(l,x) do { \
47 if ((l)->debug) {\
48 fprintf(stderr, "loopdev: [%p]: ", (l)); \
49 x; \
50 } \
51 } while(0)
52
53static inline void __attribute__ ((__format__ (__printf__, 1, 2)))
54loopdev_debug(const char *mesg, ...)
55{
56 va_list ap;
57 va_start(ap, mesg);
58 vfprintf(stderr, mesg, ap);
59 va_end(ap);
60 fputc('\n', stderr);
61}
62
63#else /* !CONFIG_LOOPDEV_DEBUG */
64# define DBG(m,x) do { ; } while(0)
65#endif
66
67
10ee5932
KZ
68#define loopcxt_ioctl_enabled(_lc) (!((_lc)->flags & LOOPDEV_FL_NOIOCTL))
69
70/*
71 * @lc: context
72 * @device: device name, absolute device path or NULL to reset the current setting
73 *
74 * Sets device, absolute paths (e.g. "/dev/loop<N>") are unchanged, device
75 * names ("loop<N>") are converted to the path (/dev/loop<N> or to
76 * /dev/loop/<N>)
77 *
78 * Returns: <0 on error, 0 on success
79 */
80int loopcxt_set_device(struct loopdev_cxt *lc, const char *device)
81{
82 if (!lc)
83 return -EINVAL;
84
85 if (lc->fd >= 0)
86 close(lc->fd);
87 lc->fd = -1;
fd7f0718 88 lc->mode = 0;
10ee5932 89 lc->has_info = 0;
6c224de1 90 lc->info_failed = 0;
10ee5932 91 *lc->device = '\0';
fd7f0718 92 memset(&lc->info, 0, sizeof(lc->info));
10ee5932
KZ
93
94 /* set new */
95 if (device) {
96 if (*device != '/') {
97 const char *dir = _PATH_DEV;
98
99 /* compose device name for /dev/loop<n> or /dev/loop/<n> */
100 if (lc->flags & LOOPDEV_FL_DEVSUBDIR) {
101 if (strlen(device) < 5)
102 return -1;
103 device += 4;
104 dir = _PATH_DEV_LOOP "/"; /* _PATH_DEV uses tailing slash */
105 }
106 snprintf(lc->device, sizeof(lc->device), "%s%s",
107 dir, device);
108 } else {
109 strncpy(lc->device, device, sizeof(lc->device));
110 lc->device[sizeof(lc->device) - 1] = '\0';
111 }
d356c5d2 112 DBG(lc, loopdev_debug("%s successfully assigned", device));
10ee5932
KZ
113 }
114
115 sysfs_deinit(&lc->sysfs);
116 return 0;
117}
118
c7e0925d
KZ
119int loopcxt_has_device(struct loopdev_cxt *lc)
120{
121 return lc && *lc->device;
122}
123
10ee5932
KZ
124/*
125 * @lc: context
126 * @flags: LOOPDEV_FL_* flags
127 *
128 * Initilize loop handler.
129 *
fd7f0718
KZ
130 * We have two sets of the flags:
131 *
132 * * LOOPDEV_FL_* flags control loopcxt_* API behavior
133 *
134 * * LO_FLAGS_* are kernel flags used for LOOP_{SET,GET}_STAT64 ioctls
135 *
136 * Note about LOOPDEV_FL_{RDONLY,RDWR} flags. These flags are used for open(2)
137 * syscall to open loop device. By default is the device open read-only.
138 *
139 * The expection is loopcxt_setup_device(), where the device is open read-write
140 * if LO_FLAGS_READ_ONLY flags is not set (see loopcxt_set_flags()).
141 *
10ee5932
KZ
142 * Returns: <0 on error, 0 on success.
143 */
144int loopcxt_init(struct loopdev_cxt *lc, int flags)
145{
0b14bf7a
KZ
146 struct stat st;
147
10ee5932
KZ
148 if (!lc)
149 return -EINVAL;
150
151 memset(lc, 0, sizeof(*lc));
152 lc->flags = flags;
153 loopcxt_set_device(lc, NULL);
154
82b4082e 155 if (!(lc->flags & LOOPDEV_FL_NOSYSFS) &&
10ee5932
KZ
156 get_linux_version() >= KERNEL_VERSION(2,6,37))
157 /*
158 * Use only sysfs for basic information about loop devices
159 */
160 lc->flags |= LOOPDEV_FL_NOIOCTL;
161
0b14bf7a
KZ
162 if (!(lc->flags & LOOPDEV_FL_CONTROL) && !stat(_PATH_DEV_LOOPCTL, &st))
163 lc->flags |= LOOPDEV_FL_CONTROL;
164
10ee5932
KZ
165 return 0;
166}
167
168/*
169 * @lc: context
170 *
171 * Deinitialize loop context
172 */
173void loopcxt_deinit(struct loopdev_cxt *lc)
174{
175 if (!lc)
176 return;
177
aee31ddc
KZ
178 DBG(lc, loopdev_debug("de-initialize"));
179
10ee5932
KZ
180 free(lc->filename);
181 lc->filename = NULL;
182
183 loopcxt_set_device(lc, NULL);
184 loopcxt_deinit_iterator(lc);
185}
186
aee31ddc
KZ
187/*
188 * @lc: context
189 * @enable: TRUE/FALSE
190 *
191 * Enabled/disables debug messages
192 */
193void loopcxt_enable_debug(struct loopdev_cxt *lc, int enable)
194{
195 if (lc)
196 lc->debug = enable ? 1 : 0;
197}
198
10ee5932
KZ
199/*
200 * @lc: context
201 *
202 * Returns newly allocated device path.
203 */
204char *loopcxt_strdup_device(struct loopdev_cxt *lc)
205{
206 if (!lc || !*lc->device)
207 return NULL;
208 return strdup(lc->device);
209}
210
211/*
212 * @lc: context
213 *
214 * Returns pointer device name in the @lc struct.
215 */
216const char *loopcxt_get_device(struct loopdev_cxt *lc)
217{
218 return lc ? lc->device : NULL;
219}
220
221/*
222 * @lc: context
223 *
224 * Returns pointer to the sysfs context (see lib/sysfs.c)
225 */
226struct sysfs_cxt *loopcxt_get_sysfs(struct loopdev_cxt *lc)
227{
228 if (!lc || !*lc->device || (lc->flags & LOOPDEV_FL_NOSYSFS))
229 return NULL;
230
231 if (!lc->sysfs.devno) {
232 dev_t devno = sysfs_devname_to_devno(lc->device, NULL);
aee31ddc
KZ
233 if (!devno) {
234 DBG(lc, loopdev_debug("sysfs: failed devname to devno"));
10ee5932 235 return NULL;
aee31ddc
KZ
236 }
237 if (sysfs_init(&lc->sysfs, devno, NULL)) {
238 DBG(lc, loopdev_debug("sysfs: init failed"));
10ee5932 239 return NULL;
aee31ddc 240 }
10ee5932 241 }
aee31ddc 242
10ee5932
KZ
243 return &lc->sysfs;
244}
245
246/*
247 * @lc: context
248 *
249 * Returns: file descriptor to the open loop device or <0 on error. The mode
250 * depends on LOOPDEV_FL_{RDWR,RDONLY} context flags. Default is
251 * read-only.
252 */
253int loopcxt_get_fd(struct loopdev_cxt *lc)
254{
255 if (!lc || !*lc->device)
fd7f0718 256 return -EINVAL;
10ee5932 257
fd7f0718
KZ
258 if (lc->fd < 0) {
259 lc->mode = lc->flags & LOOPDEV_FL_RDWR ? O_RDWR : O_RDONLY;
260 lc->fd = open(lc->device, lc->mode);
aee31ddc 261 DBG(lc, loopdev_debug("open %s", lc->fd < 0 ? "failed" : "ok"));
fd7f0718 262 }
10ee5932
KZ
263 return lc->fd;
264}
265
fd7f0718
KZ
266int loopcxt_set_fd(struct loopdev_cxt *lc, int fd, int mode)
267{
268 if (!lc)
269 return -EINVAL;
270
271 lc->fd = fd;
272 lc->mode = mode;
273 return 0;
274}
275
10ee5932
KZ
276/*
277 * @lc: context
278 * @flags: LOOPITER_FL_* flags
279 *
280 * Iterator allows to scan list of the free or used loop devices.
281 *
282 * Returns: <0 on error, 0 on success
283 */
284int loopcxt_init_iterator(struct loopdev_cxt *lc, int flags)
285{
286 struct loopdev_iter *iter;
287 struct stat st;
288
289 if (!lc)
290 return -EINVAL;
291
aee31ddc
KZ
292 DBG(lc, loopdev_debug("iter: initialize"));
293
10ee5932
KZ
294 iter = &lc->iter;
295
296 /* always zeroize
297 */
298 memset(iter, 0, sizeof(*iter));
299 iter->ncur = -1;
300 iter->flags = flags;
301 iter->default_check = 1;
302
303 if (!lc->extra_check) {
304 /*
305 * Check for /dev/loop/<N> subdirectory
306 */
82b4082e 307 if (!(lc->flags & LOOPDEV_FL_DEVSUBDIR) &&
10ee5932
KZ
308 stat(_PATH_DEV_LOOP, &st) == 0 && S_ISDIR(st.st_mode))
309 lc->flags |= LOOPDEV_FL_DEVSUBDIR;
310
311 lc->extra_check = 1;
312 }
313 return 0;
314}
315
316/*
317 * @lc: context
318 *
319 * Returns: <0 on error, 0 on success
320 */
321int loopcxt_deinit_iterator(struct loopdev_cxt *lc)
322{
323 struct loopdev_iter *iter = &lc->iter;
324
325 if (!lc)
326 return -EINVAL;
327
aee31ddc
KZ
328 DBG(lc, loopdev_debug("iter: de-initialize"));
329
10ee5932
KZ
330 iter = &lc->iter;
331
332 free(iter->minors);
333 if (iter->proc)
334 fclose(iter->proc);
335 iter->minors = NULL;
336 iter->proc = NULL;
337 iter->done = 1;
338 return 0;
339}
340
341/*
342 * Same as loopcxt_set_device, but also checks if the device is
343 * associeted with any file.
344 *
345 * Returns: <0 on error, 0 on success, 1 device does not match with
346 * LOOPITER_FL_{USED,FREE} flags.
347 */
348static int loopiter_set_device(struct loopdev_cxt *lc, const char *device)
349{
350 int rc = loopcxt_set_device(lc, device);
351 int used;
352
353 if (rc)
354 return rc;
355
356 if (!(lc->iter.flags & LOOPITER_FL_USED) &&
357 !(lc->iter.flags & LOOPITER_FL_FREE))
358 return 0; /* caller does not care about device status */
359
360 used = loopcxt_get_offset(lc, NULL) == 0;
361
362 if ((lc->iter.flags & LOOPITER_FL_USED) && used)
363 return 0;
364
365 if ((lc->iter.flags & LOOPITER_FL_FREE) && !used)
366 return 0;
367
aee31ddc 368 DBG(lc, loopdev_debug("iter: setting device"));
10ee5932
KZ
369 loopcxt_set_device(lc, NULL);
370 return 1;
371}
372
373static int cmpnum(const void *p1, const void *p2)
374{
33487796
KZ
375 return (((* (int *) p1) > (* (int *) p2)) -
376 ((* (int *) p1) < (* (int *) p2)));
10ee5932
KZ
377}
378
379/*
380 * The classic scandir() is more expensive and less portable.
381 * We needn't full loop device names -- loop numbers (loop<N>)
382 * are enough.
383 */
384static int loop_scandir(const char *dirname, int **ary, int hasprefix)
385{
386 DIR *dir;
387 struct dirent *d;
388 unsigned int n, count = 0, arylen = 0;
389
390 if (!dirname || !ary)
391 return 0;
392 dir = opendir(dirname);
393 if (!dir)
394 return 0;
10ee5932
KZ
395 free(*ary);
396 *ary = NULL;
397
398 while((d = readdir(dir))) {
399#ifdef _DIRENT_HAVE_D_TYPE
400 if (d->d_type != DT_BLK && d->d_type != DT_UNKNOWN &&
401 d->d_type != DT_LNK)
402 continue;
403#endif
404 if (!strcmp(d->d_name, ".") || !strcmp(d->d_name, ".."))
405 continue;
406
407 if (hasprefix) {
408 /* /dev/loop<N> */
409 if (sscanf(d->d_name, "loop%u", &n) != 1)
410 continue;
411 } else {
412 /* /dev/loop/<N> */
413 char *end = NULL;
414
415 n = strtol(d->d_name, &end, 10);
416 if (d->d_name == end || (end && *end) || errno)
417 continue;
418 }
419 if (n < LOOPDEV_DEFAULT_NNODES)
420 continue; /* ignore loop<0..7> */
421
422 if (count + 1 > arylen) {
423 int *tmp;
424
425 arylen += 1;
426
427 tmp = realloc(*ary, arylen * sizeof(int));
428 if (!tmp) {
429 free(*ary);
430 return -1;
431 }
432 *ary = tmp;
433 }
fc8b1f36
KZ
434 if (*ary)
435 (*ary)[count++] = n;
10ee5932 436 }
fc8b1f36 437 if (count && *ary)
10ee5932
KZ
438 qsort(*ary, count, sizeof(int), cmpnum);
439
440 closedir(dir);
441 return count;
442}
443
444/*
445 * @lc: context, has to initialized by loopcxt_init_iterator()
446 *
447 * Returns: 0 on success, -1 on error, 1 at the end of scanning. The details
448 * about the current loop device are available by
449 * loopcxt_get_{fd,backing_file,device,offset, ...} functions.
450 */
451int loopcxt_next(struct loopdev_cxt *lc)
452{
453 struct loopdev_iter *iter;
454
455 if (!lc)
456 return -EINVAL;
aee31ddc
KZ
457
458 DBG(lc, loopdev_debug("iter: next"));
459
10ee5932
KZ
460 iter = &lc->iter;
461 if (iter->done)
462 return 1;
463
464 /* A) Look for used loop devices in /proc/partitions ("losetup -a" only)
465 */
466 if (iter->flags & LOOPITER_FL_USED) {
467 char buf[BUFSIZ];
468
469 if (!iter->proc)
470 iter->proc = fopen(_PATH_PROC_PARTITIONS, "r");
471
472 while (iter->proc && fgets(buf, sizeof(buf), iter->proc)) {
473 unsigned int m;
474 char name[128];
475
476 if (sscanf(buf, " %u %*s %*s %128[^\n ]",
477 &m, name) != 2 || m != LOOPDEV_MAJOR)
478 continue;
479
480 if (loopiter_set_device(lc, name) == 0)
481 return 0;
482 }
483
484 goto done;
485 }
486
487 /* B) Classic way, try first eight loop devices (default number
488 * of loop devices). This is enough for 99% of all cases.
489 */
490 if (iter->default_check) {
491 for (++iter->ncur; iter->ncur < LOOPDEV_DEFAULT_NNODES;
492 iter->ncur++) {
493 char name[16];
494 snprintf(name, sizeof(name), "loop%d", iter->ncur);
495
496 if (loopiter_set_device(lc, name) == 0)
497 return 0;
498 }
499 iter->default_check = 0;
500 }
501
502 /* C) the worst possibility, scan whole /dev or /dev/loop/<N>
503 */
504 if (!iter->minors) {
505 iter->nminors = (lc->flags & LOOPDEV_FL_DEVSUBDIR) ?
506 loop_scandir(_PATH_DEV_LOOP, &iter->minors, 0) :
507 loop_scandir(_PATH_DEV, &iter->minors, 1);
508 iter->ncur = -1;
509 }
510 for (++iter->ncur; iter->ncur < iter->nminors; iter->ncur++) {
511 char name[16];
512 snprintf(name, sizeof(name), "loop%d", iter->minors[iter->ncur]);
513
514 if (loopiter_set_device(lc, name) == 0)
515 return 0;
516 }
517done:
518 loopcxt_deinit_iterator(lc);
519 return 1;
520}
521
522/*
523 * @device: path to device
524 */
525int is_loopdev(const char *device)
526{
527 struct stat st;
528
529 if (!device)
530 return 0;
531
532 return (stat(device, &st) == 0 &&
533 S_ISBLK(st.st_mode) &&
534 major(st.st_rdev) == LOOPDEV_MAJOR);
535}
536
537/*
538 * @lc: context
539 *
540 * Returns result from LOOP_GET_STAT64 ioctl or NULL on error.
541 */
542struct loop_info64 *loopcxt_get_info(struct loopdev_cxt *lc)
543{
544 int fd;
545
6c224de1 546 if (!lc || lc->info_failed)
10ee5932
KZ
547 return NULL;
548 if (lc->has_info)
549 return &lc->info;
550
551 fd = loopcxt_get_fd(lc);
552 if (fd < 0)
553 return NULL;
554
555 if (ioctl(fd, LOOP_GET_STATUS64, &lc->info) == 0) {
556 lc->has_info = 1;
6c224de1
KZ
557 lc->info_failed = 0;
558 DBG(lc, loopdev_debug("reading loop_info64 OK"));
10ee5932 559 return &lc->info;
6c224de1
KZ
560 } else {
561 lc->info_failed = 1;
562 DBG(lc, loopdev_debug("reading loop_info64 FAILED"));
10ee5932
KZ
563 }
564
565 return NULL;
566}
567
568/*
569 * @lc: context
570 *
571 * Returns (allocated) string with path to the file assicieted
572 * with the current loop device.
573 */
574char *loopcxt_get_backing_file(struct loopdev_cxt *lc)
575{
576 struct sysfs_cxt *sysfs = loopcxt_get_sysfs(lc);
577 char *res = NULL;
578
579 if (sysfs)
fd7f0718
KZ
580 /*
581 * This is always preffered, the loop_info64
582 * has too small buffer for the filename.
583 */
10ee5932
KZ
584 res = sysfs_strdup(sysfs, "loop/backing_file");
585
586 if (!res && loopcxt_ioctl_enabled(lc)) {
587 struct loop_info64 *lo = loopcxt_get_info(lc);
588
589 if (lo) {
590 lo->lo_file_name[LO_NAME_SIZE - 2] = '*';
591 lo->lo_file_name[LO_NAME_SIZE - 1] = '\0';
592 res = strdup((char *) lo->lo_file_name);
593 }
594 }
aee31ddc 595
6c224de1 596 DBG(lc, loopdev_debug("get_backing_file [%s]", res));
10ee5932
KZ
597 return res;
598}
599
600/*
601 * @lc: context
602 * @offset: returns offset number for the given device
603 *
604 * Returns: <0 on error, 0 on success
605 */
606int loopcxt_get_offset(struct loopdev_cxt *lc, uint64_t *offset)
607{
608 struct sysfs_cxt *sysfs = loopcxt_get_sysfs(lc);
609 int rc = -EINVAL;
610
611 if (sysfs)
612 rc = sysfs_read_u64(sysfs, "loop/offset", offset);
613
614 if (rc && loopcxt_ioctl_enabled(lc)) {
615 struct loop_info64 *lo = loopcxt_get_info(lc);
616 if (lo) {
617 if (offset)
618 *offset = lo->lo_offset;
6c224de1 619 rc = 0;
10ee5932
KZ
620 }
621 }
622
6c224de1 623 DBG(lc, loopdev_debug("get_offset [rc=%d]", rc));
10ee5932
KZ
624 return rc;
625}
626
627/*
628 * @lc: context
629 * @sizelimit: returns size limit for the given device
630 *
631 * Returns: <0 on error, 0 on success
632 */
633int loopcxt_get_sizelimit(struct loopdev_cxt *lc, uint64_t *size)
634{
635 struct sysfs_cxt *sysfs = loopcxt_get_sysfs(lc);
636 int rc = -EINVAL;
637
638 if (sysfs)
639 rc = sysfs_read_u64(sysfs, "loop/sizelimit", size);
640
641 if (rc && loopcxt_ioctl_enabled(lc)) {
642 struct loop_info64 *lo = loopcxt_get_info(lc);
643 if (lo) {
644 if (size)
645 *size = lo->lo_sizelimit;
6c224de1 646 rc = 0;
10ee5932
KZ
647 }
648 }
649
6c224de1
KZ
650 DBG(lc, loopdev_debug("get_sizelimit [rc=%d]", rc));
651 return rc;
652}
653
654/*
655 * @lc: context
656 * @devno: returns encryption type
657 *
658 * Cryptoloop is DEPRECATED!
659 *
660 * Returns: <0 on error, 0 on success
661 */
662int loopcxt_get_encrypt_type(struct loopdev_cxt *lc, uint32_t *type)
663{
664 struct loop_info64 *lo = loopcxt_get_info(lc);
665 int rc = -EINVAL;
666
667 if (lo) {
668 if (type)
669 *type = lo->lo_encrypt_type;
670 rc = 0;
671 }
672 DBG(lc, loopdev_debug("get_encrypt_type [rc=%d]", rc));
673 return rc;
674}
675
676/*
677 * @lc: context
678 * @devno: returns crypt name
679 *
680 * Cryptoloop is DEPRECATED!
681 *
682 * Returns: <0 on error, 0 on success
683 */
684const char *loopcxt_get_crypt_name(struct loopdev_cxt *lc)
685{
686 struct loop_info64 *lo = loopcxt_get_info(lc);
687
688 if (lo)
689 return (char *) lo->lo_crypt_name;
690
691 DBG(lc, loopdev_debug("get_crypt_name failed"));
692 return NULL;
693}
694
695/*
696 * @lc: context
697 * @devno: returns backing file devno
698 *
699 * Returns: <0 on error, 0 on success
700 */
701int loopcxt_get_backing_devno(struct loopdev_cxt *lc, dev_t *devno)
702{
703 struct loop_info64 *lo = loopcxt_get_info(lc);
704 int rc = -EINVAL;
705
706 if (lo) {
707 if (devno)
708 *devno = lo->lo_device;
709 rc = 0;
710 }
711 DBG(lc, loopdev_debug("get_backing_devno [rc=%d]", rc));
712 return rc;
713}
714
715/*
716 * @lc: context
717 * @ino: returns backing file inode
718 *
719 * Returns: <0 on error, 0 on success
720 */
721int loopcxt_get_backing_inode(struct loopdev_cxt *lc, ino_t *ino)
722{
723 struct loop_info64 *lo = loopcxt_get_info(lc);
724 int rc = -EINVAL;
725
726 if (lo) {
727 if (ino)
728 *ino = lo->lo_inode;
729 rc = 0;
730 }
731 DBG(lc, loopdev_debug("get_backing_inode [rc=%d]", rc));
10ee5932
KZ
732 return rc;
733}
734
59d749c3
KZ
735/*
736 * Check if the kernel supports partitioned loop devices.
737 *
738 * Notes:
739 * - kernels < 3.2 support partitioned loop devices and PT scanning
740 * only if max_part= module paremeter is non-zero
741 *
742 * - kernels >= 3.2 always support partitioned loop devices
743 *
744 * - kernels >= 3.2 always support BLKPG_{ADD,DEL}_PARTITION ioctls
745 *
746 * - kernels >= 3.2 enable PT scanner only if max_part= is non-zero or if the
747 * LO_FLAGS_PARTSCAN flag is set for the device. The PT scanner is disabled
748 * by default.
749 *
750 * See kernel commit e03c8dd14915fabc101aa495828d58598dc5af98.
751 */
752int loopmod_supports_partscan(void)
753{
754 int rc, ret = 0;
755 FILE *f;
756
757 if (get_linux_version() >= KERNEL_VERSION(3,2,0))
758 return 1;
759
760 f = fopen("/sys/module/loop/parameters/max_part", "r");
761 if (!f)
762 return 0;
763 rc = fscanf(f, "%d", &ret);
764 fclose(f);
765 return rc = 1 ? ret : 0;
766}
767
10ee5932
KZ
768/*
769 * @lc: context
770 *
59d749c3
KZ
771 * Returns: 1 if the partscan flags is set *or* (for old kernels) partitions
772 * scannig is enabled for all loop devices.
773 */
774int loopcxt_is_partscan(struct loopdev_cxt *lc)
775{
776 struct sysfs_cxt *sysfs = loopcxt_get_sysfs(lc);
777
778 if (sysfs) {
779 /* kernel >= 3.2 */
780 int fl;
781 if (sysfs_read_int(sysfs, "loop/partscan", &fl) == 0)
782 return fl;
783 }
784
785 /* old kernels (including kernels without loopN/loop/<flags> directory */
786 return loopmod_supports_partscan();
787}
788
789/*
790 * @lc: context
791 *
792 * Returns: 1 if the autoclear flags is set.
10ee5932
KZ
793 */
794int loopcxt_is_autoclear(struct loopdev_cxt *lc)
795{
796 struct sysfs_cxt *sysfs = loopcxt_get_sysfs(lc);
797
798 if (sysfs) {
799 int fl;
800 if (sysfs_read_int(sysfs, "loop/autoclear", &fl) == 0)
801 return fl;
802 }
803
804 if (loopcxt_ioctl_enabled(lc)) {
805 struct loop_info64 *lo = loopcxt_get_info(lc);
806 if (lo)
807 return lo->lo_flags & LO_FLAGS_AUTOCLEAR;
808 }
809 return 0;
810}
811
fd7f0718
KZ
812/*
813 * @lc: context
814 *
59d749c3 815 * Returns: 1 if the readonly flags is set.
fd7f0718
KZ
816 */
817int loopcxt_is_readonly(struct loopdev_cxt *lc)
818{
819 struct sysfs_cxt *sysfs = loopcxt_get_sysfs(lc);
820
821 if (sysfs) {
822 int fl;
823 if (sysfs_read_int(sysfs, "ro", &fl) == 0)
824 return fl;
825 }
826
827 if (loopcxt_ioctl_enabled(lc)) {
828 struct loop_info64 *lo = loopcxt_get_info(lc);
829 if (lo)
830 return lo->lo_flags & LO_FLAGS_READ_ONLY;
831 }
832 return 0;
833}
834
6c224de1
KZ
835/*
836 * @lc: context
837 * @st: backing file stat or NULL
838 * @backing_file: filename
839 * @offset: offset
840 * @flags: LOOPDEV_FL_OFFSET if @offset should not be ignored
841 *
842 * Returns 1 if the current @lc loopdev is associated with the given backing
843 * file. Note that the preferred way is to use devno and inode number rather
844 * than filename. The @backing_file filename is poor solution usable in case
845 * that you don't have rights to call stat().
846 *
847 * Don't forget that old kernels provide very restricted (in size) backing
848 * filename by LOOP_GET_STAT64 ioctl only.
849 */
850int loopcxt_is_used(struct loopdev_cxt *lc,
851 struct stat *st,
852 const char *backing_file,
853 uint64_t offset,
854 int flags)
855{
856 ino_t ino;
857 dev_t dev;
858
859 if (!lc)
860 return 0;
861
862 DBG(lc, loopdev_debug("checking %s vs. %s",
863 loopcxt_get_device(lc),
864 backing_file));
865
866 if (st && loopcxt_get_backing_inode(lc, &ino) == 0 &&
867 loopcxt_get_backing_devno(lc, &dev) == 0) {
868
869 if (ino == st->st_ino && dev == st->st_dev)
870 goto found;
871
872 /* don't use filename if we have devno and inode */
873 return 0;
874 }
875
876 /* poor man's solution */
877 if (backing_file) {
878 char *name = loopcxt_get_backing_file(lc);
879 int rc = name && strcmp(name, backing_file) == 0;
880
881 free(name);
882 if (rc)
883 goto found;
884 }
885
886 return 0;
887found:
888 if (flags & LOOPDEV_FL_OFFSET) {
889 uint64_t off;
890
891 return loopcxt_get_offset(lc, &off) == 0 && off == offset;
892 }
893 return 1;
894}
895
fd7f0718
KZ
896/*
897 * The setting is removed by loopcxt_set_device() loopcxt_next()!
898 */
10ee5932
KZ
899int loopcxt_set_offset(struct loopdev_cxt *lc, uint64_t offset)
900{
901 if (!lc)
902 return -EINVAL;
903 lc->info.lo_offset = offset;
aee31ddc
KZ
904
905 DBG(lc, loopdev_debug("set offset=%jd", offset));
10ee5932
KZ
906 return 0;
907}
908
fd7f0718
KZ
909/*
910 * The setting is removed by loopcxt_set_device() loopcxt_next()!
911 */
10ee5932
KZ
912int loopcxt_set_sizelimit(struct loopdev_cxt *lc, uint64_t sizelimit)
913{
914 if (!lc)
915 return -EINVAL;
916 lc->info.lo_sizelimit = sizelimit;
aee31ddc
KZ
917
918 DBG(lc, loopdev_debug("set sizelimit=%jd", sizelimit));
10ee5932
KZ
919 return 0;
920}
921
922/*
923 * @lc: context
924 * @flags: kernel LO_FLAGS_{READ_ONLY,USE_AOPS,AUTOCLEAR} flags
925 *
fd7f0718
KZ
926 * The setting is removed by loopcxt_set_device() loopcxt_next()!
927 *
10ee5932
KZ
928 * Returns: 0 on success, <0 on error.
929 */
930int loopcxt_set_flags(struct loopdev_cxt *lc, uint32_t flags)
931{
932 if (!lc)
933 return -EINVAL;
934 lc->info.lo_flags = flags;
aee31ddc
KZ
935
936 DBG(lc, loopdev_debug("set flags=%u", (unsigned) flags));
10ee5932
KZ
937 return 0;
938}
939
940/*
941 * @lc: context
942 * @filename: backing file path (the path will be canonicalized)
943 *
fd7f0718
KZ
944 * The setting is removed by loopcxt_set_device() loopcxt_next()!
945 *
10ee5932
KZ
946 * Returns: 0 on success, <0 on error.
947 */
948int loopcxt_set_backing_file(struct loopdev_cxt *lc, const char *filename)
949{
950 if (!lc)
951 return -EINVAL;
952
953 lc->filename = canonicalize_path(filename);
954 if (!lc->filename)
955 return -errno;
956
957 strncpy((char *)lc->info.lo_file_name, lc->filename, LO_NAME_SIZE);
958 lc->info.lo_file_name[LO_NAME_SIZE- 1] = '\0';
959
aee31ddc 960 DBG(lc, loopdev_debug("set backing file=%s", lc->info.lo_file_name));
10ee5932
KZ
961 return 0;
962}
963
964static int digits_only(const char *s)
965{
966 while (*s)
967 if (!isdigit(*s++))
968 return 0;
969 return 1;
970}
971
972/*
973 * @lc: context
974 * @encryption: encryption name / type (see lopsetup man page)
975 * @password
976 *
fd7f0718 977 * Note that the encryption functionality is deprecated an unmaintained. Use
10ee5932
KZ
978 * cryptsetup (it also supports AES-loops).
979 *
fd7f0718
KZ
980 * The setting is removed by loopcxt_set_device() loopcxt_next()!
981 *
10ee5932
KZ
982 * Returns: 0 on success, <0 on error.
983 */
984int loopcxt_set_encryption(struct loopdev_cxt *lc,
985 const char *encryption,
986 const char *password)
987{
988 if (!lc)
989 return -EINVAL;
990
aee31ddc
KZ
991 DBG(lc, loopdev_debug("setting encryption '%s'", encryption));
992
10ee5932
KZ
993 if (encryption && *encryption) {
994 if (digits_only(encryption)) {
995 lc->info.lo_encrypt_type = atoi(encryption);
996 } else {
997 lc->info.lo_encrypt_type = LO_CRYPT_CRYPTOAPI;
998 snprintf((char *)lc->info.lo_crypt_name, LO_NAME_SIZE,
999 "%s", encryption);
1000 }
1001 }
1002
1003 switch (lc->info.lo_encrypt_type) {
1004 case LO_CRYPT_NONE:
1005 lc->info.lo_encrypt_key_size = 0;
1006 break;
1007 default:
c7e0925d 1008 DBG(lc, loopdev_debug("setting encryption key"));
10ee5932
KZ
1009 memset(lc->info.lo_encrypt_key, 0, LO_KEY_SIZE);
1010 strncpy((char *)lc->info.lo_encrypt_key, password, LO_KEY_SIZE);
1011 lc->info.lo_encrypt_key[LO_KEY_SIZE - 1] = '\0';
1012 lc->info.lo_encrypt_key_size = LO_KEY_SIZE;
1013 break;
1014 }
c7e0925d
KZ
1015
1016 DBG(lc, loopdev_debug("encryption successfully set"));
10ee5932
KZ
1017 return 0;
1018}
1019
1020/*
1021 * @cl: context
1022 *
1023 * Associate the current device (see loopcxt_{set,get}_device()) with
1024 * a file (see loopcxt_set_backing_file()).
1025 *
fd7f0718
KZ
1026 * The device is initialized read-write by default. If you want read-only
1027 * device then set LO_FLAGS_READ_ONLY by loopcxt_set_flags(). The LOOPDEV_FL_*
1028 * flags are ignored and modified according to LO_FLAGS_*.
1029 *
1030 * If the device is already open by loopcxt_get_fd() then this setup device
1031 * function will re-open the device to fix read/write mode.
1032 *
1033 * The device is also initialized read-only if the backing file is not
1034 * possible to open read-write (e.g. read-only FS).
10ee5932
KZ
1035 *
1036 * Returns: <0 on error, 0 on success.
1037 */
1038int loopcxt_setup_device(struct loopdev_cxt *lc)
1039{
fd7f0718 1040 int file_fd, dev_fd, mode = O_RDWR, rc = -1;
10ee5932
KZ
1041
1042 if (!lc || !*lc->device || !lc->filename)
1043 return -EINVAL;
1044
aee31ddc
KZ
1045 DBG(lc, loopdev_debug("device setup requested"));
1046
10ee5932
KZ
1047 /*
1048 * Open backing file and device
1049 */
fd7f0718
KZ
1050 if (lc->info.lo_flags & LO_FLAGS_READ_ONLY)
1051 mode = O_RDONLY;
10ee5932
KZ
1052
1053 if ((file_fd = open(lc->filename, mode)) < 0) {
1054 if (mode != O_RDONLY && (errno == EROFS || errno == EACCES))
1055 file_fd = open(lc->filename, mode = O_RDONLY);
1056
aee31ddc
KZ
1057 if (file_fd < 0) {
1058 DBG(lc, loopdev_debug("open backing file failed: %m"));
10ee5932 1059 return -errno;
aee31ddc 1060 }
10ee5932 1061 }
d356c5d2 1062 DBG(lc, loopdev_debug("setup: backing file open: OK"));
10ee5932 1063
fd7f0718
KZ
1064 if (lc->fd != -1 && lc->mode != mode) {
1065 close(lc->fd);
1066 lc->fd = -1;
1067 lc->mode = 0;
1068 }
1069
10ee5932 1070 if (mode == O_RDONLY) {
fd7f0718
KZ
1071 lc->flags |= LOOPDEV_FL_RDONLY; /* open() mode */
1072 lc->info.lo_flags |= LO_FLAGS_READ_ONLY; /* kernel loopdev mode */
1073 } else {
1074 lc->flags |= LOOPDEV_FL_RDWR; /* open() mode */
1075 lc->info.lo_flags &= ~LO_FLAGS_READ_ONLY;
1076 lc->flags &= ~LOOPDEV_FL_RDONLY;
1077 }
10ee5932
KZ
1078
1079 dev_fd = loopcxt_get_fd(lc);
1080 if (dev_fd < 0) {
1081 rc = -errno;
1082 goto err;
1083 }
1084
d356c5d2
KZ
1085 DBG(lc, loopdev_debug("setup: device open: OK"));
1086
10ee5932
KZ
1087 /*
1088 * Set FD
1089 */
1090 if (ioctl(dev_fd, LOOP_SET_FD, file_fd) < 0) {
1091 rc = -errno;
aee31ddc 1092 DBG(lc, loopdev_debug("LOOP_SET_FD failed: %m"));
10ee5932
KZ
1093 goto err;
1094 }
d356c5d2
KZ
1095
1096 DBG(lc, loopdev_debug("setup: LOOP_SET_FD: OK"));
1097
10ee5932
KZ
1098 close(file_fd);
1099 file_fd = -1;
1100
aee31ddc
KZ
1101 if (ioctl(dev_fd, LOOP_SET_STATUS64, &lc->info)) {
1102 DBG(lc, loopdev_debug("LOOP_SET_STATUS64 failed: %m"));
10ee5932 1103 goto err;
aee31ddc 1104 }
d356c5d2
KZ
1105
1106 DBG(lc, loopdev_debug("setup: LOOP_SET_STATUS64: OK"));
1107
10ee5932
KZ
1108 memset(&lc->info, 0, sizeof(lc->info));
1109 lc->has_info = 0;
6c224de1 1110 lc->info_failed = 0;
10ee5932 1111
8fbbe528 1112 DBG(lc, loopdev_debug("setup success [rc=0]"));
10ee5932
KZ
1113 return 0;
1114err:
1115 if (file_fd >= 0)
1116 close(file_fd);
1117 if (dev_fd >= 0)
1118 ioctl(dev_fd, LOOP_CLR_FD, 0);
1119
8fbbe528 1120 DBG(lc, loopdev_debug("setup failed [rc=%d]", rc));
10ee5932
KZ
1121 return rc;
1122}
1123
1124int loopcxt_delete_device(struct loopdev_cxt *lc)
1125{
1126 int fd = loopcxt_get_fd(lc);
1127
1128 if (fd < 0)
1129 return -EINVAL;
1130
aee31ddc
KZ
1131 if (ioctl(fd, LOOP_CLR_FD, 0) < 0) {
1132 DBG(lc, loopdev_debug("LOOP_CLR_FD failed: %m"));
10ee5932 1133 return -errno;
aee31ddc
KZ
1134 }
1135
1136 DBG(lc, loopdev_debug("device removed"));
10ee5932
KZ
1137 return 0;
1138}
1139
59d749c3
KZ
1140/*
1141 * Note that LOOP_CTL_GET_FREE ioctl is supported since kernel 3.1. In older
1142 * kernels we have to check all loop devices to found unused one.
1143 *
1144 * See kernel commit 770fe30a46a12b6fb6b63fbe1737654d28e8484.
1145 */
10ee5932
KZ
1146int loopcxt_find_unused(struct loopdev_cxt *lc)
1147{
0b14bf7a 1148 int rc = -1;
10ee5932 1149
aee31ddc
KZ
1150 DBG(lc, loopdev_debug("find_unused requested"));
1151
0b14bf7a
KZ
1152 if (lc->flags & LOOPDEV_FL_CONTROL) {
1153 int ctl = open(_PATH_DEV_LOOPCTL, O_RDWR);
10ee5932 1154
0b14bf7a
KZ
1155 if (ctl >= 0)
1156 rc = ioctl(ctl, LOOP_CTL_GET_FREE);
1157 if (rc >= 0) {
1158 char name[16];
1159 snprintf(name, sizeof(name), "loop%d", rc);
1160
1161 rc = loopiter_set_device(lc, name);
1162 }
1163 if (ctl >= 0)
1164 close(ctl);
1165 DBG(lc, loopdev_debug("find_unused by loop-control [rc=%d]", rc));
1166 }
1167
1168 if (rc < 0) {
1169 rc = loopcxt_init_iterator(lc, LOOPITER_FL_FREE);
1170 if (rc)
1171 return rc;
10ee5932 1172
0b14bf7a
KZ
1173 rc = loopcxt_next(lc);
1174 loopcxt_deinit_iterator(lc);
1175 DBG(lc, loopdev_debug("find_unused by scan [rc=%d]", rc));
1176 }
10ee5932
KZ
1177 return rc;
1178}
1179
1180
1181
1182/*
1183 * Return: TRUE/FALSE
1184 */
1185int loopdev_is_autoclear(const char *device)
1186{
1187 struct loopdev_cxt lc;
1188 int rc;
1189
1190 if (!device)
1191 return 0;
1192
1193 loopcxt_init(&lc, 0);
1194 loopcxt_set_device(&lc, device);
1195 rc = loopcxt_is_autoclear(&lc);
1196 loopcxt_deinit(&lc);
1197
1198 return rc;
1199}
1200
1201char *loopdev_get_backing_file(const char *device)
1202{
1203 struct loopdev_cxt lc;
1204 char *res;
1205
1206 if (!device)
1207 return NULL;
1208
1209 loopcxt_init(&lc, 0);
1210 loopcxt_set_device(&lc, device);
1211 res = loopcxt_get_backing_file(&lc);
1212 loopcxt_deinit(&lc);
1213
1214 return res;
1215}
1216
1217/*
1218 * Returns: TRUE/FALSE
1219 */
1220int loopdev_is_used(const char *device, const char *filename,
1221 uint64_t offset, int flags)
1222{
1223 struct loopdev_cxt lc;
6c224de1 1224 struct stat st;
10ee5932
KZ
1225 int rc = 0;
1226
8b470b20 1227 if (!device || !filename)
10ee5932
KZ
1228 return 0;
1229
1230 loopcxt_init(&lc, 0);
1231 loopcxt_set_device(&lc, device);
1232
6c224de1
KZ
1233 rc = !stat(filename, &st);
1234 rc = loopcxt_is_used(&lc, rc ? &st : NULL, filename, offset, flags);
10ee5932 1235
10ee5932 1236 loopcxt_deinit(&lc);
10ee5932
KZ
1237 return rc;
1238}
1239
1240int loopdev_delete(const char *device)
1241{
1242 struct loopdev_cxt lc;
1243 int rc;
1244
8b470b20
KZ
1245 if (!device)
1246 return -EINVAL;
1247
10ee5932
KZ
1248 loopcxt_init(&lc, 0);
1249 rc = loopcxt_set_device(&lc, device);
1250 if (!rc)
1251 rc = loopcxt_delete_device(&lc);
1252 loopcxt_deinit(&lc);
1253 return rc;
1254}
1255
1256/*
1257 * Returns: 0 = success, < 0 error, 1 not found
1258 */
1259int loopcxt_find_by_backing_file(struct loopdev_cxt *lc, const char *filename,
1260 uint64_t offset, int flags)
1261{
6c224de1
KZ
1262 int rc, hasst;
1263 struct stat st;
10ee5932
KZ
1264
1265 if (!filename)
1266 return -EINVAL;
1267
6c224de1
KZ
1268 hasst = !stat(filename, &st);
1269
10ee5932
KZ
1270 rc = loopcxt_init_iterator(lc, LOOPITER_FL_USED);
1271 if (rc)
1272 return rc;
1273
6c224de1 1274 while ((rc = loopcxt_next(lc)) == 0) {
10ee5932 1275
6c224de1
KZ
1276 if (loopcxt_is_used(lc, hasst ? &st : NULL,
1277 filename, offset, flags))
1278 break;
10ee5932
KZ
1279 }
1280
1281 loopcxt_deinit_iterator(lc);
1282 return rc;
1283}
1284
1285/*
1286 * Returns allocated string with device name
1287 */
1288char *loopdev_find_by_backing_file(const char *filename, uint64_t offset, int flags)
1289{
1290 struct loopdev_cxt lc;
1291 char *res = NULL;
1292
1293 if (!filename)
1294 return NULL;
1295
1296 loopcxt_init(&lc, 0);
1297 if (loopcxt_find_by_backing_file(&lc, filename, offset, flags))
1298 res = loopcxt_strdup_device(&lc);
1299 loopcxt_deinit(&lc);
1300
1301 return res;
1302}
1303
d5688130
KZ
1304/*
1305 * Returns number of loop devices associated with @file, if only one loop
1306 * device is associeted with the given @filename and @loopdev is not NULL then
1307 * @loopdev returns name of the device.
1308 */
1309int loopdev_count_by_backing_file(const char *filename, char **loopdev)
1310{
1311 struct loopdev_cxt lc;
1312 int count = 0;
1313
1314 if (!filename)
1315 return -1;
1316
1317 loopcxt_init(&lc, 0);
1318 if (loopcxt_init_iterator(&lc, LOOPITER_FL_USED))
1319 return -1;
1320
1321 while(loopcxt_next(&lc) == 0) {
1322 char *backing = loopcxt_get_backing_file(&lc);
1323
1324 if (!backing || strcmp(backing, filename)) {
1325 free(backing);
1326 continue;
1327 }
1328
1329 free(backing);
1330 if (loopdev && count == 0)
1331 *loopdev = loopcxt_strdup_device(&lc);
1332 count++;
1333 }
1334
1335 loopcxt_deinit(&lc);
1336
1337 if (loopdev && count > 1) {
1338 free(*loopdev);
1339 *loopdev = NULL;
1340 }
1341 return count;
1342}
1343
10ee5932
KZ
1344
1345#ifdef TEST_PROGRAM_LOOPDEV
1346#include <errno.h>
1347#include <err.h>
10ee5932 1348
aee31ddc 1349static void test_loop_info(const char *device, int flags, int debug)
10ee5932
KZ
1350{
1351 struct loopdev_cxt lc;
1352 char *p;
1353 uint64_t u64;
1354
1355 loopcxt_init(&lc, flags);
aee31ddc
KZ
1356 loopcxt_enable_debug(&lc, debug);
1357
10ee5932
KZ
1358 if (loopcxt_set_device(&lc, device))
1359 err(EXIT_FAILURE, "failed to set device");
1360
1361 p = loopcxt_get_backing_file(&lc);
1362 printf("\tBACKING FILE: %s\n", p);
1363 free(p);
1364
1365 if (loopcxt_get_offset(&lc, &u64) == 0)
1366 printf("\tOFFSET: %jd\n", u64);
1367
1368 if (loopcxt_get_sizelimit(&lc, &u64) == 0)
1369 printf("\tSIZE LIMIT: %jd\n", u64);
1370
1371 printf("\tAUTOCLEAR: %s\n", loopcxt_is_autoclear(&lc) ? "YES" : "NOT");
1372
1373 loopcxt_deinit(&lc);
1374}
1375
aee31ddc 1376static void test_loop_scan(int flags, int debug)
10ee5932
KZ
1377{
1378 struct loopdev_cxt lc;
1379 int rc;
1380
1381 loopcxt_init(&lc, 0);
aee31ddc 1382 loopcxt_enable_debug(&lc, debug);
10ee5932
KZ
1383
1384 if (loopcxt_init_iterator(&lc, flags))
1385 err(EXIT_FAILURE, "iterator initlization failed");
1386
1387 while((rc = loopcxt_next(&lc)) == 0) {
1388 const char *device = loopcxt_get_device(&lc);
1389
1390 if (flags & LOOPITER_FL_USED) {
1391 char *backing = loopcxt_get_backing_file(&lc);
1392 printf("\t%s: %s\n", device, backing);
1393 free(backing);
1394 } else
1395 printf("\t%s\n", device);
1396 }
1397
1398 if (rc < 0)
1399 err(EXIT_FAILURE, "loopdevs scanning failed");
1400
1401 loopcxt_deinit(&lc);
1402}
1403
aee31ddc 1404static int test_loop_setup(const char *filename, const char *device, int debug)
10ee5932
KZ
1405{
1406 struct loopdev_cxt lc;
1407 int rc = 0;
1408
1409 loopcxt_init(&lc, 0);
aee31ddc 1410 loopcxt_enable_debug(&lc, debug);
10ee5932 1411
10ee5932
KZ
1412 if (device) {
1413 rc = loopcxt_set_device(&lc, device);
1414 if (rc)
1415 err(EXIT_FAILURE, "failed to set device: %s", device);
1416 }
1417
1418 do {
1419 if (!device) {
1420 rc = loopcxt_find_unused(&lc);
1421 if (rc)
ad2d0d85 1422 err(EXIT_FAILURE, "failed to find unused device");
10ee5932
KZ
1423 printf("Trying to use '%s'\n", loopcxt_get_device(&lc));
1424 }
1425
fd7f0718
KZ
1426 if (loopcxt_set_backing_file(&lc, filename))
1427 err(EXIT_FAILURE, "failed to set backing file");
1428
10ee5932
KZ
1429 rc = loopcxt_setup_device(&lc);
1430 if (rc == 0)
1431 break; /* success */
1432
1433 if (device || rc != -EBUSY)
1434 err(EXIT_FAILURE, "failed to setup device for %s",
1435 lc.filename);
1436
1437 printf("device stolen...trying again\n");
1438 } while (1);
1439
1440 loopcxt_deinit(&lc);
1441
1442 return 0;
1443}
1444
1445int main(int argc, char *argv[])
1446{
aee31ddc
KZ
1447 int dbg;
1448
10ee5932
KZ
1449 if (argc < 2)
1450 goto usage;
1451
aee31ddc
KZ
1452 dbg = getenv("LOOPDEV_DEBUG") == NULL ? 0 : 1;
1453
10ee5932
KZ
1454 if (argc == 3 && strcmp(argv[1], "--info") == 0) {
1455 printf("---sysfs & ioctl:---\n");
aee31ddc 1456 test_loop_info(argv[2], 0, dbg);
10ee5932 1457 printf("---sysfs only:---\n");
aee31ddc 1458 test_loop_info(argv[2], LOOPDEV_FL_NOIOCTL, dbg);
10ee5932 1459 printf("---ioctl only:---\n");
aee31ddc 1460 test_loop_info(argv[2], LOOPDEV_FL_NOSYSFS, dbg);
10ee5932
KZ
1461
1462 } else if (argc == 2 && strcmp(argv[1], "--used") == 0) {
1463 printf("---all used devices---\n");
aee31ddc 1464 test_loop_scan(LOOPITER_FL_USED, dbg);
10ee5932
KZ
1465
1466 } else if (argc == 2 && strcmp(argv[1], "--free") == 0) {
1467 printf("---all free devices---\n");
aee31ddc 1468 test_loop_scan(LOOPITER_FL_FREE, dbg);
10ee5932
KZ
1469
1470 } else if (argc >= 3 && strcmp(argv[1], "--setup") == 0) {
aee31ddc 1471 test_loop_setup(argv[2], argv[3], dbg);
10ee5932
KZ
1472
1473 } else if (argc == 3 && strcmp(argv[1], "--delete") == 0) {
1474 if (loopdev_delete(argv[2]))
1475 errx(EXIT_FAILURE, "failed to deinitialize device %s", argv[2]);
1476 } else
1477 goto usage;
1478
1479 return EXIT_SUCCESS;
1480
1481usage:
1482 errx(EXIT_FAILURE, "usage: \n"
1483 " %1$s --info <device>\n"
1484 " %1$s --free\n"
1485 " %1$s --used\n"
1486 " %1$s --setup <filename> [<device>]\n"
1487 " %1$s --delete\n",
1488 argv[0]);
1489}
1490
1491#endif /* TEST_PROGRAM */