diff options
author | Karel Zak | 2006-12-07 00:26:14 +0100 |
---|---|---|
committer | Karel Zak | 2006-12-07 00:26:14 +0100 |
commit | d03dd60840f0a08464d5266539ad356aefe24b03 (patch) | |
tree | 0a9ad240a7a88eb6b11b152974a7a51a0df79b75 /mount | |
parent | Imported from util-linux-2.12pre tarball. (diff) | |
download | kernel-qcow2-util-linux-d03dd60840f0a08464d5266539ad356aefe24b03.tar.gz kernel-qcow2-util-linux-d03dd60840f0a08464d5266539ad356aefe24b03.tar.xz kernel-qcow2-util-linux-d03dd60840f0a08464d5266539ad356aefe24b03.zip |
Imported from util-linux-2.12a tarball.
Diffstat (limited to 'mount')
-rw-r--r-- | mount/Makefile | 7 | ||||
-rw-r--r-- | mount/fstab.c | 72 | ||||
-rw-r--r-- | mount/fstab.h | 4 | ||||
-rw-r--r-- | mount/h/loop.h | 37 | ||||
-rw-r--r-- | mount/linux_fs.h | 36 | ||||
-rw-r--r-- | mount/lomount.c | 367 | ||||
-rw-r--r-- | mount/lomount.h | 9 | ||||
-rw-r--r-- | mount/loop.h | 51 | ||||
-rw-r--r-- | mount/losetup.8 | 84 | ||||
-rw-r--r-- | mount/mk_loop_h | 34 | ||||
-rw-r--r-- | mount/mount.8 | 33 | ||||
-rw-r--r-- | mount/mount.c | 37 | ||||
-rw-r--r-- | mount/mount_by_label.c | 26 | ||||
-rw-r--r-- | mount/mount_guess_fstype.c | 28 | ||||
-rw-r--r-- | mount/my_dev_t.h | 7 | ||||
-rw-r--r-- | mount/pivot_root.2 | 97 | ||||
-rw-r--r-- | mount/pivot_root.c | 15 | ||||
-rw-r--r-- | mount/umount.c | 60 |
18 files changed, 565 insertions, 439 deletions
diff --git a/mount/Makefile b/mount/Makefile index 5e5ca58a4..964349412 100644 --- a/mount/Makefile +++ b/mount/Makefile @@ -72,7 +72,7 @@ mount.o: $(LIB)/setproctitle.h mount.o umount.o getusername.o: getusername.h -mount.o umount.o losetup.o lomount.o: lomount.h loop.h +mount.o umount.o losetup.o lomount.o: lomount.h loop.h my_dev_t.h swapon.o: swap_constants.h swapargs.h @@ -118,12 +118,9 @@ nfsmount.o: nfs_mount4.h swapargs.h: sh swap.configure -loop.h: - sh mk_loop_h - clean: rm -f a.out core *~ *.o swapargs.h $(PROGS) $(MAYBE) - rm -f loop.h nfs_mountversion.h + rm -f nfs_mountversion.h clobber distclean realclean: clean rm -f $(GEN_FILES) diff --git a/mount/fstab.c b/mount/fstab.c index 0d9b6e94f..85a5d2df3 100644 --- a/mount/fstab.c +++ b/mount/fstab.c @@ -100,7 +100,7 @@ read_mntentchn(mntFILE *mfp, const char *fnam, struct mntentchn *mc0) { struct mntent *mnt; while ((mnt = my_getmntent (mfp)) != NULL) { - if (!streq (mnt->mnt_type, MNTTYPE_IGNORE)) { + if (!streq(mnt->mnt_type, MNTTYPE_IGNORE)) { mc->nxt = (struct mntentchn *) xmalloc(sizeof(*mc)); mc->nxt->prev = mc; mc = mc->nxt; @@ -179,30 +179,62 @@ getmntfile (const char *name) { mc0 = mtab_head(); for (mc = mc0->nxt; mc && mc != mc0; mc = mc->nxt) - if (streq (mc->m.mnt_dir, name) || - streq (mc->m.mnt_fsname, name)) + if (streq(mc->m.mnt_dir, name) || + streq(mc->m.mnt_fsname, name)) return mc; return NULL; } /* - * Given the name NAME, and the place MCPREV we found it last time, + * Given the directory name NAME, and the place MCPREV we found it last time, * try to find more occurrences. */ struct mntentchn * -getmntfilesbackward (const char *name, struct mntentchn *mcprev) { +getmntdirbackward (const char *name, struct mntentchn *mcprev) { struct mntentchn *mc, *mc0; mc0 = mtab_head(); if (!mcprev) mcprev = mc0; for (mc = mcprev->prev; mc && mc != mc0; mc = mc->prev) - if (streq (mc->m.mnt_dir, name) || - streq (mc->m.mnt_fsname, name)) + if (streq(mc->m.mnt_dir, name)) return mc; return NULL; } +/* + * Given the device name NAME, and the place MCPREV we found it last time, + * try to find more occurrences. + */ +struct mntentchn * +getmntdevbackward (const char *name, struct mntentchn *mcprev) { + struct mntentchn *mc, *mc0; + + mc0 = mtab_head(); + if (!mcprev) + mcprev = mc0; + for (mc = mcprev->prev; mc && mc != mc0; mc = mc->prev) + if (streq(mc->m.mnt_fsname, name)) + return mc; + return NULL; +} + +/* + * Given the name NAME, check that it occurs precisely once as dir or dev. + */ +int +is_mounted_once(const char *name) { + struct mntentchn *mc, *mc0; + int ct = 0; + + mc0 = mtab_head(); + for (mc = mc0->prev; mc && mc != mc0; mc = mc->prev) + if (streq(mc->m.mnt_dir, name) || + streq(mc->m.mnt_fsname, name)) + ct++; + return (ct == 1); +} + /* Given the name FILE, try to find the option "loop=FILE" in mtab. */ struct mntentchn * getmntoptfile (const char *file) { @@ -253,29 +285,29 @@ getfsspecfile (const char *spec, const char *file) { /* first attempt: names occur precisely as given */ for (mc = mc0->nxt; mc && mc != mc0; mc = mc->nxt) - if (streq (mc->m.mnt_dir, file) && - streq (mc->m.mnt_fsname, spec)) + if (streq(mc->m.mnt_dir, file) && + streq(mc->m.mnt_fsname, spec)) return mc; /* second attempt: names found after symlink resolution */ for (mc = mc0->nxt; mc && mc != mc0; mc = mc->nxt) - if ((streq (mc->m.mnt_dir, file) || - streq (canonicalize(mc->m.mnt_dir), file)) - && (streq (mc->m.mnt_fsname, spec) || - streq (canonicalize(mc->m.mnt_fsname), spec))) + if ((streq(mc->m.mnt_dir, file) || + streq(canonicalize(mc->m.mnt_dir), file)) + && (streq(mc->m.mnt_fsname, spec) || + streq(canonicalize(mc->m.mnt_fsname), spec))) return mc; /* third attempt: names found after LABEL= or UUID= resolution */ for (mc = mc0->nxt; mc && mc != mc0; mc = mc->nxt) { if (!strncmp (mc->m.mnt_fsname, "LABEL=", 6) && - (streq (mc->m.mnt_dir, file) || - streq (canonicalize(mc->m.mnt_dir), file))) { + (streq(mc->m.mnt_dir, file) || + streq(canonicalize(mc->m.mnt_dir), file))) { if (has_label(spec, mc->m.mnt_fsname+6)) return mc; } if (!strncmp (mc->m.mnt_fsname, "UUID=", 5) && - (streq (mc->m.mnt_dir, file) || - streq (canonicalize(mc->m.mnt_dir), file))) { + (streq(mc->m.mnt_dir, file) || + streq(canonicalize(mc->m.mnt_dir), file))) { if (has_uuid(spec, mc->m.mnt_fsname+5)) return mc; } @@ -290,7 +322,7 @@ getfsfile (const char *file) { mc0 = fstab_head(); for (mc = mc0->nxt; mc && mc != mc0; mc = mc->nxt) - if (streq (mc->m.mnt_dir, file)) + if (streq(mc->m.mnt_dir, file)) return mc; return NULL; } @@ -302,7 +334,7 @@ getfsspec (const char *spec) { mc0 = fstab_head(); for (mc = mc0->nxt; mc && mc != mc0; mc = mc->nxt) - if (streq (mc->m.mnt_fsname, spec)) + if (streq(mc->m.mnt_fsname, spec)) return mc; return NULL; } @@ -531,7 +563,7 @@ update_mtab (const char *dir, struct mntent *instead) { /* find last occurrence of dir */ for (mc = mc0->prev; mc && mc != mc0; mc = mc->prev) - if (streq (mc->m.mnt_dir, dir)) + if (streq(mc->m.mnt_dir, dir)) break; if (mc && mc != mc0) { if (instead == NULL) { diff --git a/mount/fstab.h b/mount/fstab.h index 820f418a0..b55b6b5b6 100644 --- a/mount/fstab.h +++ b/mount/fstab.h @@ -12,6 +12,7 @@ int mtab_is_writable(void); int mtab_does_not_exist(void); int mtab_is_a_symlink(void); +int is_mounted_once(const char *name); struct mntentchn { struct mntentchn *nxt, *prev; @@ -21,7 +22,8 @@ struct mntentchn { struct mntentchn *mtab_head (void); struct mntentchn *getmntfile (const char *name); struct mntentchn *getmntoptfile (const char *file); -struct mntentchn *getmntfilesbackward (const char *file, struct mntentchn *mc); +struct mntentchn *getmntdirbackward (const char *dir, struct mntentchn *mc); +struct mntentchn *getmntdevbackward (const char *dev, struct mntentchn *mc); struct mntentchn *fstab_head (void); struct mntentchn *getfsfile (const char *file); diff --git a/mount/h/loop.h b/mount/h/loop.h deleted file mode 100644 index 1bd7fa87a..000000000 --- a/mount/h/loop.h +++ /dev/null @@ -1,37 +0,0 @@ -/* - * include/linux/loop.h - * - * Written by Theodore Ts'o, 3/29/93. - * - * Copyright 1993 by Theodore Ts'o. Redistribution of this file is - * permitted under the GNU Public License. - */ - -#define LO_NAME_SIZE 64 -#define LO_KEY_SIZE 32 - -struct loop_info { - int lo_number; /* ioctl r/o */ - dev_t lo_device; /* ioctl r/o */ - unsigned long lo_inode; /* ioctl r/o */ - dev_t lo_rdevice; /* ioctl r/o */ - int lo_offset; - int lo_encrypt_type; - int lo_encrypt_key_size; /* ioctl w/o */ - int lo_flags; /* ioctl r/o */ - char lo_name[LO_NAME_SIZE]; - unsigned char lo_encrypt_key[LO_KEY_SIZE]; /* ioctl w/o */ - unsigned long lo_init[2]; - char reserved[4]; -}; - -#define LO_CRYPT_NONE 0 -#define LO_CRYPT_XOR 1 -#define LO_CRYPT_DES 2 -#define LO_CRYPT_IDEA 3 -#define MAX_LO_CRYPT 4 - -#define LOOP_SET_FD 0x4C00 -#define LOOP_CLR_FD 0x4C01 -#define LOOP_SET_STATUS 0x4C02 -#define LOOP_GET_STATUS 0x4C03 diff --git a/mount/linux_fs.h b/mount/linux_fs.h index 874eb8fd3..485dbe84d 100644 --- a/mount/linux_fs.h +++ b/mount/linux_fs.h @@ -221,6 +221,42 @@ struct ocfs_volume_label { #define ocfslabellen(o) assemble2le(o.label_len) #define OCFS_MAGIC "OracleCFS" +struct efs_volume_directory { /* size 16 */ + char vd_name[8]; + char vd_lbn[4]; + char vd_nbytes[4]; +}; + +struct efs_partition_table { /* size 12 */ + char pt_nblks[4]; + char pt_firstlbn[4]; + char pt_type[4]; +}; + +struct efs_volume_header { /* size 512 */ + char vh_magic[4]; + short vh_rootpt; + short vh_swappt; + char vh_bootfile[16]; + char pad[48]; + struct efs_volume_directory vh_vd[15]; + struct efs_partition_table vh_pt[16]; + int vh_csum; + int vh_fill; +}; + +struct efs_super { + char fs_stuff[512+28]; + char fs_magic[4]; + char fs_fname[6]; + char fs_fpack[6]; + /* ... */ +}; + +#define EFS_VHMAGIC 0x0be5a941 /* big endian */ +#define EFS_SBMAGIC 0x00072959 /* idem */ +#define EFS_SBMAGIC2 0x0007295a /* idem */ + static inline int assemble2le(unsigned char *p) { return (p[0] | (p[1] << 8)); diff --git a/mount/lomount.c b/mount/lomount.c index 97cd9a092..0874f3ea0 100644 --- a/mount/lomount.c +++ b/mount/lomount.c @@ -2,13 +2,18 @@ /* 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> + * 1999-03-21 Arnaldo Carvalho de Melo <acme@conectiva.com.br> * - fixed strerr(errno) in gettext calls + * 2000-09-24 Marc Mutz <Marc@Mutz.com> + * - added -p option to pass passphrases via fd's to losetup/mount. + * Used for encryption in non-interactive environments. + * The idea behind xgetpass() is stolen from GnuPG, v.1.0.3. */ -#define PROC_DEVICES "/proc/devices" +#define LOOPMAJOR 7 /* * losetup.c - setup and control loop devices @@ -36,93 +41,114 @@ 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; -} crypt_type_tbl[] = { - { 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; + +static int +loop_info64_to_old(const struct loop_info64 *info64, struct loop_info *info) +{ + memset(info, 0, sizeof(*info)); + info->lo_number = info64->lo_number; + info->lo_device = info64->lo_device; + info->lo_inode = info64->lo_inode; + info->lo_rdevice = info64->lo_rdevice; + info->lo_offset = info64->lo_offset; + info->lo_encrypt_type = info64->lo_encrypt_type; + info->lo_encrypt_key_size = info64->lo_encrypt_key_size; + info->lo_flags = info64->lo_flags; + info->lo_init[0] = info64->lo_init[0]; + info->lo_init[1] = info64->lo_init[1]; + if (info->lo_encrypt_type == LO_CRYPT_CRYPTOAPI) + memcpy(info->lo_name, info64->lo_crypt_name, LO_NAME_SIZE); + else + memcpy(info->lo_name, info64->lo_file_name, LO_NAME_SIZE); + memcpy(info->lo_encrypt_key, info64->lo_encrypt_key, LO_KEY_SIZE); + + /* error in case values were truncated */ + if (info->lo_device != info64->lo_device || + info->lo_rdevice != info64->lo_rdevice || + info->lo_inode != info64->lo_inode || + info->lo_offset != info64->lo_offset) + return -EOVERFLOW; + + return 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"; -} static int -show_loop (char *device) { +show_loop(char *device) { struct loop_info loopinfo; - int fd; + struct loop_info64 loopinfo64; + int fd, errsv; - if ((fd = open (device, O_RDONLY)) < 0) { + if ((fd = open(device, O_RDONLY)) < 0) { int errsv = errno; fprintf(stderr, _("loop: can't open device %s: %s\n"), device, strerror (errsv)); return 2; } - 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)); + + if (ioctl(fd, LOOP_GET_STATUS64, &loopinfo64) == 0) { + + loopinfo64.lo_file_name[LO_NAME_SIZE-2] = '*'; + loopinfo64.lo_file_name[LO_NAME_SIZE-1] = 0; + loopinfo64.lo_crypt_name[LO_NAME_SIZE-1] = 0; + + printf("%s: [%04llx]:%llu (%s)", + device, loopinfo64.lo_device, loopinfo64.lo_inode, + loopinfo64.lo_file_name); + + if (loopinfo64.lo_offset) + printf(_(", offset %lld"), loopinfo64.lo_offset); + + if (loopinfo64.lo_sizelimit) + printf(_(", sizelimit %lld"), loopinfo64.lo_sizelimit); + + if (loopinfo64.lo_encrypt_type || + loopinfo64.lo_crypt_name[0]) { + char *e = loopinfo64.lo_crypt_name; + + if (*e == 0 && loopinfo64.lo_encrypt_type == 1) + e = "XOR"; + printf(_(", encryption %s (type %d)"), + e, loopinfo64.lo_encrypt_type); + } + printf("\n"); close (fd); - return 1; + return 0; } - 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); - return 0; + if (ioctl(fd, LOOP_GET_STATUS, &loopinfo) == 0) { + printf ("%s: [%04x]:%ld (%s)", + device, loopinfo.lo_device, loopinfo.lo_inode, + loopinfo.lo_name); + + if (loopinfo.lo_offset) + printf(_(", offset %d"), loopinfo.lo_offset); + + if (loopinfo.lo_encrypt_type) + printf(_(", encryption type %d\n"), + loopinfo.lo_encrypt_type); + + printf("\n"); + close (fd); + return 0; + } + + errsv = errno; + fprintf(stderr, _("loop: can't get info on device %s: %s\n"), + device, strerror (errsv)); + close (fd); + return 1; } #endif 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 && + + return (stat(device, &statbuf) == 0 && S_ISBLK(statbuf.st_mode) && - major(statbuf.st_rdev) == loopmajor); + major(statbuf.st_rdev) == LOOPMAJOR); } #define SIZE(a) (sizeof(a)/sizeof(a[0])) @@ -134,10 +160,9 @@ find_unused_loop_device (void) { So, we just try /dev/loop[0-7]. */ char dev[20]; char *loop_formats[] = { "/dev/loop%d", "/dev/loop/%d" }; - int i, j, fd, somedev = 0, someloop = 0, loop_known = 0; + int i, j, fd, somedev = 0, someloop = 0; struct stat statbuf; struct loop_info loopinfo; - FILE *procdev; for (j = 0; j < SIZE(loop_formats); j++) { for(i = 0; i < 256; i++) { @@ -160,73 +185,103 @@ find_unused_loop_device (void) { } } - /* 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?")); + "mount: Could not find any loop device. Maybe this kernel " + "does not know\n" + " about the loop device? (If so, recompile or " + "`modprobe loop'.)")); } else error(_("mount: could not find any free loop device")); return 0; } +/* + * A function to read the passphrase either from the terminal or from + * an open file descriptor. + */ +static char * +xgetpass(int pfd, const char *prompt) { + char *pass; + int buflen, i; + + if (pfd < 0) /* terminal */ + return getpass(prompt); + + pass = NULL; + buflen = 0; + for (i=0; ; i++) { + if (i >= buflen-1) { + /* we're running out of space in the buffer. + * Make it bigger: */ + char *tmppass = pass; + buflen += 128; + pass = realloc(tmppass, buflen); + if (pass == NULL) { + /* realloc failed. Stop reading. */ + error("Out of memory while reading passphrase"); + pass = tmppass; /* the old buffer hasn't changed */ + break; + } + } + if (read(pfd, pass+i, 1) != 1 || pass[i] == '\n') + break; + } + if (pass == NULL) + return ""; + else { + pass[i] = 0; + return pass; + } +} + +static int +digits_only(const char *s) { + while (*s) + if (!isdigit(*s++)) + return 0; + return 1; +} + 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; +set_loop(const char *device, const char *file, int offset, + const char *encryption, int pfd, int *loopro) { + struct loop_info64 loopinfo64; + int fd, ffd, mode; char *pass; mode = (*loopro ? O_RDONLY : O_RDWR); - if ((ffd = open (file, mode)) < 0) { + if ((ffd = open(file, mode)) < 0) { if (!*loopro && errno == EROFS) - ffd = open (file, mode = O_RDONLY); + ffd = open(file, mode = O_RDONLY); if (ffd < 0) { - perror (file); + perror(file); return 1; } } - if ((fd = open (device, mode)) < 0) { + if ((fd = open(device, mode)) < 0) { perror (device); return 1; } *loopro = (mode == O_RDONLY); - memset (&loopinfo, 0, sizeof (loopinfo)); - xstrncpy (loopinfo.lo_name, file, LO_NAME_SIZE); - if (encryption && (loopinfo.lo_encrypt_type = crypt_type (encryption)) - < 0) { - fprintf (stderr, _("Unsupported encryption type %s\n"), - encryption); - return 1; + memset(&loopinfo64, 0, sizeof(loopinfo64)); + + xstrncpy(loopinfo64.lo_file_name, file, LO_NAME_SIZE); + + if (encryption && *encryption) { + if (digits_only(encryption)) { + loopinfo64.lo_encrypt_type = atoi(encryption); + } else { + loopinfo64.lo_encrypt_type = LO_CRYPT_CRYPTOAPI; + snprintf(loopinfo64.lo_crypt_name, LO_NAME_SIZE, + "%s", encryption); + } } - loopinfo.lo_offset = offset; + + loopinfo64.lo_offset = offset; #ifdef MCL_FUTURE /* @@ -241,53 +296,55 @@ set_loop (const char *device, const char *file, int offset, } #endif - switch (loopinfo.lo_encrypt_type) { + switch (loopinfo64.lo_encrypt_type) { case LO_CRYPT_NONE: - loopinfo.lo_encrypt_key_size = 0; + loopinfo64.lo_encrypt_key_size = 0; break; case LO_CRYPT_XOR: - pass = getpass (_("Password: ")); - xstrncpy (loopinfo.lo_encrypt_key, pass, LO_KEY_SIZE); - 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; - } + pass = getpass(_("Password: ")); + xstrncpy(loopinfo64.lo_encrypt_key, pass, LO_KEY_SIZE); + loopinfo64.lo_encrypt_key_size = + strlen(loopinfo64.lo_encrypt_key); break; default: - fprintf (stderr, - _("Don't know how to get key for encryption system %d\n"), - loopinfo.lo_encrypt_type); - return 1; + pass = xgetpass(pfd, _("Password: ")); + xstrncpy(loopinfo64.lo_encrypt_key, pass, LO_KEY_SIZE); + loopinfo64.lo_encrypt_key_size = LO_KEY_SIZE; } - if (ioctl (fd, LOOP_SET_FD, ffd) < 0) { - perror ("ioctl: LOOP_SET_FD"); + + 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 (ffd); + + if (ioctl(fd, LOOP_SET_STATUS64, &loopinfo64) < 0) { + struct loop_info loopinfo; + int errsv = errno; + + errno = loop_info64_to_old(&loopinfo64, &loopinfo); + if (errno) { + errno = errsv; + perror("ioctl: LOOP_SET_STATUS64"); + goto fail; + } + + if (ioctl(fd, LOOP_SET_STATUS, &loopinfo) < 0) { + perror("ioctl: LOOP_SET_STATUS"); + goto fail; + } } + close (fd); - close (ffd); if (verbose > 1) printf(_("set_loop(%s,%s,%d): success\n"), device, file, offset); return 0; + + fail: + (void) ioctl (fd, LOOP_CLR_FD, 0); + close (fd); + return 1; } int @@ -388,29 +445,34 @@ error (const char *fmt, ...) { int main(int argc, char **argv) { - char *offset, *encryption; - int delete,off,c; + char *offset, *encryption, *passfd; + int delete, off, c; int res = 0; int ro = 0; + int pfd = -1; setlocale(LC_ALL, ""); bindtextdomain(PACKAGE, LOCALEDIR); textdomain(PACKAGE); delete = off = 0; - offset = encryption = NULL; + offset = encryption = passfd = NULL; progname = argv[0]; - while ((c = getopt(argc,argv,"de:o:v")) != -1) { + while ((c = getopt(argc,argv,"de:E:o:p:v")) != -1) { switch (c) { case 'd': delete = 1; break; + case 'E': case 'e': encryption = optarg; break; case 'o': offset = optarg; break; + case 'p': + passfd = optarg; + break; case 'v': verbose = 1; break; @@ -430,7 +492,10 @@ main(int argc, char **argv) { } else { if (offset && sscanf(offset,"%d",&off) != 1) usage(); - res = set_loop(argv[optind],argv[optind+1],off,encryption,&ro); + if (passfd && sscanf(passfd,"%d",&pfd) != 1) + usage(); + res = set_loop(argv[optind], argv[optind+1], off, + encryption, pfd, &ro); } return res; } diff --git a/mount/lomount.h b/mount/lomount.h index 1a93c693f..d81fc3b5a 100644 --- a/mount/lomount.h +++ b/mount/lomount.h @@ -1,5 +1,6 @@ extern int verbose; -extern int set_loop (const char *, const char *, int, const char *, int *); -extern int del_loop (const char *); -extern int is_loop_device (const char *); -extern char * find_unused_loop_device (void); +extern int set_loop(const char *, const char *, int, const char *, + int, int *); +extern int del_loop(const char *); +extern int is_loop_device(const char *); +extern char * find_unused_loop_device(void); diff --git a/mount/loop.h b/mount/loop.h new file mode 100644 index 000000000..951a5d183 --- /dev/null +++ b/mount/loop.h @@ -0,0 +1,51 @@ +#define LO_CRYPT_NONE 0 +#define LO_CRYPT_XOR 1 +#define LO_CRYPT_DES 2 +#define LO_CRYPT_CRYPTOAPI 18 + +#define LOOP_SET_FD 0x4C00 +#define LOOP_CLR_FD 0x4C01 +#define LOOP_SET_STATUS 0x4C02 +#define LOOP_GET_STATUS 0x4C03 +#define LOOP_SET_STATUS64 0x4C04 +#define LOOP_GET_STATUS64 0x4C05 + +#define LO_NAME_SIZE 64 +#define LO_KEY_SIZE 32 + +#include "my_dev_t.h" + +struct loop_info { + int lo_number; + my_dev_t lo_device; + unsigned long lo_inode; + my_dev_t lo_rdevice; + int lo_offset; + int lo_encrypt_type; + int lo_encrypt_key_size; + int lo_flags; + char lo_name[LO_NAME_SIZE]; + unsigned char lo_encrypt_key[LO_KEY_SIZE]; + unsigned long lo_init[2]; + char reserved[4]; +}; + +/* + * Where to get __u8, __u32, __u64? Let us use unsigned char/int/long long + * and get punished when someone comes with 128-bit long longs. + */ +struct loop_info64 { + unsigned long long lo_device; + unsigned long long lo_inode; + unsigned long long lo_rdevice; + unsigned long long lo_offset; + unsigned long long lo_sizelimit; /* bytes, 0 == max available */ + unsigned int lo_number; + unsigned int lo_encrypt_type; + unsigned int lo_encrypt_key_size; + unsigned int lo_flags; + unsigned char lo_file_name[LO_NAME_SIZE]; + unsigned char lo_crypt_name[LO_NAME_SIZE]; + unsigned char lo_encrypt_key[LO_KEY_SIZE]; + unsigned long long lo_init[2]; +}; diff --git a/mount/losetup.8 b/mount/losetup.8 index d364f4f1e..9a42d70a0 100644 --- a/mount/losetup.8 +++ b/mount/losetup.8 @@ -1,15 +1,18 @@ -.TH LOSETUP 8 "Nov 24 1993" "Linux" "MAINTENANCE COMMANDS" +.TH LOSETUP 8 "2003-07-01" "Linux" "MAINTENANCE COMMANDS" .SH NAME losetup \- set up and control loop devices .SH SYNOPSIS .ad l .B losetup [ -.B \-e +.RB [ \-e | \-E ] .I encryption ] [ .B \-o .I offset +] [ +.B \-p +.I pfd ] .I loop_device file .br @@ -25,27 +28,41 @@ is used to associate loop devices with regular files or block devices, to detach loop devices and to query the status of a loop device. If only the \fIloop_device\fP argument is given, the status of the corresponding loop device is shown. + +.SS "Encryption" +It is possible to specify transfer functions (for encryption/decryption +or other purposes) using one of the +.B \-E +and +.B \-e +options. +There are two mechanisms to specify the desired encryption: by number +and by name. If an encryption is specified by number then one +has to make sure that the Linux kernel knows about the encryption with that +number, probably by patching the kernel. Standard numbers that are +always present are 0 (no encryption) and 1 (XOR encryption). +When the cryptoloop module is loaded (or compiled in), it uses number 18. +This cryptoloop module wil take the name of an arbitrary encryption type +and finds the module that knows how to perform that encryption. +(Thus, either one uses a number different from 18 with the +.B \-E +option, or one uses a name with the +.B \-e +option.) .SH OPTIONS .IP \fB\-d\fP -detach the file or device associated with the specified loop device. -.IP "\fB\-e \fIencryption\fP" -.RS -enable data encryption. The following keywords are recognized: -.IP \fBNONE\fP -use no encryption (default). -.PD 0 -.IP \fBXOR\fP -use a simple XOR encryption. -.IP \fBDES\fP -use DES encryption. DES encryption is only available if the optional -DES package has been added to the kernel. DES encryption uses an additional -start value that is used to protect passwords against dictionary -attacks. -.PD -.RE +Detach the file or device associated with the specified loop device. +.IP "\fB\-E \fIencryption_type\fP" +Enable data encryption with specified number. +.IP "\fB\-e \fIencryption_name\fP" +Enable data encryption with specified name. .IP "\fB\-o \fIoffset\fP" -the data start is moved \fIoffset\fP bytes into the specified file or +The data start is moved \fIoffset\fP bytes into the specified file or device. +.IP "\fB\-p \fInum\fP" +Read the passphrase from file descriptor with number +.I num +instead of from the terminal. .SH RETURN VALUE .B losetup returns 0 on success, nonzero on failure. When @@ -57,7 +74,7 @@ from determining the status of the device. .SH FILES .nf -/dev/loop0,/dev/loop1,... loop devices (major=7) +/dev/loop0, /dev/loop1, ... loop devices (major=7) .fi .SH EXAMPLE If you are using the loadable module you must have the module loaded @@ -65,18 +82,23 @@ first with the command .IP # insmod loop.o .LP +Maybe also encryption modules are needed. +.IP +# insmod des.o +# insmod cryptoloop.o +.LP The following commands can be used as an example of using the loop device. .nf .IP -dd if=/dev/zero of=/file bs=1k count=100 -losetup -e des /dev/loop0 /file +# dd if=/dev/zero of=/file bs=1k count=100 +# losetup -e des /dev/loop0 /file Password: Init (up to 16 hex digits): -mkfs -t ext2 /dev/loop0 100 -mount -t ext2 /dev/loop0 /mnt +# mkfs -t ext2 /dev/loop0 100 +# mount -t ext2 /dev/loop0 /mnt ... -umount /dev/loop0 -losetup -d /dev/loop0 +# umount /dev/loop0 +# losetup -d /dev/loop0 .fi .LP If you are using the loadable module you may remove the module with @@ -87,8 +109,8 @@ the command .fi .SH RESTRICTION DES encryption is painfully slow. On the other hand, XOR is terribly weak. -.SH AUTHORS -.nf -Original version: Theodore Ts'o <tytso@athena.mit.edu> -Original DES by: Eric Young <eay@psych.psy.uq.oz.au> -.fi +.\" .SH AUTHORS +.\" .nf +.\" Original version: Theodore Ts'o <tytso@athena.mit.edu> +.\" Original DES by: Eric Young <eay@psych.psy.uq.oz.au> +.\" .fi diff --git a/mount/mk_loop_h b/mount/mk_loop_h deleted file mode 100644 index 86e76f35e..000000000 --- a/mount/mk_loop_h +++ /dev/null @@ -1,34 +0,0 @@ -#!/bin/sh -# -# Figure out (i) the type of dev_t (ii) the defines for loop stuff -# - -rm -f loop.h - -# Since 1.3.79 there is an include file <asm/posix_types.h> -# that defines __kernel_dev_t. -# (The file itself appeared in 1.3.78, but there it defined __dev_t.) -# If it exists, we use it, or, rather, <linux/posix_types.h> which -# avoids namespace pollution. Otherwise we guess that __kernel_dev_t -# is an unsigned short (which is true on i386, but false on alpha). - -if [ -f /usr/include/linux/posix_types.h ]; then - echo '#include <linux/posix_types.h>' >> loop.h - echo '#undef dev_t' >> loop.h - echo '#define dev_t __kernel_dev_t' >> loop.h -else - echo '#undef dev_t' >> loop.h - echo '#define dev_t unsigned short' >> loop.h -fi - -# Next we have to find the loop stuff itself. -# First try kernel source, then a private version. - -if [ -f /usr/include/linux/loop.h ]; then - echo '#include <linux/loop.h>' >> loop.h -else - echo '#include "h/loop.h"' >> loop.h -fi - -echo '#undef dev_t' >> loop.h - diff --git a/mount/mount.8 b/mount/mount.8 index 690b12dfd..ba547c660 100644 --- a/mount/mount.8 +++ b/mount/mount.8 @@ -118,6 +118,7 @@ a second place using .B "mount --rbind olddir newdir" .RE .\" available since Linux 2.4.11. +The mount options are not changed. Since Linux 2.5.1 it is possible to atomically move a subtree to another place. The call is @@ -315,6 +316,12 @@ This is necessary for example when .I /etc is on a read-only file system. .TP +.BI \-p " num" +In case of a loop mount with encryption, read the passphrase from +file descriptor +.I num +instead of from the terminal. +.TP .B \-s Tolerate sloppy mount options rather than failing. This will ignore mount options not supported by a filesystem type. Not all filesystems @@ -376,6 +383,7 @@ currently supported are: .IR udf , .IR ufs , .IR umsdos , +.IR usbfs , .IR vfat , .IR xenix , .IR xfs , @@ -390,7 +398,10 @@ instead. Since kernel version 2.1.21 the types .I ext and .I xiafs -do not exist anymore. +do not exist anymore. Earlier, +.I usbfs +was known as +.IR usbdevfs . For most types all the .B mount @@ -1479,6 +1490,9 @@ For filesystems created by SunOS or Solaris on Sparc. .B sunx86 For filesystems created by Solaris on x86. .TP +.B hp +For filesystems created by HP-UX, read-only. +.TP .B nextstep For filesystems created by NeXTStep (on NeXT station) (currently read only). .TP @@ -1556,7 +1570,7 @@ the short name is not all upper case. .I win95 Force the short name to upper case upon display; store a long name when the short name is not all upper case. -. TP +.TP .I winnt Display the shortname as is; store a long name when the short name is not all lower case or all upper case. @@ -1568,6 +1582,21 @@ all upper case. The default is "lower". +.SH "Mount options for usbfs" +.TP +\fBdevuid=\fP\fIuid\fP and \fBdevgid=\fP\fIgid\fP and \fBdevmode=\fP\fImode\fP +Set the owner and group and mode of the device files in the usbfs file system +(default: uid=gid=0, mode=0644). The mode is given in octal. +.TP +\fBbusuid=\fP\fIuid\fP and \fBbusgid=\fP\fIgid\fP and \fBbusmode=\fP\fImode\fP +Set the owner and group and mode of the bus directories in the usbfs +file system (default: uid=gid=0, mode=0555). The mode is given in octal. +.TP +\fBlistuid=\fP\fIuid\fP and \fBlistgid=\fP\fIgid\fP and \fBlistmode=\fP\fImode\fP +Set the owner and group and mode of the file +.I devices +(default: uid=gid=0, mode=0444). The mode is given in octal. + .SH "Mount options for xenix" None. diff --git a/mount/mount.c b/mount/mount.c index 04a3cd74e..227de5607 100644 --- a/mount/mount.c +++ b/mount/mount.c @@ -113,6 +113,9 @@ static int mounttype = 0; /* True if ruid != euid. */ static int suid = 0; +/* Contains the fd to read the passphrase from, if any. */ +static int pfd = -1; + /* Map from -o and fstab option strings to the flag argument to mount(2). */ struct opt_map { const char *opt; /* option name */ @@ -601,7 +604,8 @@ loop_check(char **spec, char **type, int *flags, if (verbose) printf(_("mount: going to use the loop device %s\n"), *loopdev); offset = opt_offset ? strtoul(opt_offset, NULL, 0) : 0; - if (set_loop (*loopdev, *loopfile, offset, opt_encryption, &loopro)) { + if (set_loop(*loopdev, *loopfile, offset, + opt_encryption, pfd, &loopro)) { if (verbose) printf(_("mount: failed setting up loop device\n")); return EX_FAIL; @@ -660,6 +664,14 @@ update_mtab_entry(char *spec, char *node, char *type, char *opts, } static void +set_pfd(char *s) { + if (!isdigit(*s)) + die(EX_USAGE, + _("mount: argument to -p or --pass-fd must be a number")); + pfd = atoi(optarg); +} + +static void cdrom_setspeed(char *spec) { #define CDROM_SELECT_SPEED 0x5322 /* Set the CD-ROM speed */ if (opt_speed) { @@ -768,7 +780,7 @@ try_mount_one (const char *spec0, const char *node0, char *types0, if (mount_all && (flags & MS_NOAUTO)) return 0; - suid_check (spec, node, &flags, &user); + suid_check(spec, node, &flags, &user); mount_opts = extra_opts; @@ -776,11 +788,12 @@ try_mount_one (const char *spec0, const char *node0, char *types0, cdrom_setspeed(spec); if (!(flags & MS_REMOUNT)) { - /* don't set up a (new) loop device if we only remount - this left + /* + * Don't set up a (new) loop device if we only remount - this left * stale assignments of files to loop devices. Nasty when used for * encryption. */ - res = loop_check (&spec, &types, &flags, &loop, &loopdev, &loopfile); + res = loop_check(&spec, &types, &flags, &loop, &loopdev, &loopfile); if (res) return res; } @@ -841,7 +854,7 @@ retry_nfs: #ifdef HAVE_NFS if (mnt_err && types && streq (types, "nfs")) { - if (nfs_mount_version == 4) { + if (nfs_mount_version == 4 && mnt_err != EBUSY && mnt_err != ENOENT) { if (verbose) printf(_("mount: failed with nfs mount version 4, trying 3..\n")); nfs_mount_version = 3; @@ -912,7 +925,7 @@ retry_nfs: break; case EINVAL: { int fd; - long size; + unsigned long size; int warned=0; if (flags & MS_REMOUNT) { @@ -922,9 +935,9 @@ retry_nfs: " or too many mounted file systems"), spec); - if (stat (spec, &statbuf) == 0 && S_ISBLK(statbuf.st_mode) + if (stat(spec, &statbuf) == 0 && S_ISBLK(statbuf.st_mode) && (fd = open(spec, O_RDONLY | O_NONBLOCK)) >= 0) { - if(ioctl(fd, BLKGETSIZE, &size) == 0) { + if (ioctl(fd, BLKGETSIZE, &size) == 0) { if (size == 0) { warned++; error (" (could this be the IDE device where you in fact use\n" @@ -1357,6 +1370,7 @@ static struct option longopts[] = { { "rw", 0, 0, 'w' }, { "options", 1, 0, 'o' }, { "test-opts", 1, 0, 'O' }, + { "pass-fd", 1, 0, 'p' }, { "types", 1, 0, 't' }, { "bind", 0, 0, 128 }, { "replace", 0, 0, 129 }, @@ -1394,7 +1408,7 @@ usage (FILE *fp, int n) { " mount --move olddir newdir\n" "A device can be given by name, say /dev/hda1 or /dev/cdrom,\n" "or by label, using -L label or by uuid, using -U uuid .\n" - "Other options: [-nfFrsvw] [-o options].\n" + "Other options: [-nfFrsvw] [-o options] [-p passwdfd].\n" "For many more details, say man 8 mount .\n" )); /* @@ -1433,7 +1447,7 @@ main (int argc, char *argv[]) { initproctitle(argc, argv); #endif - while ((c = getopt_long (argc, argv, "afFhilL:no:O:rsU:vVwt:", + while ((c = getopt_long (argc, argv, "afFhilL:no:O:p:rsU:vVwt:", longopts, NULL)) != -1) { switch (c) { case 'a': /* mount everything in fstab */ @@ -1472,6 +1486,9 @@ main (int argc, char *argv[]) { else test_opts = xstrdup(optarg); break; + case 'p': /* fd on which to read passwd */ + set_pfd(optarg); + break; case 'r': /* mount readonly */ readonly = 1; readwrite = 0; diff --git a/mount/mount_by_label.c b/mount/mount_by_label.c index 524ec7ca9..54170e56f 100644 --- a/mount/mount_by_label.c +++ b/mount/mount_by_label.c @@ -139,24 +139,26 @@ uuidcache_init_evms(void) { * special devices for the xfs filesystem external log & realtime device. */ -/* - * XVM support - Eric Sandeen - * Return 1 if this looks like an xvm device that should be scanned - */ +/* Return 1 if this looks like an xvm device that should be scanned */ static int is_xvm(char *ptname) { + int len; + + /* if it doesn't start with "xvm," we're done. */ + if (strncmp(ptname, "xvm", 3)) + return 0; + + len = strlen(ptname); /* - * Scan anything with "xvm" and "data" in its name. - * That might pick up non-data xvm subvols if the - * volumename contains the string 'data' but - * that should be harmless. + * check for "log/block" or "rt/block" on the end, + * these are special - don't scan. */ + if (!strncmp(ptname+(len-9), "log/block", 9) || + !strncmp(ptname+(len-8), "rt/block", 8)) + return 0; - if (strstr(ptname, "xvm") && strstr(ptname, "data")) - return 1; - - return 0; + return 1; } static void diff --git a/mount/mount_guess_fstype.c b/mount/mount_guess_fstype.c index f23cfc84b..e8829ce04 100644 --- a/mount/mount_guess_fstype.c +++ b/mount/mount_guess_fstype.c @@ -71,7 +71,7 @@ swapped(unsigned short a) { Corrected the test for xiafs - aeb Read the superblock only once - aeb Added a very weak heuristic for vfat - aeb - Added iso9660, minix-v2, romfs, qnx4, udf, vxfs, swap - aeb + Added efs, iso9660, minix-v2, romfs, qnx4, udf, vxfs, swap - aeb Added a test for high sierra (iso9660) - quinlan@bucknell.edu Added ufs from a patch by jj. But maybe there are several types of ufs? Added ntfs from a patch by Richard Russon. @@ -84,7 +84,7 @@ swapped(unsigned short a) { */ static char *magic_known[] = { - "adfs", "bfs", "cramfs", "ext", "ext2", "ext3", + "adfs", "bfs", "cramfs", "efs", "ext", "ext2", "ext3", "hfs", "hpfs", "iso9660", "jfs", "minix", "ntfs", "qnx4", "reiserfs", "romfs", "swap", "sysv", "udf", "ufs", "vxfs", "xfs", "xiafs" @@ -229,12 +229,6 @@ do_guess_fstype(const char *device) { int fd; char *type = NULL; union { - struct minix_super_block ms; - struct ext_super_block es; - struct ext2_super_block e2s; - struct vxfs_super_block vs; - } sb; /* stuff at 1024 */ - union { struct xiafs_super_block xiasb; char romfs_magic[8]; char qnx4fs_magic[10]; /* ignore first 4 bytes */ @@ -243,7 +237,15 @@ do_guess_fstype(const char *device) { struct fat_super_block fatsb; struct xfs_super_block xfsb; struct cramfs_super_block cramfssb; - } xsb; + struct efs_volume_header efsvh; + struct efs_super efssb; + } xsb; /* stuff at 0 */ + union { + struct minix_super_block ms; + struct ext_super_block es; + struct ext2_super_block e2s; + struct vxfs_super_block vs; + } sb; /* stuff at 1024 */ struct ufs_super_block ufssb; union { struct iso_volume_descriptor iso; @@ -294,9 +296,17 @@ do_guess_fstype(const char *device) { else if(cramfsmagic(xsb.cramfssb) == CRAMFS_SUPER_MAGIC || cramfsmagic(xsb.cramfssb) == CRAMFS_SUPER_MAGIC_BE) type = "cramfs"; + else if (assemble4be(xsb.efsvh.vh_magic) == EFS_VHMAGIC) + type = "efs"; /* EFS volume header */ + /* might check checksum here */ + else if (assemble4be(xsb.efssb.fs_magic) == EFS_SBMAGIC || + assemble4be(xsb.efssb.fs_magic) == EFS_SBMAGIC2) + type = "efs"; /* EFS partition */ else if ((!strncmp(xsb.fatsb.s_os, "MSDOS", 5) || !strncmp(xsb.fatsb.s_os, "MSWIN", 5) || !strncmp(xsb.fatsb.s_os, "MTOOL", 5) || + !strncmp(xsb.fatsb.s_os, "IBM", 3) || + !strncmp(xsb.fatsb.s_os, "DRDOS", 5) || !strncmp(xsb.fatsb.s_os, "mkdosfs", 7) || !strncmp(xsb.fatsb.s_os, "kmkdosfs", 8) || /* Michal Svec: created by fdformat, old msdos utility for diff --git a/mount/my_dev_t.h b/mount/my_dev_t.h new file mode 100644 index 000000000..5ef97154e --- /dev/null +++ b/mount/my_dev_t.h @@ -0,0 +1,7 @@ +/* silliness to get dev_t defined as the kernel defines it */ +/* glibc uses a different dev_t */ +/* maybe we need __kernel_old_dev_t -- later */ +/* for ancient systems use "unsigned short" */ + +#include <linux/posix_types.h> +#define my_dev_t __kernel_dev_t diff --git a/mount/pivot_root.2 b/mount/pivot_root.2 deleted file mode 100644 index 1c8f168a7..000000000 --- a/mount/pivot_root.2 +++ /dev/null @@ -1,97 +0,0 @@ -.TH PIVOT_ROOT 2 "Feb 23, 2000" "Linux" "System Calls" -.SH NAME -pivot_root \- change the root file system -.SH SYNOPSIS -.B #include <linux/unistd.h> -.sp -.B _syscall2(int,pivot_root,const char *,new_root,const char *,put_old) -.sp -.BI "int pivot_root(const char *" new_root ", const char *" put_old ); -.SH DESCRIPTION -\fBpivot_root\fP moves the root file system of the current process to the -directory \fIput_old\fP and makes \fInew_root\fP the new root file system -of the current process. - -The typical use of \fBpivot_root\fP is during system startup, when the -system mounts a temporary root file system (e.g. an \fBinitrd\fP), then -mounts the real root file system, and eventually turns the latter into -the current root of all relevant processes or threads. - -\fBpivot_root\fP may or may not change the current root and the current -working directory (cwd) of any processes or threads which use the old -root directory. The caller of \fBpivot_root\fP -must ensure that processes with root or cwd at the old root operate -correctly in either case. An easy way to ensure this is to change their -root and cwd to \fInew_root\fP before invoking \fBpivot_root\fP. - -The paragraph above is intentionally vague because the implementation -of \fBpivot_root\fP may change in the future. At the time of writing, -\fBpivot_root\fP changes root and cwd of each process or -thread to \fInew_root\fP if they point to the old root directory. This -is necessary in order to prevent kernel threads from keeping the old -root directory busy with their root and cwd, even if they never access -the file system in any way. In the future, there may be a mechanism for -kernel threads to explicitly relinquish any access to the file system, -such that this fairly intrusive mechanism can be removed from -\fBpivot_root\fP. - -Note that this also applies to the current process: \fBpivot_root\fP may -or may not affect its cwd. It is therefore recommended to call -\fBchdir("/")\fP immediately after \fBpivot_root\fP. - -The following restrictions apply to \fInew_root\fP and \fIput_old\fP: -.IP \- 3 -They must be directories. -.IP \- 3 -\fInew_root\fP and \fIput_old\fP must not be on the same file system as -the current root. -.IP \- 3 -\fIput_old\fP must be underneath \fInew_root\fP, i.e. adding a non-zero -number of \fB/..\fP to the string pointed to by \fIput_old\fP must yield -the same directory as \fInew_root\fP. -.IP \- 3 -No other file system may be mounted on \fIput_old\fP. -.PP -See also \fBpivot_root(8)\fP for additional usage examples. - -If the current root is not a mount point (e.g. after \fBchroot(2)\fP or -\fBpivot_root\fP, see also below), not the old root directory, but the -mount point of that file system is mounted on \fIput_old\fP. -.SH NOTES -\fInew_root\fP does not have to be a mount point. In this case, -\fB/proc/mounts\fP will show the mount point of the file system containing -\fInew_root\fP as root (\fB/\fP). -.SH "RETURN VALUE" -On success, zero is returned. On error, \-1 is returned, and -\fIerrno\fP is set appropriately. -.SH ERRORS -\fBpivot_root\fP may return (in \fIerrno\fP) any of the errors returned by -\fBstat(2)\fP. Additionally, it may return: - -.TP -.B EBUSY -\fInew_root\fP or \fIput_old\fP are on the current root file system, -or a file system is already mounted on \fIput_old\fP. -.TP -.B EINVAL -\fIput_old\fP is not underneath \fInew_root\fP. -.TP -.B ENOTDIR -\fInew_root\fP or \fIput_old\fP is not a directory. -.TP -.B EPERM -The current process does not have the administrator capability. -.SH BUGS -\fBpivot_root\fP should not have to change root and cwd of all other -processes in the system. - -Some of the more obscure uses of \fBpivot_root\fP may quickly lead to -insanity. -.SH HISTORY -\fBpivot_root\fP was introduced in Linux 2.3.41. -.SH "SEE ALSO" -.BR chdir(2), -.BR chroot(2), -.BR initrd(4), -.BR pivot_root(8), -.BR stat(2) diff --git a/mount/pivot_root.c b/mount/pivot_root.c index a844b480e..ba2dbbed0 100644 --- a/mount/pivot_root.c +++ b/mount/pivot_root.c @@ -3,14 +3,17 @@ /* Written 2000 by Werner Almesberger */ #include <stdio.h> -#include <errno.h> /* needed for <linux/unistd.h> below */ +#include <sys/syscall.h> +#include <unistd.h> -#ifdef __ia64__ -# include <sys/syscall.h> -# define pivot_root(new_root,put_old) syscall(SYS_pivot_root,new_root,put_old) -#else -# include <linux/unistd.h> +#define pivot_root(new_root,put_old) syscall(SYS_pivot_root,new_root,put_old) +#if 0 +/* + * With kernelheaders 2.3.41 or later, and ancient libc, try the following. + */ +#include <errno.h> +#include <linux/unistd.h> static _syscall2(int,pivot_root,const char *,new_root,const char *,put_old) #endif diff --git a/mount/umount.c b/mount/umount.c index 29feff4fa..1b6c1cf27 100644 --- a/mount/umount.c +++ b/mount/umount.c @@ -279,7 +279,9 @@ umount_one (const char *spec, const char *node, const char *type, if (force) { /* only supported for NFS */ res = umount2 (node, MNT_FORCE); if (res == -1) { + int errsv = errno; perror("umount2"); + errno = errsv; if (errno == ENOSYS) { if (verbose) printf(_("no umount2, trying umount...\n")); @@ -400,15 +402,23 @@ umount_one (const char *spec, const char *node, const char *type, * In both cases, it is best to try the last occurrence first. */ static int -umount_one_bw (const char *file, struct mntentchn *mc) { - int res = 1; - - while (res && mc) { - res = umount_one(mc->m.mnt_fsname, mc->m.mnt_dir, - mc->m.mnt_type, mc->m.mnt_opts, mc); - mc = getmntfilesbackward (file, mc); - } - return res; +umount_one_bw (const char *file, struct mntentchn *mc0) { + struct mntentchn *mc; + int res = 1; + + mc = mc0; + while (res && mc) { + res = umount_one(mc->m.mnt_fsname, mc->m.mnt_dir, + mc->m.mnt_type, mc->m.mnt_opts, mc); + mc = getmntdirbackward(file, mc); + } + mc = mc0; + while (res && mc) { + res = umount_one(mc->m.mnt_fsname, mc->m.mnt_dir, + mc->m.mnt_type, mc->m.mnt_opts, mc); + mc = getmntdevbackward(file, mc); + } + return res; } /* Unmount all filesystems of type VFSTYPES found in mtab. Since we are @@ -525,7 +535,6 @@ get_value(string_list list, char *s) { } return 0; } -/*=======================================================================*/ static int umount_file (char *arg) { @@ -534,19 +543,27 @@ umount_file (char *arg) { string_list options; int fstab_has_user, fstab_has_users, fstab_has_owner, ok; - file = canonicalize (arg); /* mtab paths are canonicalized */ + file = canonicalize(arg); /* mtab paths are canonicalized */ if (verbose > 1) printf(_("Trying to umount %s\n"), file); - mc = getmntfilesbackward (file, NULL); + mc = getmntdirbackward(file, NULL); + if (!mc) + mc = getmntdevbackward(file, NULL); if (!mc && verbose) printf(_("Could not find %s in mtab\n"), file); if (suid) { + char *mtab_user = NULL; + if (!mc) - die (2, _("umount: %s is not mounted (according to mtab)"), file); - if (getmntfilesbackward (file, mc)) - die (2, _("umount: it seems %s is mounted multiple times"), file); + die(2, + _("umount: %s is not mounted (according to mtab)"), + file); + if (!is_mounted_once(file)) + die(2, + _("umount: it seems %s is mounted multiple times"), + file); /* If fstab contains the two lines /dev/sda1 /mnt/zip auto user,noauto 0 0 @@ -558,10 +575,12 @@ umount_file (char *arg) { if (!fs) { if (!getfsspec (file) && !getfsfile (file)) die (2, - _("umount: %s is not in the fstab (and you are not root)"), + _("umount: %s is not in the fstab " + "(and you are not root)"), file); else - die (2, _("umount: %s mount disagrees with the fstab"), file); + die (2, _("umount: %s mount disagrees with " + "the fstab"), file); } /* User mounting and unmounting is allowed only @@ -586,7 +605,6 @@ umount_file (char *arg) { if (!ok && (fstab_has_user || fstab_has_owner)) { char *user = getusername(); - char *mtab_user; options = parse_list (mc->m.mnt_opts); mtab_user = get_value(options, "user="); @@ -595,7 +613,8 @@ umount_file (char *arg) { ok = 1; } if (!ok) - die (2, _("umount: only root can unmount %s from %s"), + die (2, _("umount: only %s can unmount %s from %s"), + mtab_user ? mtab_user : "root", fs->m.mnt_fsname, fs->m.mnt_dir); } @@ -673,8 +692,9 @@ main (int argc, char *argv[]) { argv += optind; if (all) { + /* nodev stuff: sysfs, usbfs, oprofilefs, ... */ if (types == NULL) - types = "noproc,nodevfs"; + types = "noproc,nodevfs,nodevpts"; result = umount_all (types, test_opts); } else if (argc < 1) { usage (stderr, 2); |