1 /* Taken from Ted's losetup.c - Mitch <m.dsouza@mrc-apu.cam.ac.uk> */
2 /* Added vfs mount options - aeb - 960223 */
3 /* Removed lomount - aeb - 960224 */
5 /* 1999-02-22 Arkadiusz MiĆkiewicz <misiek@pld.ORG.PL>
6 * - added Native Language Support
7 * Sun Mar 21 1999 - Arnaldo Carvalho de Melo <acme@conectiva.com.br>
8 * - fixed strerr(errno) in gettext calls
11 #define PROC_DEVICES "/proc/devices"
14 * losetup.c - setup and control loop devices
26 #include <sys/ioctl.h>
29 #include <sys/types.h>
31 #include <sys/sysmacros.h>
32 #include <linux/loop.h>
38 #ifndef LOOP_CTL_GET_FREE
39 #define LOOP_CTL_GET_FREE 0x4C82
42 #define SIZE(a) (sizeof(a)/sizeof(a[0]))
44 char *find_loop_by_file(const char *filename)
48 char dev[64], *found = NULL, *p;
51 struct loop_info loopinfo;
52 const char VIRT_BLOCK[] = "/sys/devices/virtual/block";
54 char bf_path[PATH_MAX];
55 char backing_file[PATH_MAX];
57 dir = opendir(VIRT_BLOCK);
61 while ((dent = readdir(dir)) != NULL) {
62 if (strncmp(dent->d_name,"loop",4))
65 if (snprintf(path, PATH_MAX, "%s/%s/dev", VIRT_BLOCK,
66 dent->d_name) >= PATH_MAX)
69 fd = open(path, O_RDONLY);
73 bytes_read = read(fd, dev, sizeof(dev) - 1);
74 if (bytes_read <= 0) {
81 dev[bytes_read] = '\0';
82 p = strchr(dev, '\n');
85 if (snprintf(path, PATH_MAX, "/dev/block/%s", dev) >= PATH_MAX)
88 fd = open (path, O_RDONLY);
92 if (fstat (fd, &statbuf) != 0 ||
93 !S_ISBLK(statbuf.st_mode)) {
98 if (ioctl (fd, LOOP_GET_STATUS, &loopinfo) != 0) {
105 if (0 == strcmp(filename, loopinfo.lo_name)) {
106 found = realpath(path, NULL);
111 * filename is a realpath, while loopinfo.lo_name may hold just the
112 * basename. If that's the case, try to match filename against the
113 * backing_file entry for this loop entry
115 if (snprintf(bf_path, PATH_MAX, "%s/%s/loop/backing_file", VIRT_BLOCK,
116 dent->d_name) >= PATH_MAX)
119 fd = open(bf_path, O_RDONLY);
123 bytes_read = read(fd, backing_file, sizeof(backing_file) - 1);
124 if (bytes_read <= 0) {
131 backing_file[bytes_read-1] = '\0';
133 if (0 == strcmp(filename, backing_file)) {
134 found = realpath(path, NULL);
142 static char *find_unused_loop_device(int mode, int *loop_fd)
145 int fd, next_loop = 0, somedev = 0, someloop = 0, loop_known = 0;
148 struct loop_info loopinfo;
151 next_loop_fd = open("/dev/loop-control", O_RDWR);
152 if (next_loop_fd < 0)
155 if (!(fstat(next_loop_fd, &statbuf) == 0 && S_ISCHR(statbuf.st_mode)))
159 next_loop = ioctl(next_loop_fd, LOOP_CTL_GET_FREE);
163 sprintf(dev, "/dev/loop%d", next_loop);
165 fd = open (dev, mode);
167 if (fstat (fd, &statbuf) == 0 &&
168 S_ISBLK(statbuf.st_mode)) {
170 if(ioctl (fd, LOOP_GET_STATUS, &loopinfo) == 0)
171 someloop++; /* in use */
172 else if (errno == ENXIO) {
173 char *name = strdup(dev);
186 /* continue trying as long as devices exist */
195 /* Nothing found. Why not? */
196 if ((procdev = fopen(PROC_DEVICES, "r")) != NULL) {
199 while (fgets (line, sizeof(line), procdev))
201 if (strstr (line, " loop\n")) {
213 fprintf(stderr, "mount: could not find any device /dev/loop#\n");
215 else if (!someloop) {
218 "mount: Could not find any loop device.\n"
219 " Maybe /dev/loop# has a wrong major number?\n");
220 else if (loop_known == -1)
222 "mount: Could not find any loop device, and, according to %s,\n"
223 " this kernel does not know about the loop device.\n"
224 " (If so, then recompile or `modprobe loop'.)\n",
228 "mount: Could not find any loop device. Maybe this kernel does not know\n"
229 " about the loop device (then recompile or `modprobe loop'), or\n"
230 " maybe /dev/loop# has the wrong major number?\n");
232 fprintf(stderr, "mount: could not find any free loop device\n");
236 int set_loop(char **device, const char *file, int offset, int *loopro)
238 struct loop_info loopinfo;
239 int fd = -1, ret = 1, ffd, mode;
241 mode = (*loopro ? O_RDONLY : O_RDWR);
243 if ((ffd = open (file, mode)) < 0) {
245 if (!*loopro && (errno == EROFS || errno == EACCES))
246 ffd = open (file, mode = O_RDONLY);
254 *device = find_unused_loop_device(mode, &fd);
260 *loopro = (mode == O_RDONLY);
261 memset (&loopinfo, 0, sizeof (loopinfo));
263 xstrncpy (loopinfo.lo_name, file, LO_NAME_SIZE);
264 loopinfo.lo_offset = offset;
265 loopinfo.lo_encrypt_type = LO_CRYPT_NONE;
266 loopinfo.lo_encrypt_key_size = 0;
268 if (ioctl(fd, LOOP_SET_FD, (void*)(uintptr_t)(ffd)) < 0) {
269 perror ("ioctl: LOOP_SET_FD");
273 if (ioctl (fd, LOOP_SET_STATUS, &loopinfo) < 0) {
274 (void) ioctl (fd, LOOP_CLR_FD, 0);
275 perror ("ioctl: LOOP_SET_STATUS");
286 int del_loop(const char *device)
291 if ((fd = open (device, O_RDONLY)) < 0) {
293 fprintf(stderr, "loop: can't delete device %s: %s\n",
294 device, strerror (errsv));
298 while (ioctl (fd, LOOP_CLR_FD, 0) < 0) {
299 if (errno != EBUSY || retries-- <= 0) {
300 perror ("ioctl: LOOP_CLR_FD");
305 "loop: device %s still in use, retrying delete\n",