From 22853e4a82c6ef7b336527529acb94b14a0b0fd8 Mon Sep 17 00:00:00 2001 From: Karel Zak Date: Thu, 7 Dec 2006 00:25:43 +0100 Subject: Imported from util-linux-2.10m tarball. --- mount/lomount.c | 553 ++++++++++++++++++++++++++++++++++---------------------- 1 file changed, 339 insertions(+), 214 deletions(-) (limited to 'mount/lomount.c') 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 #include #include +#include #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 +#include + +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 -- cgit v1.2.3-55-g7522