summaryrefslogtreecommitdiffstats
path: root/mount/lomount.c
diff options
context:
space:
mode:
authorKarel Zak2006-12-07 00:25:32 +0100
committerKarel Zak2006-12-07 00:25:32 +0100
commit6dbe3af945a63f025561abb83275cee9ff06c57b (patch)
tree19e59eac8ac465b5bc409b5adf815b582c92f633 /mount/lomount.c
downloadkernel-qcow2-util-linux-6dbe3af945a63f025561abb83275cee9ff06c57b.tar.gz
kernel-qcow2-util-linux-6dbe3af945a63f025561abb83275cee9ff06c57b.tar.xz
kernel-qcow2-util-linux-6dbe3af945a63f025561abb83275cee9ff06c57b.zip
Imported from util-linux-2.2 tarball.
Diffstat (limited to 'mount/lomount.c')
-rw-r--r--mount/lomount.c223
1 files changed, 223 insertions, 0 deletions
diff --git a/mount/lomount.c b/mount/lomount.c
new file mode 100644
index 000000000..5dd02d8bb
--- /dev/null
+++ b/mount/lomount.c
@@ -0,0 +1,223 @@
+/* Taken from Ted's losetup.c - Mitch <m.dsouza@mrc-apu.cam.ac.uk> */
+
+/*
+ * losetup.c - setup and control loop devices
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/ioctl.h>
+#include <linux/fs.h>
+#include "loop.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 **);
+
+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
+ }
+};
+
+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";
+}
+
+int
+crypt_type (char *name)
+{
+ 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;
+}
+
+void
+show_loop (char *device)
+{
+ struct loop_info loopinfo;
+ int fd;
+
+ if ((fd = open (device, O_RDWR)) < 0) {
+ fprintf(stderr, "loop: can't open device %s: %s\n",
+ device, strerror (errno));
+ return;
+ }
+ if (ioctl (fd, LOOP_GET_STATUS, &loopinfo) < 0) {
+ fprintf(stderr, "loop: can't get info on device %s: %s\n",
+ device, strerror (errno));
+ 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);
+}
+
+int
+set_loop (const char *device, const char *file, int offset, char *encryption)
+{
+ struct loop_info loopinfo;
+ int fd,
+ ffd,
+ i;
+ char *pass;
+
+ if ((fd = open (device, O_RDWR)) < 0) {
+ perror (device);
+ return 1;
+ }
+ if ((ffd = open (file, O_RDWR)) < 0) {
+ perror (file);
+ return 1;
+ }
+ 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", 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);
+ return 0;
+}
+
+int
+del_loop (const char *device)
+{
+ int fd;
+
+ if ((fd = open (device, O_RDONLY)) < 0) {
+ fprintf(stderr, "loop: can't delete device %s: %s\n",
+ device, strerror (errno));
+ return 1;
+ }
+ if (ioctl (fd, LOOP_CLR_FD, 0) < 0) {
+#if 0
+ perror ("ioctl: LOOP_CLR_FD");
+#endif
+ return 1;
+ }
+ return 0;
+}
+
+
+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;
+}