From 8485e7093bf506e3a4e13ffbe59ba83ef6853a32 Mon Sep 17 00:00:00 2001 From: Karel Zak Date: Tue, 28 Sep 2010 01:26:31 +0200 Subject: [PATCH] libmount: add FS detection Signed-off-by: Karel Zak --- shlibs/mount/src/cache.c | 112 +++++++++++++++++++++++++++++++----- shlibs/mount/src/context.c | 36 +++++++++++- shlibs/mount/src/fs.c | 30 +++++----- shlibs/mount/src/mount.h.in | 1 + shlibs/mount/src/mount.sym | 1 + 5 files changed, 151 insertions(+), 29 deletions(-) diff --git a/shlibs/mount/src/cache.c b/shlibs/mount/src/cache.c index d7a679b5..fe05feba 100644 --- a/shlibs/mount/src/cache.c +++ b/shlibs/mount/src/cache.c @@ -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 } }; diff --git a/shlibs/mount/src/context.c b/shlibs/mount/src/context.c index 61b5d26f..664ef918 100644 --- a/shlibs/mount/src/context.c +++ b/shlibs/mount/src/context.c @@ -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) diff --git a/shlibs/mount/src/fs.c b/shlibs/mount/src/fs.c index 8c7baa26..140bdb19 100644 --- a/shlibs/mount/src/fs.c +++ b/shlibs/mount/src/fs.c @@ -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); diff --git a/shlibs/mount/src/mount.h.in b/shlibs/mount/src/mount.h.in index 37ff3366..faa86bfe 100644 --- a/shlibs/mount/src/mount.h.in +++ b/shlibs/mount/src/mount.h.in @@ -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, diff --git a/shlibs/mount/src/mount.sym b/shlibs/mount/src/mount.sym index bb3ac242..bb1ae4f9 100644 --- a/shlibs/mount/src/mount.sym +++ b/shlibs/mount/src/mount.sym @@ -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; -- 2.39.5