summaryrefslogtreecommitdiffstats
path: root/mount/lomount.c
diff options
context:
space:
mode:
authorKarel Zak2006-12-07 00:25:43 +0100
committerKarel Zak2006-12-07 00:25:43 +0100
commit22853e4a82c6ef7b336527529acb94b14a0b0fd8 (patch)
treeee28e4598c8c449d7e811711d8ce8eb17caecfb6 /mount/lomount.c
parentImported from util-linux-2.10f tarball. (diff)
downloadkernel-qcow2-util-linux-22853e4a82c6ef7b336527529acb94b14a0b0fd8.tar.gz
kernel-qcow2-util-linux-22853e4a82c6ef7b336527529acb94b14a0b0fd8.tar.xz
kernel-qcow2-util-linux-22853e4a82c6ef7b336527529acb94b14a0b0fd8.zip
Imported from util-linux-2.10m tarball.
Diffstat (limited to 'mount/lomount.c')
-rw-r--r--mount/lomount.c553
1 files changed, 339 insertions, 214 deletions
diff --git a/mount/lomount.c b/mount/lomount.c
index d99078585..52157a14a 100644
--- a/mount/lomount.c
+++ b/mount/lomount.c
@@ -23,268 +23,393 @@
#include <unistd.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
+#include <sys/mman.h>
#include "loop.h"
#include "lomount.h"
#include "nls.h"
-char *xstrdup (const char *s); /* not: #include "sundries.h" */
-void error (const char *fmt, ...); /* idem */
+extern int verbose;
+extern char *xstrdup (const char *s); /* not: #include "sundries.h" */
+extern void error (const char *fmt, ...); /* idem */
#ifdef LOOP_SET_FD
struct crypt_type_struct {
- int id;
- char *name;
+ 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 }
};
static int
-crypt_type (const char *name)
-{
- int i;
-
- 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;
+crypt_type (const char *name) {
+ int i;
+
+ 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;
}
-#if 0
+#ifdef MAIN
static char *
-crypt_name (int id)
-{
- 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";
+crypt_name (int id) {
+ 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";
}
static void
-show_loop (char *device)
-{
- struct loop_info loopinfo;
- int fd;
-
- if ((fd = open (device, O_RDONLY)) < 0) {
- int errsv = errno;
- fprintf(stderr, _("loop: can't open device %s: %s\n"),
- device, strerror (errsv));
- return;
- }
- if (ioctl (fd, LOOP_GET_STATUS, &loopinfo) < 0) {
- int errsv = errno;
- fprintf(stderr, _("loop: can't get info on device %s: %s\n"),
- device, strerror (errsv));
- close (fd);
- return;
- }
- printf (_("%s: [%04x]:%ld (%s) offset %d, %s encryption\n"),
- device, loopinfo.lo_device, loopinfo.lo_inode,
- loopinfo.lo_name, loopinfo.lo_offset,
- crypt_name (loopinfo.lo_encrypt_type));
- close (fd);
+show_loop (char *device) {
+ struct loop_info loopinfo;
+ int fd;
+
+ if ((fd = open (device, O_RDONLY)) < 0) {
+ int errsv = errno;
+ fprintf(stderr, _("loop: can't open device %s: %s\n"),
+ device, strerror (errsv));
+ return;
+ }
+ if (ioctl (fd, LOOP_GET_STATUS, &loopinfo) < 0) {
+ int errsv = errno;
+ fprintf(stderr, _("loop: can't get info on device %s: %s\n"),
+ device, strerror (errsv));
+ close (fd);
+ return;
+ }
+ printf (_("%s: [%04x]:%ld (%s) offset %d, %s encryption\n"),
+ device, loopinfo.lo_device, loopinfo.lo_inode,
+ loopinfo.lo_name, loopinfo.lo_offset,
+ 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;
+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;
}
- 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?"));
- 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'.)"), 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?"));
- } else
- error(_("mount: could not find any free loop device"));
- return 0;
+
+ /* 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?"));
+ 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'.)"),
+ 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?"));
+ } else
+ error(_("mount: could not find any free loop device"));
+ return 0;
}
int
set_loop (const char *device, const char *file, int offset,
- const char *encryption, int *loopro)
-{
- struct loop_info loopinfo;
- int fd, ffd, mode, i;
- char *pass;
-
- 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 ((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;
- if (encryption && (loopinfo.lo_encrypt_type = crypt_type (encryption))
- < 0) {
- fprintf (stderr, _("Unsupported encryption type %s\n"), encryption);
- return 1;
- }
- loopinfo.lo_offset = offset;
- switch (loopinfo.lo_encrypt_type) {
- case LO_CRYPT_NONE:
- loopinfo.lo_encrypt_key_size = 0;
- break;
- case LO_CRYPT_XOR:
- pass = getpass (_("Password: "));
- strncpy (loopinfo.lo_encrypt_key, pass, LO_KEY_SIZE);
- loopinfo.lo_encrypt_key[LO_KEY_SIZE - 1] = 0;
- loopinfo.lo_encrypt_key_size = strlen (loopinfo.lo_encrypt_key);
- break;
- case LO_CRYPT_DES:
- pass = getpass (_("Password: "));
- strncpy (loopinfo.lo_encrypt_key, pass, 8);
- loopinfo.lo_encrypt_key[8] = 0;
- loopinfo.lo_encrypt_key_size = 8;
- pass = getpass (_("Init (up to 16 hex digits): "));
- for (i = 0; i < 16 && pass[i]; i++)
- if (isxdigit (pass[i]))
- loopinfo.lo_init[i >> 3] |= (pass[i] > '9' ?
- (islower (pass[i]) ? toupper (pass[i]) :
- pass[i]) - 'A' + 10 : pass[i] - '0') << (i & 7) * 4;
- else {
- fprintf (stderr, _("Non-hex digit '%c'.\n"), pass[i]);
- return 1;
- }
- break;
- default:
- fprintf (stderr,
- _("Don't know how to get key for encryption system %d\n"),
- loopinfo.lo_encrypt_type);
- return 1;
- }
- if (ioctl (fd, LOOP_SET_FD, ffd) < 0) {
- perror ("ioctl: LOOP_SET_FD");
- return 1;
- }
- if (ioctl (fd, LOOP_SET_STATUS, &loopinfo) < 0) {
- (void) ioctl (fd, LOOP_CLR_FD, 0);
- perror ("ioctl: LOOP_SET_STATUS");
- return 1;
- }
- close (fd);
- close (ffd);
- if (verbose > 1)
- printf(_("set_loop(%s,%s,%d): success\n"), device, file, offset);
- return 0;
+ const char *encryption, int *loopro) {
+ struct loop_info loopinfo;
+ int fd, ffd, mode, i;
+ char *pass;
+
+ 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 ((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;
+ if (encryption && (loopinfo.lo_encrypt_type = crypt_type (encryption))
+ < 0) {
+ fprintf (stderr, _("Unsupported encryption type %s\n"),
+ encryption);
+ return 1;
+ }
+ loopinfo.lo_offset = offset;
+
+#ifdef MCL_FUTURE
+ /*
+ * Oh-oh, sensitive data coming up. Better lock into memory to prevent
+ * passwd etc being swapped out and left somewhere on disk.
+ */
+
+ if(mlockall(MCL_CURRENT|MCL_FUTURE)) {
+ perror("memlock");
+ fprintf(stderr, _("Couldn't lock into memory, exiting.\n"));
+ exit(1);
+ }
+#endif
+
+ switch (loopinfo.lo_encrypt_type) {
+ case LO_CRYPT_NONE:
+ loopinfo.lo_encrypt_key_size = 0;
+ break;
+ case LO_CRYPT_XOR:
+ pass = getpass (_("Password: "));
+ strncpy (loopinfo.lo_encrypt_key, pass, LO_KEY_SIZE);
+ loopinfo.lo_encrypt_key[LO_KEY_SIZE - 1] = 0;
+ loopinfo.lo_encrypt_key_size = strlen(loopinfo.lo_encrypt_key);
+ break;
+ case LO_CRYPT_DES:
+ pass = getpass (_("Password: "));
+ strncpy (loopinfo.lo_encrypt_key, pass, 8);
+ loopinfo.lo_encrypt_key[8] = 0;
+ loopinfo.lo_encrypt_key_size = 8;
+ pass = getpass (_("Init (up to 16 hex digits): "));
+ for (i = 0; i < 16 && pass[i]; i++)
+ if (isxdigit (pass[i])) {
+ loopinfo.lo_init[i >> 3] |= (pass[i] > '9' ?
+ (islower (pass[i]) ? toupper (pass[i]) :
+ pass[i])-'A'+10 : pass[i]-'0') << (i&7) * 4;
+ } else {
+ fprintf (stderr, _("Non-hex digit '%c'.\n"),
+ pass[i]);
+ return 1;
+ }
+ break;
+ default:
+ fprintf (stderr,
+ _("Don't know how to get key for encryption system %d\n"),
+ loopinfo.lo_encrypt_type);
+ return 1;
+ }
+ if (ioctl (fd, LOOP_SET_FD, ffd) < 0) {
+ perror ("ioctl: LOOP_SET_FD");
+ return 1;
+ }
+ if (ioctl (fd, LOOP_SET_STATUS, &loopinfo) < 0) {
+ (void) ioctl (fd, LOOP_CLR_FD, 0);
+ perror ("ioctl: LOOP_SET_STATUS");
+ return 1;
+ }
+ close (fd);
+ close (ffd);
+ if (verbose > 1)
+ printf(_("set_loop(%s,%s,%d): success\n"),
+ device, file, offset);
+ return 0;
}
int
-del_loop (const char *device)
-{
- int fd;
-
- if ((fd = open (device, O_RDONLY)) < 0) {
- int errsv = errno;
- fprintf(stderr, _("loop: can't delete device %s: %s\n"),
- device, strerror (errsv));
- return 1;
- }
- if (ioctl (fd, LOOP_CLR_FD, 0) < 0) {
- perror ("ioctl: LOOP_CLR_FD");
- return 1;
- }
- close (fd);
- if (verbose > 1)
- printf(_("del_loop(%s): success\n"), device);
- return 0;
+del_loop (const char *device) {
+ int fd;
+
+ if ((fd = open (device, O_RDONLY)) < 0) {
+ int errsv = errno;
+ fprintf(stderr, _("loop: can't delete device %s: %s\n"),
+ device, strerror (errsv));
+ return 1;
+ }
+ if (ioctl (fd, LOOP_CLR_FD, 0) < 0) {
+ perror ("ioctl: LOOP_CLR_FD");
+ 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"));
+ fprintf(stderr,
+ _("This mount was compiled without loop support. "
+ "Please recompile.\n"));
}
int
set_loop (const char *device, const char *file, int offset,
const char *encryption, int *loopro) {
- mutter();
- return 1;
+ mutter();
+ return 1;
}
int
del_loop (const char *device) {
- mutter();
- return 1;
+ mutter();
+ return 1;
}
char *
find_unused_loop_device (void) {
- mutter();
- return 0;
+ mutter();
+ return 0;
}
#endif
+
+#ifdef MAIN
+
+#ifdef LOOP_SET_FD
+
+#include <getopt.h>
+#include <stdarg.h>
+
+int verbose = 0;
+static char *progname;
+
+static void
+usage(void) {
+ fprintf(stderr, _("usage:\n\
+ %s loop_device # give info\n\
+ %s -d loop_device # delete\n\
+ %s [ -e encryption ] [ -o offset ] loop_device file # setup\n"),
+ progname, progname, progname);
+ exit(1);
+}
+
+char *
+xstrdup (const char *s) {
+ char *t;
+
+ if (s == NULL)
+ return NULL;
+
+ t = strdup (s);
+
+ if (t == NULL) {
+ fprintf(stderr, _("not enough memory"));
+ exit(1);
+ }
+
+ return t;
+}
+
+void
+error (const char *fmt, ...) {
+ va_list args;
+
+ va_start (args, fmt);
+ vfprintf (stderr, fmt, args);
+ va_end (args);
+ fprintf (stderr, "\n");
+}
+
+int
+main(int argc, char **argv) {
+ char *offset, *encryption;
+ int delete,off,c;
+ int res = 0;
+ int ro = 0;
+
+ setlocale(LC_ALL, "");
+ bindtextdomain(PACKAGE, LOCALEDIR);
+ textdomain(PACKAGE);
+
+ delete = off = 0;
+ offset = encryption = NULL;
+ progname = argv[0];
+ while ((c = getopt(argc,argv,"de:o:v")) != EOF) {
+ switch (c) {
+ case 'd':
+ delete = 1;
+ break;
+ case 'e':
+ encryption = optarg;
+ break;
+ case 'o':
+ offset = optarg;
+ break;
+ case 'v':
+ verbose = 1;
+ break;
+ default:
+ usage();
+ }
+ }
+ if (argc == 1) usage();
+ if ((delete && (argc != optind+1 || encryption || offset)) ||
+ (!delete && (argc < optind+1 || argc > optind+2)))
+ usage();
+ if (argc == optind+1) {
+ if (delete)
+ res = del_loop(argv[optind]);
+ else
+ show_loop(argv[optind]);
+ } else {
+ if (offset && sscanf(offset,"%d",&off) != 1)
+ usage();
+ res = set_loop(argv[optind],argv[optind+1],off,encryption,&ro);
+ }
+ return res;
+}
+
+#else /* LOOP_SET_FD not defined */
+
+int
+main(int argc, char **argv) {
+ fprintf(stderr,
+ _("No loop support was available at compile time. "
+ "Please recompile.\n"));
+ return -1;
+}
+#endif
+#endif