Imported from util-linux-2.12h tarball.

This commit is contained in:
Karel Zak 2006-12-07 00:26:19 +01:00
parent 2cccd0ff2b
commit d26aa358f4
42 changed files with 2289 additions and 2102 deletions

12
HISTORY
View File

@ -1,3 +1,15 @@
util-linux 2.12e,f,g,h
* cfdisk: avoid crash if no partition table
* elvtune: tell user that this only works on 2.4 kernels
* lomount: clear passwords after use
* mount: accept comments (introduced by \;) in fstab - withdrawn again
* mount: accept comments (specified by comment=) in fstab
* mount: support ocfs, ocfs2
* [u]mount: be more careful with malloc, try to avoid OOM with many mounts
* sfdisk: __attribute__used nonsense to support gcc 3.4
* shutdown: do not unmount various virtual filesystems
util-linux 2.12c,d util-linux 2.12c,d
* mount.8: added recent ext2 mount options * mount.8: added recent ext2 mount options

View File

@ -7,6 +7,12 @@
# - set USE_TTY_GROUP=no # - set USE_TTY_GROUP=no
# - define DESTDIR # - define DESTDIR
## Configuration outside of this file you might want to do for mount:
## If make_include has HAVE_BLKID=yes, turn that into HAVE_BLKID=no
## if you do not want to use the blkid library.
## In mount/realpath.c turn #define resolve_symlinks into
## #undef resolve_symlinks if you use devfs and hate long names.
# Select for ARCH one of intel, alpha, sparc, arm, m68k, mips # Select for ARCH one of intel, alpha, sparc, arm, m68k, mips
# Select for CPU i386 if the binaries must be able to run on an intel 386 # Select for CPU i386 if the binaries must be able to run on an intel 386
# (by default i486 code is generated, see below) # (by default i486 code is generated, see below)

4
README
View File

@ -5,5 +5,7 @@ misc-utils, sys-utils, getopt-* should be rather distribution-neutral,
and installing it does no harm. and installing it does no harm.
On the other hand, the stuff in login-utils defines initial boot-time On the other hand, the stuff in login-utils defines initial boot-time
stuff, things that are done in different ways by different distributions. stuff, things that are done in different ways by different distributions.
If you install it, your machine may not boot anymore. If you install it, your machine may not boot anymore, or you may be
unable to login.
No RPMs are provided - get yours from your distributor. No RPMs are provided - get yours from your distributor.

View File

@ -1 +1 @@
2.12d 2.12h

View File

@ -20,12 +20,15 @@
* Public License, version 2. * Public License, version 2.
*/ */
#include <getopt.h>
#include <fcntl.h> #include <fcntl.h>
#include <errno.h>
#include <stdio.h> #include <stdio.h>
#include <sys/ioctl.h> #include <getopt.h>
#include <unistd.h> #include <unistd.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/utsname.h>
#include "nls.h" #include "nls.h"
/* this has to match with the kernel structure */ /* this has to match with the kernel structure */
@ -37,6 +40,7 @@ typedef struct blkelv_ioctl_arg_s {
int max_bomb_segments; int max_bomb_segments;
} blkelv_ioctl_arg_t; } blkelv_ioctl_arg_t;
/* ioctls introduced in 2.2.16, removed in 2.5.58 */
#define BLKELVGET _IOR(0x12,106,size_t) #define BLKELVGET _IOR(0x12,106,size_t)
#define BLKELVSET _IOW(0x12,107,size_t) #define BLKELVSET _IOW(0x12,107,size_t)
@ -48,6 +52,8 @@ usage(void) {
" /dev/blkdev1 [/dev/blkdev2...]\n"); " /dev/blkdev1 [/dev/blkdev2...]\n");
fprintf(stderr, "\telvtune -h\n"); fprintf(stderr, "\telvtune -h\n");
fprintf(stderr, "\telvtune -v\n"); fprintf(stderr, "\telvtune -v\n");
fprintf(stderr, "\tNOTE: elvtune only works with 2.4 kernels\n");
/* (ioctls exist in 2.2.16 - 2.5.57) */
} }
static void static void
@ -55,6 +61,23 @@ version(void) {
fprintf(stderr, "elvtune (%s)\n", util_linux_version); fprintf(stderr, "elvtune (%s)\n", util_linux_version);
} }
#define MAKE_VERSION(p,q,r) (65536*(p) + 256*(q) + (r))
static int
linux_version_code(void) {
struct utsname my_utsname;
int p, q, r;
if (uname(&my_utsname) == 0) {
p = atoi(strtok(my_utsname.release, "."));
q = atoi(strtok(NULL, "."));
r = atoi(strtok(NULL, "."));
return MAKE_VERSION(p,q,r);
}
return 0;
}
int int
main(int argc, char * argv[]) { main(int argc, char * argv[]) {
int read_value = 0xbeefbeef, write_value = 0xbeefbeef, bomb_value = 0xbeefbeef; int read_value = 0xbeefbeef, write_value = 0xbeefbeef, bomb_value = 0xbeefbeef;
@ -110,8 +133,20 @@ main(int argc, char * argv[]) {
break; break;
} }
/* mmj: If we get EINVAL it's not a 2.4 kernel, so warn about
that and exit. It should return ENOTTY however, so check for
that as well in case it gets corrected in the future */
if (ioctl(fd, BLKELVGET, &elevator) < 0) { if (ioctl(fd, BLKELVGET, &elevator) < 0) {
int errsv = errno;
perror("ioctl get"); perror("ioctl get");
if ((errsv == EINVAL || errsv == ENOTTY) &&
linux_version_code() >= MAKE_VERSION(2,5,58)) {
fprintf(stderr,
"\nelvtune is only useful on older "
"kernels;\nfor 2.6 use IO scheduler "
"sysfs tunables instead..\n");
}
break; break;
} }

View File

@ -1488,55 +1488,68 @@ said_yes(char answer) {
static void static void
get_partition_table_geometry(partition_table *bufp) { get_partition_table_geometry(partition_table *bufp) {
struct partition *p; struct partition *p;
int i,h,s,hh,ss; int i,h,s,hh,ss;
int first = TRUE; int first = TRUE;
int bad = FALSE; int bad = FALSE;
if (bufp->p.magicflag[0] != PART_TABLE_FLAG0 || for (i=0; i<66; i++)
bufp->p.magicflag[1] != PART_TABLE_FLAG1) { if (bufp->c.b[446+i])
/* Matthew Wilcox: slightly friendlier version of goto nonz;
fatal(_("Bad signature on partition table"), 3);
*/
int cont;
mvaddstr(WARNING_START, 0,
_("No partition table or unknown signature on partition table"));
mvaddstr(WARNING_START+1, 0,
_("Do you wish to start with a zero table [y/N] ?"));
putchar(BELL);
refresh();
cont = getch();
if (cont == EOF || !said_yes(cont))
die_x(3);
zero_table = TRUE;
return;
/* Oskar Liljeblad suggested: /* zero table */
Bad signature blah blah if (!curses_started) {
If this is a brand new harddrive that has not been partitioned fatal(_("No partition table.\n"), 3);
before, please run cfdisk -z. return;
*/ } else {
} mvaddstr(WARNING_START, 0,
_("No partition table. Starting with zero table."));
hh = ss = 0; putchar(BELL);
for (i=0; i<4; i++) { refresh();
p = &(bufp->p.part[i]); zero_table = TRUE;
if (p->sys_ind != 0) { return;
h = p->end_head + 1;
s = (p->end_sector & 077);
if (first) {
hh = h;
ss = s;
first = FALSE;
} else if (hh != h || ss != s)
bad = TRUE;
} }
} nonz:
if (bufp->p.magicflag[0] != PART_TABLE_FLAG0 ||
bufp->p.magicflag[1] != PART_TABLE_FLAG1) {
if (!curses_started)
fatal(_("Bad signature on partition table"), 3);
if (!first && !bad) { /* Matthew Wilcox */
pt_heads = hh; mvaddstr(WARNING_START, 0,
pt_sectors = ss; _("Unknown partition table type"));
} mvaddstr(WARNING_START+1, 0,
_("Do you wish to start with a zero table [y/N] ?"));
putchar(BELL);
refresh();
{
int cont = getch();
if (cont == EOF || !said_yes(cont))
die_x(3);
}
zero_table = TRUE;
return;
}
hh = ss = 0;
for (i=0; i<4; i++) {
p = &(bufp->p.part[i]);
if (p->sys_ind != 0) {
h = p->end_head + 1;
s = (p->end_sector & 077);
if (first) {
hh = h;
ss = s;
first = FALSE;
} else if (hh != h || ss != s)
bad = TRUE;
}
}
if (!first && !bad) {
pt_heads = hh;
pt_sectors = ss;
}
} }
static void static void

View File

@ -129,6 +129,18 @@ fatal(char *s, ...) {
exit(1); exit(1);
} }
/*
* GCC nonsense - needed for GCC 3.4.x with -O2
*/
#if defined(__GNUC__PREREQ) && __GNUC_PREREQ(3,4)
#define __attribute__used __attribute__ ((used))
#else
#define __attribute__used
#endif
/* Or test with #if (__GNUC__ >= 3) && (__GNUC_MINOR__ >= 4) */
/* /*
* A. About seeking * A. About seeking
*/ */
@ -143,8 +155,13 @@ fatal(char *s, ...) {
* *
* Note: we use 512-byte sectors here, irrespective of the hardware ss. * Note: we use 512-byte sectors here, irrespective of the hardware ss.
*/ */
#if !defined (__alpha__) && !defined (__ia64__) && !defined (__x86_64__) && !defined (__s390x__) #undef use_lseek
static #if defined (__alpha__) || defined (__ia64__) || defined (__x86_64__) || defined (__s390x__)
#define use_lseek
#endif
#ifndef use_lseek
static __attribute__used
_syscall5(int, _llseek, unsigned int, fd, ulong, hi, ulong, lo, _syscall5(int, _llseek, unsigned int, fd, ulong, hi, ulong, lo,
loff_t *, res, unsigned int, wh); loff_t *, res, unsigned int, wh);
#endif #endif
@ -155,7 +172,7 @@ sseek(char *dev, unsigned int fd, unsigned long s) {
in = ((loff_t) s << 9); in = ((loff_t) s << 9);
out = 1; out = 1;
#if !defined (__alpha__) && !defined (__ia64__) && !defined (__x86_64__) && !defined (__s390x__) #ifndef use_lseek
if (_llseek (fd, in>>32, in & 0xffffffff, &out, SEEK_SET) != 0) { if (_llseek (fd, in>>32, in & 0xffffffff, &out, SEEK_SET) != 0) {
#else #else
if ((out = lseek(fd, in, SEEK_SET)) != in) { if ((out = lseek(fd, in, SEEK_SET)) != in) {
@ -1876,6 +1893,7 @@ max_length(int pno, int is_extended, struct part_desc *ep, int format,
} }
/* compute starting sector of a partition inside an extended one */ /* compute starting sector of a partition inside an extended one */
/* return 0 on failure */
/* ep is 0 or points to surrounding extended partition */ /* ep is 0 or points to surrounding extended partition */
static int static int
compute_start_sect(struct part_desc *p, struct part_desc *ep) { compute_start_sect(struct part_desc *p, struct part_desc *ep) {
@ -1889,6 +1907,7 @@ compute_start_sect(struct part_desc *p, struct part_desc *ep) {
delta = -inc; delta = -inc;
else else
delta = 0; delta = 0;
if (delta < 0) { if (delta < 0) {
p->start -= delta; p->start -= delta;
p->size += delta; p->size += delta;

View File

@ -632,7 +632,18 @@ unmount_disks_ourselves(void)
} }
n = 0; n = 0;
while (n < 100 && (mnt = getmntent(mtab))) { while (n < 100 && (mnt = getmntent(mtab))) {
if (strcmp (mnt->mnt_type, "devfs") == 0) continue; /*
* Neil Phillips: trying to unmount temporary / kernel
* filesystems is pointless and may cause error messages;
* /dev can be a ramfs managed by udev.
*/
if (strcmp(mnt->mnt_type, "devfs") == 0 ||
strcmp(mnt->mnt_type, "proc") == 0 ||
strcmp(mnt->mnt_type, "sysfs") == 0 ||
strcmp(mnt->mnt_type, "ramfs") == 0 ||
strcmp(mnt->mnt_type, "tmpfs") == 0 ||
strcmp(mnt->mnt_type, "devpts") == 0)
continue;
mntlist[n++] = strdup(mnt->mnt_dir); mntlist[n++] = strdup(mnt->mnt_dir);
} }
endmntent(mtab); endmntent(mtab);

View File

@ -157,9 +157,9 @@ For documentation on all nfs-specific options have a look at
Common for all types of file system are the options ``noauto'' Common for all types of file system are the options ``noauto''
(do not mount when "mount -a" is given, e.g., at boot time), ``user'' (do not mount when "mount -a" is given, e.g., at boot time), ``user''
(allow a user to mount), and ``owner'' (allow a user to mount), and ``owner''
(allow device owner to mount), and ``_netdev'' (device requires network (allow device owner to mount), and ``comment''
to be available). (e.g., for use by fstab-maintaining programs).
The ``owner'' and ``_netdev'' options are Linux-specific. The ``owner'' and ``comment'' options are Linux-specific.
For more details, see For more details, see
.BR mount (8). .BR mount (8).

View File

@ -13,6 +13,7 @@
#include "fstab.h" #include "fstab.h"
#include "sundries.h" /* for xmalloc() etc */ #include "sundries.h" /* for xmalloc() etc */
#include "mount_blkid.h" #include "mount_blkid.h"
#include "paths.h"
#include "nls.h" #include "nls.h"
#define streq(s, t) (strcmp ((s), (t)) == 0) #define streq(s, t) (strcmp ((s), (t)) == 0)
@ -94,12 +95,32 @@ fstab_head() {
return &fstab; return &fstab;
} }
static void
my_free(const void *s) {
if (s)
free((void *) s);
}
static void
discard_mntentchn(struct mntentchn *mc0) {
struct mntentchn *mc, *mc1;
for (mc = mc0->nxt; mc != mc0; mc = mc1) {
mc1 = mc->nxt;
my_free(mc->m.mnt_fsname);
my_free(mc->m.mnt_dir);
my_free(mc->m.mnt_type);
my_free(mc->m.mnt_opts);
free(mc);
}
}
static void static void
read_mntentchn(mntFILE *mfp, const char *fnam, struct mntentchn *mc0) { read_mntentchn(mntFILE *mfp, const char *fnam, struct mntentchn *mc0) {
struct mntentchn *mc = mc0; struct mntentchn *mc = mc0;
struct mntent *mnt; struct my_mntent *mnt;
while ((mnt = my_getmntent (mfp)) != NULL) { 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 = (struct mntentchn *) xmalloc(sizeof(*mc));
mc->nxt->prev = mc; mc->nxt->prev = mc;
@ -109,7 +130,7 @@ read_mntentchn(mntFILE *mfp, const char *fnam, struct mntentchn *mc0) {
} }
} }
mc0->prev = mc; mc0->prev = mc;
if (ferror (mfp->mntent_fp)) { if (ferror(mfp->mntent_fp)) {
int errsv = errno; int errsv = errno;
error(_("warning: error reading %s: %s"), error(_("warning: error reading %s: %s"),
fnam, strerror (errsv)); fnam, strerror (errsv));
@ -239,7 +260,7 @@ is_mounted_once(const char *name) {
struct mntentchn * struct mntentchn *
getmntoptfile (const char *file) { getmntoptfile (const char *file) {
struct mntentchn *mc, *mc0; struct mntentchn *mc, *mc0;
char *opts, *s; const char *opts, *s;
int l; int l;
if (!file) if (!file)
@ -404,13 +425,14 @@ setlkw_timeout (int sig) {
/* Where does the link point to? Obvious choices are mtab and mtab~~. /* Where does the link point to? Obvious choices are mtab and mtab~~.
HJLu points out that the latter leads to races. Right now we use HJLu points out that the latter leads to races. Right now we use
mtab~.<pid> instead. */ mtab~.<pid> instead. Use 20 as upper bound for the length of %d. */
#define MOUNTLOCK_LINKTARGET MOUNTED_LOCK "%d" #define MOUNTLOCK_LINKTARGET MOUNTED_LOCK "%d"
#define MOUNTLOCK_LINKTARGET_LTH (sizeof(MOUNTED_LOCK)+20)
void void
lock_mtab (void) { lock_mtab (void) {
int tries = 3; int tries = 3;
char *linktargetfile; char linktargetfile[MOUNTLOCK_LINKTARGET_LTH];
if (!signals_have_been_setup) { if (!signals_have_been_setup) {
int sig = 0; int sig = 0;
@ -431,9 +453,6 @@ lock_mtab (void) {
signals_have_been_setup = 1; signals_have_been_setup = 1;
} }
/* somewhat clumsy, but some ancient systems do not have snprintf() */
/* use 20 as upper bound for the length of %d output */
linktargetfile = xmalloc(strlen(MOUNTLOCK_LINKTARGET) + 20);
sprintf(linktargetfile, MOUNTLOCK_LINKTARGET, getpid ()); sprintf(linktargetfile, MOUNTLOCK_LINKTARGET, getpid ());
/* Repeat until it was us who made the link */ /* Repeat until it was us who made the link */
@ -542,11 +561,11 @@ unlock_mtab (void) {
*/ */
void void
update_mtab (const char *dir, struct mntent *instead) { update_mtab (const char *dir, struct my_mntent *instead) {
mntFILE *mfp, *mftmp; mntFILE *mfp, *mftmp;
const char *fnam = MOUNTED; const char *fnam = MOUNTED;
struct mntentchn mtabhead; /* dummy */ struct mntentchn mtabhead; /* dummy */
struct mntentchn *mc, *mc0, absent; struct mntentchn *mc, *mc0, *absent = NULL;
if (mtab_does_not_exist() || mtab_is_a_symlink()) if (mtab_does_not_exist() || mtab_is_a_symlink())
return; return;
@ -577,6 +596,7 @@ update_mtab (const char *dir, struct mntent *instead) {
if (mc && mc != mc0) { if (mc && mc != mc0) {
mc->prev->nxt = mc->nxt; mc->prev->nxt = mc->nxt;
mc->nxt->prev = mc->prev; mc->nxt->prev = mc->prev;
free(mc);
} }
} else { } else {
/* A remount */ /* A remount */
@ -584,12 +604,13 @@ update_mtab (const char *dir, struct mntent *instead) {
} }
} else if (instead) { } else if (instead) {
/* not found, add a new entry */ /* not found, add a new entry */
absent.m = *instead; absent = xmalloc(sizeof(*absent));
absent.nxt = mc0; absent->m = *instead;
absent.prev = mc0->prev; absent->nxt = mc0;
mc0->prev = &absent; absent->prev = mc0->prev;
mc0->prev = absent;
if (mc0->nxt == NULL) if (mc0->nxt == NULL)
mc0->nxt = &absent; mc0->nxt = absent;
} }
/* write chain to mtemp */ /* write chain to mtemp */
@ -609,6 +630,8 @@ update_mtab (const char *dir, struct mntent *instead) {
} }
} }
discard_mntentchn(mc0);
if (fchmod (fileno (mftmp->mntent_fp), if (fchmod (fileno (mftmp->mntent_fp),
S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH) < 0) { S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH) < 0) {
int errsv = errno; int errsv = errno;

View File

@ -1,14 +1,4 @@
#include <mntent.h> #include "mntent.h"
#define _PATH_FSTAB "/etc/fstab"
#ifdef _PATH_MOUNTED
#define MOUNTED_LOCK _PATH_MOUNTED "~"
#define MOUNTED_TEMP _PATH_MOUNTED ".tmp"
#else
#define MOUNTED_LOCK "/etc/mtab~"
#define MOUNTED_TEMP "/etc/mtab.tmp"
#endif
#define LOCK_TIMEOUT 10
int mtab_is_writable(void); int mtab_is_writable(void);
int mtab_does_not_exist(void); int mtab_does_not_exist(void);
int mtab_is_a_symlink(void); int mtab_is_a_symlink(void);
@ -16,7 +6,7 @@ int is_mounted_once(const char *name);
struct mntentchn { struct mntentchn {
struct mntentchn *nxt, *prev; struct mntentchn *nxt, *prev;
struct mntent m; struct my_mntent m;
}; };
struct mntentchn *mtab_head (void); struct mntentchn *mtab_head (void);
@ -32,7 +22,6 @@ struct mntentchn *getfsspecfile (const char *spec, const char *file);
struct mntentchn *getfsuuidspec (const char *uuid); struct mntentchn *getfsuuidspec (const char *uuid);
struct mntentchn *getfsvolspec (const char *label); struct mntentchn *getfsvolspec (const char *label);
#include <mntent.h>
void lock_mtab (void); void lock_mtab (void);
void unlock_mtab (void); void unlock_mtab (void);
void update_mtab (const char *special, struct mntent *with); void update_mtab (const char *special, struct my_mntent *with);

View File

@ -62,7 +62,7 @@ reiserfs_magic_version(const char *magic) {
/* /*
* Get both label and uuid. * Get both label and uuid.
* For now, only ext2, ext3, xfs, ocfs, reiserfs are supported * For now, only ext2, ext3, xfs, ocfs, ocfs2, reiserfs are supported
*/ */
int int
get_label_uuid(const char *device, char **label, char *uuid) { get_label_uuid(const char *device, char **label, char *uuid) {
@ -74,6 +74,7 @@ get_label_uuid(const char *device, char **label, char *uuid) {
struct jfs_super_block jfssb; struct jfs_super_block jfssb;
struct ocfs_volume_header ovh; /* Oracle */ struct ocfs_volume_header ovh; /* Oracle */
struct ocfs_volume_label olbl; struct ocfs_volume_label olbl;
struct ocfs2_super_block osb;
struct reiserfs_super_block reiserfssb; struct reiserfs_super_block reiserfssb;
fd = open(device, O_RDONLY); fd = open(device, O_RDONLY);
@ -160,6 +161,29 @@ get_label_uuid(const char *device, char **label, char *uuid) {
memcpy(uuid, reiserfssb.s_uuid, sizeof (reiserfssb.s_uuid)); memcpy(uuid, reiserfssb.s_uuid, sizeof (reiserfssb.s_uuid));
rv = 0; rv = 0;
} }
else {
int blksize, blkoff;
for (blksize = OCFS2_MIN_BLOCKSIZE;
blksize <= OCFS2_MAX_BLOCKSIZE;
blksize <<= 1) {
blkoff = blksize * OCFS2_SUPER_BLOCK_BLKNO;
if (lseek(fd, blkoff, SEEK_SET) == blkoff
&& read(fd, (char *) &osb, sizeof(osb))
== sizeof(osb)
&& strncmp(osb.signature,
OCFS2_SUPER_BLOCK_SIGNATURE,
sizeof(OCFS2_SUPER_BLOCK_SIGNATURE))
== 0) {
memcpy(uuid, osb.s_uuid, sizeof(osb.s_uuid));
namesize = sizeof(osb.s_label);
if ((*label = calloc(namesize, 1)) != NULL)
memcpy(*label, osb.s_label, namesize);
rv = 0;
break;
}
}
}
close(fd); close(fd);
return rv; return rv;

View File

@ -236,35 +236,49 @@ struct ocfs_volume_label {
#define ocfslabellen(o) assemble2le(o.label_len) #define ocfslabellen(o) assemble2le(o.label_len)
#define OCFS_MAGIC "OracleCFS" #define OCFS_MAGIC "OracleCFS"
struct ocfs2_super_block {
u_char signature[8];
u_char s_dummy1[184];
u_char s_dummy2[80];
u_char s_label[64];
u_char s_uuid[16];
};
#define OCFS2_MIN_BLOCKSIZE 512
#define OCFS2_MAX_BLOCKSIZE 4096
#define OCFS2_SUPER_BLOCK_BLKNO 2
#define OCFS2_SUPER_BLOCK_SIGNATURE "OCFSV2"
struct efs_volume_directory { /* size 16 */ struct efs_volume_directory { /* size 16 */
char vd_name[8]; char vd_name[8];
char vd_lbn[4]; char vd_lbn[4];
char vd_nbytes[4]; char vd_nbytes[4];
}; };
struct efs_partition_table { /* size 12 */ struct efs_partition_table { /* size 12 */
char pt_nblks[4]; char pt_nblks[4];
char pt_firstlbn[4]; char pt_firstlbn[4];
char pt_type[4]; char pt_type[4];
}; };
struct efs_volume_header { /* size 512 */ struct efs_volume_header { /* size 512 */
char vh_magic[4]; char vh_magic[4];
short vh_rootpt; short vh_rootpt;
short vh_swappt; short vh_swappt;
char vh_bootfile[16]; char vh_bootfile[16];
char pad[48]; char pad[48];
struct efs_volume_directory vh_vd[15]; struct efs_volume_directory vh_vd[15];
struct efs_partition_table vh_pt[16]; struct efs_partition_table vh_pt[16];
int vh_csum; int vh_csum;
int vh_fill; int vh_fill;
}; };
struct efs_super { struct efs_super {
char fs_stuff[512+28]; char fs_stuff[512+28];
char fs_magic[4]; char fs_magic[4];
char fs_fname[6]; char fs_fname[6];
char fs_fpack[6]; char fs_fpack[6];
/* ... */ /* ... */
}; };

View File

@ -249,7 +249,7 @@ int
set_loop(const char *device, const char *file, unsigned long long offset, set_loop(const char *device, const char *file, unsigned long long offset,
const char *encryption, int pfd, int *loopro) { const char *encryption, int pfd, int *loopro) {
struct loop_info64 loopinfo64; struct loop_info64 loopinfo64;
int fd, ffd, mode; int fd, ffd, mode, i;
char *pass; char *pass;
mode = (*loopro ? O_RDONLY : O_RDWR); mode = (*loopro ? O_RDONLY : O_RDWR);
@ -303,12 +303,14 @@ set_loop(const char *device, const char *file, unsigned long long offset,
case LO_CRYPT_XOR: case LO_CRYPT_XOR:
pass = getpass(_("Password: ")); pass = getpass(_("Password: "));
xstrncpy(loopinfo64.lo_encrypt_key, pass, LO_KEY_SIZE); xstrncpy(loopinfo64.lo_encrypt_key, pass, LO_KEY_SIZE);
memset(pass, 0, strlen(pass));
loopinfo64.lo_encrypt_key_size = loopinfo64.lo_encrypt_key_size =
strlen(loopinfo64.lo_encrypt_key); strlen(loopinfo64.lo_encrypt_key);
break; break;
default: default:
pass = xgetpass(pfd, _("Password: ")); pass = xgetpass(pfd, _("Password: "));
xstrncpy(loopinfo64.lo_encrypt_key, pass, LO_KEY_SIZE); xstrncpy(loopinfo64.lo_encrypt_key, pass, LO_KEY_SIZE);
memset(pass, 0, strlen(pass));
loopinfo64.lo_encrypt_key_size = LO_KEY_SIZE; loopinfo64.lo_encrypt_key_size = LO_KEY_SIZE;
} }
@ -318,33 +320,35 @@ set_loop(const char *device, const char *file, unsigned long long offset,
} }
close (ffd); close (ffd);
if (ioctl(fd, LOOP_SET_STATUS64, &loopinfo64) < 0) { i = ioctl(fd, LOOP_SET_STATUS64, &loopinfo64);
if (i) {
struct loop_info loopinfo; struct loop_info loopinfo;
int errsv = errno; int errsv = errno;
errno = loop_info64_to_old(&loopinfo64, &loopinfo); i = loop_info64_to_old(&loopinfo64, &loopinfo);
if (errno) { if (i) {
errno = errsv; errno = errsv;
perror("ioctl: LOOP_SET_STATUS64"); perror("ioctl: LOOP_SET_STATUS64");
goto fail; } else {
} i = ioctl(fd, LOOP_SET_STATUS, &loopinfo);
if (i)
if (ioctl(fd, LOOP_SET_STATUS, &loopinfo) < 0) { perror("ioctl: LOOP_SET_STATUS");
perror("ioctl: LOOP_SET_STATUS");
goto fail;
} }
memset(&loopinfo, 0, sizeof(loopinfo));
} }
memset(&loopinfo64, 0, sizeof(loopinfo64));
if (i) {
ioctl (fd, LOOP_CLR_FD, 0);
close (fd);
return 1;
}
close (fd); close (fd);
if (verbose > 1) if (verbose > 1)
printf(_("set_loop(%s,%s,%llu): success\n"), printf(_("set_loop(%s,%s,%llu): success\n"),
device, file, offset); device, file, offset);
return 0; return 0;
fail:
(void) ioctl (fd, LOOP_CLR_FD, 0);
close (fd);
return 1;
} }
int int

View File

@ -21,7 +21,7 @@
static unsigned char need_escaping[] = { ' ', '\t', '\n', '\\' }; static unsigned char need_escaping[] = { ' ', '\t', '\n', '\\' };
static char * static char *
mangle(unsigned char *s) { mangle(const unsigned char *s) {
char *ss, *sp; char *ss, *sp;
int n; int n;
@ -98,7 +98,7 @@ my_setmntent (const char *file, char *mode) {
mntFILE *mfp = xmalloc(sizeof(*mfp)); mntFILE *mfp = xmalloc(sizeof(*mfp));
mode_t old_umask = umask(077); mode_t old_umask = umask(077);
mfp->mntent_fp = fopen (file, mode); mfp->mntent_fp = fopen(file, mode);
umask(old_umask); umask(old_umask);
mfp->mntent_file = xstrdup(file); mfp->mntent_file = xstrdup(file);
mfp->mntent_errs = (mfp->mntent_fp == NULL); mfp->mntent_errs = (mfp->mntent_fp == NULL);
@ -118,9 +118,8 @@ my_endmntent (mntFILE *mfp) {
} }
} }
int int
my_addmntent (mntFILE *mfp, struct mntent *mnt) { my_addmntent (mntFILE *mfp, struct my_mntent *mnt) {
char *m1, *m2, *m3, *m4; char *m1, *m2, *m3, *m4;
int res; int res;
@ -132,22 +131,21 @@ my_addmntent (mntFILE *mfp, struct mntent *mnt) {
m3 = mangle(mnt->mnt_type); m3 = mangle(mnt->mnt_type);
m4 = mangle(mnt->mnt_opts); m4 = mangle(mnt->mnt_opts);
res = ((fprintf (mfp->mntent_fp, "%s %s %s %s %d %d\n", res = fprintf (mfp->mntent_fp, "%s %s %s %s %d %d\n",
m1, m2, m3, m4, mnt->mnt_freq, mnt->mnt_passno) m1, m2, m3, m4, mnt->mnt_freq, mnt->mnt_passno);
< 0) ? 1 : 0);
free(m1); free(m1);
free(m2); free(m2);
free(m3); free(m3);
free(m4); free(m4);
return res; return (res < 0) ? 1 : 0;
} }
/* Read the next entry from the file fp. Stop reading at an incorrect entry. */ /* Read the next entry from the file fp. Stop reading at an incorrect entry. */
struct mntent * struct my_mntent *
my_getmntent (mntFILE *mfp) { my_getmntent (mntFILE *mfp) {
static char buf[4096]; static char buf[4096];
static struct mntent me; static struct my_mntent me;
char *s; char *s;
again: again:
@ -193,7 +191,7 @@ my_getmntent (mntFILE *mfp) {
s = skip_nonspaces(s); s = skip_nonspaces(s);
s = skip_spaces(s); s = skip_spaces(s);
if(isdigit(*s)) { if (isdigit(*s)) {
me.mnt_freq = atoi(s); me.mnt_freq = atoi(s);
while(isdigit(*s)) s++; while(isdigit(*s)) s++;
} else } else

View File

@ -1,4 +1,14 @@
#include <mntent.h> /* for struct mntent */ #ifndef MY_MNTENT_H
#define MY_MNTENT_H
struct my_mntent {
const char *mnt_fsname;
const char *mnt_dir;
const char *mnt_type;
const char *mnt_opts;
int mnt_freq;
int mnt_passno;
};
#define ERR_MAX 5 #define ERR_MAX 5
@ -12,5 +22,7 @@ typedef struct mntFILEstruct {
mntFILE *my_setmntent (const char *file, char *mode); mntFILE *my_setmntent (const char *file, char *mode);
void my_endmntent (mntFILE *mfp); void my_endmntent (mntFILE *mfp);
int my_addmntent (mntFILE *mfp, struct mntent *mnt); int my_addmntent (mntFILE *mfp, struct my_mntent *mnt);
struct mntent *my_getmntent (mntFILE *mfp); struct my_mntent *my_getmntent (mntFILE *mfp);
#endif

View File

@ -109,6 +109,7 @@ file hierarchy somewhere else. The call is
.B "mount --bind olddir newdir" .B "mount --bind olddir newdir"
.RE .RE
After this call the same contents is accessible in two places. After this call the same contents is accessible in two places.
One can also remount a single file (on a single file).
This call attaches only (part of) a single filesystem, not possible This call attaches only (part of) a single filesystem, not possible
submounts. The entire file hierarchy including submounts is attached submounts. The entire file hierarchy including submounts is attached
@ -120,7 +121,7 @@ a second place using
.\" available since Linux 2.4.11. .\" available since Linux 2.4.11.
The mount options are not changed. The mount options are not changed.
Since Linux 2.5.1 it is possible to atomically move a subtree Since Linux 2.5.1 it is possible to atomically move a mounted tree
to another place. The call is to another place. The call is
.RS .RS
.br .br
@ -242,6 +243,8 @@ option below). It is possible to replace
.I /etc/mtab .I /etc/mtab
by a symbolic link to by a symbolic link to
.IR /proc/mounts , .IR /proc/mounts ,
and especially when you have very large numbers of mounts
things will be much faster with that symlink,
but some information is lost that way, and in particular but some information is lost that way, and in particular
working with the loop device will be less convenient, working with the loop device will be less convenient,
and using the "user" option will fail. and using the "user" option will fail.
@ -421,35 +424,15 @@ program have different calling conventions,
.I /sbin/mount.smbfs .I /sbin/mount.smbfs
may have to be a shell script that sets up the desired call. may have to be a shell script that sets up the desired call.
The type If no
.I iso9660
is the default. If no
.B \-t .B \-t
option is given, or if the option is given, or if the
.B auto .B auto
type is specified, the superblock is probed for the filesystem type type is specified, mount will try to guess the desired type.
.RI ( adfs , If mount was compiled with the blkid library, the guessing is done
.IR bfs , by this library. Otherwise, mount guesses itself by probing the
.IR cramfs , superblock; if that does not turn up anything that looks familiar,
.IR ext , mount will try to read the file
.IR ext2 ,
.IR ext3 ,
.IR hfs ,
.IR hpfs ,
.IR iso9660 ,
.IR jfs ,
.IR minix ,
.IR ntfs ,
.IR qnx4 ,
.IR reiserfs ,
.IR romfs ,
.IR udf ,
.IR ufs ,
.IR vxfs ,
.IR xfs ,
.IR xiafs
are supported).
If this probe fails, mount will try to read the file
.IR /etc/filesystems , .IR /etc/filesystems ,
or, if that does not exist, or, if that does not exist,
.IR /proc/filesystems . .IR /proc/filesystems .
@ -470,8 +453,8 @@ The
type may be useful for user-mounted floppies. type may be useful for user-mounted floppies.
Creating a file Creating a file
.I /etc/filesystems .I /etc/filesystems
can be useful to change the probe order (e.g., to try vfat before msdos) can be useful to change the probe order (e.g., to try vfat before msdos
or if you use a kernel module autoloader. or ext3 before ext2) or if you use a kernel module autoloader.
Warning: the probing uses a heuristic (the presence of appropriate `magic'), Warning: the probing uses a heuristic (the presence of appropriate `magic'),
and could recognize the wrong filesystem type, possibly with catastrophic and could recognize the wrong filesystem type, possibly with catastrophic
consequences. If your data is valuable, don't ask consequences. If your data is valuable, don't ask
@ -587,9 +570,9 @@ Do not interpret character or block special devices on the file
system. system.
.TP .TP
.B noexec .B noexec
Do not allow execution of any binaries on the mounted file system. Do not allow direct execution of any binaries on the mounted file system.
This option might be useful for a server that has file systems containing (Until recently it was possible to run binaries anyway using a command like
binaries for architectures other than its own. /lib/ld*.so /mnt/binary. This trick fails since Linux 2.4.25 / 2.6.0.)
.TP .TP
.B nosuid .B nosuid
Do not allow set-user-identifier or set-group-identifier bits to take Do not allow set-user-identifier or set-group-identifier bits to take

View File

@ -2,43 +2,7 @@
* A mount(8) for Linux 0.99. * A mount(8) for Linux 0.99.
* mount.c,v 1.1.1.1 1993/11/18 08:40:51 jrs Exp * mount.c,v 1.1.1.1 1993/11/18 08:40:51 jrs Exp
* *
* Wed Sep 14 22:43:00 1994: Mitchum DSouza * Modifications by many people. Distributed under GPL.
* (mitch@mrc-applied-psychology.cambridge.ac.uk) added support for mounting
* the "loop" device.
*
* Wed Sep 14 22:55:10 1994: Sander van Malssen (svm@kozmix.hacktic.nl)
* added support for remounting readonly file systems readonly.
*
* Wed Feb 8 12:27:00 1995: Andries.Brouwer@cwi.nl fixed up error messages.
* Sat Jun 3 20:44:38 1995: Patches from Andries.Brouwer@cwi.nl applied.
* Tue Sep 26 22:38:20 1995: aeb@cwi.nl, many changes
* Fri Feb 23 13:47:00 1996: aeb@cwi.nl, loop device related changes
*
* Since then, many changes - aeb.
*
* Wed Oct 1 23:55:28 1997: Dick Streefland <dick_streefland@tasking.com>
* Implemented the "bg", "fg" and "retry" mount options for NFS.
*
* Tue Aug 4 15:54:31 1998: aeb@cwi.nl:
* Open fd 0,1,2 so that printf's do not clobber /etc/mtab or so.
* Mangle filenames with embedded spaces. Add ufsmagic. Add locking.
* Avoid unnecessary error messages about /proc.
* Improve support for noncanonical names in /etc/fstab.
* Add support for volume labels and UUIDs.
*
* 1999-02-22 Arkadiusz Mikiewicz <misiek@pld.ORG.PL>
* - added Native Language Support
* 1999-03-21 Arnaldo Carvalho de Melo <acme@conectiva.com.br>
* - fixed strerr(errno) in gettext calls
* 1999-07-05 Hirokazu Takahashi <h-takaha@sss.abk.nec.co.jp>
* - fixed use of nouser option
* 1999-09-09 Michael K. Johnson <johnsonm@redhat.com>
* - added `owner' mount option
* 2000-05-11 Mark A. Peloquin <peloquin@us.ibm.com>
* - check_special_mountprog now returns correct status
* 2000-11-08 aeb: accept nonnumeric uid=, gid= options
* 2001-07-13 Michael K. Johnson <johnsonm@redhat.com>
* - implemented -a -O
*/ */
#include <unistd.h> #include <unistd.h>
@ -69,6 +33,7 @@
#include "mount_guess_fstype.h" #include "mount_guess_fstype.h"
#include "mount_by_label.h" #include "mount_by_label.h"
#include "getusername.h" #include "getusername.h"
#include "paths.h"
#include "env.h" #include "env.h"
#include "nls.h" #include "nls.h"
@ -131,11 +96,11 @@ struct opt_map {
#define MS_USERS 0x40000000 #define MS_USERS 0x40000000
#define MS_USER 0x20000000 #define MS_USER 0x20000000
#define MS_OWNER 0x10000000 #define MS_OWNER 0x10000000
#define MS_NETDEV 0x00020000 #define MS_COMMENT 0x00020000
#define MS_LOOP 0x00010000 #define MS_LOOP 0x00010000
/* Options that we keep the mount system call from seeing. */ /* Options that we keep the mount system call from seeing. */
#define MS_NOSYS (MS_NOAUTO|MS_USERS|MS_USER|MS_NETDEV|MS_LOOP) #define MS_NOSYS (MS_NOAUTO|MS_USERS|MS_USER|MS_COMMENT|MS_LOOP)
/* Options that we keep from appearing in the options field in the mtab. */ /* Options that we keep from appearing in the options field in the mtab. */
#define MS_NOMTAB (MS_REMOUNT|MS_NOAUTO|MS_USERS|MS_USER) #define MS_NOMTAB (MS_REMOUNT|MS_NOAUTO|MS_USERS|MS_USER)
@ -170,7 +135,9 @@ static const struct opt_map opt_map[] = {
{ "nouser", 0, 1, MS_USER }, /* Forbid ordinary user to mount */ { "nouser", 0, 1, MS_USER }, /* Forbid ordinary user to mount */
{ "owner", 0, 0, MS_OWNER }, /* Let the owner of the device mount */ { "owner", 0, 0, MS_OWNER }, /* Let the owner of the device mount */
{ "noowner", 0, 1, MS_OWNER }, /* Device owner has no special privs */ { "noowner", 0, 1, MS_OWNER }, /* Device owner has no special privs */
{ "_netdev", 0, 0, MS_NETDEV }, /* Device accessible only via network */ { "_netdev", 0, 0, MS_COMMENT}, /* Device requires network */
{ "comment", 0, 0, MS_COMMENT}, /* fstab comment only (kudzu,_netdev)*/
/* add new options here */ /* add new options here */
#ifdef MS_NOSUB #ifdef MS_NOSUB
{ "sub", 0, 1, MS_NOSUB }, /* allow submounts */ { "sub", 0, 1, MS_NOSUB }, /* allow submounts */
@ -196,19 +163,20 @@ static const struct opt_map opt_map[] = {
{ NULL, 0, 0, 0 } { NULL, 0, 0, 0 }
}; };
static char *opt_loopdev, *opt_vfstype, *opt_offset, *opt_encryption, static const char *opt_loopdev, *opt_vfstype, *opt_offset, *opt_encryption,
*opt_speed; *opt_speed, *opt_comment;
static struct string_opt_map { static struct string_opt_map {
char *tag; char *tag;
int skip; int skip;
char **valptr; const char **valptr;
} string_opt_map[] = { } string_opt_map[] = {
{ "loop=", 0, &opt_loopdev }, { "loop=", 0, &opt_loopdev },
{ "vfs=", 1, &opt_vfstype }, { "vfs=", 1, &opt_vfstype },
{ "offset=", 0, &opt_offset }, { "offset=", 0, &opt_offset },
{ "encryption=", 0, &opt_encryption }, { "encryption=", 0, &opt_encryption },
{ "speed=", 0, &opt_speed }, { "speed=", 0, &opt_speed },
{ "comment=", 1, &opt_comment },
{ NULL, 0, NULL } { NULL, 0, NULL }
}; };
@ -239,23 +207,23 @@ int mount_quiet=0;
/* Report on a single mount. */ /* Report on a single mount. */
static void static void
print_one (const struct mntent *me) { print_one (const struct my_mntent *me) {
if (mount_quiet) if (mount_quiet)
return; return;
printf ("%s on %s", me->mnt_fsname, me->mnt_dir); printf ("%s on %s", me->mnt_fsname, me->mnt_dir);
if (me->mnt_type != NULL && *(me->mnt_type) != '\0') if (me->mnt_type != NULL && *(me->mnt_type) != '\0')
printf (" type %s", me->mnt_type); printf (" type %s", me->mnt_type);
if (me->mnt_opts != NULL) if (me->mnt_opts != NULL)
printf (" (%s)", me->mnt_opts); printf (" (%s)", me->mnt_opts);
if (list_with_volumelabel) { if (list_with_volumelabel) {
const char *label; const char *label;
label = mount_get_volume_label_by_spec(me->mnt_fsname); label = mount_get_volume_label_by_spec(me->mnt_fsname);
if (label) { if (label) {
printf (" [%s]", label); printf (" [%s]", label);
/* free(label); */ /* free(label); */
} }
} }
printf ("\n"); printf ("\n");
} }
/* Report on everything in mtab (of the specified types if any). */ /* Report on everything in mtab (of the specified types if any). */
@ -271,6 +239,11 @@ print_all (char *types) {
exit (0); exit (0);
} }
static void
my_free(const void *s) {
if (s)
free((void *) s);
}
/* /*
* Look for OPT in opt_map table and return mask value. * Look for OPT in opt_map table and return mask value.
@ -332,21 +305,24 @@ parse_opt (const char *opt, int *mask, char *extra_opts) {
/* Take -o options list and compute 4th and 5th args to mount(2). flags /* Take -o options list and compute 4th and 5th args to mount(2). flags
gets the standard options (indicated by bits) and extra_opts all the rest */ gets the standard options (indicated by bits) and extra_opts all the rest */
static void static void
parse_opts (char *opts, int *flags, char **extra_opts) { parse_opts (const char *options, int *flags, char **extra_opts) {
char *opt;
*flags = 0; *flags = 0;
*extra_opts = NULL; *extra_opts = NULL;
clear_string_opts(); clear_string_opts();
if (opts != NULL) { if (options != NULL) {
char *opts = xstrdup(options);
char *opt;
*extra_opts = xmalloc (strlen (opts) + 1); *extra_opts = xmalloc (strlen (opts) + 1);
**extra_opts = '\0'; **extra_opts = '\0';
for (opt = strtok (opts, ","); opt; opt = strtok (NULL, ",")) for (opt = strtok (opts, ","); opt; opt = strtok (NULL, ","))
if (!parse_string_opt (opt)) if (!parse_string_opt (opt))
parse_opt (opt, flags, *extra_opts); parse_opt (opt, flags, *extra_opts);
free(opts);
} }
if (readonly) if (readonly)
@ -363,7 +339,7 @@ fix_opts_string (int flags, const char *extra_opts, const char *user) {
const struct string_opt_map *m; const struct string_opt_map *m;
char *new_opts; char *new_opts;
new_opts = (flags & MS_RDONLY) ? "ro" : "rw"; new_opts = xstrdup((flags & MS_RDONLY) ? "ro" : "rw");
for (om = opt_map; om->opt != NULL; om++) { for (om = opt_map; om->opt != NULL; om++) {
if (om->skip) if (om->skip)
continue; continue;
@ -388,63 +364,66 @@ fix_opts_string (int flags, const char *extra_opts, const char *user) {
static int static int
already (const char *spec, const char *node) { already (const char *spec, const char *node) {
struct mntentchn *mc; struct mntentchn *mc;
int ret = 1; int ret = 1;
if ((mc = getmntfile(node)) != NULL) if ((mc = getmntfile(node)) != NULL)
error (_("mount: according to mtab, %s is already mounted on %s"), error (_("mount: according to mtab, "
mc->m.mnt_fsname, node); "%s is already mounted on %s"),
else if (spec && strcmp (spec, "none") && mc->m.mnt_fsname, node);
(mc = getmntfile(spec)) != NULL) else if (spec && strcmp (spec, "none") &&
error (_("mount: according to mtab, %s is mounted on %s"), (mc = getmntfile(spec)) != NULL)
spec, mc->m.mnt_dir); error (_("mount: according to mtab, %s is mounted on %s"),
else spec, mc->m.mnt_dir);
ret = 0; else
return ret; ret = 0;
return ret;
} }
/* Create mtab with a root entry. */ /* Create mtab with a root entry. */
static void static void
create_mtab (void) { create_mtab (void) {
struct mntentchn *fstab; struct mntentchn *fstab;
struct mntent mnt; struct my_mntent mnt;
int flags; int flags;
char *extra_opts; mntFILE *mfp;
mntFILE *mfp;
lock_mtab(); lock_mtab();
mfp = my_setmntent (MOUNTED, "a+"); mfp = my_setmntent (MOUNTED, "a+");
if (mfp == NULL || mfp->mntent_fp == NULL) { if (mfp == NULL || mfp->mntent_fp == NULL) {
int errsv = errno; int errsv = errno;
die (EX_FILEIO, _("mount: can't open %s for writing: %s"), die (EX_FILEIO, _("mount: can't open %s for writing: %s"),
MOUNTED, strerror (errsv)); MOUNTED, strerror (errsv));
} }
/* Find the root entry by looking it up in fstab */ /* Find the root entry by looking it up in fstab */
if ((fstab = getfsfile ("/")) || (fstab = getfsfile ("root"))) { if ((fstab = getfsfile ("/")) || (fstab = getfsfile ("root"))) {
parse_opts (xstrdup (fstab->m.mnt_opts), &flags, &extra_opts); char *extra_opts;
mnt.mnt_dir = "/"; parse_opts (fstab->m.mnt_opts, &flags, &extra_opts);
mnt.mnt_fsname = canonicalize (fstab->m.mnt_fsname); mnt.mnt_dir = "/";
mnt.mnt_type = fstab->m.mnt_type; mnt.mnt_fsname = canonicalize (fstab->m.mnt_fsname);
mnt.mnt_opts = fix_opts_string (flags, extra_opts, NULL); mnt.mnt_type = fstab->m.mnt_type;
mnt.mnt_freq = mnt.mnt_passno = 0; mnt.mnt_opts = fix_opts_string (flags, extra_opts, NULL);
mnt.mnt_freq = mnt.mnt_passno = 0;
my_free(extra_opts);
if (my_addmntent (mfp, &mnt) == 1) { if (my_addmntent (mfp, &mnt) == 1) {
int errsv = errno; int errsv = errno;
die (EX_FILEIO, _("mount: error writing %s: %s"), die (EX_FILEIO, _("mount: error writing %s: %s"),
MOUNTED, strerror (errsv)); MOUNTED, strerror (errsv));
} }
} }
if (fchmod (fileno (mfp->mntent_fp), S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH) < 0) if (fchmod (fileno (mfp->mntent_fp), 0644) < 0)
if (errno != EROFS) { if (errno != EROFS) {
int errsv = errno; int errsv = errno;
die (EX_FILEIO, _("mount: error changing mode of %s: %s"), die (EX_FILEIO,
MOUNTED, strerror (errsv)); _("mount: error changing mode of %s: %s"),
} MOUNTED, strerror (errsv));
my_endmntent (mfp); }
my_endmntent (mfp);
unlock_mtab(); unlock_mtab();
} }
/* count successful mount system calls */ /* count successful mount system calls */
@ -477,8 +456,8 @@ do_mount_syscall (struct mountargs *args) {
* on return types is filled with the type used. * on return types is filled with the type used.
*/ */
static int static int
guess_fstype_and_mount (char *spec, char *node, char **types, guess_fstype_and_mount(const char *spec, const char *node, const char **types,
int flags, char *mount_opts) { int flags, char *mount_opts) {
struct mountargs args = { spec, node, NULL, flags & ~MS_NOSYS, mount_opts }; struct mountargs args = { spec, node, NULL, flags & ~MS_NOSYS, mount_opts };
if (*types && strcasecmp (*types, "auto") == 0) if (*types && strcasecmp (*types, "auto") == 0)
@ -526,12 +505,12 @@ guess_fstype_and_mount (char *spec, char *node, char **types,
* Die if the user is not allowed to do this. * Die if the user is not allowed to do this.
*/ */
static void static void
suid_check(char *spec, char *node, int *flags, char **user) { suid_check(const char *spec, const char *node, int *flags, char **user) {
if (suid) { if (suid) {
/* RedHat patch: allow owners to mount when fstab contains /* RedHat patch: allow owners to mount when fstab contains
the owner option. Note that this should never be used the owner option. Note that this should never be used
in a high security environment, but may be useful to give in a high security environment, but may be useful to give
people at the console the possibility of mounting a floppy. */ people at the console the possibility of mounting a floppy. */
if (*flags & MS_OWNER) { if (*flags & MS_OWNER) {
if (!strncmp(spec, "/dev/", 5)) { if (!strncmp(spec, "/dev/", 5)) {
struct stat sb; struct stat sb;
@ -545,14 +524,14 @@ suid_check(char *spec, char *node, int *flags, char **user) {
/* James Kehl <mkehl@gil.com.au> came with a similar patch: /* James Kehl <mkehl@gil.com.au> came with a similar patch:
allow an arbitrary user to mount when he is the owner of allow an arbitrary user to mount when he is the owner of
the mount-point and has write-access to the device. the mount-point and has write-access to the device.
This is even less secure. Let me skip it for the time being; This is even less secure. Let me skip it for the time being;
there should be an explicit fstab line allowing such things. */ there should be an explicit fstab line allowing such things. */
if (!(*flags & (MS_USER | MS_USERS))) { if (!(*flags & (MS_USER | MS_USERS))) {
if (already (spec, node)) if (already (spec, node))
die (EX_USAGE, _("mount failed")); die (EX_USAGE, _("mount failed"));
else else
die (EX_USAGE, _("mount: only root can mount %s on %s"), spec, node); die (EX_USAGE, _("mount: only root can mount %s on %s"), spec, node);
} }
if (*flags & MS_USER) if (*flags & MS_USER)
*user = getusername(); *user = getusername();
@ -563,8 +542,8 @@ suid_check(char *spec, char *node, int *flags, char **user) {
} }
static int static int
loop_check(char **spec, char **type, int *flags, loop_check(const char **spec, const char **type, int *flags,
int *loop, char **loopdev, char **loopfile) { int *loop, const char **loopdev, const char **loopfile) {
int looptype; int looptype;
unsigned long long offset; unsigned long long offset;
@ -627,45 +606,47 @@ loop_check(char **spec, char **type, int *flags,
} }
static void static void
update_mtab_entry(char *spec, char *node, char *type, char *opts, update_mtab_entry(const char *spec, const char *node, const char *type,
int flags, int freq, int pass) { const char *opts, int flags, int freq, int pass) {
struct mntent mnt; struct my_mntent mnt;
mnt.mnt_fsname = canonicalize (spec); mnt.mnt_fsname = canonicalize (spec);
mnt.mnt_dir = canonicalize (node); mnt.mnt_dir = canonicalize (node);
mnt.mnt_type = type; mnt.mnt_type = type;
mnt.mnt_opts = opts; mnt.mnt_opts = opts;
mnt.mnt_freq = freq; mnt.mnt_freq = freq;
mnt.mnt_passno = pass; mnt.mnt_passno = pass;
/* We get chatty now rather than after the update to mtab since the /* We get chatty now rather than after the update to mtab since the
mount succeeded, even if the write to /etc/mtab should fail. */ mount succeeded, even if the write to /etc/mtab should fail. */
if (verbose) if (verbose)
print_one (&mnt); print_one (&mnt);
if (!nomtab && mtab_is_writable()) { if (!nomtab && mtab_is_writable()) {
if (flags & MS_REMOUNT) if (flags & MS_REMOUNT)
update_mtab (mnt.mnt_dir, &mnt); update_mtab (mnt.mnt_dir, &mnt);
else { else {
mntFILE *mfp; mntFILE *mfp;
lock_mtab(); lock_mtab();
mfp = my_setmntent(MOUNTED, "a+"); mfp = my_setmntent(MOUNTED, "a+");
if (mfp == NULL || mfp->mntent_fp == NULL) { if (mfp == NULL || mfp->mntent_fp == NULL) {
int errsv = errno; int errsv = errno;
error(_("mount: can't open %s: %s"), MOUNTED, error(_("mount: can't open %s: %s"), MOUNTED,
strerror (errsv)); strerror (errsv));
} else { } else {
if ((my_addmntent (mfp, &mnt)) == 1) { if ((my_addmntent (mfp, &mnt)) == 1) {
int errsv = errno; int errsv = errno;
error(_("mount: error writing %s: %s"), MOUNTED, error(_("mount: error writing %s: %s"),
strerror (errsv)); MOUNTED, strerror (errsv));
}
}
my_endmntent(mfp);
unlock_mtab();
} }
my_endmntent(mfp);
}
unlock_mtab();
} }
} my_free(mnt.mnt_fsname);
my_free(mnt.mnt_dir);
} }
static void static void
@ -677,20 +658,21 @@ set_pfd(char *s) {
} }
static void static void
cdrom_setspeed(char *spec) { cdrom_setspeed(const char *spec) {
#define CDROM_SELECT_SPEED 0x5322 /* Set the CD-ROM speed */ #define CDROM_SELECT_SPEED 0x5322 /* Set the CD-ROM speed */
if (opt_speed) { if (opt_speed) {
int cdrom; int cdrom;
int speed = atoi(opt_speed); int speed = atoi(opt_speed);
if ((cdrom = open(spec, O_RDONLY | O_NONBLOCK)) < 0) if ((cdrom = open(spec, O_RDONLY | O_NONBLOCK)) < 0)
die(EX_FAIL, _("mount: cannot open %s for setting speed"), die(EX_FAIL,
spec); _("mount: cannot open %s for setting speed"),
if (ioctl(cdrom, CDROM_SELECT_SPEED, speed) < 0) spec);
die(EX_FAIL, _("mount: cannot set speed: %s"), if (ioctl(cdrom, CDROM_SELECT_SPEED, speed) < 0)
strerror(errno)); die(EX_FAIL, _("mount: cannot set speed: %s"),
close(cdrom); strerror(errno));
} close(cdrom);
}
} }
/* /*
@ -700,8 +682,8 @@ cdrom_setspeed(char *spec) {
*/ */
static int static int
check_special_mountprog(char *spec, char *node, char *type, int flags, check_special_mountprog(const char *spec, const char *node, const char *type,
char *extra_opts, int *status) { int flags, char *extra_opts, int *status) {
char mountprog[120]; char mountprog[120];
struct stat statbuf; struct stat statbuf;
int res; int res;
@ -714,7 +696,7 @@ check_special_mountprog(char *spec, char *node, char *type, int flags,
if (stat(mountprog, &statbuf) == 0) { if (stat(mountprog, &statbuf) == 0) {
res = fork(); res = fork();
if (res == 0) { if (res == 0) {
char *oo, *mountargs[10]; const char *oo, *mountargs[10];
int i = 0; int i = 0;
setuid(getuid()); setuid(getuid());
@ -732,7 +714,7 @@ check_special_mountprog(char *spec, char *node, char *type, int flags,
mountargs[i++] = oo; mountargs[i++] = oo;
} }
mountargs[i] = NULL; mountargs[i] = NULL;
execv(mountprog, mountargs); execv(mountprog, (char **) mountargs);
exit(1); /* exec failed */ exit(1); /* exec failed */
} else if (res != -1) { } else if (res != -1) {
int st; int st;
@ -758,32 +740,35 @@ check_special_mountprog(char *spec, char *node, char *type, int flags,
* return status from wait * return status from wait
*/ */
static int static int
try_mount_one (const char *spec0, const char *node0, char *types0, try_mount_one (const char *spec0, const char *node0, const char *types0,
const char *opts0, int freq, int pass, int bg, int ro) { const char *opts0, int freq, int pass, int bg, int ro) {
int res, status; int res = 0, status;
int mnt5_res = 0; /* only for gcc */ int mnt5_res = 0; /* only for gcc */
int mnt_err; int mnt_err;
int flags; int flags;
char *extra_opts; /* written in mtab */ char *extra_opts; /* written in mtab */
char *mount_opts; /* actually used on system call */ char *mount_opts; /* actually used on system call */
const char *opts; const char *opts, *spec, *node, *types;
char *spec, *node, *types;
char *user = 0; char *user = 0;
int loop = 0; int loop = 0;
char *loopdev = 0, *loopfile = 0; const char *loopdev = 0, *loopfile = 0;
struct stat statbuf; struct stat statbuf;
int nfs_mount_version = 0; /* any version */ int nfs_mount_version = 0; /* any version */
spec = xstrdup(spec0); /* copies for freeing on exit */
node = xstrdup(node0); const char *opts1, *spec1, *node1, *types1, *extra_opts1;
types = xstrdup(types0);
opts = xstrdup(opts0);
parse_opts (xstrdup (opts), &flags, &extra_opts); spec = spec1 = xstrdup(spec0);
node = node1 = xstrdup(node0);
types = types1 = xstrdup(types0);
opts = opts1 = xstrdup(opts0);
parse_opts (opts, &flags, &extra_opts);
extra_opts1 = extra_opts;
/* quietly succeed for fstab entries that don't get mounted automatically */ /* quietly succeed for fstab entries that don't get mounted automatically */
if (mount_all && (flags & MS_NOAUTO)) if (mount_all && (flags & MS_NOAUTO))
return 0; goto out;
suid_check(spec, node, &flags, &user); suid_check(spec, node, &flags, &user);
@ -800,7 +785,7 @@ try_mount_one (const char *spec0, const char *node0, char *types0,
*/ */
res = loop_check(&spec, &types, &flags, &loop, &loopdev, &loopfile); res = loop_check(&spec, &types, &flags, &loop, &loopdev, &loopfile);
if (res) if (res)
return res; goto out;
} }
/* /*
@ -808,8 +793,10 @@ try_mount_one (const char *spec0, const char *node0, char *types0,
* For the moment these types are ncpfs and smbfs. Maybe also vxfs. * For the moment these types are ncpfs and smbfs. Maybe also vxfs.
* All such special things must occur isolated in the types string. * All such special things must occur isolated in the types string.
*/ */
if (check_special_mountprog (spec, node, types, flags, extra_opts, &status)) if (check_special_mountprog(spec, node, types, flags, extra_opts, &status)) {
return status; res = status;
goto out;
}
/* /*
* Also nfs requires a separate program, but it is built in. * Also nfs requires a separate program, but it is built in.
@ -819,11 +806,13 @@ try_mount_one (const char *spec0, const char *node0, char *types0,
retry_nfs: retry_nfs:
mnt_err = nfsmount (spec, node, &flags, &extra_opts, &mount_opts, mnt_err = nfsmount (spec, node, &flags, &extra_opts, &mount_opts,
&nfs_mount_version, bg); &nfs_mount_version, bg);
if (mnt_err) if (mnt_err) {
return mnt_err; res = mnt_err;
goto out;
}
#else #else
die (EX_SOFTWARE, _("mount: this version was compiled " die (EX_SOFTWARE, _("mount: this version was compiled "
"without support for the type `nfs'")); "without support for the type `nfs'"));
#endif #endif
} }
@ -847,7 +836,8 @@ retry_nfs:
pass); pass);
block_signals (SIG_UNBLOCK); block_signals (SIG_UNBLOCK);
return 0; res = 0;
goto out;
} }
mnt_err = errno; mnt_err = errno;
@ -913,13 +903,13 @@ retry_nfs:
else if (stat (spec, &statbuf)) else if (stat (spec, &statbuf))
error (_("mount: special device %s does not exist"), spec); error (_("mount: special device %s does not exist"), spec);
else { else {
errno = mnt_err; errno = mnt_err;
perror("mount"); perror("mount");
} }
break; break;
case ENOTDIR: case ENOTDIR:
if (stat (node, &statbuf) || ! S_ISDIR(statbuf.st_mode)) if (stat (node, &statbuf) || ! S_ISDIR(statbuf.st_mode))
error (_("mount: mount point %s is not a directory"), node); error (_("mount: mount point %s is not a directory"), node);
else if (stat (spec, &statbuf) && errno == ENOTDIR) else if (stat (spec, &statbuf) && errno == ENOTDIR)
error (_("mount: special device %s does not exist\n" error (_("mount: special device %s does not exist\n"
" (a path prefix is not a directory)\n"), spec); " (a path prefix is not a directory)\n"), spec);
@ -981,7 +971,7 @@ retry_nfs:
char *lowtype, *p; char *lowtype, *p;
int u; int u;
error (_("mount: fs type %s not supported by kernel"), types); error (_("mount: unknown filesystem type '%s'"), types);
/* maybe this loser asked for FAT or ISO9660 or isofs */ /* maybe this loser asked for FAT or ISO9660 or isofs */
lowtype = xstrdup(types); lowtype = xstrdup(types);
@ -995,7 +985,9 @@ retry_nfs:
if (u && is_in_procfs(lowtype) == 1) if (u && is_in_procfs(lowtype) == 1)
error (_("mount: probably you meant %s"), lowtype); error (_("mount: probably you meant %s"), lowtype);
else if (!strncmp(lowtype, "iso", 3) && is_in_procfs("iso9660") == 1) else if (!strncmp(lowtype, "iso", 3) && is_in_procfs("iso9660") == 1)
error (_("mount: maybe you meant iso9660 ?")); error (_("mount: maybe you meant 'iso9660'?"));
else if (!strncmp(lowtype, "fat", 3) && is_in_procfs("vfat") == 1)
error (_("mount: maybe you meant 'vfat'?"));
free(lowtype); free(lowtype);
} else } else
error (_("mount: %s has wrong device number or fs type %s not supported"), error (_("mount: %s has wrong device number or fs type %s not supported"),
@ -1033,16 +1025,18 @@ retry_nfs:
types = types0; types = types0;
} }
if (opts) { if (opts) {
char *opts1 = realloc(xstrdup(opts), strlen(opts)+4); char *opts2 = realloc(xstrdup(opts), strlen(opts)+4);
strcat(opts1, ",ro"); strcat(opts2, ",ro");
opts = opts1; my_free(opts1);
opts = opts1 = opts2;
} else } else
opts = "ro"; opts = "ro";
if (types && !strcmp(types, "guess")) if (types && !strcmp(types, "guess"))
types = 0; types = 0;
error (_("mount: %s%s is write-protected, mounting read-only"), error (_("mount: %s%s is write-protected, mounting read-only"),
bd, spec0); bd, spec0);
return try_mount_one (spec0, node0, types, opts, freq, pass, bg, 1); res = try_mount_one (spec0, node0, types, opts, freq, pass, bg, 1);
goto out;
} }
break; break;
} }
@ -1050,7 +1044,16 @@ retry_nfs:
error ("mount: %s", strerror (mnt_err)); break; error ("mount: %s", strerror (mnt_err)); break;
} }
} }
return EX_FAIL; res = EX_FAIL;
out:
my_free(extra_opts1);
my_free(spec1);
my_free(node1);
my_free(opts1);
my_free(types1);
return res;
} }
/* /*
@ -1094,14 +1097,20 @@ usersubst(const char *opts) {
} }
return opts; return opts;
} }
static int
is_existing_file (const char *s) {
struct stat statbuf;
return (stat(s, &statbuf) == 0);
}
/* /*
* Return 0 for success (either mounted sth or -a and NOAUTO was given) * Return 0 for success (either mounted sth or -a and NOAUTO was given)
*/ */
static int static int
mount_one (const char *spec, const char *node, char *types, const char *opts, mount_one (const char *spec, const char *node, const char *types,
char *cmdlineopts, int freq, int pass) { const char *opts, char *cmdlineopts, int freq, int pass) {
int status, status2; int status, status2;
const char *nspec; const char *nspec;
@ -1119,7 +1128,7 @@ mount_one (const char *spec, const char *node, char *types, const char *opts,
if (nspec) if (nspec)
spec = nspec; spec = nspec;
if (types == NULL && !mounttype) { if (types == NULL && !mounttype && !is_existing_file(spec)) {
if (strchr (spec, ':') != NULL) { if (strchr (spec, ':') != NULL) {
types = "nfs"; types = "nfs";
if (verbose) if (verbose)
@ -1161,25 +1170,34 @@ mount_one (const char *spec, const char *node, char *types, const char *opts,
/* Check if an fsname/dir pair was already in the old mtab. */ /* Check if an fsname/dir pair was already in the old mtab. */
static int static int
mounted (const char *spec, char *node) { mounted (const char *spec0, const char *node0) {
struct mntentchn *mc, *mc0; struct mntentchn *mc, *mc0;
char *spec, *node;
int ret = 0;
/* Handle possible UUID= and LABEL= in spec */ /* Handle possible UUID= and LABEL= in spec */
spec = mount_get_devname(spec); spec0 = mount_get_devname(spec0);
spec = canonicalize(spec); spec = canonicalize(spec0);
node = canonicalize(node); node = canonicalize(node0);
mc0 = mtab_head(); mc0 = mtab_head();
for (mc = mc0->nxt; mc && mc != mc0; mc = mc->nxt) for (mc = mc0->nxt; mc && mc != mc0; mc = mc->nxt)
if (streq (spec, mc->m.mnt_fsname) && streq (node, mc->m.mnt_dir)) if (streq (spec, mc->m.mnt_fsname) &&
return 1; streq (node, mc->m.mnt_dir)) {
return 0; ret = 1;
break;
}
free(spec);
free(node);
return ret;
} }
/* avoid using stat() on things we are not going to mount anyway.. */ /* avoid using stat() on things we are not going to mount anyway.. */
static int static int
has_noauto (char *opts) { has_noauto (const char *opts) {
char *s; char *s;
if (!opts) if (!opts)
@ -1586,8 +1604,7 @@ main (int argc, char *argv[]) {
die (EX_USAGE, die (EX_USAGE,
_("mount: cannot find %s in %s"), _("mount: cannot find %s in %s"),
spec, _PATH_FSTAB); spec, _PATH_FSTAB);
/* struct mntent does not have const qualifiers */ mc->m.mnt_fsname = spec;
mc->m.mnt_fsname = (char *) spec;
} else { } else {
/* Try to find the other pathname in fstab. */ /* Try to find the other pathname in fstab. */
spec = canonicalize (*argv); spec = canonicalize (*argv);
@ -1605,6 +1622,8 @@ main (int argc, char *argv[]) {
/* Earlier mtab was tried first, but this would /* Earlier mtab was tried first, but this would
sometimes try the wrong mount in case mtab had sometimes try the wrong mount in case mtab had
the root device entry wrong. */ the root device entry wrong. */
my_free(spec);
} }
result = mount_one (xstrdup (mc->m.mnt_fsname), result = mount_one (xstrdup (mc->m.mnt_fsname),

View File

@ -97,11 +97,12 @@ swapped(unsigned short a) {
Added jfs - Christoph Hellwig Added jfs - Christoph Hellwig
Added sysv - Tim Launchbury Added sysv - Tim Launchbury
Added udf - Bryce Nesbitt Added udf - Bryce Nesbitt
Added ocfs, ocfs2 - Manish Singh - http://oss.oracle.com/projects/ocfs2/
*/ */
static char static char
*magic_known[] = { *magic_known[] = {
"adfs", "bfs", "cramfs", "efs", "ext", "ext2", "ext3", "adfs", "bfs", "cramfs", "efs", "ext", "ext2", "ext3",
"hfs", "hpfs", "iso9660", "jfs", "minix", "ntfs", "hfs", "hpfs", "iso9660", "jfs", "minix", "ntfs", "ocfs", "ocfs2",
"qnx4", "reiserfs", "romfs", "swap", "sysv", "udf", "ufs", "qnx4", "reiserfs", "romfs", "swap", "sysv", "udf", "ufs",
"vxfs", "xfs", "xiafs" "vxfs", "xfs", "xiafs"
}; };
@ -212,6 +213,7 @@ do_guess_fstype(const char *device) {
struct fat_super_block fatsb; struct fat_super_block fatsb;
struct xfs_super_block xfsb; struct xfs_super_block xfsb;
struct cramfs_super_block cramfssb; struct cramfs_super_block cramfssb;
struct ocfs_volume_header ovh;
struct efs_volume_header efsvh; struct efs_volume_header efsvh;
struct efs_super efssb; struct efs_super efssb;
} xsb; /* stuff at 0 */ } xsb; /* stuff at 0 */
@ -232,6 +234,7 @@ do_guess_fstype(const char *device) {
struct hpfs_super_block hpfssb; struct hpfs_super_block hpfssb;
struct adfs_super_block adfssb; struct adfs_super_block adfssb;
struct sysv_super_block svsb; struct sysv_super_block svsb;
struct ocfs2_super_block osb;
struct stat statbuf; struct stat statbuf;
/* opening and reading an arbitrary unknown path can have /* opening and reading an arbitrary unknown path can have
@ -261,6 +264,8 @@ do_guess_fstype(const char *device) {
type = "romfs"; type = "romfs";
else if(!strncmp(xsb.xfsb.s_magic, XFS_SUPER_MAGIC, 4)) else if(!strncmp(xsb.xfsb.s_magic, XFS_SUPER_MAGIC, 4))
type = "xfs"; type = "xfs";
else if(!strncmp(xsb.ovh.signature, OCFS_MAGIC, sizeof(OCFS_MAGIC)))
type = "ocfs";
else if(!strncmp(xsb.qnx4fs_magic+4, "QNX4FS", 6)) else if(!strncmp(xsb.qnx4fs_magic+4, "QNX4FS", 6))
type = "qnx4"; type = "qnx4";
else if(xsb.bfs_magic == 0x1badface) else if(xsb.bfs_magic == 0x1badface)
@ -438,6 +443,22 @@ do_guess_fstype(const char *device) {
type = "reiserfs"; type = "reiserfs";
} }
if (!type) {
int blksize, blkoff;
for (blksize = OCFS2_MIN_BLOCKSIZE;
blksize <= OCFS2_MAX_BLOCKSIZE;
blksize <<= 1) {
blkoff = blksize * OCFS2_SUPER_BLOCK_BLKNO;
if (lseek(fd, blkoff, SEEK_SET) != blkoff
|| read(fd, (char *) &osb, sizeof(osb)) != sizeof(osb))
goto io_error;
if (strncmp(osb.signature, OCFS2_SUPER_BLOCK_SIGNATURE,
sizeof(OCFS2_SUPER_BLOCK_SIGNATURE)) == 0)
type = "ocfs2";
}
}
if (!type) { if (!type) {
/* perhaps the user tries to mount the swap space /* perhaps the user tries to mount the swap space
on a new disk; warn her before she does mke2fs on it */ on a new disk; warn her before she does mke2fs on it */
@ -573,11 +594,11 @@ is_in_procfs(const char *type) {
/* when 1 is returned, *types is NULL */ /* when 1 is returned, *types is NULL */
int int
procfsloop(int (*mount_fn)(struct mountargs *), struct mountargs *args, procfsloop(int (*mount_fn)(struct mountargs *), struct mountargs *args,
char **types) { const char **types) {
char *files[2] = { ETC_FILESYSTEMS, PROC_FILESYSTEMS }; char *files[2] = { ETC_FILESYSTEMS, PROC_FILESYSTEMS };
FILE *procfs; FILE *procfs;
char *fsname; char *fsname;
char *notypes = NULL; const char *notypes = NULL;
int no = 0; int no = 0;
int ret = 1; int ret = 1;
int errsv = 0; int errsv = 0;

View File

@ -11,6 +11,6 @@ extern int verbose;
char *guess_fstype(const char *device); char *guess_fstype(const char *device);
char *do_guess_fstype(const char *device); char *do_guess_fstype(const char *device);
int procfsloop(int (*mount_fn)(struct mountargs *), struct mountargs *args, int procfsloop(int (*mount_fn)(struct mountargs *), struct mountargs *args,
char **type); const char **type);
int is_in_procfs(const char *fstype); int is_in_procfs(const char *fstype);

10
mount/paths.h Normal file
View File

@ -0,0 +1,10 @@
#include <mntent.h>
#define _PATH_FSTAB "/etc/fstab"
#ifdef _PATH_MOUNTED
#define MOUNTED_LOCK _PATH_MOUNTED "~"
#define MOUNTED_TEMP _PATH_MOUNTED ".tmp"
#else
#define MOUNTED_LOCK "/etc/mtab~"
#define MOUNTED_TEMP "/etc/mtab.tmp"
#endif
#define LOCK_TIMEOUT 10

View File

@ -32,17 +32,13 @@
#define MAX_READLINKS 32 #define MAX_READLINKS 32
/* this leaks some memory - unimportant for mount */
char * char *
myrealpath(const char *path, char *resolved_path, int maxreslth) { myrealpath(const char *path, char *resolved_path, int maxreslth) {
int readlinks = 0; int readlinks = 0;
char *npath; char *npath;
char link_path[PATH_MAX+1]; char link_path[PATH_MAX+1];
int n; int n;
#ifdef resolve_symlinks char *buf = NULL;
char *buf;
int m;
#endif
npath = resolved_path; npath = resolved_path;
@ -83,7 +79,7 @@ myrealpath(const char *path, char *resolved_path, int maxreslth) {
while (*path != '\0' && *path != '/') { while (*path != '\0' && *path != '/') {
if (npath-resolved_path > maxreslth-2) { if (npath-resolved_path > maxreslth-2) {
errno = ENAMETOOLONG; errno = ENAMETOOLONG;
return NULL; goto err;
} }
*npath++ = *path++; *npath++ = *path++;
} }
@ -91,7 +87,7 @@ myrealpath(const char *path, char *resolved_path, int maxreslth) {
/* Protect against infinite loops. */ /* Protect against infinite loops. */
if (readlinks++ > MAX_READLINKS) { if (readlinks++ > MAX_READLINKS) {
errno = ELOOP; errno = ELOOP;
return NULL; goto err;
} }
/* See if last pathname component is a symlink. */ /* See if last pathname component is a symlink. */
@ -100,9 +96,11 @@ myrealpath(const char *path, char *resolved_path, int maxreslth) {
if (n < 0) { if (n < 0) {
/* EINVAL means the file exists but isn't a symlink. */ /* EINVAL means the file exists but isn't a symlink. */
if (errno != EINVAL) if (errno != EINVAL)
return NULL; goto err;
} else { } else {
#ifdef resolve_symlinks /* Richard Gooch dislikes sl resolution */ #ifdef resolve_symlinks /* Richard Gooch dislikes sl resolution */
int m;
/* Note: readlink doesn't add the null byte. */ /* Note: readlink doesn't add the null byte. */
link_path[n] = '\0'; link_path[n] = '\0';
if (*link_path == '/') if (*link_path == '/')
@ -115,6 +113,8 @@ myrealpath(const char *path, char *resolved_path, int maxreslth) {
/* Insert symlink contents into path. */ /* Insert symlink contents into path. */
m = strlen(path); m = strlen(path);
if (buf)
free(buf);
buf = xmalloc(m + n + 1); buf = xmalloc(m + n + 1);
memcpy(buf, link_path, n); memcpy(buf, link_path, n);
memcpy(buf + n, path, m + 1); memcpy(buf + n, path, m + 1);
@ -128,5 +128,13 @@ myrealpath(const char *path, char *resolved_path, int maxreslth) {
npath--; npath--;
/* Make sure it's null terminated. */ /* Make sure it's null terminated. */
*npath = '\0'; *npath = '\0';
if (buf)
free(buf);
return resolved_path; return resolved_path;
err:
if (buf)
free(buf);
return NULL;
} }

View File

@ -73,6 +73,7 @@ xstrconcat2 (const char *s, const char *t) {
return res; return res;
} }
/* frees its first arg - typical use: s = xstrconcat3(s,t,u); */
char * char *
xstrconcat3 (const char *s, const char *t, const char *u) { xstrconcat3 (const char *s, const char *t, const char *u) {
char *res; char *res;
@ -84,9 +85,11 @@ xstrconcat3 (const char *s, const char *t, const char *u) {
strcpy(res, s); strcpy(res, s);
strcat(res, t); strcat(res, t);
strcat(res, u); strcat(res, u);
free((void *) s);
return res; return res;
} }
/* frees its first arg - typical use: s = xstrconcat4(s,t,u,v); */
char * char *
xstrconcat4 (const char *s, const char *t, const char *u, const char *v) { xstrconcat4 (const char *s, const char *t, const char *u, const char *v) {
char *res; char *res;
@ -100,6 +103,7 @@ xstrconcat4 (const char *s, const char *t, const char *u, const char *v) {
strcat(res, t); strcat(res, t);
strcat(res, u); strcat(res, u);
strcat(res, v); strcat(res, v);
free((void *) s);
return res; return res;
} }
@ -269,19 +273,18 @@ matching_opts (const char *options, const char *test_opts) {
we return unmodified. */ we return unmodified. */
char * char *
canonicalize (const char *path) { canonicalize (const char *path) {
char *canonical; char canonical[PATH_MAX+2];
if (path == NULL) if (path == NULL)
return NULL; return NULL;
if (streq(path, "none") || streq(path, "proc") || streq(path, "devpts")) if (streq(path, "none") ||
return xstrdup(path); streq(path, "proc") ||
streq(path, "devpts"))
return xstrdup(path);
canonical = xmalloc (PATH_MAX+2); if (myrealpath (path, canonical, PATH_MAX+1))
return xstrdup(canonical);
if (myrealpath (path, canonical, PATH_MAX+1))
return canonical;
free(canonical); return xstrdup(path);
return xstrdup(path);
} }

View File

@ -249,7 +249,7 @@ do_swapoff(const char *special, int quiet) {
exit(1); /* any further swapoffs will also fail */ exit(1); /* any further swapoffs will also fail */
} }
if (!quiet) { if (!quiet || errno == ENOMEM) {
int errsv = errno; int errsv = errno;
fprintf(stderr, "%s: %s: %s\n", program_name, fprintf(stderr, "%s: %s: %s\n", program_name,
special, strerror(errsv)); special, strerror(errsv));

View File

@ -316,7 +316,7 @@ umount_one (const char *spec, const char *node, const char *type,
res = mount(spec, node, NULL, res = mount(spec, node, NULL,
MS_MGC_VAL | MS_REMOUNT | MS_RDONLY, NULL); MS_MGC_VAL | MS_REMOUNT | MS_RDONLY, NULL);
if (res == 0) { if (res == 0) {
struct mntent remnt; struct my_mntent remnt;
fprintf(stderr, fprintf(stderr,
_("umount: %s busy - remounted read-only\n"), _("umount: %s busy - remounted read-only\n"),
spec); spec);
@ -392,6 +392,8 @@ umount_one (const char *spec, const char *node, const char *type,
} }
/* /*
* umount_one_bw: unmount FILE that has last occurrence MC0
*
* Why this loop? * Why this loop?
* 1. People who boot a system with a bad fstab root entry * 1. People who boot a system with a bad fstab root entry
* will get an incorrect "/dev/foo on /" in mtab. * will get an incorrect "/dev/foo on /" in mtab.
@ -472,52 +474,18 @@ usage (FILE *fp, int n)
int mount_quiet = 0; int mount_quiet = 0;
/*=======================================================================*/ /*
/* string list stuff - no longer used by mount - will disappear entirely */ * Look for an option in a comma-separated list
typedef struct string_list { */
char *hd;
struct string_list *tl;
} *string_list;
#define car(p) ((p) -> hd)
#define cdr(p) ((p) -> tl)
static string_list
cons (char *a, const string_list b) {
string_list p;
p = xmalloc (sizeof *p);
car (p) = a;
cdr (p) = b;
return p;
}
/* Parse a list of strings like str[,str]... into a string list. */
static string_list
parse_list (char *strings) {
string_list list;
char *s, *t;
if (strings == NULL)
return NULL;
/* strtok() destroys its argument, so we have to use a copy */
s = xstrdup(strings);
list = cons (strtok (s, ","), NULL);
while ((t = strtok (NULL, ",")) != NULL)
list = cons (t, list);
return list;
}
static int static int
contains(string_list list, char *s) { contains(const char *list, const char *s) {
while (list) { int n = strlen(s);
if (streq (car (list), s))
while (*list) {
if (strncmp(list, s, n) == 0 &&
(list[n] == 0 || list[n] == ','))
return 1; return 1;
list = cdr (list); while (*list && *list++ != ',') ;
} }
return 0; return 0;
} }
@ -526,12 +494,18 @@ contains(string_list list, char *s) {
* If list contains "user=peter" and we ask for "user=", return "peter" * If list contains "user=peter" and we ask for "user=", return "peter"
*/ */
static char * static char *
get_value(string_list list, char *s) { get_value(const char *list, const char *s) {
const char *t;
int n = strlen(s); int n = strlen(s);
while (list) {
if (strncmp (car (list), s, n) == 0) while (*list) {
return car(list)+n; if (strncmp(list, s, n) == 0) {
list = cdr (list); s = t = list+n;
while (*s && *s != ',')
s++;
return xstrndup(t, s-t);
}
while (*list && *list++ != ',') ;
} }
return 0; return 0;
} }
@ -539,8 +513,7 @@ get_value(string_list list, char *s) {
static int static int
umount_file (char *arg) { umount_file (char *arg) {
struct mntentchn *mc, *fs; struct mntentchn *mc, *fs;
char *file; const char *file, *options;
string_list options;
int fstab_has_user, fstab_has_users, fstab_has_owner, ok; 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 */
@ -594,7 +567,9 @@ umount_file (char *arg) {
/* A convenient side effect is that the user who mounted /* A convenient side effect is that the user who mounted
is visible in mtab. */ is visible in mtab. */
options = parse_list (fs->m.mnt_opts); options = fs->m.mnt_opts;
if (!options)
options = "";
fstab_has_user = contains(options, "user"); fstab_has_user = contains(options, "user");
fstab_has_users = contains(options, "users"); fstab_has_users = contains(options, "users");
fstab_has_owner = contains(options, "owner"); fstab_has_owner = contains(options, "owner");
@ -606,7 +581,9 @@ umount_file (char *arg) {
if (!ok && (fstab_has_user || fstab_has_owner)) { if (!ok && (fstab_has_user || fstab_has_owner)) {
char *user = getusername(); char *user = getusername();
options = parse_list (mc->m.mnt_opts); options = mc->m.mnt_opts;
if (!options)
options = "";
mtab_user = get_value(options, "user="); mtab_user = get_value(options, "user=");
if (user && mtab_user && streq (user, mtab_user)) if (user && mtab_user && streq (user, mtab_user))

View File

@ -10,7 +10,7 @@
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: util-linux 2.12\n" "Project-Id-Version: util-linux 2.12\n"
"POT-Creation-Date: 2004-09-07 03:04+0200\n" "POT-Creation-Date: 2004-09-07 03:05+0200\n"
"PO-Revision-Date: 2003-08-01 10:59+0200\n" "PO-Revision-Date: 2003-08-01 10:59+0200\n"
"Last-Translator: Antoni Bella Perez <bella5@teleline.es>\n" "Last-Translator: Antoni Bella Perez <bella5@teleline.es>\n"
"Language-Team: Catalan <ca@dodds.net>\n" "Language-Team: Catalan <ca@dodds.net>\n"

File diff suppressed because it is too large Load Diff

View File

@ -4,7 +4,7 @@
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: util-linux-2.11d\n" "Project-Id-Version: util-linux-2.11d\n"
"POT-Creation-Date: 2004-09-07 03:04+0200\n" "POT-Creation-Date: 2004-09-07 03:05+0200\n"
"PO-Revision-Date: 2001-05-30 15:11+0200\n" "PO-Revision-Date: 2001-05-30 15:11+0200\n"
"Last-Translator: Jiøí Pavlovský <pavlovsk@ff.cuni.cz>\n" "Last-Translator: Jiøí Pavlovský <pavlovsk@ff.cuni.cz>\n"
"Language-Team: Czech <cs@li.org>\n" "Language-Team: Czech <cs@li.org>\n"

View File

@ -12,7 +12,7 @@
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: util-linux 2.11y\n" "Project-Id-Version: util-linux 2.11y\n"
"POT-Creation-Date: 2004-09-07 03:04+0200\n" "POT-Creation-Date: 2004-09-07 03:05+0200\n"
"PO-Revision-Date: 2002-12-02 21:15GMT\n" "PO-Revision-Date: 2002-12-02 21:15GMT\n"
"Last-Translator: Claus Hindsgaul <claus_h@image.dk>\n" "Last-Translator: Claus Hindsgaul <claus_h@image.dk>\n"
"Language-Team: Danish <dansk@klid.dk>\n" "Language-Team: Danish <dansk@klid.dk>\n"

View File

@ -44,7 +44,7 @@
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: util-linux 2.12\n" "Project-Id-Version: util-linux 2.12\n"
"POT-Creation-Date: 2004-09-07 03:04+0200\n" "POT-Creation-Date: 2004-09-07 03:05+0200\n"
"PO-Revision-Date: 2003-08-14 15:43:31+0200\n" "PO-Revision-Date: 2003-08-14 15:43:31+0200\n"
"Last-Translator: Michael Piefel <piefel@informatik.hu-berlin.de>\n" "Last-Translator: Michael Piefel <piefel@informatik.hu-berlin.de>\n"
"Language-Team: German <de@li.org>\n" "Language-Team: German <de@li.org>\n"

View File

@ -12,7 +12,7 @@
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: util-linux 2.12\n" "Project-Id-Version: util-linux 2.12\n"
"POT-Creation-Date: 2004-09-07 03:04+0200\n" "POT-Creation-Date: 2004-09-07 03:05+0200\n"
"PO-Revision-Date: 2003-08-09 16:18+0200\n" "PO-Revision-Date: 2003-08-09 16:18+0200\n"
"Last-Translator: Santiago Vila Doncel <sanvila@unex.es>\n" "Last-Translator: Santiago Vila Doncel <sanvila@unex.es>\n"
"Language-Team: Spanish <es@li.org>\n" "Language-Team: Spanish <es@li.org>\n"

View File

@ -11,7 +11,7 @@
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: util-linux 2.11r\n" "Project-Id-Version: util-linux 2.11r\n"
"POT-Creation-Date: 2004-09-07 03:04+0200\n" "POT-Creation-Date: 2004-09-07 03:05+0200\n"
"PO-Revision-Date: 2002-05-19 20:04GMT+0300\n" "PO-Revision-Date: 2002-05-19 20:04GMT+0300\n"
"Last-Translator: Meelis Roos <mroos@linux.ee>\n" "Last-Translator: Meelis Roos <mroos@linux.ee>\n"
"Language-Team: Estonian <et@li.org>\n" "Language-Team: Estonian <et@li.org>\n"

View File

@ -14,7 +14,7 @@
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: util-linux 2.12\n" "Project-Id-Version: util-linux 2.12\n"
"POT-Creation-Date: 2004-09-07 03:04+0200\n" "POT-Creation-Date: 2004-09-07 03:05+0200\n"
"PO-Revision-Date: 2003-08-20 11:40+0300\n" "PO-Revision-Date: 2003-08-20 11:40+0300\n"
"Last-Translator: Lauri Nurmi <lanurmi@iki.fi>\n" "Last-Translator: Lauri Nurmi <lanurmi@iki.fi>\n"
"Language-Team: Finnish <translation-team-fi@lists.sourceforge.net>\n" "Language-Team: Finnish <translation-team-fi@lists.sourceforge.net>\n"

View File

@ -9,7 +9,7 @@
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: util-linux 2.12\n" "Project-Id-Version: util-linux 2.12\n"
"POT-Creation-Date: 2004-09-07 03:04+0200\n" "POT-Creation-Date: 2004-09-07 03:05+0200\n"
"PO-Revision-Date: 2004-05-10 08:00-0500\n" "PO-Revision-Date: 2004-05-10 08:00-0500\n"
"Last-Translator: Michel Robitaille <robitail@IRO.UMontreal.CA>\n" "Last-Translator: Michel Robitaille <robitail@IRO.UMontreal.CA>\n"
"Language-Team: French <traduc@traduc.org>\n" "Language-Team: French <traduc@traduc.org>\n"

View File

@ -4,7 +4,7 @@
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: util-linux 2.10f\n" "Project-Id-Version: util-linux 2.10f\n"
"POT-Creation-Date: 2004-09-07 03:04+0200\n" "POT-Creation-Date: 2004-09-07 03:05+0200\n"
"PO-Revision-Date: 2000-04-04 21:52-0800\n" "PO-Revision-Date: 2000-04-04 21:52-0800\n"
"Last-Translator: Beth Powell <bpowell@turbolinux.com>\n" "Last-Translator: Beth Powell <bpowell@turbolinux.com>\n"
"Language-Team: <support@turbolinux.com>\n" "Language-Team: <support@turbolinux.com>\n"

View File

@ -7,7 +7,7 @@
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: util-linux 2.11n\n" "Project-Id-Version: util-linux 2.11n\n"
"POT-Creation-Date: 2004-09-07 03:04+0200\n" "POT-Creation-Date: 2004-09-07 03:05+0200\n"
"PO-Revision-Date: 2001-12-11 22:43+0900\n" "PO-Revision-Date: 2001-12-11 22:43+0900\n"
"Last-Translator: Daisuke Yamashita <yamad@mb.infoweb.ne.jp>\n" "Last-Translator: Daisuke Yamashita <yamad@mb.infoweb.ne.jp>\n"
"Language-Team: Japanese <ja@li.org>\n" "Language-Team: Japanese <ja@li.org>\n"

View File

@ -19,7 +19,7 @@
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: util-linux 2.12\n" "Project-Id-Version: util-linux 2.12\n"
"POT-Creation-Date: 2004-09-07 03:04+0200\n" "POT-Creation-Date: 2004-09-07 03:05+0200\n"
"PO-Revision-Date: 2003-07-29 22:55+0100\n" "PO-Revision-Date: 2003-07-29 22:55+0100\n"
"Last-Translator: Taco Witte <T.C.Witte@phys.uu.nl>\n" "Last-Translator: Taco Witte <T.C.Witte@phys.uu.nl>\n"
"Language-Team: Dutch <vertaling@nl.linux.org>\n" "Language-Team: Dutch <vertaling@nl.linux.org>\n"

View File

@ -13,7 +13,7 @@
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: util-linux 2.11b\n" "Project-Id-Version: util-linux 2.11b\n"
"POT-Creation-Date: 2004-09-07 03:04+0200\n" "POT-Creation-Date: 2004-09-07 03:05+0200\n"
"PO-Revision-Date: 2001-05-24 16:03-03:00\n" "PO-Revision-Date: 2001-05-24 16:03-03:00\n"
"Last-Translator: Rodrigo Stulzer Lopes <rodrigo@conectiva.com.br>\n" "Last-Translator: Rodrigo Stulzer Lopes <rodrigo@conectiva.com.br>\n"
"Language-Team: Brazilian Portuguese <ldp-br@bazar.conectiva.com.br>\n" "Language-Team: Brazilian Portuguese <ldp-br@bazar.conectiva.com.br>\n"

View File

@ -11,7 +11,7 @@
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: util-linux 2.11y\n" "Project-Id-Version: util-linux 2.11y\n"
"POT-Creation-Date: 2004-09-07 03:04+0200\n" "POT-Creation-Date: 2004-09-07 03:05+0200\n"
"PO-Revision-Date: 2003-01-28 16:30+0100\n" "PO-Revision-Date: 2003-01-28 16:30+0100\n"
"Last-Translator: Primo¾ Peterlin <primoz.peterlin@biofiz.mf.uni-lj.si>\n" "Last-Translator: Primo¾ Peterlin <primoz.peterlin@biofiz.mf.uni-lj.si>\n"
"Language-Team: Slovenian <translation-team-sl@lists.sourceforge.net>\n" "Language-Team: Slovenian <translation-team-sl@lists.sourceforge.net>\n"

View File

@ -10,7 +10,7 @@
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: util-linux 2.12\n" "Project-Id-Version: util-linux 2.12\n"
"POT-Creation-Date: 2004-09-07 03:04+0200\n" "POT-Creation-Date: 2004-09-07 03:05+0200\n"
"PO-Revision-Date: 2003-08-01 01:33+0200\n" "PO-Revision-Date: 2003-08-01 01:33+0200\n"
"Last-Translator: Christian Rose <menthos@menthos.com>\n" "Last-Translator: Christian Rose <menthos@menthos.com>\n"
"Language-Team: Swedish <sv@li.org>\n" "Language-Team: Swedish <sv@li.org>\n"

View File

@ -10,7 +10,7 @@
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: util-linux 2.12\n" "Project-Id-Version: util-linux 2.12\n"
"POT-Creation-Date: 2004-09-07 03:04+0200\n" "POT-Creation-Date: 2004-09-07 03:05+0200\n"
"PO-Revision-Date: 2003-08-03 13:18+0300\n" "PO-Revision-Date: 2003-08-03 13:18+0300\n"
"Last-Translator: Nilgün Belma Bugüner <nilgun@superonline.com>\n" "Last-Translator: Nilgün Belma Bugüner <nilgun@superonline.com>\n"
"Language-Team: Turkish <gnu-tr-u12a@lists.sourceforge.net>\n" "Language-Team: Turkish <gnu-tr-u12a@lists.sourceforge.net>\n"

View File

@ -6,7 +6,7 @@
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: util-linux 2.12\n" "Project-Id-Version: util-linux 2.12\n"
"POT-Creation-Date: 2004-09-07 03:04+0200\n" "POT-Creation-Date: 2004-09-07 03:05+0200\n"
"PO-Revision-Date: 2004-02-24 10:45+0200\n" "PO-Revision-Date: 2004-02-24 10:45+0200\n"
"Last-Translator: Maxim V. Dziumanenko <mvd@mylinux.com.ua>\n" "Last-Translator: Maxim V. Dziumanenko <mvd@mylinux.com.ua>\n"
"Language-Team: Ukrainian <translation-team-uk@lists.sourceforge.net>\n" "Language-Team: Ukrainian <translation-team-uk@lists.sourceforge.net>\n"