]> err.no Git - util-linux/commitdiff
libmount: add FS detection
authorKarel Zak <kzak@redhat.com>
Mon, 27 Sep 2010 23:26:31 +0000 (01:26 +0200)
committerKarel Zak <kzak@redhat.com>
Mon, 3 Jan 2011 11:28:43 +0000 (12:28 +0100)
Signed-off-by: Karel Zak <kzak@redhat.com>
shlibs/mount/src/cache.c
shlibs/mount/src/context.c
shlibs/mount/src/fs.c
shlibs/mount/src/mount.h.in
shlibs/mount/src/mount.sym

index d7a679b5b642bfadd5635818039c9a659aeddaaf..fe05febaa03b3952fd9d47a4f5439a344d8d16e0 100644 (file)
@@ -60,6 +60,9 @@ struct _mnt_cache {
         *    better to reuse the blkid_cache.
         */
        blkid_cache             bc;
+       blkid_probe             pr;
+
+       char                    *filename;
 };
 
 /**
@@ -98,8 +101,10 @@ void mnt_free_cache(mnt_cache *cache)
                free(e->native);
        }
        free(cache->ents);
+       free(cache->filename);
        if (cache->bc)
                blkid_put_cache(cache->bc);
+       blkid_free_probe(cache->pr);
        free(cache);
 }
 
@@ -233,6 +238,41 @@ const char *mnt_cache_find_tag(mnt_cache *cache,
        return NULL;
 }
 
+/*
+ * returns (in @res) blkid prober, the @cache argument is optional
+ */
+static int mnt_cache_get_probe(mnt_cache *cache, const char *devname,
+                          blkid_probe *res)
+{
+       blkid_probe pr = cache ? cache->pr : NULL;
+
+       assert(devname);
+       assert(res);
+
+       if (cache && cache->pr && strcmp(devname, cache->filename)) {
+               blkid_free_probe(cache->pr);
+               free(cache->filename);
+               cache->filename = NULL;
+               pr = cache->pr = NULL;
+       }
+
+       if (!pr) {
+               pr = blkid_new_probe_from_filename(devname);
+               if (!pr)
+                       return -1;
+               if (cache) {
+                       cache->pr = pr;
+                       cache->filename = strdup(devname);
+                       if (!cache->filename)
+                               return -ENOMEM;
+               }
+
+       }
+
+       *res = pr;
+       return 0;
+}
+
 /**
  * mnt_cache_read_tags
  * @cache: pointer to mnt_cache instance
@@ -245,9 +285,9 @@ const char *mnt_cache_find_tag(mnt_cache *cache,
  */
 int mnt_cache_read_tags(mnt_cache *cache, const char *devname)
 {
-       int i, ntags = 0;
-       static blkid_probe pr;
-       const char *tags[] = { "LABEL", "UUID" };
+       int i, ntags = 0, rc;
+       blkid_probe pr;
+       const char *tags[] = { "LABEL", "UUID", "TYPE" };
 
        assert(cache);
        assert(devname);
@@ -267,16 +307,17 @@ int mnt_cache_read_tags(mnt_cache *cache, const char *devname)
                        return 0;
        }
 
-       pr = blkid_new_probe_from_filename(devname);
-       if (!pr)
-               return -1;
+       rc = mnt_cache_get_probe(cache, devname, &pr);
+       if (rc)
+               return rc;
 
-       blkid_probe_enable_superblocks(pr, 1);
+       blkid_probe_enable_superblocks(cache->pr, 1);
 
-       blkid_probe_set_superblocks_flags(pr,
-                       BLKID_SUBLKS_LABEL | BLKID_SUBLKS_UUID);
+       blkid_probe_set_superblocks_flags(cache->pr,
+                       BLKID_SUBLKS_LABEL | BLKID_SUBLKS_UUID |
+                       BLKID_SUBLKS_TYPE);
 
-       if (blkid_do_safeprobe(pr))
+       if (blkid_do_safeprobe(cache->pr))
                goto error;
 
        DBG(CACHE, mnt_debug_h(cache, "reading tags for: %s", devname));
@@ -285,7 +326,7 @@ int mnt_cache_read_tags(mnt_cache *cache, const char *devname)
                const char *data;
                char *dev;
 
-               if (blkid_probe_lookup_value(pr, tags[i], &data, NULL))
+               if (blkid_probe_lookup_value(cache->pr, tags[i], &data, NULL))
                        continue;
                if (mnt_cache_find_tag(cache, tags[i], data))
                        continue; /* already cached */
@@ -303,7 +344,6 @@ int mnt_cache_read_tags(mnt_cache *cache, const char *devname)
 
        return ntags ? 0 : 1;
 error:
-       blkid_free_probe(pr);
        return -1;
 }
 
@@ -359,6 +399,38 @@ char *mnt_cache_find_tag_value(mnt_cache *cache,
        return NULL;
 }
 
+/**
+ * mnt_get_fstype:
+ * @devname: device name
+ * @cache: cache for results or NULL
+ *
+ * Returns: fileststem type or NULL in case of error. The result has to be
+ * deallocated by free() if @cache is NULL.
+ */
+char *mnt_get_fstype(const char *devname, mnt_cache *cache)
+{
+       blkid_probe pr;
+       const char *data;
+       char *type = NULL;
+
+       if (cache)
+               return mnt_cache_find_tag_value(cache, devname, "TYPE");
+
+       if (mnt_cache_get_probe(NULL, devname, &pr))
+               return NULL;
+
+       blkid_probe_enable_superblocks(pr, 1);
+
+       blkid_probe_set_superblocks_flags(pr, BLKID_SUBLKS_TYPE);
+
+       if (!blkid_do_safeprobe(pr) &&
+           !blkid_probe_lookup_value(pr, "TYPE", &data, NULL))
+               type = strdup(data);
+
+       blkid_free_probe(pr);
+       return type;
+}
+
 /**
  * mnt_resolve_path:
  * @path: "native" path
@@ -526,6 +598,7 @@ int test_read_tags(struct mtest *ts, int argc, char *argv[])
 {
        char line[BUFSIZ];
        mnt_cache *cache;
+       int i;
 
        cache = mnt_new_cache();
        if (!cache)
@@ -537,6 +610,9 @@ int test_read_tags(struct mtest *ts, int argc, char *argv[])
                if (line[sz - 1] == '\n')
                        line[sz - 1] = '\0';
 
+               if (!strcmp(line, "quit"))
+                       break;
+
                if (*line == '/') {
                        if (mnt_cache_read_tags(cache, line) < 0)
                                fprintf(stderr, "%s: read tags faild\n", line);
@@ -557,6 +633,16 @@ int test_read_tags(struct mtest *ts, int argc, char *argv[])
                                printf("%s: not cached\n", line);
                }
        }
+
+       for (i = 0; i < cache->nents; i++) {
+               struct mnt_cache_entry *e = &cache->ents[i];
+               if (!(e->flag & MNT_CACHE_ISTAG))
+                       continue;
+
+               printf("%15s : %5s : %s\n", e->real, e->native,
+                               e->native + strlen(e->native) + 1);
+       }
+
        mnt_free_cache(cache);
        return 0;
 
@@ -567,7 +653,7 @@ int main(int argc, char *argv[])
        struct mtest ts[] = {
                { "--resolve-path", test_resolve_path, "  resolve paths from stdin" },
                { "--resolve-spec", test_resolve_spec, "  evaluate specs from stdin" },
-               { "--read-tags", test_read_tags,       "  read devname or TAG from stdin" },
+               { "--read-tags", test_read_tags,       "  read devname or TAG from stdin (\"quit\" to exit)" },
                { NULL }
        };
 
index 61b5d26fc92d17cefa99d282efd1f065854579b3..664ef91826058c8e06defdc0842daf07bf44cbda 100644 (file)
@@ -1090,7 +1090,41 @@ static int mnt_context_prepare_srcpath(mnt_context *cxt)
 
 static int mnt_context_detect_fstype(mnt_context *cxt)
 {
-       return 0; /* TODO */
+       char *type = NULL;
+
+       if (!cxt || !cxt->fs)
+               return -EINVAL;
+
+       if (cxt->mountflags & (MS_BIND | MS_MOVE | MS_PROPAGATION)) {
+               mnt_fs_set_fstype(cxt->fs, "none");
+               return 0;
+       }
+
+       type = (char *) mnt_fs_get_fstype(cxt->fs);
+       if (type && !strcmp(type, "auto")) {
+               mnt_fs_set_fstype(cxt->fs, NULL);
+               type = NULL;
+       }
+
+       if (!type && !(cxt->flags & MS_REMOUNT)) {
+               mnt_cache *cache;
+               const char *dev = mnt_fs_get_srcpath(cxt->fs);
+
+               if (!dev)
+                       return -EINVAL;
+
+               cache = mnt_context_get_cache(cxt);
+               type = mnt_get_fstype(dev, cache);
+
+               if (!type)
+                       return -EINVAL;
+               mnt_fs_set_fstype(cxt->fs, type);
+               if (!cache)
+                       free(type);     /* type is not cached */
+               return 0;
+       }
+
+       return 0;
 }
 
 static int mnt_context_merge_mountflags(mnt_context *cxt)
index 8c7baa266840b6eb5947628e5e3f9e2d19fca0bc..140bdb19a29b9e519e7985064d5f98966848ef04 100644 (file)
@@ -340,9 +340,6 @@ int __mnt_fs_set_fstype_ptr(mnt_fs *fs, char *fstype)
 {
        assert(fs);
 
-       if (!fstype)
-               return -EINVAL;
-
        if (fstype != fs->fstype)
                free(fs->fstype);
 
@@ -351,13 +348,14 @@ int __mnt_fs_set_fstype_ptr(mnt_fs *fs, char *fstype)
        fs->flags &= ~MNT_FS_NET;
 
        /* save info about pseudo filesystems */
-       if (mnt_fstype_is_pseudofs(fs->fstype))
-               fs->flags |= MNT_FS_PSEUDO;
-       else if (mnt_fstype_is_netfs(fs->fstype))
-               fs->flags |= MNT_FS_NET;
-       else if (!strcmp(fs->fstype, "swap"))
-               fs->flags |= MNT_FS_SWAP;
-
+       if (fs->fstype) {
+               if (mnt_fstype_is_pseudofs(fs->fstype))
+                       fs->flags |= MNT_FS_PSEUDO;
+               else if (mnt_fstype_is_netfs(fs->fstype))
+                       fs->flags |= MNT_FS_NET;
+               else if (!strcmp(fs->fstype, "swap"))
+                       fs->flags |= MNT_FS_SWAP;
+       }
        return 0;
 }
 
@@ -372,14 +370,16 @@ int __mnt_fs_set_fstype_ptr(mnt_fs *fs, char *fstype)
  */
 int mnt_fs_set_fstype(mnt_fs *fs, const char *fstype)
 {
-       char *p;
+       char *p = NULL;
        int rc;
 
-       if (!fs || !fstype)
+       if (!fs)
                return -EINVAL;
-       p = strdup(fstype);
-       if (!p)
-               return -ENOMEM;
+       if (fstype) {
+               p = strdup(fstype);
+               if (!p)
+                       return -ENOMEM;
+       }
        rc =  __mnt_fs_set_fstype_ptr(fs, p);
        if (rc)
                free(p);
index 37ff33666c87a1c2279c116fb20088d39585c049..faa86bfe0ada30a61f7ae89fc284b0af612eaac5 100644 (file)
@@ -149,6 +149,7 @@ extern char *mnt_cache_find_tag_value(mnt_cache *cache,
 extern char *mnt_resolve_path(const char *path, mnt_cache *cache);
 extern char *mnt_resolve_tag(const char *token, const char *value, mnt_cache *cache);
 extern char *mnt_resolve_spec(const char *spec, mnt_cache *cache);
+extern char *mnt_get_fstype(const char *devname, mnt_cache *cache);
 
 /* optstr.c */
 extern int mnt_optstr_next_option(char **optstr, char **name, size_t *namesz,
index bb3ac24211ec28c6ed32d686aee750f72dc3fe65..bb1ae4f92d91d275559f125324de03e58b463e33 100644 (file)
@@ -90,6 +90,7 @@ global:
        mnt_resolve_path;
        mnt_resolve_spec;
        mnt_resolve_tag;
+       mnt_get_fstype;
        mnt_split_optstr;
        mnt_tab_add_fs;
        mnt_tab_find_next_fs;