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 <sysmacros.h>
29 #include <asm/posix_types.h>
30 #include <linux/loop.h>
35 #ifndef LOOP_CTL_GET_FREE
36 #define LOOP_CTL_GET_FREE 0x4C82
39 #if !defined (__alpha__) && !defined (__ia64__) && !defined (__x86_64__) \
40 && !defined (__s390x__)
41 #define int2ptr(x) ((void *) ((int) x))
43 #define int2ptr(x) ((void *) ((long) x))
47 xstrdup (const char *s)
57 fprintf(stderr, "not enough memory");
65 is_loop_device (const char *device)
77 if ((procdev = fopen(PROC_DEVICES, "r")) != NULL) {
79 while (fgets (line, sizeof(line), procdev)) {
81 if ((cp = strstr (line, " loop\n")) != NULL) {
91 return (loopmajor && stat(device, &statbuf) == 0 &&
92 S_ISBLK(statbuf.st_mode) &&
93 major(statbuf.st_rdev) == loopmajor);
96 #define SIZE(a) (sizeof(a)/sizeof(a[0]))
99 find_loop_by_file (const char * filename)
102 char *loop_formats[] = { "/dev/loop%d", "/dev/loop/%d" };
105 struct loop_info loopinfo;
109 if (stat (filename, &statbuf) != 0) {
112 file_dev = statbuf.st_dev;
113 file_ino = statbuf.st_ino;
115 for (j = 0; j < SIZE(loop_formats); j++) {
117 for (i = 0; i < 256; i++) {
118 sprintf (dev, loop_formats[j], i);
120 if (stat (dev, &statbuf) != 0 ||
121 !S_ISBLK(statbuf.st_mode))
124 fd = open (dev, O_RDONLY);
129 if (ioctl (fd, LOOP_GET_STATUS, &loopinfo) != 0) {
134 if (loopinfo.lo_device == file_dev && loopinfo.lo_inode == file_ino) {
136 return xstrdup(dev); /*found */
147 find_unused_loop_device (void)
149 /* Just creating a device, say in /tmp, is probably a bad idea -
150 people might have problems with backup or so.
151 So, we just try /dev/loop[0-7]. */
154 char *loop_formats[] = { "/dev/loop%d", "/dev/loop/%d" };
155 int i, j, fd, first = 0, somedev = 0, someloop = 0, loop_known = 0;
157 struct loop_info loopinfo;
160 if (stat("/dev/loop-control", &statbuf) == 0 &&
161 S_ISCHR(statbuf.st_mode)) {
162 fd = open("/dev/loop-control", O_RDWR);
164 first = ioctl(fd, LOOP_CTL_GET_FREE);
169 for (j = 0; j < SIZE(loop_formats); j++) {
171 for(i = first; i < 256; i++) {
172 sprintf(dev, loop_formats[j], i);
174 if (stat (dev, &statbuf) == 0 && S_ISBLK(statbuf.st_mode)) {
176 fd = open (dev, O_RDONLY);
180 if(ioctl (fd, LOOP_GET_STATUS, &loopinfo) == 0)
181 someloop++; /* in use */
183 else if (errno == ENXIO) {
185 return xstrdup(dev);/* probably free */
191 /* continue trying as long as devices exist */
198 /* Nothing found. Why not? */
199 if ((procdev = fopen(PROC_DEVICES, "r")) != NULL) {
202 while (fgets (line, sizeof(line), procdev))
204 if (strstr (line, " loop\n")) {
216 fprintf(stderr, "mount: could not find any device /dev/loop#");
218 else if (!someloop) {
222 "mount: Could not find any loop device.\n"
223 " Maybe /dev/loop# has a wrong major number?");
225 else if (loop_known == -1)
227 "mount: Could not find any loop device, and, according to %s,\n"
228 " this kernel does not know about the loop device.\n"
229 " (If so, then recompile or `modprobe loop'.)",
234 "mount: Could not find any loop device. Maybe this kernel does not know\n"
235 " about the loop device (then recompile or `modprobe loop'), or\n"
236 " maybe /dev/loop# has the wrong major number?");
239 fprintf(stderr, "mount: could not find any free loop device");
245 set_loop (const char *device, const char *file, int offset, int *loopro)
247 struct loop_info loopinfo;
250 mode = (*loopro ? O_RDONLY : O_RDWR);
252 if ((ffd = open (file, mode)) < 0) {
254 if (!*loopro && (errno == EROFS || errno == EACCES))
255 ffd = open (file, mode = O_RDONLY);
263 if ((fd = open (device, mode)) < 0) {
268 *loopro = (mode == O_RDONLY);
269 memset (&loopinfo, 0, sizeof (loopinfo));
271 xstrncpy (loopinfo.lo_name, file, LO_NAME_SIZE);
272 loopinfo.lo_offset = offset;
273 loopinfo.lo_encrypt_type = LO_CRYPT_NONE;
274 loopinfo.lo_encrypt_key_size = 0;
276 if (ioctl (fd, LOOP_SET_FD, int2ptr(ffd)) < 0) {
277 perror ("ioctl: LOOP_SET_FD");
283 if (ioctl (fd, LOOP_SET_STATUS, &loopinfo) < 0) {
284 (void) ioctl (fd, LOOP_CLR_FD, 0);
285 perror ("ioctl: LOOP_SET_STATUS");
297 del_loop (const char *device)
302 if ((fd = open (device, O_RDONLY)) < 0) {
304 fprintf(stderr, "loop: can't delete device %s: %s\n",
305 device, strerror (errsv));
309 while (ioctl (fd, LOOP_CLR_FD, 0) < 0) {
310 if (errno != EBUSY || retries-- <= 0) {
311 perror ("ioctl: LOOP_CLR_FD");
316 "loop: device %s still in use, retrying delete\n",