]> err.no Git - util-linux/commitdiff
mount: generic blkid/volume_id wrapper, use blkid_evaluate_*
authorKarel Zak <kzak@redhat.com>
Tue, 17 Feb 2009 00:01:35 +0000 (01:01 +0100)
committerKarel Zak <kzak@redhat.com>
Tue, 17 Feb 2009 00:18:22 +0000 (01:18 +0100)
 * 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>
15 files changed:
configure.ac
include/fsprobe.h [new file with mode: 0644]
lib/fsprobe.c [new file with mode: 0644]
mount/Makefile.am
mount/devname.c [new file with mode: 0644]
mount/devname.h [new file with mode: 0644]
mount/fsprobe.c [deleted file]
mount/fsprobe.h [deleted file]
mount/fsprobe_blkid.c [deleted file]
mount/fsprobe_volumeid.c [deleted file]
mount/fstab.c
mount/mount.c
mount/sundries.c
mount/sundries.h
mount/swapon.c

index 04c1f611181d61651e130e8ef118b9333e8102ed..3952e83f9019e35d7d5726143e0cff75468d3ff2 100644 (file)
@@ -190,6 +190,7 @@ elif test "x$with_fsprobe" = xvolume_id; then
 elif test "x$with_fsprobe" = xbuiltin; then
   have_blkid=yes
   AC_DEFINE(HAVE_LIBBLKID,1,[Define to 1 if you have the -lblkid.])
+  AC_DEFINE(HAVE_BLKID_EVALUATE_SPEC,1,[Define to 1 if you have the blkid_evaluate_spec().])
   AM_CONDITIONAL(HAVE_BLKID, true)
   AM_CONDITIONAL(BUILD_LIBBLKID, true)
 fi
diff --git a/include/fsprobe.h b/include/fsprobe.h
new file mode 100644 (file)
index 0000000..ed2cce1
--- /dev/null
@@ -0,0 +1,23 @@
+#ifndef FSPROBE_H
+#define FSPROBE_H
+/*
+ * This is the generic interface for filesystem guessing libraries.
+ * Implementations are provided by
+ */
+extern void fsprobe_init(void);
+extern void fsprobe_exit(void);
+
+extern int fsprobe_parse_spec(const char *spec, char **name, char **value);
+
+extern const char *fsprobe_get_devname_by_uuid(const char *uuid);
+extern const char *fsprobe_get_devname_by_label(const char *label);
+extern const char *fsprobe_get_devname_by_spec(const char *spec);
+
+extern const char *fsprobe_get_label_by_devname(const char *devname);
+extern const char *fsprobe_get_uuid_by_devname(const char *devname);
+extern const char *fsprobe_get_fstype_by_devname(const char *devname);
+
+
+extern int fsprobe_known_fstype(const char *fstype);
+
+#endif /* FSPROBE_H */
diff --git a/lib/fsprobe.c b/lib/fsprobe.c
new file mode 100644 (file)
index 0000000..d8d927d
--- /dev/null
@@ -0,0 +1,388 @@
+#include <stdio.h>
+#include <string.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <stdlib.h>
+
+#include <blkid/blkid.h> /* TODO: <blkid.h>, -I/usr/include/blkid */
+
+#include "blkdev.h"
+#include "canonicalize.h"
+#include "pathnames.h"
+#include "fsprobe.h"
+
+/* ask kernel developers why we need such ugly open() method... */
+static int
+open_device(const char *devname)
+{
+       int retries = 0;
+
+       do {
+               int fd = open(devname, O_RDONLY);
+               if (fd >= 0)
+                       return fd;
+               if (errno != ENOMEDIUM)
+                       break;
+               if (retries >= CRDOM_NOMEDIUM_RETRIES)
+                       break;
+               ++retries;
+               sleep(3);
+       } while(1);
+
+       return -1;
+}
+
+/*
+ * Parses NAME=value, returns -1 on parse error, 0 success. The success is also
+ * when the 'spec' doesn't contain name=value pair (because the spec could be
+ * a devname too). In particular case the pointer 'name' is set to NULL.
+
+ * The result is a new allocated string (the 'name' pointer).
+ */
+int
+fsprobe_parse_spec(const char *spec, char **name, char **value)
+{
+       char *vl, *tk, *cp;
+
+       *name = NULL;
+       *value = NULL;
+
+       if (!(cp = strchr(spec, '=')))
+               return 0;                               /* no name= */
+
+       tk = strdup(spec);
+       vl = tk + (cp - spec);
+       *vl++ = '\0';
+
+       if (*vl == '"' || *vl == '\'') {
+               if (!(cp = strrchr(vl+1, *vl))) {
+                       free(tk);
+                       return -1;                      /* parse error */
+               }
+               vl++;
+               *cp = '\0';
+       }
+
+       *name = tk;
+       *value = vl;
+       return 0;
+}
+
+const char *
+fsprobe_get_devname_by_spec(const char *spec)
+{
+       char *name, *value;
+
+       if (!spec)
+               return NULL;
+       if (fsprobe_parse_spec(spec, &name, &value) != 0)
+               return NULL;                            /* parse error */
+       if (name) {
+               const char *nspec = NULL;
+
+               if (!strcmp(name,"LABEL"))
+                       nspec = fsprobe_get_devname_by_label(value);
+               else if (!strcmp(name,"UUID"))
+                       nspec = fsprobe_get_devname_by_uuid(value);
+
+               free((void *) name);
+               return nspec;
+       }
+
+       return canonicalize_path(spec);
+}
+
+#ifdef HAVE_LIBBLKID
+static blkid_cache blcache;
+
+void
+fsprobe_init(void)
+{
+       blcache = NULL;
+}
+
+int
+fsprobe_known_fstype(const char *fstype)
+{
+       return blkid_known_fstype(fstype);
+}
+
+#ifdef HAVE_BLKID_EVALUATE_SPEC
+/*
+ * libblkid from util-linux-ng
+ * -- recommended
+ */
+static blkid_probe blprobe;
+
+void
+fsprobe_exit(void)
+{
+       if (blprobe)
+               blkid_free_probe(blprobe);
+       if (blcache)
+               blkid_put_cache(blcache);
+}
+
+/* returns device LABEL, UUID, FSTYPE, ... by low-level
+ * probing interface
+ */
+static const char *
+fsprobe_get_value(const char *name, const char *devname)
+{
+       int fd;
+       unsigned char *data = NULL;
+
+       if (!devname || !name)
+               return NULL;
+       fd = open_device(devname);
+       if (fd < 0)
+               return NULL;
+       if (!blprobe)
+               blprobe = blkid_new_probe();
+       if (!blprobe)
+               goto done;
+       if (blkid_probe_set_device(blprobe, fd, 0, 0))
+               goto done;
+       if (blkid_probe_set_request(blprobe, BLKID_PROBREQ_LABEL |
+                        BLKID_PROBREQ_UUID | BLKID_PROBREQ_TYPE ))
+               goto done;
+       if (blkid_do_safeprobe(blprobe))
+               goto done;
+       if (blkid_probe_lookup_value(blprobe, name, &data, NULL))
+               goto done;
+done:
+       close(fd);
+       return data ? strdup((char *) data) : NULL;
+}
+
+const char *
+fsprobe_get_label_by_devname(const char *devname)
+{
+       return fsprobe_get_value("LABEL", devname);
+}
+
+const char *
+fsprobe_get_uuid_by_devname(const char *devname)
+{
+       return fsprobe_get_value("UUID", devname);
+}
+
+const char *
+fsprobe_get_fstype_by_devname(const char *devname)
+{
+       return fsprobe_get_value("TYPE", devname);
+}
+
+const char *
+fsprobe_get_devname_by_uuid(const char *uuid)
+{
+       return blkid_evaluate_spec("UUID", uuid, &blcache);
+}
+
+const char *
+fsprobe_get_devname_by_label(const char *label)
+{
+       return blkid_evaluate_spec("LABEL", label, &blcache);
+}
+
+#else /* !HAVE_BLKID_EVALUATE_SPEC */
+
+/*
+ * Classic libblkid (from e2fsprogs) without blkid_evaluate_spec()
+ * -- deprecated
+ */
+#define BLKID_EMPTY_CACHE      "/dev/null"
+
+void
+fsprobe_exit(void)
+{
+       if (blcache)
+               blkid_put_cache(blcache);
+}
+
+const char *
+fsprobe_get_devname_by_uuid(const char *uuid)
+{
+       if (!blcache)
+               blkid_get_cache(&blcache, NULL);
+
+       return blkid_get_devname(blcache, "UUID", uuid);
+}
+
+const char *
+fsprobe_get_devname_by_label(const char *label)
+{
+       if (!blcache)
+               blkid_get_cache(&blcache, NULL);
+
+       return blkid_get_devname(blcache, "LABEL", label);
+}
+
+const char *
+fsprobe_get_fstype_by_devname(const char *devname)
+{
+       blkid_cache c;
+       const char *tp;
+
+       if (blcache)
+               return blkid_get_tag_value(blcache, "TYPE", devname);
+
+       /* The cache is not initialized yet. Use empty cache rather than waste
+        * time with /etc/blkid.tab. It seems that probe FS is faster than
+        * parse the cache file.  -- kzak (17-May-2007)
+        */
+       blkid_get_cache(&c, BLKID_EMPTY_CACHE);
+       tp = blkid_get_tag_value(c, "TYPE", devname);
+       blkid_put_cache(c);
+
+       return tp;
+}
+
+const char *
+fsprobe_get_label_by_devname(const char *devname)
+{
+       if (!blcache)
+               blkid_get_cache(&blcache, NULL);
+
+       return blkid_get_tag_value(blcache, "LABEL", devname);
+}
+
+const char *
+fsprobe_get_uuid_by_devname(const char *devname)
+{
+       if (!blcache)
+               blkid_get_cache(&blcache, NULL);
+
+       return blkid_get_tag_value(blcache, "UUID", devname);
+}
+
+#endif /* !HAVE_BLKID_EVALUATE_SPEC */
+#else  /* !HAVE_LIBBLKID */
+
+/*
+ * libvolume_id from udev
+ * -- deprecated
+ */
+#include <libvolume_id.h>
+
+enum probe_type {
+       VOLUME_ID_NONE,
+       VOLUME_ID_LABEL,
+       VOLUME_ID_UUID,
+       VOLUME_ID_TYPE,
+};
+
+static char
+*probe(const char *device, enum probe_type type)
+{
+       int fd;
+       uint64_t size;
+       struct volume_id *id;
+       const char *val;
+       char *value = NULL;
+       int retries = 0;
+
+       fd = open_device(devname);
+       if (fd < 0)
+               return NULL;
+       id = volume_id_open_fd(fd);
+       if (!id) {
+               close(fd);
+               return NULL;
+       }
+       if (blkdev_get_size(fd, &size) != 0)
+               size = 0;
+       if (volume_id_probe_all(id, 0, size) == 0) {
+               switch(type) {
+               case VOLUME_ID_LABEL:
+                       if (volume_id_get_label(id, &val))
+                               value  = xstrdup(val);
+                       break;
+               case VOLUME_ID_UUID:
+                       if (volume_id_get_uuid(id, &val))
+                               value  = xstrdup(val);
+                       break;
+               case VOLUME_ID_TYPE:
+                       if (volume_id_get_type(id, &val))
+                               value  = xstrdup(val);
+                       break;
+               default:
+                       break;
+               }
+       }
+       volume_id_close(id);
+       close(fd);
+       return value;
+}
+
+void
+fsprobe_init(void)
+{
+}
+
+void
+fsprobe_exit(void)
+{
+}
+
+int
+fsprobe_known_fstype(const char *fstype)
+{
+       if (volume_id_get_prober_by_type(fstype) != NULL)
+               return 1;
+       return 0;
+}
+
+const char *
+fsprobe_get_uuid_by_devname(const char *devname)
+{
+       return probe(devname, VOLUME_ID_UUID);
+}
+
+const char *
+fsprobe_get_label_by_devname(const char *devname)
+{
+       return probe(devname, VOLUME_ID_LABEL);
+}
+
+const char *
+fsprobe_get_fstype_by_devname(const char *devname)
+{
+       return probe(devname, VOLUME_ID_TYPE);
+}
+
+const char *
+fsprobe_get_devname_by_uuid(const char *uuid)
+{
+       char dev[PATH_MAX];
+       size_t len;
+
+       if (!uuid)
+               return NULL;
+
+       strcpy(dev, _PATH_DEV_BYUUID "/");
+       len = strlen(_PATH_DEV_BYUUID "/");
+       if (!volume_id_encode_string(uuid, &dev[len], sizeof(dev) - len))
+               return NULL;
+       return canonicalize_path(dev);
+}
+
+const char *
+fsprobe_get_devname_by_label(const char *label)
+{
+       char dev[PATH_MAX];
+       size_t len;
+
+       if (!label)
+               return NULL;
+       strcpy(dev, _PATH_DEV_BYLABEL "/");
+       len = strlen(_PATH_DEV_BYLABEL "/");
+       if (!volume_id_encode_string(label, &dev[len], sizeof(dev) - len))
+               return NULL;
+       return canonicalize_path(dev);
+}
+
+#endif /* HAVE_LIBVOLUME_ID  */
index 1128fa85c89ba2c185167e390ad5e1419f7ac752..261b8c9aa94d597e026ddb79e1737070d7650341 100644 (file)
@@ -11,12 +11,12 @@ srcs_common = sundries.c xmalloc.c ../lib/canonicalize.c
 
 # generic header for mount and umount
 hdrs_mount = fstab.h mount_mntent.h mount_constants.h \
-       lomount.h fsprobe.h xmalloc.h getusername.h loop.h sundries.h
+       lomount.h xmalloc.h getusername.h loop.h sundries.h
 
 # generic sources for mount and umount
-srcs_mount = fstab.c mount_mntent.c getusername.c lomount.c \
+srcs_mount = fstab.c mount_mntent.c getusername.c lomount.c devname.c devname.h \
        $(srcs_common) $(hdrs_mount) ../lib/env.c ../lib/linux_version.c \
-       ../lib/blkdev.c fsprobe.c
+       ../lib/blkdev.c ../lib/fsprobe.c
 
 # generic flags for all programs (except losetup)
 # -- note that pkg-config autoconf macros (pkg.m4) does not differentiate
@@ -38,8 +38,8 @@ umount_CFLAGS = $(SUID_CFLAGS) $(AM_CFLAGS) $(cflags_common)
 umount_LDFLAGS = $(SUID_LDFLAGS) $(AM_LDFLAGS)
 umount_LDADD = $(ldadd_common)
 
-swapon_SOURCES = swapon.c swap_constants.h $(srcs_common) \
-       ../lib/linux_version.c ../lib/blkdev.c fsprobe.c
+swapon_SOURCES = swapon.c swap_constants.h $(srcs_common) devname.c devname.h \
+       ../lib/linux_version.c ../lib/blkdev.c ../lib/fsprobe.c
 swapon_CFLAGS = $(cflags_common)
 swapon_LDADD = $(ldadd_common)
 
@@ -51,6 +51,7 @@ mount_static_LDADD =
 if HAVE_STATIC_MOUNT
 bin_PROGRAMS += mount.static
 mount_static_SOURCES = $(mount_SOURCES)
+mount_static_CFLAGS = $(cflags_common)
 mount_static_LDFLAGS = $(ldflags_static)
 mount_static_LDADD += $(ldadd_static)
 endif
@@ -58,6 +59,7 @@ endif
 if HAVE_STATIC_UMOUNT
 bin_PROGRAMS += umount.static
 umount_static_SOURCES = $(umount_SOURCES)
+umount_static_CFLAGS = $(cflags_common)
 umount_static_LDFLAGS = $(ldflags_static)
 umount_static_LDADD = $(ldadd_static)
 endif
@@ -70,8 +72,6 @@ losetup_static_CPPFLAGS = -DMAIN $(AM_CPPFLAGS)
 endif
 
 if HAVE_BLKID
-srcs_mount += fsprobe_blkid.c
-swapon_SOURCES += fsprobe_blkid.c
 if BUILD_LIBBLKID
 ldadd_common += $(ul_libblkid_la)
 ldadd_static += $(ul_libblkid_la)
@@ -84,8 +84,6 @@ endif
 endif
 
 if HAVE_VOLUME_ID
-srcs_mount += fsprobe_volumeid.c
-swapon_SOURCES += fsprobe_volumeid.c
 ldadd_common += $(VOLUMEID_LIBS)
 ldadd_static += $(VOLUMEID_LIBS_STATIC)
 cflags_common += $(VOLUMEID_CFLAGS)
diff --git a/mount/devname.c b/mount/devname.c
new file mode 100644 (file)
index 0000000..585d259
--- /dev/null
@@ -0,0 +1,15 @@
+#include "fsprobe.h"
+
+#include "devname.h"
+#include "sundries.h"          /* for xstrdup */
+
+const char *
+spec_to_devname(const char *spec)
+{
+       if (!spec)
+               return NULL;
+       if (is_pseudo_fs(spec))
+               return xstrdup(spec);
+       return fsprobe_get_devname_by_spec(spec);
+}
+
diff --git a/mount/devname.h b/mount/devname.h
new file mode 100644 (file)
index 0000000..d6adeff
--- /dev/null
@@ -0,0 +1,6 @@
+#ifndef MOUNT_DEVNAME_H
+#define MOUNT_DEVNAME_H
+
+extern const char *spec_to_devname(const char *spec);
+
+#endif
diff --git a/mount/fsprobe.c b/mount/fsprobe.c
deleted file mode 100644 (file)
index 04e267f..0000000
+++ /dev/null
@@ -1,228 +0,0 @@
-#include <stdio.h>
-#include <string.h>
-#include <fcntl.h>
-#include <errno.h>
-#include <unistd.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include "pathnames.h"
-#include "fsprobe.h"
-#include "sundries.h"          /* for xstrdup */
-#include "nls.h"
-
-/* list of already tested filesystems by fsprobe_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 */
-int
-fsprobe_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 */
-int
-fsprobe_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 &&
-                                  fsprobe_known_fstype_in_procfs(fsname) == 1) {
-                               *types = "guess";
-                               ret = -1;
-                               errsv = errno;
-                               break;
-                       }
-               }
-               free_tested();
-               fclose(procfs);
-               errno = errsv;
-               return ret;
-       nexti:;
-       }
-       return 1;
-}
-
-const char *
-fsprobe_get_devname_for_mounting(const char *spec)
-{
-       char *name, *value;
-
-       if (!spec)
-               return NULL;
-
-       if (is_pseudo_fs(spec))
-               return xstrdup(spec);
-
-       if (parse_spec(spec, &name, &value) != 0)
-               return NULL;                            /* parse error */
-
-       if (name) {
-               const char *nspec = NULL;
-
-               if (!strcmp(name,"LABEL"))
-                       nspec = fsprobe_get_devname_by_label(value);
-               else if (!strcmp(name,"UUID"))
-                       nspec = fsprobe_get_devname_by_uuid(value);
-
-               if (nspec && verbose > 1)
-                       printf(_("mount: going to mount %s by %s\n"), spec, name);
-
-               free((void *) name);
-               return nspec;
-       }
-
-       /* no LABEL, no UUID, .. probably a path */
-       if (verbose > 1)
-               printf(_("mount: no LABEL=, no UUID=, going to mount %s by path\n"), spec);
-
-       return canonicalize(spec);
-}
-
-/* like fsprobe_get_devname_for_mounting(), but without verbose messages */
-const char *
-fsprobe_get_devname(const char *spec)
-{
-       char *name, *value;
-
-       if (!spec)
-               return NULL;
-       if (is_pseudo_fs(spec))
-               return xstrdup(spec);
-
-       if (parse_spec(spec, &name, &value) != 0)
-               return NULL;                            /* parse error */
-
-       if (name) {
-               const char *nspec = NULL;
-
-               if (!strcmp(name,"LABEL"))
-                       nspec = fsprobe_get_devname_by_label(value);
-               else if (!strcmp(name,"UUID"))
-                       nspec = fsprobe_get_devname_by_uuid(value);
-
-               free((void *) name);
-               return nspec;
-       }
-
-       return canonicalize(spec);
-}
-
diff --git a/mount/fsprobe.h b/mount/fsprobe.h
deleted file mode 100644 (file)
index 1c50e1a..0000000
+++ /dev/null
@@ -1,46 +0,0 @@
-#ifndef MOUNT_FSPROBE_H
-#define MOUNT_FSPROBE_H
-/*
- * This is the generic interface for filesystem guessing libraries.
- * Implementations are provided by
- *
- *    fsprobe_blkid.c for libblkid from e2fsprogs
- *    fsprobe_volumeid.c for libvolume_id from udev
- *
- * Copyright (C) 2007 Kay Sievers <kay.sievers@vrfy.org>
- * Copyright (C) 2007 Matthias Koenig <mkoenig@suse.de>
- * Copyright (C) 2007 Karel Zak <kzak@redhat.com>
- */
-
-extern void fsprobe_init(void);
-extern void fsprobe_exit(void);
-
-extern const char *fsprobe_get_devname_by_uuid(const char *uuid);
-extern const char *fsprobe_get_devname_by_label(const char *label);
-
-extern const char *fsprobe_get_label_by_devname(const char *devname);
-extern const char *fsprobe_get_uuid_by_devname(const char *devname);
-extern const char *fsprobe_get_fstype_by_devname(const char *devname);
-
-extern const char *fsprobe_get_devname(const char *spec);
-extern const char *fsprobe_get_devname_for_mounting(const char *spec);
-
-extern int fsprobe_known_fstype(const char *fstype);
-
-struct mountargs {
-       const char *spec;
-       const char *node;
-       const char *type;
-       int flags;
-       void *data;
-};
-
-extern int fsprobe_known_fstype_in_procfs(const char *type);
-
-extern int fsprobe_procfsloop_mount(
-                       int (*mount_fn)(struct mountargs *, int *, int *),
-                       struct mountargs *args,
-                       const char **types,
-                       int *special, int *status);
-
-#endif /* MOUNT_FSPROBE_H */
diff --git a/mount/fsprobe_blkid.c b/mount/fsprobe_blkid.c
deleted file mode 100644 (file)
index 4d28897..0000000
+++ /dev/null
@@ -1,82 +0,0 @@
-#include <stdio.h>
-#include <blkid/blkid.h>
-#include "fsprobe.h"
-
-#define BLKID_EMPTY_CACHE      "/dev/null"
-static blkid_cache blkid;
-
-void
-fsprobe_init(void)
-{
-       blkid = NULL;
-}
-
-void
-fsprobe_exit(void)
-{
-       if (blkid)
-               blkid_put_cache(blkid);
-}
-
-const char *
-fsprobe_get_label_by_devname(const char *devname)
-{
-       if (!blkid)
-               blkid_get_cache(&blkid, NULL);
-
-       return blkid_get_tag_value(blkid, "LABEL", devname);
-}
-
-const char *
-fsprobe_get_uuid_by_devname(const char *devname)
-{
-       if (!blkid)
-               blkid_get_cache(&blkid, NULL);
-
-       return blkid_get_tag_value(blkid, "UUID", devname);
-}
-
-const char *
-fsprobe_get_devname_by_uuid(const char *uuid)
-{
-       if (!blkid)
-               blkid_get_cache(&blkid, NULL);
-
-       return blkid_get_devname(blkid, "UUID", uuid);
-}
-
-const char *
-fsprobe_get_devname_by_label(const char *label)
-{
-       if (!blkid)
-               blkid_get_cache(&blkid, NULL);
-
-       return blkid_get_devname(blkid, "LABEL", label);
-}
-
-int
-fsprobe_known_fstype(const char *fstype)
-{
-       return blkid_known_fstype(fstype);
-}
-
-const char *
-fsprobe_get_fstype_by_devname(const char *devname)
-{
-       blkid_cache c;
-       const char *tp;
-
-       if (blkid)
-               return blkid_get_tag_value(blkid, "TYPE", devname);
-
-       /* The cache is not initialized yet. Use empty cache rather than waste
-        * time with /etc/blkid.tab. It seems that probe FS is faster than
-        * parse the cache file.  -- kzak (17-May-2007)
-        */
-       blkid_get_cache(&c, BLKID_EMPTY_CACHE);
-       tp = blkid_get_tag_value(c, "TYPE", devname);
-       blkid_put_cache(c);
-
-       return tp;
-}
-
diff --git a/mount/fsprobe_volumeid.c b/mount/fsprobe_volumeid.c
deleted file mode 100644 (file)
index a5c9282..0000000
+++ /dev/null
@@ -1,144 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <string.h>
-#include <stddef.h>
-#include <errno.h>
-#include <sys/mount.h>
-#include <sys/ioctl.h>
-#include <fcntl.h>
-#include <libvolume_id.h>
-
-#include "blkdev.h"
-
-#include "fsprobe.h"
-#include "pathnames.h"
-#include "sundries.h"
-
-enum probe_type {
-       VOLUME_ID_NONE,
-       VOLUME_ID_LABEL,
-       VOLUME_ID_UUID,
-       VOLUME_ID_TYPE,
-};
-
-static char
-*probe(const char *device, enum probe_type type)
-{
-       int fd;
-       uint64_t size;
-       struct volume_id *id;
-       const char *val;
-       char *value = NULL;
-       int retries = 0;
-
-retry:
-       fd = open(device, O_RDONLY);
-       if (fd < 0) {
-               if (errno == ENOMEDIUM && retries < CRDOM_NOMEDIUM_RETRIES) {
-                       ++retries;
-                       sleep(3);
-                       goto retry;
-               }
-               return NULL;
-       }
-
-       id = volume_id_open_fd(fd);
-       if (!id) {
-               close(fd);
-               return NULL;
-       }
-
-       if (blkdev_get_size(fd, &size) != 0)
-               size = 0;
-
-       if (volume_id_probe_all(id, 0, size) == 0) {
-               switch(type) {
-               case VOLUME_ID_LABEL:
-                       if (volume_id_get_label(id, &val))
-                               value  = xstrdup(val);
-                       break;
-               case VOLUME_ID_UUID:
-                       if (volume_id_get_uuid(id, &val))
-                               value  = xstrdup(val);
-                       break;
-               case VOLUME_ID_TYPE:
-                       if (volume_id_get_type(id, &val))
-                               value  = xstrdup(val);
-                       break;
-               default:
-                       break;
-               }
-       }
-
-       volume_id_close(id);
-       close(fd);
-       return value;
-}
-
-void
-fsprobe_init(void)
-{
-}
-
-void
-fsprobe_exit(void)
-{
-}
-
-int
-fsprobe_known_fstype(const char *fstype)
-{
-       if (volume_id_get_prober_by_type(fstype) != NULL)
-               return 1;
-       return 0;
-}
-
-const char *
-fsprobe_get_uuid_by_devname(const char *devname)
-{
-       return probe(devname, VOLUME_ID_UUID);
-}
-
-const char *
-fsprobe_get_label_by_devname(const char *devname)
-{
-       return probe(devname, VOLUME_ID_LABEL);
-}
-
-const char *
-fsprobe_get_fstype_by_devname(const char *devname)
-{
-       return probe(devname, VOLUME_ID_TYPE);
-}
-
-const char *
-fsprobe_get_devname_by_uuid(const char *uuid)
-{
-       char dev[PATH_MAX];
-       size_t len;
-
-       if (!uuid)
-               return NULL;
-
-       strcpy(dev, _PATH_DEV_BYUUID "/");
-       len = strlen(_PATH_DEV_BYUUID "/");
-       if (!volume_id_encode_string(uuid, &dev[len], sizeof(dev) - len))
-               return NULL;
-       return canonicalize(dev);
-}
-
-const char *
-fsprobe_get_devname_by_label(const char *label)
-{
-       char dev[PATH_MAX];
-       size_t len;
-
-       if (!label)
-               return NULL;
-       strcpy(dev, _PATH_DEV_BYLABEL "/");
-       len = strlen(_PATH_DEV_BYLABEL "/");
-       if (!volume_id_encode_string(label, &dev[len], sizeof(dev) - len))
-               return NULL;
-       return canonicalize(dev);
-}
index bcbc3a9db1ed3565b9922300b9920237726d19ac..57954598b78a35c85892614ba4a07e172ae338dc 100644 (file)
@@ -394,7 +394,7 @@ getfs_by_spec (const char *spec) {
        if (!spec)
                return NULL;
 
-       if (parse_spec(spec, &name, &value) != 0)
+       if (fsprobe_parse_spec(spec, &name, &value) != 0)
                return NULL;                            /* parse error */
 
        if (name) {
@@ -918,6 +918,7 @@ update_mtab (const char *dir, struct my_mntent *instead) {
 /* dummy */
 const char *fsprobe_get_label_by_devname(const char *spec) { return NULL; }
 const char *fsprobe_get_uuid_by_devname(const char *spec) { return NULL; }
+int fsprobe_parse_spec(const char *spec, char **name, char **value) { return 0; }
 struct my_mntent *my_getmntent (mntFILE *mfp) { return NULL; }
 mntFILE *my_setmntent (const char *file, char *mode) { return NULL; }
 void my_endmntent (mntFILE *mfp) { }
index e04dbdb516688ef9c7edcd1a18723cc29c342fa1..3f0b0c61d53203a28299a29011db2f93695dbc00 100644 (file)
@@ -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);
index bdaf117221c9afdf1c9bad92cf4918193ed22156..3980f81ad8c41375ef44b29a9d64fe4647618c91 100644 (file)
@@ -242,42 +242,6 @@ matching_opts (const char *options, const char *test_opts) {
      return 1;
 }
 
-/*
- * Parses NAME=value, returns -1 on parse error, 0 success. The success is also
- * when the 'spec' doesn't contain name=value pair (because the spec could be
- * a devname too). In particular case the pointer 'name' is set to NULL.
-
- * The result is a new allocated string (the 'name' pointer).
- */
-int
-parse_spec(const char *spec, char **name, char **value)
-{
-       char *vl, *tk, *cp;
-
-       *name = NULL;
-       *value = NULL;
-
-       if (!(cp = strchr(spec, '=')))
-               return 0;                               /* no name= */
-
-       tk = xstrdup(spec);
-       vl = tk + (cp - spec);
-       *vl++ = '\0';
-
-       if (*vl == '"' || *vl == '\'') {
-               if (!(cp = strrchr(vl+1, *vl))) {
-                       free(tk);
-                       return -1;                      /* parse error */
-               }
-               vl++;
-               *cp = '\0';
-       }
-
-       *name = tk;
-       *value = vl;
-       return 0;
-}
-
 int
 is_pseudo_fs(const char *type)
 {
index c8570128753752b83ec01ee3036063a68426cc53..6d576e9d020c047b7bb2925c5297d154ec90a7e5 100644 (file)
@@ -35,8 +35,6 @@ char *xstrndup (const char *s, int n);
 char *xstrconcat3 (char *, const char *, const char *);
 char *xstrconcat4 (char *, const char *, const char *, const char *);
 
-int parse_spec(const char *spec, char **name, char **value);
-
 int is_pseudo_fs(const char *type);
 
 char *canonicalize (const char *path);
index c50c32ae56183bb984ea30996e77d3b27333f9b6..8cdb7fb1813fc03421aa61335c09034f8974b02d 100644 (file)
@@ -20,6 +20,7 @@
 #include "swap_constants.h"
 #include "nls.h"
 #include "fsprobe.h"
+#include "devname.h"
 #include "pathnames.h"
 #include "sundries.h"
 #include "swapheader.h"
@@ -362,7 +363,7 @@ do_swapon(const char *orig_special, int prio, int canonic) {
                printf(_("%s on %s\n"), progname, orig_special);
 
        if (!canonic) {
-               special = fsprobe_get_devname(orig_special);
+               special = spec_to_devname(orig_special);
                if (!special)
                        return cannot_find(orig_special);
        }
@@ -475,7 +476,7 @@ do_swapoff(const char *orig_special, int quiet, int canonic) {
                printf(_("%s on %s\n"), progname, orig_special);
 
        if (!canonic) {
-               special = fsprobe_get_devname(orig_special);
+               special = spec_to_devname(orig_special);
                if (!special)
                        return cannot_find(orig_special);
        }
@@ -546,7 +547,7 @@ swapon_all(void) {
                if (skip)
                        continue;
 
-               special = fsprobe_get_devname(fstab->mnt_fsname);
+               special = spec_to_devname(fstab->mnt_fsname);
                if (!special) {
                        if (!ifexists)
                                status |= cannot_find(fstab->mnt_fsname);
@@ -727,7 +728,7 @@ main_swapoff(int argc, char *argv[]) {
                        if (!streq(fstab->mnt_type, MNTTYPE_SWAP))
                                continue;
 
-                       special = fsprobe_get_devname(fstab->mnt_fsname);
+                       special = spec_to_devname(fstab->mnt_fsname);
                        if (!special)
                                continue;