summaryrefslogtreecommitdiffstats
path: root/mount/lomount.c
diff options
context:
space:
mode:
authorKarel Zak2006-12-07 00:25:34 +0100
committerKarel Zak2006-12-07 00:25:34 +0100
commitfd6b7a7ffc50400704beb41d5a23af5f9edb1eed (patch)
tree997c0ca2abc018369babd7da59bcd0afe492068e /mount/lomount.c
parentImported from util-linux-2.5 tarball. (diff)
downloadkernel-qcow2-util-linux-fd6b7a7ffc50400704beb41d5a23af5f9edb1eed.tar.gz
kernel-qcow2-util-linux-fd6b7a7ffc50400704beb41d5a23af5f9edb1eed.tar.xz
kernel-qcow2-util-linux-fd6b7a7ffc50400704beb41d5a23af5f9edb1eed.zip
Imported from util-linux-2.7.1 tarball.
Diffstat (limited to 'mount/lomount.c')
-rw-r--r--mount/lomount.c232
1 files changed, 145 insertions, 87 deletions
diff --git a/mount/lomount.c b/mount/lomount.c
index 5dd02d8bb..a6ad187ae 100644
--- a/mount/lomount.c
+++ b/mount/lomount.c
@@ -1,4 +1,8 @@
/* Taken from Ted's losetup.c - Mitch <m.dsouza@mrc-apu.cam.ac.uk> */
+/* Added vfs mount options - aeb - 960223 */
+/* Removed lomount - aeb - 960224 */
+
+#define PROC_DEVICES "/proc/devices"
/*
* losetup.c - setup and control loop devices
@@ -8,71 +12,62 @@
#include <string.h>
#include <ctype.h>
#include <fcntl.h>
+#include <errno.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/ioctl.h>
-#include <linux/fs.h>
-#include "loop.h"
+#include <sys/stat.h>
-char *crypt_name (int);
-int crypt_type (char *);
-void show_loop (char *);
-int del_loop (const char *);
-int set_loop (const char *, const char *, int offset, char *);
-int lomount (const char *, const char *, const char *, char **,
- int *, char **, char **);
+#if defined(__GLIBC__)
+#define _SOCKETBITS_H
+#endif /* __GLIBC */
+#include "sundries.h" /* for xstrdup */
+#include "loop.h"
+#include "lomount.h"
+#ifdef LOOP_SET_FD
struct crypt_type_struct {
int id;
char *name;
} crypt_type_tbl[] = {
-
- {
- LO_CRYPT_NONE, "no"
- },
- {
- LO_CRYPT_NONE, "none"
- },
- {
- LO_CRYPT_XOR, "xor"
- },
- {
- LO_CRYPT_DES, "DES"
- },
- {
- -1, NULL
- }
+ { LO_CRYPT_NONE, "no" },
+ { LO_CRYPT_NONE, "none" },
+ { LO_CRYPT_XOR, "xor" },
+ { LO_CRYPT_DES, "DES" },
+ { -1, NULL }
};
-char *
-crypt_name (int id)
+static int
+crypt_type (const char *name)
{
int i;
- for (i = 0; crypt_type_tbl[i].id != -1; i++)
- if (id == crypt_type_tbl[i].id)
- return crypt_type_tbl[i].name;
- return "undefined";
+ if (name)
+ for (i = 0; crypt_type_tbl[i].id != -1; i++)
+ if (!strcasecmp (name, crypt_type_tbl[i].name))
+ return crypt_type_tbl[i].id;
+ return -1;
}
-int
-crypt_type (char *name)
+#if 0
+static char *
+crypt_name (int id)
{
int i;
for (i = 0; crypt_type_tbl[i].id != -1; i++)
- if (!strcasecmp (name, crypt_type_tbl[i].name))
- return crypt_type_tbl[i].id;
- return -1;
+ if (id == crypt_type_tbl[i].id)
+ return crypt_type_tbl[i].name;
+ return "undefined";
}
-void
+static void
show_loop (char *device)
{
struct loop_info loopinfo;
int fd;
- if ((fd = open (device, O_RDWR)) < 0) {
+ if ((fd = open (device, O_RDONLY)) < 0) {
fprintf(stderr, "loop: can't open device %s: %s\n",
device, strerror (errno));
return;
@@ -89,24 +84,97 @@ show_loop (char *device)
crypt_name (loopinfo.lo_encrypt_type));
close (fd);
}
+#endif
+
+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];
+ int i, fd, somedev = 0, someloop = 0, loop_known = 0;
+ struct stat statbuf;
+ struct loop_info loopinfo;
+ FILE *procdev;
+
+ for(i = 0; i < 256; i++) {
+ sprintf(dev, "/dev/loop%d", i);
+ if (stat (dev, &statbuf) == 0 && S_ISBLK(statbuf.st_mode)) {
+ somedev++;
+ fd = open (dev, O_RDONLY);
+ if (fd >= 0) {
+ if(ioctl (fd, LOOP_GET_STATUS, &loopinfo) == 0)
+ someloop++; /* in use */
+ else if (errno == ENXIO) {
+ close (fd);
+ return xstrdup(dev); /* probably free */
+ }
+ close (fd);
+ }
+ continue; /* continue trying as long as devices exist */
+ }
+ if (i >= 7)
+ break;
+ }
+
+ /* Nothing found. Why not? */
+ if ((procdev = fopen(PROC_DEVICES, "r")) != NULL) {
+ char line[100];
+ while (fgets (line, sizeof(line), procdev))
+ if (strstr (line, " loop\n")) {
+ loop_known = 1;
+ break;
+ }
+ fclose(procdev);
+ if (!loop_known)
+ loop_known = -1;
+ }
+
+ if (!somedev)
+ error("mount: could not find any device /dev/loop#");
+ else if(!someloop) {
+ if (loop_known == 1)
+ error(
+"mount: Could not find any loop device.\n"
+" Maybe /dev/loop# has a wrong major number?\n");
+ else if (loop_known == -1)
+ error(
+"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 `insmod loop.o'.)\n", PROC_DEVICES);
+ else
+ error(
+"mount: Could not find any loop device. Maybe this kernel does not know\n"
+" about the loop device (then recompile or `insmod loop.o'), or\n"
+" maybe /dev/loop# has the wrong major number?\n");
+ } else
+ error("mount: could not find any free loop device");
+ return 0;
+}
int
-set_loop (const char *device, const char *file, int offset, char *encryption)
+set_loop (const char *device, const char *file, int offset,
+ const char *encryption, int *loopro)
{
struct loop_info loopinfo;
- int fd,
- ffd,
- i;
+ int fd, ffd, mode, i;
char *pass;
- if ((fd = open (device, O_RDWR)) < 0) {
- perror (device);
- return 1;
+ mode = (*loopro ? O_RDONLY : O_RDWR);
+ if ((ffd = open (file, mode)) < 0) {
+ if (!*loopro && errno == EROFS)
+ ffd = open (file, mode = O_RDONLY);
+ if (ffd < 0) {
+ perror (file);
+ return 1;
+ }
}
- if ((ffd = open (file, O_RDWR)) < 0) {
- perror (file);
+ if ((fd = open (device, mode)) < 0) {
+ perror (device);
return 1;
}
+ *loopro = (mode == O_RDONLY);
memset (&loopinfo, 0, sizeof (loopinfo));
strncpy (loopinfo.lo_name, file, LO_NAME_SIZE);
loopinfo.lo_name[LO_NAME_SIZE - 1] = 0;
@@ -159,6 +227,8 @@ set_loop (const char *device, const char *file, int offset, char *encryption)
}
close (fd);
close (ffd);
+ if (verbose > 1)
+ printf("set_loop(%s,%s,%d): success\n", device, file, offset);
return 0;
}
@@ -173,51 +243,39 @@ del_loop (const char *device)
return 1;
}
if (ioctl (fd, LOOP_CLR_FD, 0) < 0) {
-#if 0
perror ("ioctl: LOOP_CLR_FD");
-#endif
return 1;
}
+ close (fd);
+ if (verbose > 1)
+ printf("del_loop(%s): success\n", device);
return 0;
}
+#else /* no LOOP_SET_FD defined */
+static void
+mutter(void) {
+ fprintf(stderr,
+ "This mount was compiled without loop support. Please recompile.\n");
+}
-int
-lomount (const char *spec, const char *node, const char *device, char **type,
- int *flags, char **extra_opts, char **mount_opts)
-{
- char *opt,
- *opteq;
- int val;
- char *encryption = NULL, *vfs = NULL;
- int offset = 0, err;
- char new_opts[1024];
-
- for (opt = strtok (*extra_opts, ","); opt; opt = strtok (NULL, ",")) {
- if ((opteq = strchr (opt, '='))) {
- val = atoi (opteq + 1);
- *opteq = '\0';
- if (!strcmp (opt, "encryption"))
- encryption = strdup(opteq + 1);
- else if (!strcmp (opt, "vfs"))
- vfs = strdup(opteq + 1);
- else if (!strcmp (opt, "offset"))
- offset = val;
- else {
- printf ("unknown loop mount parameter: "
- "%s=%d (%s)\n", opt, val, opteq+1);
- return 1;
- }
- } else {
- printf ("unknown loop mount parameter: "
- "%s\n", opt);
- return 1;
- }
- }
- err = set_loop (device, spec, offset, encryption);
- sprintf(new_opts, "vfs=%s,offset=%d,encryption=%s",
- *type = vfs ? vfs : FSTYPE_DEFAULT, offset,
- encryption=crypt_type(encryption)<0?"none":encryption);
- *extra_opts=strdup(new_opts);
- return err;
+int
+set_loop (const char *device, const char *file, int offset,
+ const char *encryption, int *loopro) {
+ mutter();
+ return 1;
+}
+
+int
+del_loop (const char *device) {
+ mutter();
+ return 1;
}
+
+char *
+find_unused_loop_device (void) {
+ mutter();
+ return 0;
+}
+
+#endif