]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
libmount: update utab after successful extern helper mount
authorKarel Zak <kzak@redhat.com>
Mon, 4 Nov 2013 11:45:33 +0000 (12:45 +0100)
committerKarel Zak <kzak@redhat.com>
Mon, 4 Nov 2013 13:24:41 +0000 (14:24 +0100)
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>
libmount/src/context.c
libmount/src/mountP.h
libmount/src/tab_update.c

index 5a88bcdccd2e132a93061c4f65686a95b308597f..2ef3d3001ec964d00ca893f95031c0f4bcfcfa94 100644 (file)
@@ -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;
        }
 
index 9362c0042e5f35029a2cfb1eae02a14677c02510..adc245af4a949662d0fbab121396dce159b4adde 100644 (file)
@@ -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 */
index 13f6f6ebec9bd6c4c9ca686b4f091728851966ea..bbe0cb2d710f5359b484953923b88bf8e6760920 100644 (file)
@@ -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)