summaryrefslogtreecommitdiffstats
path: root/mount/mount.c
diff options
context:
space:
mode:
authorKarel Zak2009-02-17 01:01:35 +0100
committerKarel Zak2009-02-17 01:18:22 +0100
commit17f29d7bac86dc6e42c8ea728a2b7d1dc873b3dc (patch)
tree60261cb64ad167a98e193f43e7e9f23de2319349 /mount/mount.c
parentblkid: add Christoph's note about libdisk to TODO (diff)
downloadkernel-qcow2-util-linux-17f29d7bac86dc6e42c8ea728a2b7d1dc873b3dc.tar.gz
kernel-qcow2-util-linux-17f29d7bac86dc6e42c8ea728a2b7d1dc873b3dc.tar.xz
kernel-qcow2-util-linux-17f29d7bac86dc6e42c8ea728a2b7d1dc873b3dc.zip
mount: generic blkid/volume_id wrapper, use blkid_evaluate_*
* moves the generic libblkid/libvolume_id wrapper (fsprobe.c) from mount/ to lib/. We'll use the wrapper in cfdisk and fsck. The wrapper supports: - obsolete volume_id (udev) - obsolete libblkid (e2fsprogs) - libblkid (util-linux-ng) * mount, umount and swapon when linked against the new libblkid use - low-level probing code to read LABEL, UUID or FSTYPE from a device - high-level blkid_evaluate_spec() to convert LABEL/UUID to devname Signed-off-by: Karel Zak <kzak@redhat.com>
Diffstat (limited to 'mount/mount.c')
-rw-r--r--mount/mount.c181
1 files changed, 171 insertions, 10 deletions
diff --git a/mount/mount.c b/mount/mount.c
index e04dbdb51..3f0b0c61d 100644
--- a/mount/mount.c
+++ b/mount/mount.c
@@ -29,6 +29,7 @@
#include "pathnames.h"
#include "fsprobe.h"
+#include "devname.h"
#include "mount_constants.h"
#include "sundries.h"
#include "xmalloc.h"
@@ -85,6 +86,15 @@ static int restricted = 1;
/* Contains the fd to read the passphrase from, if any. */
static int pfd = -1;
+/* mount(2) options */
+struct mountargs {
+ const char *spec;
+ const char *node;
+ const char *type;
+ int flags;
+ void *data;
+};
+
/* Map from -o and fstab option strings to the flag argument to mount(2). */
struct opt_map {
const char *opt; /* option name */
@@ -241,7 +251,7 @@ print_one (const struct my_mntent *me) {
if (me->mnt_opts != NULL)
printf (" (%s)", me->mnt_opts);
if (list_with_volumelabel && is_pseudo_fs(me->mnt_type) == 0) {
- const char *devname = fsprobe_get_devname(me->mnt_fsname);
+ const char *devname = spec_to_devname(me->mnt_fsname);
if (devname) {
const char *label;
@@ -547,7 +557,7 @@ create_mtab (void) {
char *extra_opts;
parse_opts (fstab->m.mnt_opts, &flags, &extra_opts);
mnt.mnt_dir = "/";
- mnt.mnt_fsname = fsprobe_get_devname(fstab->m.mnt_fsname);
+ mnt.mnt_fsname = spec_to_devname(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;
@@ -696,6 +706,157 @@ check_special_mountprog(const char *spec, const char *node, const char *type, in
}
+/* list of already tested filesystems by procfsloop_mount() */
+static struct tried {
+ struct tried *next;
+ char *type;
+} *tried = NULL;
+
+static int
+was_tested(const char *fstype) {
+ struct tried *t;
+
+ if (fsprobe_known_fstype(fstype))
+ return 1;
+ for (t = tried; t; t = t->next) {
+ if (!strcmp(t->type, fstype))
+ return 1;
+ }
+ return 0;
+}
+
+static void
+set_tested(const char *fstype) {
+ struct tried *t = xmalloc(sizeof(struct tried));
+
+ t->next = tried;
+ t->type = xstrdup(fstype);
+ tried = t;
+}
+
+static void
+free_tested(void) {
+ struct tried *t, *tt;
+
+ t = tried;
+ while(t) {
+ free(t->type);
+ tt = t->next;
+ free(t);
+ t = tt;
+ }
+ tried = NULL;
+}
+
+static char *
+procfsnext(FILE *procfs) {
+ char line[100];
+ char fsname[100];
+
+ while (fgets(line, sizeof(line), procfs)) {
+ if (sscanf (line, "nodev %[^\n]\n", fsname) == 1) continue;
+ if (sscanf (line, " %[^ \n]\n", fsname) != 1) continue;
+ return xstrdup(fsname);
+ }
+ return 0;
+}
+
+/* Only use /proc/filesystems here, this is meant to test what
+ the kernel knows about, so /etc/filesystems is irrelevant.
+ Return: 1: yes, 0: no, -1: cannot open procfs */
+static int
+known_fstype_in_procfs(const char *type)
+{
+ FILE *procfs;
+ char *fsname;
+ int ret = -1;
+
+ procfs = fopen(_PATH_PROC_FILESYSTEMS, "r");
+ if (procfs) {
+ ret = 0;
+ while ((fsname = procfsnext(procfs)) != NULL)
+ if (!strcmp(fsname, type)) {
+ ret = 1;
+ break;
+ }
+ fclose(procfs);
+ procfs = NULL;
+ }
+ return ret;
+}
+
+/* Try all types in FILESYSTEMS, except those in *types,
+ in case *types starts with "no" */
+/* return: 0: OK, -1: error in errno, 1: type not found */
+/* when 0 or -1 is returned, *types contains the type used */
+/* when 1 is returned, *types is NULL */
+static int
+procfsloop_mount(int (*mount_fn)(struct mountargs *, int *, int *),
+ struct mountargs *args,
+ const char **types,
+ int *special, int *status)
+{
+ char *files[2] = { _PATH_FILESYSTEMS, _PATH_PROC_FILESYSTEMS };
+ FILE *procfs;
+ char *fsname;
+ const char *notypes = NULL;
+ int no = 0;
+ int ret = 1;
+ int errsv = 0;
+ int i;
+
+ if (*types && !strncmp(*types, "no", 2)) {
+ no = 1;
+ notypes = (*types) + 2;
+ }
+ *types = NULL;
+
+ /* Use _PATH_PROC_FILESYSTEMS only when _PATH_FILESYSTEMS
+ * (/etc/filesystems) does not exist. In some cases trying a
+ * filesystem that the kernel knows about on the wrong data will crash
+ * the kernel; in such cases _PATH_FILESYSTEMS can be used to list the
+ * filesystems that we are allowed to try, and in the order they should
+ * be tried. End _PATH_FILESYSTEMS with a line containing a single '*'
+ * only, if _PATH_PROC_FILESYSTEMS should be tried afterwards.
+ */
+ for (i=0; i<2; i++) {
+ procfs = fopen(files[i], "r");
+ if (!procfs)
+ continue;
+ while ((fsname = procfsnext(procfs)) != NULL) {
+ if (!strcmp(fsname, "*")) {
+ fclose(procfs);
+ goto nexti;
+ }
+ if (was_tested (fsname))
+ continue;
+ if (no && matching_type(fsname, notypes))
+ continue;
+ set_tested (fsname);
+ args->type = fsname;
+ if (verbose)
+ printf(_("Trying %s\n"), fsname);
+ if ((*mount_fn) (args, special, status) == 0) {
+ *types = fsname;
+ ret = 0;
+ break;
+ } else if (errno != EINVAL &&
+ known_fstype_in_procfs(fsname) == 1) {
+ *types = "guess";
+ ret = -1;
+ errsv = errno;
+ break;
+ }
+ }
+ free_tested();
+ fclose(procfs);
+ errno = errsv;
+ return ret;
+ nexti:;
+ }
+ return 1;
+}
+
static const char *
guess_fstype_by_devname(const char *devname)
{
@@ -769,7 +930,7 @@ guess_fstype_and_mount(const char *spec, const char *node, const char **types,
return do_mount (&args, special, status);
}
- return fsprobe_procfsloop_mount(do_mount, &args, types, special, status);
+ return procfsloop_mount(do_mount, &args, types, special, status);
}
/*
@@ -1296,7 +1457,7 @@ mount_retry:
error (_("mount: %s: can't read superblock"), spec); break;
case ENODEV:
{
- int pfs = fsprobe_known_fstype_in_procfs(types);
+ int pfs = known_fstype_in_procfs(types);
if (pfs == 1 || !strcmp(types, "guess"))
error(_("mount: %s: unknown device"), spec);
@@ -1315,13 +1476,13 @@ mount_retry:
u++;
}
}
- if (u && fsprobe_known_fstype_in_procfs(lowtype) == 1)
+ if (u && known_fstype_in_procfs(lowtype) == 1)
error (_("mount: probably you meant %s"), lowtype);
else if (!strncmp(lowtype, "iso", 3) &&
- fsprobe_known_fstype_in_procfs("iso9660") == 1)
+ known_fstype_in_procfs("iso9660") == 1)
error (_("mount: maybe you meant 'iso9660'?"));
else if (!strncmp(lowtype, "fat", 3) &&
- fsprobe_known_fstype_in_procfs("vfat") == 1)
+ known_fstype_in_procfs("vfat") == 1)
error (_("mount: maybe you meant 'vfat'?"));
free(lowtype);
} else
@@ -1499,7 +1660,7 @@ mount_one (const char *spec, const char *node, const char *types,
if (types == NULL || (strncmp(types, "nfs", 3) &&
strncmp(types, "cifs", 4) &&
strncmp(types, "smbfs", 5))) {
- nspec = fsprobe_get_devname_for_mounting(spec);
+ nspec = spec_to_devname(spec);
if (nspec)
spec = nspec;
}
@@ -1515,7 +1676,7 @@ mounted (const char *spec0, const char *node0) {
int ret = 0;
/* Handle possible UUID= and LABEL= in spec */
- spec = fsprobe_get_devname(spec0);
+ spec = spec_to_devname(spec0);
if (!spec)
return ret;
@@ -1791,7 +1952,7 @@ getfs(const char *spec, const char *uuid, const char *label)
else if (label)
devname = fsprobe_get_devname_by_label(label);
else
- devname = fsprobe_get_devname(spec);
+ devname = spec_to_devname(spec);
if (devname)
mc = getfs_by_devname(devname);