summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--shlibs/mount/src/context_umount.c27
-rw-r--r--shlibs/mount/src/fs.c112
-rw-r--r--shlibs/mount/src/libmount.h.in6
-rw-r--r--shlibs/mount/src/libmount.sym4
-rw-r--r--shlibs/mount/src/mountP.h6
-rw-r--r--shlibs/mount/src/tab.c4
-rw-r--r--shlibs/mount/src/tab_parse.c16
-rw-r--r--shlibs/mount/src/tab_update.c2
8 files changed, 123 insertions, 54 deletions
diff --git a/shlibs/mount/src/context_umount.c b/shlibs/mount/src/context_umount.c
index 122ef7f84..bd9be6956 100644
--- a/shlibs/mount/src/context_umount.c
+++ b/shlibs/mount/src/context_umount.c
@@ -25,7 +25,7 @@ static int lookup_umount_fs(struct libmnt_context *cxt)
{
int rc;
const char *tgt;
- struct libmnt_table *mtab;
+ struct libmnt_table *mtab = NULL;
struct libmnt_fs *fs;
assert(cxt);
@@ -69,30 +69,19 @@ static int lookup_umount_fs(struct libmnt_context *cxt)
}
if (!fs) {
- DBG(CXT, mnt_debug_h(cxt, "cannot found %s in mtab", tgt));
+ DBG(CXT, mnt_debug_h(cxt, "umount: cannot found %s in mtab", tgt));
return 0;
}
/* copy from mtab to our FS description
*/
- rc = mnt_fs_set_source(cxt->fs, mnt_fs_get_source(fs));
- if (!rc)
- rc = mnt_fs_set_target(cxt->fs, mnt_fs_get_target(fs));
-
- if (!rc && !mnt_fs_get_fstype(cxt->fs))
- rc = mnt_fs_set_fstype(cxt->fs, mnt_fs_get_fstype(fs));
-
- if (!rc)
- rc = mnt_fs_set_vfs_options(cxt->fs, mnt_fs_get_vfs_options(fs));
- if (!rc)
- rc = mnt_fs_set_fs_options(cxt->fs, mnt_fs_get_fs_options(fs));
- if (!rc)
- rc = mnt_fs_set_user_options(cxt->fs, mnt_fs_get_user_options(fs));
- if (!rc)
- rc = mnt_fs_set_attributes(cxt->fs, mnt_fs_get_attributes(fs));
+ mnt_fs_set_source(cxt->fs, NULL);
+ mnt_fs_set_target(cxt->fs, NULL);
- if (!rc && mnt_fs_get_bindsrc(fs))
- rc = mnt_fs_set_bindsrc(cxt->fs, mnt_fs_get_bindsrc(fs));
+ if (!mnt_copy_fs(cxt->fs, fs)) {
+ DBG(CXT, mnt_debug_h(cxt, "umount: failed to copy FS"));
+ return -errno;
+ }
DBG(CXT, mnt_debug_h(cxt, "umount: mtab applied"));
cxt->flags |= MNT_FL_TAB_APPLIED;
diff --git a/shlibs/mount/src/fs.c b/shlibs/mount/src/fs.c
index 1477812f6..c2deff5f1 100644
--- a/shlibs/mount/src/fs.c
+++ b/shlibs/mount/src/fs.c
@@ -33,6 +33,7 @@ struct libmnt_fs *mnt_new_fs(void)
if (!fs)
return NULL;
+ /*DBG(FS, mnt_debug_h(fs, "alloc"));*/
INIT_LIST_HEAD(&fs->ents);
return fs;
}
@@ -49,6 +50,8 @@ void mnt_free_fs(struct libmnt_fs *fs)
return;
list_del(&fs->ents);
+ /*DBG(FS, mnt_debug_h(fs, "free"));*/
+
free(fs->source);
free(fs->bindsrc);
free(fs->tagname);
@@ -64,7 +67,19 @@ void mnt_free_fs(struct libmnt_fs *fs)
free(fs);
}
-static inline int cpy_str(char **dest, const char *src)
+/**
+ * mnt_reset_fs:
+ * @fs: fs pointer
+ *
+ * Resets (zeroize) @fs.
+ */
+void mnt_reset_fs(struct libmnt_fs *fs)
+{
+ if (fs)
+ memset(fs, 0, sizeof(*fs));
+}
+
+static inline int update_str(char **dest, const char *src)
{
size_t sz;
char *x;
@@ -91,57 +106,71 @@ static inline int cpy_str_at_offset(void *new, const void *old, size_t offset)
char **o = (char **) (old + offset);
char **n = (char **) (new + offset);
- return cpy_str(n, *o);
+ if (*n)
+ return 0; /* already set, not overwrite */
+
+ return update_str(n, *o);
}
/**
* mnt_copy_fs:
- * @fs: source FS
+ * @dest: destination FS
+ * @src: source FS
+ *
+ * If @dest is NULL, then a new FS is allocated, if any @dest field is already
+ * set then the field is NOT overwrited.
*
* This function does not copy userdata (se mnt_fs_set_userdata()). A new copy is
* not linked with any existing mnt_tab.
*
- * Returns: copy of @fs
+ * Returns: @dest or NULL in case of error
*/
-struct libmnt_fs *mnt_copy_fs(const struct libmnt_fs *fs)
+struct libmnt_fs *mnt_copy_fs(struct libmnt_fs *dest,
+ const struct libmnt_fs *src)
{
- struct libmnt_fs *n = mnt_new_fs();
+ const struct libmnt_fs *org = dest;
- if (!n)
- return NULL;
+ if (!dest) {
+ dest = mnt_new_fs();
+ if (!dest)
+ return NULL;
+ }
- n->id = fs->id;
- n->parent = fs->parent;
- n->devno = fs->devno;
+ /*DBG(FS, mnt_debug_h(dest, "copy from %p", src));*/
- if (cpy_str_at_offset(n, fs, offsetof(struct libmnt_fs, source)))
+ dest->id = src->id;
+ dest->parent = src->parent;
+ dest->devno = src->devno;
+
+ if (cpy_str_at_offset(dest, src, offsetof(struct libmnt_fs, source)))
goto err;
- if (cpy_str_at_offset(n, fs, offsetof(struct libmnt_fs, tagname)))
+ if (cpy_str_at_offset(dest, src, offsetof(struct libmnt_fs, tagname)))
goto err;
- if (cpy_str_at_offset(n, fs, offsetof(struct libmnt_fs, tagval)))
+ if (cpy_str_at_offset(dest, src, offsetof(struct libmnt_fs, tagval)))
goto err;
- if (cpy_str_at_offset(n, fs, offsetof(struct libmnt_fs, root)))
+ if (cpy_str_at_offset(dest, src, offsetof(struct libmnt_fs, root)))
goto err;
- if (cpy_str_at_offset(n, fs, offsetof(struct libmnt_fs, target)))
+ if (cpy_str_at_offset(dest, src, offsetof(struct libmnt_fs, target)))
goto err;
- if (cpy_str_at_offset(n, fs, offsetof(struct libmnt_fs, fstype)))
+ if (cpy_str_at_offset(dest, src, offsetof(struct libmnt_fs, fstype)))
goto err;
- if (cpy_str_at_offset(n, fs, offsetof(struct libmnt_fs, vfs_optstr)))
+ if (cpy_str_at_offset(dest, src, offsetof(struct libmnt_fs, vfs_optstr)))
goto err;
- if (cpy_str_at_offset(n, fs, offsetof(struct libmnt_fs, fs_optstr)))
+ if (cpy_str_at_offset(dest, src, offsetof(struct libmnt_fs, fs_optstr)))
goto err;
- if (cpy_str_at_offset(n, fs, offsetof(struct libmnt_fs, user_optstr)))
+ if (cpy_str_at_offset(dest, src, offsetof(struct libmnt_fs, user_optstr)))
goto err;
- if (cpy_str_at_offset(n, fs, offsetof(struct libmnt_fs, attrs)))
+ if (cpy_str_at_offset(dest, src, offsetof(struct libmnt_fs, attrs)))
goto err;
- n->freq = fs->freq;
- n->passno = fs->passno;
- n->flags = fs->flags;
+ dest->freq = src->freq;
+ dest->passno = src->passno;
+ dest->flags = src->flags;
- return n;
+ return dest;
err:
- mnt_free_fs(n);
+ if (!org)
+ mnt_free_fs(dest);
return NULL;
}
@@ -400,6 +429,31 @@ int mnt_fs_set_target(struct libmnt_fs *fs, const char *target)
return 0;
}
+int __mnt_fs_get_flags(struct libmnt_fs *fs)
+{
+ return fs ? fs->flags : 0;
+}
+
+int __mnt_fs_set_flags(struct libmnt_fs *fs, int flags)
+{
+ if (fs) {
+ fs->flags = flags;
+ return 0;
+ }
+ return -EINVAL;
+}
+
+/**
+ * mnt_fs_is_kernel:
+ * @fs: filesystem
+ *
+ * Returns: 1 if the filesystem description is read from kernel e.g. /proc/mounts.
+ */
+int mnt_fs_is_kernel(struct libmnt_fs *fs)
+{
+ return __mnt_fs_get_flags(fs) & MNT_FS_KERNEL;
+}
+
/**
* mnt_fs_get_fstype:
* @fs: fstab/mtab/mountinfo entry pointer
@@ -1400,11 +1454,11 @@ int mnt_fs_to_mntent(struct libmnt_fs *fs, struct mntent **mnt)
return -ENOMEM;
}
- if ((rc = cpy_str(&m->mnt_fsname, mnt_fs_get_source(fs))))
+ if ((rc = update_str(&m->mnt_fsname, mnt_fs_get_source(fs))))
goto err;
- if ((rc = cpy_str(&m->mnt_dir, mnt_fs_get_target(fs))))
+ if ((rc = update_str(&m->mnt_dir, mnt_fs_get_target(fs))))
goto err;
- if ((rc = cpy_str(&m->mnt_type, mnt_fs_get_fstype(fs))))
+ if ((rc = update_str(&m->mnt_type, mnt_fs_get_fstype(fs))))
goto err;
errno = 0;
diff --git a/shlibs/mount/src/libmount.h.in b/shlibs/mount/src/libmount.h.in
index aa00b938d..1831ed18a 100644
--- a/shlibs/mount/src/libmount.h.in
+++ b/shlibs/mount/src/libmount.h.in
@@ -199,7 +199,9 @@ extern int mnt_lock_file(struct libmnt_lock *ml);
/* fs.c */
extern struct libmnt_fs *mnt_new_fs(void);
extern void mnt_free_fs(struct libmnt_fs *fs);
-extern struct libmnt_fs *mnt_copy_fs(const struct libmnt_fs *fs);
+extern void mnt_reset_fs(struct libmnt_fs *fs);
+extern struct libmnt_fs *mnt_copy_fs(struct libmnt_fs *dest,
+ const struct libmnt_fs *src);
extern void *mnt_fs_get_userdata(struct libmnt_fs *fs);
extern int mnt_fs_set_userdata(struct libmnt_fs *fs, void *data);
extern const char *mnt_fs_get_source(struct libmnt_fs *fs);
@@ -263,6 +265,8 @@ extern int mnt_fs_match_fstype(struct libmnt_fs *fs, const char *types);
extern int mnt_fs_match_options(struct libmnt_fs *fs, const char *options);
extern int mnt_fs_print_debug(struct libmnt_fs *fs, FILE *file);
+extern int mnt_fs_is_kernel(struct libmnt_fs *fs);
+
extern void mnt_free_mntent(struct mntent *mnt);
extern int mnt_fs_to_mntent(struct libmnt_fs *fs, struct mntent **mnt);
diff --git a/shlibs/mount/src/libmount.sym b/shlibs/mount/src/libmount.sym
index 2481b4931..d0ebfd728 100644
--- a/shlibs/mount/src/libmount.sym
+++ b/shlibs/mount/src/libmount.sym
@@ -36,6 +36,7 @@ global:
mnt_context_get_status;
mnt_context_get_target;
mnt_context_get_user_mflags;
+ mnt_context_helper_setopt;
mnt_context_init_helper;
mnt_context_is_fake;
mnt_context_is_force;
@@ -46,7 +47,6 @@ global:
mnt_context_is_sloppy;
mnt_context_is_verbose;
mnt_context_mount;
- mnt_context_helper_setopt;
mnt_context_prepare_mount;
mnt_context_prepare_umount;
mnt_context_set_cache;
@@ -98,6 +98,7 @@ global:
mnt_fs_get_userdata;
mnt_fs_get_user_options;
mnt_fs_get_vfs_options;
+ mnt_fs_is_kernel;
mnt_fs_match_fstype;
mnt_fs_match_options;
mnt_fs_match_source;
@@ -157,6 +158,7 @@ global:
mnt_optstr_set_option;
mnt_parse_version_string;
mnt_reset_context;
+ mnt_reset_fs;
mnt_reset_iter;
mnt_resolve_path;
mnt_resolve_spec;
diff --git a/shlibs/mount/src/mountP.h b/shlibs/mount/src/mountP.h
index a38aa10e4..aeceb7f96 100644
--- a/shlibs/mount/src/mountP.h
+++ b/shlibs/mount/src/mountP.h
@@ -193,6 +193,12 @@ struct libmnt_fs {
#define MNT_FS_PSEUDO (1 << 1) /* pseudo filesystem */
#define MNT_FS_NET (1 << 2) /* network filesystem */
#define MNT_FS_SWAP (1 << 3) /* swap device */
+#define MNT_FS_KERNEL (1 << 4) /* data from /proc/{mounts,self/mountinfo} */
+#define MNT_FS_MERGED (1 << 5) /* already merged data from /dev/.mount/utab */
+
+extern int __mnt_fs_get_flags(struct libmnt_fs *fs);
+extern int __mnt_fs_set_flags(struct libmnt_fs *fs, int flags);
+
/*
* mtab/fstab/mountinfo file
diff --git a/shlibs/mount/src/tab.c b/shlibs/mount/src/tab.c
index ab4117683..2d2e72fd1 100644
--- a/shlibs/mount/src/tab.c
+++ b/shlibs/mount/src/tab.c
@@ -424,7 +424,7 @@ struct libmnt_fs *mnt_table_find_target(struct libmnt_table *tb, const char *pat
if (!tb || !path)
return NULL;
- DBG(TAB, mnt_debug_h(tb, "lookup target: %s", path));
+ DBG(TAB, mnt_debug_h(tb, "lookup TARGET: %s", path));
/* native @target */
mnt_reset_iter(&itr, direction);
@@ -733,7 +733,7 @@ int test_copy_fs(struct libmnt_test *ts, int argc, char *argv[])
printf("ORIGINAL:\n");
mnt_fs_print_debug(fs, stdout);
- fs = mnt_copy_fs(fs);
+ fs = mnt_copy_fs(NULL, fs);
if (!fs)
goto done;
diff --git a/shlibs/mount/src/tab_parse.c b/shlibs/mount/src/tab_parse.c
index 42b108ff8..4eb32eb63 100644
--- a/shlibs/mount/src/tab_parse.c
+++ b/shlibs/mount/src/tab_parse.c
@@ -140,6 +140,7 @@ static int mnt_parse_mountinfo_line(struct libmnt_fs *fs, char *s)
&fs->fs_optstr);
if (rc == 10) {
+ fs->flags |= MNT_FS_KERNEL;
fs->devno = makedev(maj, min);
unmangle_string(fs->root);
@@ -335,6 +336,7 @@ int mnt_table_parse_stream(struct libmnt_table *tb, FILE *f, const char *filenam
{
int nlines = 0;
int rc = -1;
+ int flags = 0;
assert(tb);
assert(f);
@@ -342,6 +344,12 @@ int mnt_table_parse_stream(struct libmnt_table *tb, FILE *f, const char *filenam
DBG(TAB, mnt_debug_h(tb, "%s: start parsing", filename));
+ /* necessary for /proc/mounts only, the /proc/self/mountinfo
+ * parser sets propertly the flag
+ */
+ if (filename && strcmp(filename, _PATH_PROC_MOUNTS) == 0)
+ flags = MNT_FS_KERNEL;
+
while (!feof(f)) {
struct libmnt_fs *fs = mnt_new_fs();
@@ -349,8 +357,10 @@ int mnt_table_parse_stream(struct libmnt_table *tb, FILE *f, const char *filenam
goto err;
rc = mnt_table_parse_next(tb, f, fs, filename, &nlines);
- if (!rc)
+ if (!rc) {
rc = mnt_table_add_fs(tb, fs);
+ fs->flags |= flags;
+ }
if (rc) {
mnt_free_fs(fs);
if (rc == 1)
@@ -631,6 +641,9 @@ static struct libmnt_fs *mnt_table_merge_user_fs(struct libmnt_table *tb, struct
*t = mnt_fs_get_target(fs),
*r = mnt_fs_get_root(fs);
+ if (fs->flags & MNT_FS_MERGED)
+ continue;
+
if (s && t && r && !strcmp(t, target) &&
!strcmp(s, src) && !strcmp(r, root))
break;
@@ -641,6 +654,7 @@ static struct libmnt_fs *mnt_table_merge_user_fs(struct libmnt_table *tb, struct
mnt_fs_append_user_options(fs, optstr);
mnt_fs_append_attributes(fs, attrs);
mnt_fs_set_bindsrc(fs, mnt_fs_get_bindsrc(uf));
+ fs->flags |= MNT_FS_MERGED;
DBG(TAB, mnt_debug_h(tb, "found fs:"));
DBG(TAB, mnt_fs_print_debug(fs, stderr));
diff --git a/shlibs/mount/src/tab_update.c b/shlibs/mount/src/tab_update.c
index 60a628a4a..d66b64f94 100644
--- a/shlibs/mount/src/tab_update.c
+++ b/shlibs/mount/src/tab_update.c
@@ -324,7 +324,7 @@ static int utab_new_entry(struct libmnt_fs *fs, unsigned long mountflags, struct
}
/* allocate the entry */
- *ent = mnt_copy_fs(fs);
+ *ent = mnt_copy_fs(NULL, fs);
if (!*ent) {
rc = -ENOMEM;
goto err;