summaryrefslogtreecommitdiffstats
path: root/libmount
diff options
context:
space:
mode:
authorKarel Zak2013-11-04 12:45:33 +0100
committerKarel Zak2013-11-04 14:24:41 +0100
commit7e0c06194f5e65eb2a9ae38515d78f4ef301c809 (patch)
tree9016b997f030a5f288ed7a5b48b399c5e80624ef /libmount
parentlibmount: allow to use -s (sloppy) for all external helpers (diff)
downloadkernel-qcow2-util-linux-7e0c06194f5e65eb2a9ae38515d78f4ef301c809.tar.gz
kernel-qcow2-util-linux-7e0c06194f5e65eb2a9ae38515d78f4ef301c809.tar.xz
kernel-qcow2-util-linux-7e0c06194f5e65eb2a9ae38515d78f4ef301c809.zip
libmount: update utab after successful extern helper mount
This patch allows to maintain private utab libmount file also for external mount/umount helpers that are not linked with libmount. The libmount check if utab has been updated after successful extern helper execution (status=0). If not then the file is updated. This patch affects only 'user' fstab mount option. So, for example with suid mount.cifs you can use: //server/foo /mnt cifs username=foo,noauto,user Signed-off-by: Karel Zak <kzak@redhat.com>
Diffstat (limited to 'libmount')
-rw-r--r--libmount/src/context.c30
-rw-r--r--libmount/src/mountP.h2
-rw-r--r--libmount/src/tab_update.c62
3 files changed, 84 insertions, 10 deletions
diff --git a/libmount/src/context.c b/libmount/src/context.c
index 5a88bcdcc..2ef3d3001 100644
--- a/libmount/src/context.c
+++ b/libmount/src/context.c
@@ -1725,10 +1725,6 @@ int mnt_context_prepare_update(struct libmnt_context *cxt)
DBG(CXT, mnt_debug_h(cxt, "skip update: NOMTAB flag"));
return 0;
}
- if (cxt->helper) {
- DBG(CXT, mnt_debug_h(cxt, "skip update: external helper"));
- return 0;
- }
if (!cxt->mtab_writable && !cxt->utab_writable) {
DBG(CXT, mnt_debug_h(cxt, "skip update: no writable destination"));
return 0;
@@ -1777,16 +1773,30 @@ int mnt_context_update_tabs(struct libmnt_context *cxt)
DBG(CXT, mnt_debug_h(cxt, "don't update: NOMTAB flag"));
return 0;
}
- if (cxt->helper) {
- DBG(CXT, mnt_debug_h(cxt, "don't update: external helper"));
- return 0;
- }
if (!cxt->update || !mnt_update_is_ready(cxt->update)) {
DBG(CXT, mnt_debug_h(cxt, "don't update: no update prepared"));
return 0;
}
- if (cxt->syscall_status) {
- DBG(CXT, mnt_debug_h(cxt, "don't update: syscall failed/not called"));
+
+ /* check utab update when external helper executed */
+ if (mnt_context_helper_executed(cxt)
+ && mnt_context_get_helper_status(cxt) == 0
+ && cxt->utab_writable) {
+
+ if (mnt_update_already_done(cxt->update, cxt->lock)) {
+ DBG(CXT, mnt_debug_h(cxt, "don't update: error evaluate or already updated"));
+ return 0;
+ }
+ } else if (cxt->helper) {
+ DBG(CXT, mnt_debug_h(cxt, "don't update: external helper"));
+ return 0;
+ }
+
+ if (cxt->syscall_status != 0
+ && !(mnt_context_helper_executed(cxt) &&
+ mnt_context_get_helper_status(cxt) == 0)) {
+
+ DBG(CXT, mnt_debug_h(cxt, "don't update: syscall/helper failed/not called"));
return 0;
}
diff --git a/libmount/src/mountP.h b/libmount/src/mountP.h
index 9362c0042..adc245af4 100644
--- a/libmount/src/mountP.h
+++ b/libmount/src/mountP.h
@@ -460,5 +460,7 @@ extern int mnt_context_set_tabfilter(struct libmnt_context *cxt,
/* tab_update.c */
extern int mnt_update_set_filename(struct libmnt_update *upd,
const char *filename, int userspace_only);
+extern int mnt_update_already_done(struct libmnt_update *upd,
+ struct libmnt_lock *lc);
#endif /* _LIBMOUNT_PRIVATE_H */
diff --git a/libmount/src/tab_update.c b/libmount/src/tab_update.c
index 13f6f6ebe..bbe0cb2d7 100644
--- a/libmount/src/tab_update.c
+++ b/libmount/src/tab_update.c
@@ -286,6 +286,7 @@ int mnt_update_force_rdonly(struct libmnt_update *upd, int rdonly)
return rc;
}
+
/*
* Allocates an utab entry (upd->fs) for mount/remount. This function should be
* called *before* mount(2) syscall. The @fs is used as a read-only template.
@@ -873,6 +874,67 @@ int mnt_update_table(struct libmnt_update *upd, struct libmnt_lock *lc)
return rc;
}
+int mnt_update_already_done(struct libmnt_update *upd, struct libmnt_lock *lc)
+{
+ struct libmnt_table *tb = NULL;
+ struct libmnt_lock *lc0 = lc;
+ int rc = 0;
+
+ if (!upd || !upd->filename || (!upd->fs && !upd->target))
+ return -EINVAL;
+
+ DBG(UPDATE, mnt_debug_h(upd, "%s: checking for previous update", upd->filename));
+
+ if (!lc) {
+ lc = mnt_new_lock(upd->filename, 0);
+ if (lc)
+ mnt_lock_block_signals(lc, TRUE);
+ }
+ if (lc && upd->userspace_only)
+ mnt_lock_use_simplelock(lc, TRUE); /* use flock */
+ if (lc)
+ rc = mnt_lock_file(lc);
+ if (rc)
+ goto done;
+
+ tb = __mnt_new_table_from_file(upd->filename,
+ upd->userspace_only ? MNT_FMT_UTAB : MNT_FMT_MTAB);
+ if (lc)
+ mnt_unlock_file(lc);
+ if (!tb)
+ goto done;
+
+ if (upd->fs) {
+ /* mount */
+ const char *tgt = mnt_fs_get_target(upd->fs);
+ const char *src = mnt_fs_get_bindsrc(upd->fs) ?
+ mnt_fs_get_bindsrc(upd->fs) :
+ mnt_fs_get_source(upd->fs);
+
+ if (mnt_table_find_pair(tb, src, tgt, MNT_ITER_BACKWARD)) {
+ DBG(UPDATE, mnt_debug_h(upd, "%s: found %s %s",
+ upd->filename, src, tgt));
+ rc = 1;
+ }
+ } else if (upd->target) {
+ /* umount */
+ if (!mnt_table_find_target(tb, upd->target, MNT_ITER_BACKWARD)) {
+ DBG(UPDATE, mnt_debug_h(upd, "%s: not-found (umounted) %s",
+ upd->filename, upd->target));
+ rc = 1;
+ }
+ }
+
+ mnt_unref_table(tb);
+done:
+ if (lc && lc != lc0)
+ mnt_free_lock(lc);
+ DBG(UPDATE, mnt_debug_h(upd, "%s: previous update check done [rc=%d]",
+ upd->filename, rc));
+ return rc;
+}
+
+
#ifdef TEST_PROGRAM
static int update(const char *target, struct libmnt_fs *fs, unsigned long mountflags)