/* Added vfs mount options - aeb - 960223 */
/* Removed lomount - aeb - 960224 */
-/* 1999-02-22 Arkadiusz Mi¶kiewicz <misiek@pld.ORG.PL>
+/* 1999-02-22 Arkadiusz Miśkiewicz <misiek@pld.ORG.PL>
* - added Native Language Support
* Sun Mar 21 1999 - Arnaldo Carvalho de Melo <acme@conectiva.com.br>
* - fixed strerr(errno) in gettext calls
#include <fcntl.h>
#include <errno.h>
#include <stdlib.h>
+#include <stdint.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <sys/mman.h>
-#include <sysmacros.h>
-#include <asm/posix_types.h>
+#include <sys/types.h>
+#include <dirent.h>
+#include <sys/sysmacros.h>
#include <linux/loop.h>
+#include <limits.h>
#include "lopart.h"
#include "xstrncpy.h"
#define LOOP_CTL_GET_FREE 0x4C82
#endif
-#if !defined (__alpha__) && !defined (__ia64__) && !defined (__x86_64__) \
- && !defined (__s390x__)
-#define int2ptr(x) ((void *) ((int) x))
-#else
-#define int2ptr(x) ((void *) ((long) x))
-#endif
-
static char *
xstrdup (const char *s)
{
return t;
}
-extern int
-is_loop_device (const char *device)
-{
- struct stat statbuf;
- int loopmajor;
-#if 1
- loopmajor = 7;
-#else
- FILE *procdev;
- char line[100], *cp;
-
- loopmajor = 0;
-
- if ((procdev = fopen(PROC_DEVICES, "r")) != NULL) {
-
- while (fgets (line, sizeof(line), procdev)) {
-
- if ((cp = strstr (line, " loop\n")) != NULL) {
- *cp='\0';
- loopmajor=atoi(line);
- break;
- }
- }
-
- fclose(procdev);
- }
-#endif
- return (loopmajor && stat(device, &statbuf) == 0 &&
- S_ISBLK(statbuf.st_mode) &&
- major(statbuf.st_rdev) == loopmajor);
-}
-
#define SIZE(a) (sizeof(a)/sizeof(a[0]))
-extern char *
-find_loop_by_file (const char * filename)
+char *find_loop_by_file(const char *filename)
{
- char dev[64];
- char *loop_formats[] = { "/dev/loop%d", "/dev/loop/%d" };
- int i, j, fd;
+ DIR *dir;
+ struct dirent *dent;
+ char dev[64], *found = NULL, *p;
+ int fd, bytes_read;
struct stat statbuf;
struct loop_info loopinfo;
+ const char VIRT_BLOCK[] = "/sys/devices/virtual/block";
+ char path[PATH_MAX];
- for (j = 0; j < SIZE(loop_formats); j++) {
+ dir = opendir(VIRT_BLOCK);
+ if (!dir)
+ return NULL;
- for (i = 0; i < 256; i++) {
- sprintf (dev, loop_formats[j], i);
+ while ((dent = readdir(dir)) != NULL) {
+ if (strncmp(dent->d_name,"loop",4))
+ continue;
- if (stat (dev, &statbuf) != 0 ||
- !S_ISBLK(statbuf.st_mode))
- continue;
+ if (snprintf(path, PATH_MAX, "%s/%s/dev", VIRT_BLOCK,
+ dent->d_name) >= PATH_MAX)
+ continue;
- fd = open (dev, O_RDONLY);
+ fd = open(path, O_RDONLY);
+ if (fd < 0)
+ continue;
- if (fd < 0)
- break;
+ bytes_read = read(fd, dev, sizeof(dev) - 1);
+ if (bytes_read <= 0) {
+ close(fd);
+ continue;
+ }
- if (ioctl (fd, LOOP_GET_STATUS, &loopinfo) != 0) {
- close (fd);
- continue;
- }
+ close(fd);
- if (0 == strcmp(filename, loopinfo.lo_name)) {
- close (fd);
- return xstrdup(dev); /*found */
- }
+ dev[bytes_read] = '\0';
+ p = strchr(dev, '\n');
+ if (p != NULL)
+ *p = '\0';
+ if (snprintf(path, PATH_MAX, "/dev/block/%s", dev) >= PATH_MAX)
+ continue;
+ fd = open (path, O_RDONLY);
+ if (fd < 0)
+ continue;
+
+ if (fstat (fd, &statbuf) != 0 ||
+ !S_ISBLK(statbuf.st_mode)) {
close (fd);
continue;
}
+
+ if (ioctl (fd, LOOP_GET_STATUS, &loopinfo) != 0) {
+ close (fd);
+ continue;
+ }
+
+ close (fd);
+
+ if (0 == strcmp(filename, loopinfo.lo_name)) {
+ found = realpath(path, NULL);
+ break;
+ }
}
- return NULL;
+ closedir(dir);
+ return found;
}
-extern char *
-find_unused_loop_device (void)
+char *find_unused_loop_device(void)
{
- /* Just creating a device, say in /tmp, is probably a bad idea -
- people might have problems with backup or so.
- So, we just try /dev/loop[0-7]. */
-
- char dev[20];
- char *loop_formats[] = { "/dev/loop%d", "/dev/loop/%d" };
- int i, j, fd, first = 0, somedev = 0, someloop = 0, loop_known = 0;
+ char dev[20], *next_loop_dev = NULL;
+ int fd, next_loop = 0, somedev = 0, someloop = 0, loop_known = 0;
struct stat statbuf;
struct loop_info loopinfo;
FILE *procdev;
- if (stat("/dev/loop-control", &statbuf) == 0 &&
- S_ISCHR(statbuf.st_mode)) {
- fd = open("/dev/loop-control", O_RDWR);
- if (fd >= 0)
- first = ioctl(fd, LOOP_CTL_GET_FREE);
- close(fd);
- if (first < 0)
- first = 0;
- }
- for (j = 0; j < SIZE(loop_formats); j++) {
-
- for(i = first; i < 256; i++) {
- sprintf(dev, loop_formats[j], i);
-
- if (stat (dev, &statbuf) == 0 && S_ISBLK(statbuf.st_mode)) {
- somedev++;
- fd = open (dev, O_RDONLY);
+ while (next_loop_dev == NULL) {
+ if (stat("/dev/loop-control", &statbuf) == 0 &&
+ S_ISCHR(statbuf.st_mode)) {
+ int next_loop_fd;
+
+ next_loop_fd = open("/dev/loop-control", O_RDWR);
+ if (next_loop_fd < 0)
+ return NULL;
+ next_loop = ioctl(next_loop_fd, LOOP_CTL_GET_FREE);
+ close(next_loop_fd);
+ if (next_loop < 0)
+ return NULL;
+ }
- if (fd >= 0) {
+ sprintf(dev, "/dev/loop%d", next_loop);
+ fd = open (dev, O_RDONLY);
+ if (fd >= 0) {
+ if (fstat (fd, &statbuf) == 0 &&
+ S_ISBLK(statbuf.st_mode)) {
+ somedev++;
if(ioctl (fd, LOOP_GET_STATUS, &loopinfo) == 0)
someloop++; /* in use */
+ else if (errno == ENXIO)
+ next_loop_dev = xstrdup(dev);
- else if (errno == ENXIO) {
- close (fd);
- return xstrdup(dev);/* probably free */
- }
-
- close (fd);
}
-
+ close (fd);
+
/* continue trying as long as devices exist */
continue;
}
break;
- }
}
+ if (next_loop_dev)
+ return next_loop_dev;
/* Nothing found. Why not? */
if ((procdev = fopen(PROC_DEVICES, "r")) != NULL) {
fprintf(stderr, "mount: could not find any device /dev/loop#");
else if (!someloop) {
-
- if (loop_known == 1)
- fprintf(stderr,
- "mount: Could not find any loop device.\n"
- " Maybe /dev/loop# has a wrong major number?");
-
- else if (loop_known == -1)
- fprintf(stderr,
- "mount: Could not find any loop device, and, according to %s,\n"
- " this kernel does not know about the loop device.\n"
- " (If so, then recompile or `modprobe loop'.)",
- PROC_DEVICES);
-
- else
- fprintf(stderr,
- "mount: Could not find any loop device. Maybe this kernel does not know\n"
- " about the loop device (then recompile or `modprobe loop'), or\n"
- " maybe /dev/loop# has the wrong major number?");
-
+ if (loop_known == 1)
+ fprintf(stderr,
+ "mount: Could not find any loop device.\n"
+ " Maybe /dev/loop# has a wrong major number?");
+ else if (loop_known == -1)
+ fprintf(stderr,
+ "mount: Could not find any loop device, and, according to %s,\n"
+ " this kernel does not know about the loop device.\n"
+ " (If so, then recompile or `modprobe loop'.)",
+ PROC_DEVICES);
+ else
+ fprintf(stderr,
+ "mount: Could not find any loop device. Maybe this kernel does not know\n"
+ " about the loop device (then recompile or `modprobe loop'), or\n"
+ " maybe /dev/loop# has the wrong major number?");
} else
fprintf(stderr, "mount: could not find any free loop device");
-
- return 0;
+ return NULL;
}
-extern int
-set_loop (const char *device, const char *file, int offset, int *loopro)
+int set_loop(const char *device, const char *file, int offset, int *loopro)
{
struct loop_info loopinfo;
int fd, ffd, mode;
}
if ((fd = open (device, mode)) < 0) {
+ close(ffd);
perror (device);
return 1;
}
loopinfo.lo_encrypt_type = LO_CRYPT_NONE;
loopinfo.lo_encrypt_key_size = 0;
- if (ioctl (fd, LOOP_SET_FD, int2ptr(ffd)) < 0) {
+ if (ioctl(fd, LOOP_SET_FD, (void*)(uintptr_t)(ffd)) < 0) {
perror ("ioctl: LOOP_SET_FD");
close (fd);
close (ffd);
return 0;
}
-extern int
-del_loop (const char *device)
+int del_loop(const char *device)
{
- int retries = 3;
+ int retries = 5;
int fd;
if ((fd = open (device, O_RDONLY)) < 0) {