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
* mount.8: added recent ext2 mount options

View File

@ -7,6 +7,12 @@
# - set USE_TTY_GROUP=no
# - 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 CPU i386 if the binaries must be able to run on an intel 386
# (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.
On the other hand, the stuff in login-utils defines initial boot-time
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.

View File

@ -1 +1 @@
2.12d
2.12h

View File

@ -20,12 +20,15 @@
* Public License, version 2.
*/
#include <getopt.h>
#include <fcntl.h>
#include <errno.h>
#include <stdio.h>
#include <sys/ioctl.h>
#include <getopt.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/utsname.h>
#include "nls.h"
/* this has to match with the kernel structure */
@ -37,6 +40,7 @@ typedef struct blkelv_ioctl_arg_s {
int max_bomb_segments;
} blkelv_ioctl_arg_t;
/* ioctls introduced in 2.2.16, removed in 2.5.58 */
#define BLKELVGET _IOR(0x12,106,size_t)
#define BLKELVSET _IOW(0x12,107,size_t)
@ -48,6 +52,8 @@ usage(void) {
" /dev/blkdev1 [/dev/blkdev2...]\n");
fprintf(stderr, "\telvtune -h\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
@ -55,6 +61,23 @@ version(void) {
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
main(int argc, char * argv[]) {
int read_value = 0xbeefbeef, write_value = 0xbeefbeef, bomb_value = 0xbeefbeef;
@ -110,8 +133,20 @@ main(int argc, char * argv[]) {
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) {
int errsv = errno;
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;
}

View File

@ -1488,55 +1488,68 @@ said_yes(char answer) {
static void
get_partition_table_geometry(partition_table *bufp) {
struct partition *p;
int i,h,s,hh,ss;
int first = TRUE;
int bad = FALSE;
struct partition *p;
int i,h,s,hh,ss;
int first = TRUE;
int bad = FALSE;
if (bufp->p.magicflag[0] != PART_TABLE_FLAG0 ||
bufp->p.magicflag[1] != PART_TABLE_FLAG1) {
/* Matthew Wilcox: slightly friendlier version of
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;
for (i=0; i<66; i++)
if (bufp->c.b[446+i])
goto nonz;
/* Oskar Liljeblad suggested:
Bad signature blah blah
If this is a brand new harddrive that has not been partitioned
before, please run cfdisk -z.
*/
}
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;
/* zero table */
if (!curses_started) {
fatal(_("No partition table.\n"), 3);
return;
} else {
mvaddstr(WARNING_START, 0,
_("No partition table. Starting with zero table."));
putchar(BELL);
refresh();
zero_table = TRUE;
return;
}
}
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) {
pt_heads = hh;
pt_sectors = ss;
}
/* Matthew Wilcox */
mvaddstr(WARNING_START, 0,
_("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

View File

@ -129,6 +129,18 @@ fatal(char *s, ...) {
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
*/
@ -143,8 +155,13 @@ fatal(char *s, ...) {
*
* Note: we use 512-byte sectors here, irrespective of the hardware ss.
*/
#if !defined (__alpha__) && !defined (__ia64__) && !defined (__x86_64__) && !defined (__s390x__)
static
#undef use_lseek
#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,
loff_t *, res, unsigned int, wh);
#endif
@ -155,7 +172,7 @@ sseek(char *dev, unsigned int fd, unsigned long s) {
in = ((loff_t) s << 9);
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) {
#else
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 */
/* return 0 on failure */
/* ep is 0 or points to surrounding extended partition */
static int
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;
else
delta = 0;
if (delta < 0) {
p->start -= delta;
p->size += delta;

View File

@ -632,7 +632,18 @@ unmount_disks_ourselves(void)
}
n = 0;
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);
}
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''
(do not mount when "mount -a" is given, e.g., at boot time), ``user''
(allow a user to mount), and ``owner''
(allow device owner to mount), and ``_netdev'' (device requires network
to be available).
The ``owner'' and ``_netdev'' options are Linux-specific.
(allow device owner to mount), and ``comment''
(e.g., for use by fstab-maintaining programs).
The ``owner'' and ``comment'' options are Linux-specific.
For more details, see
.BR mount (8).

View File

@ -13,6 +13,7 @@
#include "fstab.h"
#include "sundries.h" /* for xmalloc() etc */
#include "mount_blkid.h"
#include "paths.h"
#include "nls.h"
#define streq(s, t) (strcmp ((s), (t)) == 0)
@ -94,12 +95,32 @@ fstab_head() {
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
read_mntentchn(mntFILE *mfp, const char *fnam, struct mntentchn *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)) {
mc->nxt = (struct mntentchn *) xmalloc(sizeof(*mc));
mc->nxt->prev = mc;
@ -109,7 +130,7 @@ read_mntentchn(mntFILE *mfp, const char *fnam, struct mntentchn *mc0) {
}
}
mc0->prev = mc;
if (ferror (mfp->mntent_fp)) {
if (ferror(mfp->mntent_fp)) {
int errsv = errno;
error(_("warning: error reading %s: %s"),
fnam, strerror (errsv));
@ -239,7 +260,7 @@ is_mounted_once(const char *name) {
struct mntentchn *
getmntoptfile (const char *file) {
struct mntentchn *mc, *mc0;
char *opts, *s;
const char *opts, *s;
int l;
if (!file)
@ -404,13 +425,14 @@ setlkw_timeout (int sig) {
/* 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
mtab~.<pid> instead. */
#define MOUNTLOCK_LINKTARGET MOUNTED_LOCK "%d"
mtab~.<pid> instead. Use 20 as upper bound for the length of %d. */
#define MOUNTLOCK_LINKTARGET MOUNTED_LOCK "%d"
#define MOUNTLOCK_LINKTARGET_LTH (sizeof(MOUNTED_LOCK)+20)
void
lock_mtab (void) {
int tries = 3;
char *linktargetfile;
char linktargetfile[MOUNTLOCK_LINKTARGET_LTH];
if (!signals_have_been_setup) {
int sig = 0;
@ -431,9 +453,6 @@ lock_mtab (void) {
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 ());
/* Repeat until it was us who made the link */
@ -542,11 +561,11 @@ unlock_mtab (void) {
*/
void
update_mtab (const char *dir, struct mntent *instead) {
update_mtab (const char *dir, struct my_mntent *instead) {
mntFILE *mfp, *mftmp;
const char *fnam = MOUNTED;
struct mntentchn mtabhead; /* dummy */
struct mntentchn *mc, *mc0, absent;
struct mntentchn *mc, *mc0, *absent = NULL;
if (mtab_does_not_exist() || mtab_is_a_symlink())
return;
@ -577,6 +596,7 @@ update_mtab (const char *dir, struct mntent *instead) {
if (mc && mc != mc0) {
mc->prev->nxt = mc->nxt;
mc->nxt->prev = mc->prev;
free(mc);
}
} else {
/* A remount */
@ -584,12 +604,13 @@ update_mtab (const char *dir, struct mntent *instead) {
}
} else if (instead) {
/* not found, add a new entry */
absent.m = *instead;
absent.nxt = mc0;
absent.prev = mc0->prev;
mc0->prev = &absent;
absent = xmalloc(sizeof(*absent));
absent->m = *instead;
absent->nxt = mc0;
absent->prev = mc0->prev;
mc0->prev = absent;
if (mc0->nxt == NULL)
mc0->nxt = &absent;
mc0->nxt = absent;
}
/* 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),
S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH) < 0) {
int errsv = errno;

View File

@ -1,14 +1,4 @@
#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
#include "mntent.h"
int mtab_is_writable(void);
int mtab_does_not_exist(void);
int mtab_is_a_symlink(void);
@ -16,7 +6,7 @@ int is_mounted_once(const char *name);
struct mntentchn {
struct mntentchn *nxt, *prev;
struct mntent m;
struct my_mntent m;
};
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 *getfsvolspec (const char *label);
#include <mntent.h>
void lock_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.
* For now, only ext2, ext3, xfs, ocfs, reiserfs are supported
* For now, only ext2, ext3, xfs, ocfs, ocfs2, reiserfs are supported
*/
int
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 ocfs_volume_header ovh; /* Oracle */
struct ocfs_volume_label olbl;
struct ocfs2_super_block osb;
struct reiserfs_super_block reiserfssb;
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));
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);
return rv;

View File

@ -236,35 +236,49 @@ struct ocfs_volume_label {
#define ocfslabellen(o) assemble2le(o.label_len)
#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 */
char vd_name[8];
char vd_lbn[4];
char vd_nbytes[4];
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];
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;
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];
char fs_stuff[512+28];
char fs_magic[4];
char fs_fname[6];
char fs_fpack[6];
/* ... */
};

View File

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

View File

@ -21,7 +21,7 @@
static unsigned char need_escaping[] = { ' ', '\t', '\n', '\\' };
static char *
mangle(unsigned char *s) {
mangle(const unsigned char *s) {
char *ss, *sp;
int n;
@ -98,7 +98,7 @@ my_setmntent (const char *file, char *mode) {
mntFILE *mfp = xmalloc(sizeof(*mfp));
mode_t old_umask = umask(077);
mfp->mntent_fp = fopen (file, mode);
mfp->mntent_fp = fopen(file, mode);
umask(old_umask);
mfp->mntent_file = xstrdup(file);
mfp->mntent_errs = (mfp->mntent_fp == NULL);
@ -118,9 +118,8 @@ my_endmntent (mntFILE *mfp) {
}
}
int
my_addmntent (mntFILE *mfp, struct mntent *mnt) {
my_addmntent (mntFILE *mfp, struct my_mntent *mnt) {
char *m1, *m2, *m3, *m4;
int res;
@ -132,22 +131,21 @@ my_addmntent (mntFILE *mfp, struct mntent *mnt) {
m3 = mangle(mnt->mnt_type);
m4 = mangle(mnt->mnt_opts);
res = ((fprintf (mfp->mntent_fp, "%s %s %s %s %d %d\n",
m1, m2, m3, m4, mnt->mnt_freq, mnt->mnt_passno)
< 0) ? 1 : 0);
res = fprintf (mfp->mntent_fp, "%s %s %s %s %d %d\n",
m1, m2, m3, m4, mnt->mnt_freq, mnt->mnt_passno);
free(m1);
free(m2);
free(m3);
free(m4);
return res;
return (res < 0) ? 1 : 0;
}
/* Read the next entry from the file fp. Stop reading at an incorrect entry. */
struct mntent *
struct my_mntent *
my_getmntent (mntFILE *mfp) {
static char buf[4096];
static struct mntent me;
static struct my_mntent me;
char *s;
again:
@ -193,7 +191,7 @@ my_getmntent (mntFILE *mfp) {
s = skip_nonspaces(s);
s = skip_spaces(s);
if(isdigit(*s)) {
if (isdigit(*s)) {
me.mnt_freq = atoi(s);
while(isdigit(*s)) s++;
} 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
@ -12,5 +22,7 @@ typedef struct mntFILEstruct {
mntFILE *my_setmntent (const char *file, char *mode);
void my_endmntent (mntFILE *mfp);
int my_addmntent (mntFILE *mfp, struct mntent *mnt);
struct mntent *my_getmntent (mntFILE *mfp);
int my_addmntent (mntFILE *mfp, struct my_mntent *mnt);
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"
.RE
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
submounts. The entire file hierarchy including submounts is attached
@ -120,7 +121,7 @@ a second place using
.\" 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
Since Linux 2.5.1 it is possible to atomically move a mounted tree
to another place. The call is
.RS
.br
@ -242,6 +243,8 @@ option below). It is possible to replace
.I /etc/mtab
by a symbolic link to
.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
working with the loop device will be less convenient,
and using the "user" option will fail.
@ -421,35 +424,15 @@ program have different calling conventions,
.I /sbin/mount.smbfs
may have to be a shell script that sets up the desired call.
The type
.I iso9660
is the default. If no
If no
.B \-t
option is given, or if the
.B auto
type is specified, the superblock is probed for the filesystem type
.RI ( adfs ,
.IR bfs ,
.IR cramfs ,
.IR ext ,
.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
type is specified, mount will try to guess the desired type.
If mount was compiled with the blkid library, the guessing is done
by this library. Otherwise, mount guesses itself by probing the
superblock; if that does not turn up anything that looks familiar,
mount will try to read the file
.IR /etc/filesystems ,
or, if that does not exist,
.IR /proc/filesystems .
@ -470,8 +453,8 @@ The
type may be useful for user-mounted floppies.
Creating a file
.I /etc/filesystems
can be useful to change the probe order (e.g., to try vfat before msdos)
or if you use a kernel module autoloader.
can be useful to change the probe order (e.g., to try vfat before msdos
or ext3 before ext2) or if you use a kernel module autoloader.
Warning: the probing uses a heuristic (the presence of appropriate `magic'),
and could recognize the wrong filesystem type, possibly with catastrophic
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.
.TP
.B noexec
Do not allow execution of any binaries on the mounted file system.
This option might be useful for a server that has file systems containing
binaries for architectures other than its own.
Do not allow direct execution of any binaries on the mounted file system.
(Until recently it was possible to run binaries anyway using a command like
/lib/ld*.so /mnt/binary. This trick fails since Linux 2.4.25 / 2.6.0.)
.TP
.B nosuid
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.
* mount.c,v 1.1.1.1 1993/11/18 08:40:51 jrs Exp
*
* Wed Sep 14 22:43:00 1994: Mitchum DSouza
* (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
* Modifications by many people. Distributed under GPL.
*/
#include <unistd.h>
@ -69,6 +33,7 @@
#include "mount_guess_fstype.h"
#include "mount_by_label.h"
#include "getusername.h"
#include "paths.h"
#include "env.h"
#include "nls.h"
@ -131,11 +96,11 @@ struct opt_map {
#define MS_USERS 0x40000000
#define MS_USER 0x20000000
#define MS_OWNER 0x10000000
#define MS_NETDEV 0x00020000
#define MS_COMMENT 0x00020000
#define MS_LOOP 0x00010000
/* 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. */
#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 */
{ "owner", 0, 0, MS_OWNER }, /* Let the owner of the device mount */
{ "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 */
#ifdef MS_NOSUB
{ "sub", 0, 1, MS_NOSUB }, /* allow submounts */
@ -196,19 +163,20 @@ static const struct opt_map opt_map[] = {
{ NULL, 0, 0, 0 }
};
static char *opt_loopdev, *opt_vfstype, *opt_offset, *opt_encryption,
*opt_speed;
static const char *opt_loopdev, *opt_vfstype, *opt_offset, *opt_encryption,
*opt_speed, *opt_comment;
static struct string_opt_map {
char *tag;
int skip;
char **valptr;
const char **valptr;
} string_opt_map[] = {
{ "loop=", 0, &opt_loopdev },
{ "vfs=", 1, &opt_vfstype },
{ "offset=", 0, &opt_offset },
{ "encryption=", 0, &opt_encryption },
{ "speed=", 0, &opt_speed },
{ "comment=", 1, &opt_comment },
{ NULL, 0, NULL }
};
@ -239,23 +207,23 @@ int mount_quiet=0;
/* Report on a single mount. */
static void
print_one (const struct mntent *me) {
if (mount_quiet)
return;
printf ("%s on %s", me->mnt_fsname, me->mnt_dir);
if (me->mnt_type != NULL && *(me->mnt_type) != '\0')
printf (" type %s", me->mnt_type);
if (me->mnt_opts != NULL)
printf (" (%s)", me->mnt_opts);
if (list_with_volumelabel) {
const char *label;
label = mount_get_volume_label_by_spec(me->mnt_fsname);
if (label) {
printf (" [%s]", label);
/* free(label); */
}
}
printf ("\n");
print_one (const struct my_mntent *me) {
if (mount_quiet)
return;
printf ("%s on %s", me->mnt_fsname, me->mnt_dir);
if (me->mnt_type != NULL && *(me->mnt_type) != '\0')
printf (" type %s", me->mnt_type);
if (me->mnt_opts != NULL)
printf (" (%s)", me->mnt_opts);
if (list_with_volumelabel) {
const char *label;
label = mount_get_volume_label_by_spec(me->mnt_fsname);
if (label) {
printf (" [%s]", label);
/* free(label); */
}
}
printf ("\n");
}
/* Report on everything in mtab (of the specified types if any). */
@ -271,6 +239,11 @@ print_all (char *types) {
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.
@ -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
gets the standard options (indicated by bits) and extra_opts all the rest */
static void
parse_opts (char *opts, int *flags, char **extra_opts) {
char *opt;
parse_opts (const char *options, int *flags, char **extra_opts) {
*flags = 0;
*extra_opts = NULL;
clear_string_opts();
if (opts != NULL) {
if (options != NULL) {
char *opts = xstrdup(options);
char *opt;
*extra_opts = xmalloc (strlen (opts) + 1);
**extra_opts = '\0';
for (opt = strtok (opts, ","); opt; opt = strtok (NULL, ","))
if (!parse_string_opt (opt))
parse_opt (opt, flags, *extra_opts);
free(opts);
}
if (readonly)
@ -363,7 +339,7 @@ fix_opts_string (int flags, const char *extra_opts, const char *user) {
const struct string_opt_map *m;
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++) {
if (om->skip)
continue;
@ -388,63 +364,66 @@ fix_opts_string (int flags, const char *extra_opts, const char *user) {
static int
already (const char *spec, const char *node) {
struct mntentchn *mc;
int ret = 1;
struct mntentchn *mc;
int ret = 1;
if ((mc = getmntfile(node)) != NULL)
error (_("mount: according to mtab, %s is already mounted on %s"),
mc->m.mnt_fsname, node);
else if (spec && strcmp (spec, "none") &&
(mc = getmntfile(spec)) != NULL)
error (_("mount: according to mtab, %s is mounted on %s"),
spec, mc->m.mnt_dir);
else
ret = 0;
return ret;
if ((mc = getmntfile(node)) != NULL)
error (_("mount: according to mtab, "
"%s is already mounted on %s"),
mc->m.mnt_fsname, node);
else if (spec && strcmp (spec, "none") &&
(mc = getmntfile(spec)) != NULL)
error (_("mount: according to mtab, %s is mounted on %s"),
spec, mc->m.mnt_dir);
else
ret = 0;
return ret;
}
/* Create mtab with a root entry. */
static void
create_mtab (void) {
struct mntentchn *fstab;
struct mntent mnt;
int flags;
char *extra_opts;
mntFILE *mfp;
struct mntentchn *fstab;
struct my_mntent mnt;
int flags;
mntFILE *mfp;
lock_mtab();
lock_mtab();
mfp = my_setmntent (MOUNTED, "a+");
if (mfp == NULL || mfp->mntent_fp == NULL) {
int errsv = errno;
die (EX_FILEIO, _("mount: can't open %s for writing: %s"),
MOUNTED, strerror (errsv));
}
mfp = my_setmntent (MOUNTED, "a+");
if (mfp == NULL || mfp->mntent_fp == NULL) {
int errsv = errno;
die (EX_FILEIO, _("mount: can't open %s for writing: %s"),
MOUNTED, strerror (errsv));
}
/* Find the root entry by looking it up in fstab */
if ((fstab = getfsfile ("/")) || (fstab = getfsfile ("root"))) {
parse_opts (xstrdup (fstab->m.mnt_opts), &flags, &extra_opts);
mnt.mnt_dir = "/";
mnt.mnt_fsname = canonicalize (fstab->m.mnt_fsname);
mnt.mnt_type = fstab->m.mnt_type;
mnt.mnt_opts = fix_opts_string (flags, extra_opts, NULL);
mnt.mnt_freq = mnt.mnt_passno = 0;
/* Find the root entry by looking it up in fstab */
if ((fstab = getfsfile ("/")) || (fstab = getfsfile ("root"))) {
char *extra_opts;
parse_opts (fstab->m.mnt_opts, &flags, &extra_opts);
mnt.mnt_dir = "/";
mnt.mnt_fsname = canonicalize (fstab->m.mnt_fsname);
mnt.mnt_type = fstab->m.mnt_type;
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) {
int errsv = errno;
die (EX_FILEIO, _("mount: error writing %s: %s"),
MOUNTED, strerror (errsv));
}
}
if (fchmod (fileno (mfp->mntent_fp), S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH) < 0)
if (errno != EROFS) {
int errsv = errno;
die (EX_FILEIO, _("mount: error changing mode of %s: %s"),
MOUNTED, strerror (errsv));
}
my_endmntent (mfp);
if (my_addmntent (mfp, &mnt) == 1) {
int errsv = errno;
die (EX_FILEIO, _("mount: error writing %s: %s"),
MOUNTED, strerror (errsv));
}
}
if (fchmod (fileno (mfp->mntent_fp), 0644) < 0)
if (errno != EROFS) {
int errsv = errno;
die (EX_FILEIO,
_("mount: error changing mode of %s: %s"),
MOUNTED, strerror (errsv));
}
my_endmntent (mfp);
unlock_mtab();
unlock_mtab();
}
/* count successful mount system calls */
@ -477,8 +456,8 @@ do_mount_syscall (struct mountargs *args) {
* on return types is filled with the type used.
*/
static int
guess_fstype_and_mount (char *spec, char *node, char **types,
int flags, char *mount_opts) {
guess_fstype_and_mount(const char *spec, const char *node, const char **types,
int flags, char *mount_opts) {
struct mountargs args = { spec, node, NULL, flags & ~MS_NOSYS, mount_opts };
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.
*/
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) {
/* RedHat patch: allow owners to mount when fstab contains
the owner option. Note that this should never be used
in a high security environment, but may be useful to give
people at the console the possibility of mounting a floppy. */
in a high security environment, but may be useful to give
people at the console the possibility of mounting a floppy. */
if (*flags & MS_OWNER) {
if (!strncmp(spec, "/dev/", 5)) {
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:
allow an arbitrary user to mount when he is the owner of
the mount-point and has write-access to the device.
This is even less secure. Let me skip it for the time being;
there should be an explicit fstab line allowing such things. */
This is even less secure. Let me skip it for the time being;
there should be an explicit fstab line allowing such things. */
if (!(*flags & (MS_USER | MS_USERS))) {
if (already (spec, node))
if (already (spec, node))
die (EX_USAGE, _("mount failed"));
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)
*user = getusername();
@ -563,8 +542,8 @@ suid_check(char *spec, char *node, int *flags, char **user) {
}
static int
loop_check(char **spec, char **type, int *flags,
int *loop, char **loopdev, char **loopfile) {
loop_check(const char **spec, const char **type, int *flags,
int *loop, const char **loopdev, const char **loopfile) {
int looptype;
unsigned long long offset;
@ -627,45 +606,47 @@ loop_check(char **spec, char **type, int *flags,
}
static void
update_mtab_entry(char *spec, char *node, char *type, char *opts,
int flags, int freq, int pass) {
struct mntent mnt;
update_mtab_entry(const char *spec, const char *node, const char *type,
const char *opts, int flags, int freq, int pass) {
struct my_mntent mnt;
mnt.mnt_fsname = canonicalize (spec);
mnt.mnt_dir = canonicalize (node);
mnt.mnt_type = type;
mnt.mnt_opts = opts;
mnt.mnt_freq = freq;
mnt.mnt_passno = pass;
mnt.mnt_fsname = canonicalize (spec);
mnt.mnt_dir = canonicalize (node);
mnt.mnt_type = type;
mnt.mnt_opts = opts;
mnt.mnt_freq = freq;
mnt.mnt_passno = pass;
/* We get chatty now rather than after the update to mtab since the
mount succeeded, even if the write to /etc/mtab should fail. */
if (verbose)
print_one (&mnt);
/* We get chatty now rather than after the update to mtab since the
mount succeeded, even if the write to /etc/mtab should fail. */
if (verbose)
print_one (&mnt);
if (!nomtab && mtab_is_writable()) {
if (flags & MS_REMOUNT)
update_mtab (mnt.mnt_dir, &mnt);
else {
mntFILE *mfp;
if (!nomtab && mtab_is_writable()) {
if (flags & MS_REMOUNT)
update_mtab (mnt.mnt_dir, &mnt);
else {
mntFILE *mfp;
lock_mtab();
mfp = my_setmntent(MOUNTED, "a+");
if (mfp == NULL || mfp->mntent_fp == NULL) {
int errsv = errno;
error(_("mount: can't open %s: %s"), MOUNTED,
strerror (errsv));
} else {
if ((my_addmntent (mfp, &mnt)) == 1) {
int errsv = errno;
error(_("mount: error writing %s: %s"), MOUNTED,
strerror (errsv));
lock_mtab();
mfp = my_setmntent(MOUNTED, "a+");
if (mfp == NULL || mfp->mntent_fp == NULL) {
int errsv = errno;
error(_("mount: can't open %s: %s"), MOUNTED,
strerror (errsv));
} else {
if ((my_addmntent (mfp, &mnt)) == 1) {
int errsv = errno;
error(_("mount: error writing %s: %s"),
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
@ -677,20 +658,21 @@ set_pfd(char *s) {
}
static void
cdrom_setspeed(char *spec) {
cdrom_setspeed(const char *spec) {
#define CDROM_SELECT_SPEED 0x5322 /* Set the CD-ROM speed */
if (opt_speed) {
int cdrom;
int speed = atoi(opt_speed);
if (opt_speed) {
int cdrom;
int speed = atoi(opt_speed);
if ((cdrom = open(spec, O_RDONLY | O_NONBLOCK)) < 0)
die(EX_FAIL, _("mount: cannot open %s for setting speed"),
spec);
if (ioctl(cdrom, CDROM_SELECT_SPEED, speed) < 0)
die(EX_FAIL, _("mount: cannot set speed: %s"),
strerror(errno));
close(cdrom);
}
if ((cdrom = open(spec, O_RDONLY | O_NONBLOCK)) < 0)
die(EX_FAIL,
_("mount: cannot open %s for setting speed"),
spec);
if (ioctl(cdrom, CDROM_SELECT_SPEED, speed) < 0)
die(EX_FAIL, _("mount: cannot set speed: %s"),
strerror(errno));
close(cdrom);
}
}
/*
@ -700,8 +682,8 @@ cdrom_setspeed(char *spec) {
*/
static int
check_special_mountprog(char *spec, char *node, char *type, int flags,
char *extra_opts, int *status) {
check_special_mountprog(const char *spec, const char *node, const char *type,
int flags, char *extra_opts, int *status) {
char mountprog[120];
struct stat statbuf;
int res;
@ -714,7 +696,7 @@ check_special_mountprog(char *spec, char *node, char *type, int flags,
if (stat(mountprog, &statbuf) == 0) {
res = fork();
if (res == 0) {
char *oo, *mountargs[10];
const char *oo, *mountargs[10];
int i = 0;
setuid(getuid());
@ -732,7 +714,7 @@ check_special_mountprog(char *spec, char *node, char *type, int flags,
mountargs[i++] = oo;
}
mountargs[i] = NULL;
execv(mountprog, mountargs);
execv(mountprog, (char **) mountargs);
exit(1); /* exec failed */
} else if (res != -1) {
int st;
@ -758,32 +740,35 @@ check_special_mountprog(char *spec, char *node, char *type, int flags,
* return status from wait
*/
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) {
int res, status;
int res = 0, status;
int mnt5_res = 0; /* only for gcc */
int mnt_err;
int flags;
char *extra_opts; /* written in mtab */
char *mount_opts; /* actually used on system call */
const char *opts;
char *spec, *node, *types;
const char *opts, *spec, *node, *types;
char *user = 0;
int loop = 0;
char *loopdev = 0, *loopfile = 0;
const char *loopdev = 0, *loopfile = 0;
struct stat statbuf;
int nfs_mount_version = 0; /* any version */
spec = xstrdup(spec0);
node = xstrdup(node0);
types = xstrdup(types0);
opts = xstrdup(opts0);
/* copies for freeing on exit */
const char *opts1, *spec1, *node1, *types1, *extra_opts1;
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 */
if (mount_all && (flags & MS_NOAUTO))
return 0;
goto out;
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);
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.
* All such special things must occur isolated in the types string.
*/
if (check_special_mountprog (spec, node, types, flags, extra_opts, &status))
return status;
if (check_special_mountprog(spec, node, types, flags, extra_opts, &status)) {
res = status;
goto out;
}
/*
* 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:
mnt_err = nfsmount (spec, node, &flags, &extra_opts, &mount_opts,
&nfs_mount_version, bg);
if (mnt_err)
return mnt_err;
if (mnt_err) {
res = mnt_err;
goto out;
}
#else
die (EX_SOFTWARE, _("mount: this version was compiled "
"without support for the type `nfs'"));
"without support for the type `nfs'"));
#endif
}
@ -847,7 +836,8 @@ retry_nfs:
pass);
block_signals (SIG_UNBLOCK);
return 0;
res = 0;
goto out;
}
mnt_err = errno;
@ -913,13 +903,13 @@ retry_nfs:
else if (stat (spec, &statbuf))
error (_("mount: special device %s does not exist"), spec);
else {
errno = mnt_err;
perror("mount");
errno = mnt_err;
perror("mount");
}
break;
case ENOTDIR:
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)
error (_("mount: special device %s does not exist\n"
" (a path prefix is not a directory)\n"), spec);
@ -981,7 +971,7 @@ retry_nfs:
char *lowtype, *p;
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 */
lowtype = xstrdup(types);
@ -995,7 +985,9 @@ retry_nfs:
if (u && is_in_procfs(lowtype) == 1)
error (_("mount: probably you meant %s"), lowtype);
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);
} else
error (_("mount: %s has wrong device number or fs type %s not supported"),
@ -1033,16 +1025,18 @@ retry_nfs:
types = types0;
}
if (opts) {
char *opts1 = realloc(xstrdup(opts), strlen(opts)+4);
strcat(opts1, ",ro");
opts = opts1;
char *opts2 = realloc(xstrdup(opts), strlen(opts)+4);
strcat(opts2, ",ro");
my_free(opts1);
opts = opts1 = opts2;
} else
opts = "ro";
if (types && !strcmp(types, "guess"))
types = 0;
error (_("mount: %s%s is write-protected, mounting read-only"),
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;
}
@ -1050,7 +1044,16 @@ retry_nfs:
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;
}
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)
*/
static int
mount_one (const char *spec, const char *node, char *types, const char *opts,
char *cmdlineopts, int freq, int pass) {
mount_one (const char *spec, const char *node, const char *types,
const char *opts, char *cmdlineopts, int freq, int pass) {
int status, status2;
const char *nspec;
@ -1119,7 +1128,7 @@ mount_one (const char *spec, const char *node, char *types, const char *opts,
if (nspec)
spec = nspec;
if (types == NULL && !mounttype) {
if (types == NULL && !mounttype && !is_existing_file(spec)) {
if (strchr (spec, ':') != NULL) {
types = "nfs";
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. */
static int
mounted (const char *spec, char *node) {
struct mntentchn *mc, *mc0;
mounted (const char *spec0, const char *node0) {
struct mntentchn *mc, *mc0;
char *spec, *node;
int ret = 0;
/* Handle possible UUID= and LABEL= in spec */
spec = mount_get_devname(spec);
/* Handle possible UUID= and LABEL= in spec */
spec0 = mount_get_devname(spec0);
spec = canonicalize(spec);
node = canonicalize(node);
spec = canonicalize(spec0);
node = canonicalize(node0);
mc0 = mtab_head();
for (mc = mc0->nxt; mc && mc != mc0; mc = mc->nxt)
if (streq (spec, mc->m.mnt_fsname) && streq (node, mc->m.mnt_dir))
return 1;
return 0;
mc0 = mtab_head();
for (mc = mc0->nxt; mc && mc != mc0; mc = mc->nxt)
if (streq (spec, mc->m.mnt_fsname) &&
streq (node, mc->m.mnt_dir)) {
ret = 1;
break;
}
free(spec);
free(node);
return ret;
}
/* avoid using stat() on things we are not going to mount anyway.. */
static int
has_noauto (char *opts) {
has_noauto (const char *opts) {
char *s;
if (!opts)
@ -1586,8 +1604,7 @@ main (int argc, char *argv[]) {
die (EX_USAGE,
_("mount: cannot find %s in %s"),
spec, _PATH_FSTAB);
/* struct mntent does not have const qualifiers */
mc->m.mnt_fsname = (char *) spec;
mc->m.mnt_fsname = spec;
} else {
/* Try to find the other pathname in fstab. */
spec = canonicalize (*argv);
@ -1605,6 +1622,8 @@ main (int argc, char *argv[]) {
/* Earlier mtab was tried first, but this would
sometimes try the wrong mount in case mtab had
the root device entry wrong. */
my_free(spec);
}
result = mount_one (xstrdup (mc->m.mnt_fsname),

View File

@ -97,11 +97,12 @@ swapped(unsigned short a) {
Added jfs - Christoph Hellwig
Added sysv - Tim Launchbury
Added udf - Bryce Nesbitt
Added ocfs, ocfs2 - Manish Singh - http://oss.oracle.com/projects/ocfs2/
*/
static char
*magic_known[] = {
"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",
"vxfs", "xfs", "xiafs"
};
@ -212,6 +213,7 @@ do_guess_fstype(const char *device) {
struct fat_super_block fatsb;
struct xfs_super_block xfsb;
struct cramfs_super_block cramfssb;
struct ocfs_volume_header ovh;
struct efs_volume_header efsvh;
struct efs_super efssb;
} xsb; /* stuff at 0 */
@ -232,6 +234,7 @@ do_guess_fstype(const char *device) {
struct hpfs_super_block hpfssb;
struct adfs_super_block adfssb;
struct sysv_super_block svsb;
struct ocfs2_super_block osb;
struct stat statbuf;
/* opening and reading an arbitrary unknown path can have
@ -261,6 +264,8 @@ do_guess_fstype(const char *device) {
type = "romfs";
else if(!strncmp(xsb.xfsb.s_magic, XFS_SUPER_MAGIC, 4))
type = "xfs";
else if(!strncmp(xsb.ovh.signature, OCFS_MAGIC, sizeof(OCFS_MAGIC)))
type = "ocfs";
else if(!strncmp(xsb.qnx4fs_magic+4, "QNX4FS", 6))
type = "qnx4";
else if(xsb.bfs_magic == 0x1badface)
@ -438,6 +443,22 @@ do_guess_fstype(const char *device) {
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) {
/* perhaps the user tries to mount the swap space
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 */
int
procfsloop(int (*mount_fn)(struct mountargs *), struct mountargs *args,
char **types) {
const char **types) {
char *files[2] = { ETC_FILESYSTEMS, PROC_FILESYSTEMS };
FILE *procfs;
char *fsname;
char *notypes = NULL;
const char *notypes = NULL;
int no = 0;
int ret = 1;
int errsv = 0;

View File

@ -11,6 +11,6 @@ extern int verbose;
char *guess_fstype(const char *device);
char *do_guess_fstype(const char *device);
int procfsloop(int (*mount_fn)(struct mountargs *), struct mountargs *args,
char **type);
const char **type);
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
/* this leaks some memory - unimportant for mount */
char *
myrealpath(const char *path, char *resolved_path, int maxreslth) {
int readlinks = 0;
char *npath;
char link_path[PATH_MAX+1];
int n;
#ifdef resolve_symlinks
char *buf;
int m;
#endif
char *buf = NULL;
npath = resolved_path;
@ -83,7 +79,7 @@ myrealpath(const char *path, char *resolved_path, int maxreslth) {
while (*path != '\0' && *path != '/') {
if (npath-resolved_path > maxreslth-2) {
errno = ENAMETOOLONG;
return NULL;
goto err;
}
*npath++ = *path++;
}
@ -91,7 +87,7 @@ myrealpath(const char *path, char *resolved_path, int maxreslth) {
/* Protect against infinite loops. */
if (readlinks++ > MAX_READLINKS) {
errno = ELOOP;
return NULL;
goto err;
}
/* See if last pathname component is a symlink. */
@ -100,9 +96,11 @@ myrealpath(const char *path, char *resolved_path, int maxreslth) {
if (n < 0) {
/* EINVAL means the file exists but isn't a symlink. */
if (errno != EINVAL)
return NULL;
goto err;
} else {
#ifdef resolve_symlinks /* Richard Gooch dislikes sl resolution */
int m;
/* Note: readlink doesn't add the null byte. */
link_path[n] = '\0';
if (*link_path == '/')
@ -115,6 +113,8 @@ myrealpath(const char *path, char *resolved_path, int maxreslth) {
/* Insert symlink contents into path. */
m = strlen(path);
if (buf)
free(buf);
buf = xmalloc(m + n + 1);
memcpy(buf, link_path, n);
memcpy(buf + n, path, m + 1);
@ -128,5 +128,13 @@ myrealpath(const char *path, char *resolved_path, int maxreslth) {
npath--;
/* Make sure it's null terminated. */
*npath = '\0';
if (buf)
free(buf);
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;
}
/* frees its first arg - typical use: s = xstrconcat3(s,t,u); */
char *
xstrconcat3 (const char *s, const char *t, const char *u) {
char *res;
@ -84,9 +85,11 @@ xstrconcat3 (const char *s, const char *t, const char *u) {
strcpy(res, s);
strcat(res, t);
strcat(res, u);
free((void *) s);
return res;
}
/* frees its first arg - typical use: s = xstrconcat4(s,t,u,v); */
char *
xstrconcat4 (const char *s, const char *t, const char *u, const char *v) {
char *res;
@ -100,6 +103,7 @@ xstrconcat4 (const char *s, const char *t, const char *u, const char *v) {
strcat(res, t);
strcat(res, u);
strcat(res, v);
free((void *) s);
return res;
}
@ -269,19 +273,18 @@ matching_opts (const char *options, const char *test_opts) {
we return unmodified. */
char *
canonicalize (const char *path) {
char *canonical;
char canonical[PATH_MAX+2];
if (path == NULL)
return NULL;
if (path == NULL)
return NULL;
if (streq(path, "none") || streq(path, "proc") || streq(path, "devpts"))
return xstrdup(path);
if (streq(path, "none") ||
streq(path, "proc") ||
streq(path, "devpts"))
return xstrdup(path);
canonical = xmalloc (PATH_MAX+2);
if (myrealpath (path, canonical, PATH_MAX+1))
return canonical;
if (myrealpath (path, canonical, PATH_MAX+1))
return xstrdup(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 */
}
if (!quiet) {
if (!quiet || errno == ENOMEM) {
int errsv = errno;
fprintf(stderr, "%s: %s: %s\n", program_name,
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,
MS_MGC_VAL | MS_REMOUNT | MS_RDONLY, NULL);
if (res == 0) {
struct mntent remnt;
struct my_mntent remnt;
fprintf(stderr,
_("umount: %s busy - remounted read-only\n"),
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?
* 1. People who boot a system with a bad fstab root entry
* will get an incorrect "/dev/foo on /" in mtab.
@ -472,52 +474,18 @@ usage (FILE *fp, int n)
int mount_quiet = 0;
/*=======================================================================*/
/* string list stuff - no longer used by mount - will disappear entirely */
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;
}
/*
* Look for an option in a comma-separated list
*/
static int
contains(string_list list, char *s) {
while (list) {
if (streq (car (list), s))
contains(const char *list, const char *s) {
int n = strlen(s);
while (*list) {
if (strncmp(list, s, n) == 0 &&
(list[n] == 0 || list[n] == ','))
return 1;
list = cdr (list);
while (*list && *list++ != ',') ;
}
return 0;
}
@ -526,12 +494,18 @@ contains(string_list list, char *s) {
* If list contains "user=peter" and we ask for "user=", return "peter"
*/
static char *
get_value(string_list list, char *s) {
get_value(const char *list, const char *s) {
const char *t;
int n = strlen(s);
while (list) {
if (strncmp (car (list), s, n) == 0)
return car(list)+n;
list = cdr (list);
while (*list) {
if (strncmp(list, s, n) == 0) {
s = t = list+n;
while (*s && *s != ',')
s++;
return xstrndup(t, s-t);
}
while (*list && *list++ != ',') ;
}
return 0;
}
@ -539,8 +513,7 @@ get_value(string_list list, char *s) {
static int
umount_file (char *arg) {
struct mntentchn *mc, *fs;
char *file;
string_list options;
const char *file, *options;
int fstab_has_user, fstab_has_users, fstab_has_owner, ok;
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
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_users = contains(options, "users");
fstab_has_owner = contains(options, "owner");
@ -606,7 +581,9 @@ umount_file (char *arg) {
if (!ok && (fstab_has_user || fstab_has_owner)) {
char *user = getusername();
options = parse_list (mc->m.mnt_opts);
options = mc->m.mnt_opts;
if (!options)
options = "";
mtab_user = get_value(options, "user=");
if (user && mtab_user && streq (user, mtab_user))

View File

@ -10,7 +10,7 @@
msgid ""
msgstr ""
"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"
"Last-Translator: Antoni Bella Perez <bella5@teleline.es>\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 ""
msgstr ""
"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"
"Last-Translator: Jiøí Pavlovský <pavlovsk@ff.cuni.cz>\n"
"Language-Team: Czech <cs@li.org>\n"

View File

@ -12,7 +12,7 @@
msgid ""
msgstr ""
"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"
"Last-Translator: Claus Hindsgaul <claus_h@image.dk>\n"
"Language-Team: Danish <dansk@klid.dk>\n"

View File

@ -44,7 +44,7 @@
msgid ""
msgstr ""
"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"
"Last-Translator: Michael Piefel <piefel@informatik.hu-berlin.de>\n"
"Language-Team: German <de@li.org>\n"

View File

@ -12,7 +12,7 @@
msgid ""
msgstr ""
"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"
"Last-Translator: Santiago Vila Doncel <sanvila@unex.es>\n"
"Language-Team: Spanish <es@li.org>\n"

View File

@ -11,7 +11,7 @@
msgid ""
msgstr ""
"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"
"Last-Translator: Meelis Roos <mroos@linux.ee>\n"
"Language-Team: Estonian <et@li.org>\n"

View File

@ -14,7 +14,7 @@
msgid ""
msgstr ""
"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"
"Last-Translator: Lauri Nurmi <lanurmi@iki.fi>\n"
"Language-Team: Finnish <translation-team-fi@lists.sourceforge.net>\n"

View File

@ -9,7 +9,7 @@
msgid ""
msgstr ""
"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"
"Last-Translator: Michel Robitaille <robitail@IRO.UMontreal.CA>\n"
"Language-Team: French <traduc@traduc.org>\n"

View File

@ -4,7 +4,7 @@
msgid ""
msgstr ""
"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"
"Last-Translator: Beth Powell <bpowell@turbolinux.com>\n"
"Language-Team: <support@turbolinux.com>\n"

View File

@ -7,7 +7,7 @@
msgid ""
msgstr ""
"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"
"Last-Translator: Daisuke Yamashita <yamad@mb.infoweb.ne.jp>\n"
"Language-Team: Japanese <ja@li.org>\n"

View File

@ -19,7 +19,7 @@
msgid ""
msgstr ""
"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"
"Last-Translator: Taco Witte <T.C.Witte@phys.uu.nl>\n"
"Language-Team: Dutch <vertaling@nl.linux.org>\n"

View File

@ -13,7 +13,7 @@
msgid ""
msgstr ""
"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"
"Last-Translator: Rodrigo Stulzer Lopes <rodrigo@conectiva.com.br>\n"
"Language-Team: Brazilian Portuguese <ldp-br@bazar.conectiva.com.br>\n"

View File

@ -11,7 +11,7 @@
msgid ""
msgstr ""
"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"
"Last-Translator: Primo¾ Peterlin <primoz.peterlin@biofiz.mf.uni-lj.si>\n"
"Language-Team: Slovenian <translation-team-sl@lists.sourceforge.net>\n"

View File

@ -10,7 +10,7 @@
msgid ""
msgstr ""
"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"
"Last-Translator: Christian Rose <menthos@menthos.com>\n"
"Language-Team: Swedish <sv@li.org>\n"

View File

@ -10,7 +10,7 @@
msgid ""
msgstr ""
"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"
"Last-Translator: Nilgün Belma Bugüner <nilgun@superonline.com>\n"
"Language-Team: Turkish <gnu-tr-u12a@lists.sourceforge.net>\n"

View File

@ -6,7 +6,7 @@
msgid ""
msgstr ""
"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"
"Last-Translator: Maxim V. Dziumanenko <mvd@mylinux.com.ua>\n"
"Language-Team: Ukrainian <translation-team-uk@lists.sourceforge.net>\n"