summaryrefslogtreecommitdiffstats
path: root/shlibs
diff options
context:
space:
mode:
authorKarel Zak2010-09-28 01:26:31 +0200
committerKarel Zak2011-01-03 12:28:43 +0100
commit8485e7093bf506e3a4e13ffbe59ba83ef6853a32 (patch)
tree249f48e342df6956b2a0f2a5ff2e4cc977dbf4ef /shlibs
parentlibmount: better permissions and optstr evaliation (diff)
downloadkernel-qcow2-util-linux-8485e7093bf506e3a4e13ffbe59ba83ef6853a32.tar.gz
kernel-qcow2-util-linux-8485e7093bf506e3a4e13ffbe59ba83ef6853a32.tar.xz
kernel-qcow2-util-linux-8485e7093bf506e3a4e13ffbe59ba83ef6853a32.zip
libmount: add FS detection
Signed-off-by: Karel Zak <kzak@redhat.com>
Diffstat (limited to 'shlibs')
-rw-r--r--shlibs/mount/src/cache.c112
-rw-r--r--shlibs/mount/src/context.c36
-rw-r--r--shlibs/mount/src/fs.c30
-rw-r--r--shlibs/mount/src/mount.h.in1
-rw-r--r--shlibs/mount/src/mount.sym1
5 files changed, 151 insertions, 29 deletions
diff --git a/shlibs/mount/src/cache.c b/shlibs/mount/src/cache.c
index d7a679b5b..fe05febaa 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;
}
@@ -360,6 +400,38 @@ char *mnt_cache_find_tag_value(mnt_cache *cache,
}
/**
+ * 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
* @cache: cache for results or NULL
@@ -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 61b5d26fc..664ef9182 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 8c7baa266..140bdb19a 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 37ff33666..faa86bfe0 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 bb3ac2421..bb1ae4f92 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;