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
25 #include <sys/ioctl.h>
28 #include <sys/types.h>
30 #include "sysmacros.h"
31 #include <linux/loop.h>
36 #ifndef LOOP_CTL_GET_FREE
37 #define LOOP_CTL_GET_FREE 0x4C82
40 #if !defined (__alpha__) && !defined (__ia64__) && !defined (__x86_64__) \
41 && !defined (__s390x__)
42 #define int2ptr(x) ((void *) ((int) x))
44 #define int2ptr(x) ((void *) ((long) x))
48 xstrdup (const char *s)
58 fprintf(stderr, "not enough memory");
66 is_loop_device (const char *device)
78 if ((procdev = fopen(PROC_DEVICES, "r")) != NULL) {
80 while (fgets (line, sizeof(line), procdev)) {
82 if ((cp = strstr (line, " loop\n")) != NULL) {
92 return (loopmajor && stat(device, &statbuf) == 0 &&
93 S_ISBLK(statbuf.st_mode) &&
94 major(statbuf.st_rdev) == loopmajor);
97 #define SIZE(a) (sizeof(a)/sizeof(a[0]))
100 find_loop_by_file (const char * filename)
104 char dev[64], *found = NULL;
107 struct loop_info loopinfo;
109 dir = opendir("/dev");
113 while ((dent = readdir(dir)) != NULL) {
114 if (strncmp(dent->d_name,"loop",4))
116 if (!strcmp(dent->d_name, "loop-control"))
118 sprintf(dev, "/dev/%s", dent->d_name);
120 fd = open (dev, O_RDONLY);
124 if (fstat (fd, &statbuf) != 0 ||
125 !S_ISBLK(statbuf.st_mode)) {
130 if (ioctl (fd, LOOP_GET_STATUS, &loopinfo) != 0) {
135 if (0 == strcmp(filename, loopinfo.lo_name)) {
137 found = xstrdup(dev);
148 find_unused_loop_device (void)
150 char dev[20], *next_loop_dev = NULL;
151 int fd, next_loop = 0, somedev = 0, someloop = 0, loop_known = 0;
153 struct loop_info loopinfo;
156 while (next_loop_dev == NULL) {
157 if (stat("/dev/loop-control", &statbuf) == 0 &&
158 S_ISCHR(statbuf.st_mode)) {
161 next_loop_fd = open("/dev/loop-control", O_RDWR);
162 if (next_loop_fd < 0)
164 next_loop = ioctl(next_loop_fd, LOOP_CTL_GET_FREE);
170 sprintf(dev, "/dev/loop%d", next_loop);
172 fd = open (dev, O_RDONLY);
174 if (fstat (fd, &statbuf) == 0 &&
175 S_ISBLK(statbuf.st_mode)) {
177 if(ioctl (fd, LOOP_GET_STATUS, &loopinfo) == 0)
178 someloop++; /* in use */
179 else if (errno == ENXIO)
180 next_loop_dev = xstrdup(dev);
185 /* continue trying as long as devices exist */
191 return next_loop_dev;
193 /* Nothing found. Why not? */
194 if ((procdev = fopen(PROC_DEVICES, "r")) != NULL) {
197 while (fgets (line, sizeof(line), procdev))
199 if (strstr (line, " loop\n")) {
211 fprintf(stderr, "mount: could not find any device /dev/loop#");
213 else if (!someloop) {
216 "mount: Could not find any loop device.\n"
217 " Maybe /dev/loop# has a wrong major number?");
218 else if (loop_known == -1)
220 "mount: Could not find any loop device, and, according to %s,\n"
221 " this kernel does not know about the loop device.\n"
222 " (If so, then recompile or `modprobe loop'.)",
226 "mount: Could not find any loop device. Maybe this kernel does not know\n"
227 " about the loop device (then recompile or `modprobe loop'), or\n"
228 " maybe /dev/loop# has the wrong major number?");
230 fprintf(stderr, "mount: could not find any free loop device");
235 set_loop (const char *device, const char *file, int offset, int *loopro)
237 struct loop_info loopinfo;
240 mode = (*loopro ? O_RDONLY : O_RDWR);
242 if ((ffd = open (file, mode)) < 0) {
244 if (!*loopro && (errno == EROFS || errno == EACCES))
245 ffd = open (file, mode = O_RDONLY);
253 if ((fd = open (device, mode)) < 0) {
259 *loopro = (mode == O_RDONLY);
260 memset (&loopinfo, 0, sizeof (loopinfo));
262 xstrncpy (loopinfo.lo_name, file, LO_NAME_SIZE);
263 loopinfo.lo_offset = offset;
264 loopinfo.lo_encrypt_type = LO_CRYPT_NONE;
265 loopinfo.lo_encrypt_key_size = 0;
267 if (ioctl (fd, LOOP_SET_FD, int2ptr(ffd)) < 0) {
268 perror ("ioctl: LOOP_SET_FD");
274 if (ioctl (fd, LOOP_SET_STATUS, &loopinfo) < 0) {
275 (void) ioctl (fd, LOOP_CLR_FD, 0);
276 perror ("ioctl: LOOP_SET_STATUS");
288 del_loop (const char *device)
293 if ((fd = open (device, O_RDONLY)) < 0) {
295 fprintf(stderr, "loop: can't delete device %s: %s\n",
296 device, strerror (errsv));
300 while (ioctl (fd, LOOP_CLR_FD, 0) < 0) {
301 if (errno != EBUSY || retries-- <= 0) {
302 perror ("ioctl: LOOP_CLR_FD");
307 "loop: device %s still in use, retrying delete\n",