- add command line option to override is running check. - don't use proc fs for is running check. - fix fail on included browse map not found. - fix incorrect multi source messages. - clear stale flag on map read. - fix proximity other rpc ping timeout. - refactor mount request vars code. - make handle_mounts startup condition distinct. - fix submount shutdown handling. - try not to block on expire. - add configuration paramter UMOUNT_WAIT. - fix multi mount race. - fix nfs4 colon escape handling. - check replicated list after probe. - add replicated server selection debug logging. - update replicated server selection documentation. - use /dev/urandom instead of /dev/random. - check for mtab pointing to /proc/mounts. - fix interface config buffer size. - fix percent hack heap corruption.
1218 lines
31 KiB
Diff
1218 lines
31 KiB
Diff
autofs-5.0.3 - refactor mount request vars
|
|
|
|
From: Ian Kent <raven@themaw.net>
|
|
|
|
There is code duplication between the direct and indirect mount
|
|
modules that sets up the variables available to maps. This patch
|
|
reorganizes and moves that code to a common location.
|
|
|
|
Signed-off-by: Ian Kent <raven@themaw.net>
|
|
---
|
|
|
|
daemon/direct.c | 131 ----------------
|
|
daemon/indirect.c | 131 ----------------
|
|
include/automount.h | 56 -------
|
|
include/mounts.h | 91 +++++++++++
|
|
include/parse_subs.h | 3
|
|
lib/mounts.c | 410 ++++++++++++++++++++++++++++++++++++++++++++------
|
|
lib/parse_subs.c | 230 ----------------------------
|
|
7 files changed, 458 insertions(+), 594 deletions(-)
|
|
create mode 100644 include/mounts.h
|
|
|
|
|
|
diff --git a/daemon/direct.c b/daemon/direct.c
|
|
index 072ef97..a3869a5 100644
|
|
--- a/daemon/direct.c
|
|
+++ b/daemon/direct.c
|
|
@@ -35,8 +35,6 @@
|
|
#include <sys/mount.h>
|
|
#include <sys/vfs.h>
|
|
#include <sched.h>
|
|
-#include <pwd.h>
|
|
-#include <grp.h>
|
|
|
|
#include "automount.h"
|
|
|
|
@@ -1237,15 +1235,6 @@ static void *do_mount_direct(void *arg)
|
|
{
|
|
struct pending_args *args, mt;
|
|
struct autofs_point *ap;
|
|
- struct passwd pw;
|
|
- struct passwd *ppw = &pw;
|
|
- struct passwd **pppw = &ppw;
|
|
- struct group gr;
|
|
- struct group *pgr;
|
|
- struct group **ppgr;
|
|
- char *pw_tmp, *gr_tmp;
|
|
- struct thread_stdenv_vars *tsv;
|
|
- int tmplen, grplen;
|
|
struct stat st;
|
|
int status, state;
|
|
|
|
@@ -1291,126 +1280,8 @@ static void *do_mount_direct(void *arg)
|
|
|
|
info(ap->logopt, "attempting to mount entry %s", mt.name);
|
|
|
|
- /*
|
|
- * Setup thread specific data values for macro
|
|
- * substution in map entries during the mount.
|
|
- * Best effort only as it must go ahead.
|
|
- */
|
|
-
|
|
- tsv = malloc(sizeof(struct thread_stdenv_vars));
|
|
- if (!tsv)
|
|
- goto cont;
|
|
-
|
|
- tsv->uid = mt.uid;
|
|
- tsv->gid = mt.gid;
|
|
-
|
|
- /* Try to get passwd info */
|
|
-
|
|
- tmplen = sysconf(_SC_GETPW_R_SIZE_MAX);
|
|
- if (tmplen < 0) {
|
|
- error(ap->logopt, "failed to get buffer size for getpwuid_r");
|
|
- free(tsv);
|
|
- goto cont;
|
|
- }
|
|
-
|
|
- pw_tmp = malloc(tmplen + 1);
|
|
- if (!pw_tmp) {
|
|
- error(ap->logopt, "failed to malloc buffer for getpwuid_r");
|
|
- free(tsv);
|
|
- goto cont;
|
|
- }
|
|
-
|
|
- status = getpwuid_r(tsv->uid, ppw, pw_tmp, tmplen, pppw);
|
|
- if (status || !ppw) {
|
|
- error(ap->logopt, "failed to get passwd info from getpwuid_r");
|
|
- free(tsv);
|
|
- free(pw_tmp);
|
|
- goto cont;
|
|
- }
|
|
-
|
|
- tsv->user = strdup(pw.pw_name);
|
|
- if (!tsv->user) {
|
|
- error(ap->logopt, "failed to malloc buffer for user");
|
|
- free(tsv);
|
|
- free(pw_tmp);
|
|
- goto cont;
|
|
- }
|
|
-
|
|
- tsv->home = strdup(pw.pw_dir);
|
|
- if (!tsv->home) {
|
|
- error(ap->logopt, "failed to malloc buffer for home");
|
|
- free(pw_tmp);
|
|
- free(tsv->user);
|
|
- free(tsv);
|
|
- goto cont;
|
|
- }
|
|
-
|
|
- free(pw_tmp);
|
|
-
|
|
- /* Try to get group info */
|
|
-
|
|
- grplen = sysconf(_SC_GETGR_R_SIZE_MAX);
|
|
- if (tmplen < 0) {
|
|
- error(ap->logopt, "failed to get buffer size for getgrgid_r");
|
|
- free(tsv->user);
|
|
- free(tsv->home);
|
|
- free(tsv);
|
|
- goto cont;
|
|
- }
|
|
-
|
|
- gr_tmp = NULL;
|
|
- tmplen = grplen;
|
|
- while (1) {
|
|
- char *tmp = realloc(gr_tmp, tmplen + 1);
|
|
- if (!tmp) {
|
|
- error(ap->logopt, "failed to malloc buffer for getgrgid_r");
|
|
- if (gr_tmp)
|
|
- free(gr_tmp);
|
|
- free(tsv->user);
|
|
- free(tsv->home);
|
|
- free(tsv);
|
|
- goto cont;
|
|
- }
|
|
- gr_tmp = tmp;
|
|
- pgr = &gr;
|
|
- ppgr = &pgr;
|
|
- status = getgrgid_r(tsv->gid, pgr, gr_tmp, tmplen, ppgr);
|
|
- if (status != ERANGE)
|
|
- break;
|
|
- tmplen += grplen;
|
|
- }
|
|
-
|
|
- if (status || !pgr) {
|
|
- error(ap->logopt, "failed to get group info from getgrgid_r");
|
|
- free(tsv->user);
|
|
- free(tsv->home);
|
|
- free(tsv);
|
|
- free(gr_tmp);
|
|
- goto cont;
|
|
- }
|
|
-
|
|
- tsv->group = strdup(gr.gr_name);
|
|
- if (!tsv->group) {
|
|
- error(ap->logopt, "failed to malloc buffer for group");
|
|
- free(tsv->user);
|
|
- free(tsv->home);
|
|
- free(tsv);
|
|
- free(gr_tmp);
|
|
- goto cont;
|
|
- }
|
|
-
|
|
- free(gr_tmp);
|
|
-
|
|
- status = pthread_setspecific(key_thread_stdenv_vars, tsv);
|
|
- if (status) {
|
|
- error(ap->logopt, "failed to set stdenv thread var");
|
|
- free(tsv->group);
|
|
- free(tsv->user);
|
|
- free(tsv->home);
|
|
- free(tsv);
|
|
- }
|
|
+ set_tsd_user_vars(ap->logopt, mt.uid, mt.gid);
|
|
|
|
-cont:
|
|
status = lookup_nss_mount(ap, NULL, mt.name, mt.len);
|
|
/*
|
|
* Direct mounts are always a single mount. If it fails there's
|
|
diff --git a/daemon/indirect.c b/daemon/indirect.c
|
|
index ccdd8bf..3922f3f 100644
|
|
--- a/daemon/indirect.c
|
|
+++ b/daemon/indirect.c
|
|
@@ -33,8 +33,6 @@
|
|
#include <sys/time.h>
|
|
#include <sys/mount.h>
|
|
#include <sched.h>
|
|
-#include <pwd.h>
|
|
-#include <grp.h>
|
|
|
|
#include "automount.h"
|
|
|
|
@@ -672,15 +670,7 @@ static void *do_mount_indirect(void *arg)
|
|
struct autofs_point *ap;
|
|
char buf[PATH_MAX + 1];
|
|
struct stat st;
|
|
- struct passwd pw;
|
|
- struct passwd *ppw = &pw;
|
|
- struct passwd **pppw = &ppw;
|
|
- struct group gr;
|
|
- struct group *pgr;
|
|
- struct group **ppgr;
|
|
- char *pw_tmp, *gr_tmp;
|
|
- struct thread_stdenv_vars *tsv;
|
|
- int len, tmplen, grplen, status, state;
|
|
+ int len, status, state;
|
|
|
|
args = (struct pending_args *) arg;
|
|
|
|
@@ -722,125 +712,8 @@ static void *do_mount_indirect(void *arg)
|
|
|
|
info(ap->logopt, "attempting to mount entry %s", buf);
|
|
|
|
- /*
|
|
- * Setup thread specific data values for macro
|
|
- * substution in map entries during the mount.
|
|
- * Best effort only as it must go ahead.
|
|
- */
|
|
-
|
|
- tsv = malloc(sizeof(struct thread_stdenv_vars));
|
|
- if (!tsv)
|
|
- goto cont;
|
|
-
|
|
- tsv->uid = mt.uid;
|
|
- tsv->gid = mt.gid;
|
|
-
|
|
- /* Try to get passwd info */
|
|
-
|
|
- tmplen = sysconf(_SC_GETPW_R_SIZE_MAX);
|
|
- if (tmplen < 0) {
|
|
- error(ap->logopt, "failed to get buffer size for getpwuid_r");
|
|
- free(tsv);
|
|
- goto cont;
|
|
- }
|
|
-
|
|
- pw_tmp = malloc(tmplen + 1);
|
|
- if (!pw_tmp) {
|
|
- error(ap->logopt, "failed to malloc buffer for getpwuid_r");
|
|
- free(tsv);
|
|
- goto cont;
|
|
- }
|
|
-
|
|
- status = getpwuid_r(tsv->uid, ppw, pw_tmp, tmplen, pppw);
|
|
- if (status || !ppw) {
|
|
- error(ap->logopt, "failed to get passwd info from getpwuid_r");
|
|
- free(tsv);
|
|
- free(pw_tmp);
|
|
- goto cont;
|
|
- }
|
|
-
|
|
- tsv->user = strdup(pw.pw_name);
|
|
- if (!tsv->user) {
|
|
- error(ap->logopt, "failed to malloc buffer for user");
|
|
- free(tsv);
|
|
- free(pw_tmp);
|
|
- goto cont;
|
|
- }
|
|
-
|
|
- tsv->home = strdup(pw.pw_dir);
|
|
- if (!tsv->home) {
|
|
- error(ap->logopt, "failed to malloc buffer for home");
|
|
- free(pw_tmp);
|
|
- free(tsv->user);
|
|
- free(tsv);
|
|
- goto cont;
|
|
- }
|
|
+ set_tsd_user_vars(ap->logopt, mt.uid, mt.gid);
|
|
|
|
- free(pw_tmp);
|
|
-
|
|
- /* Try to get group info */
|
|
-
|
|
- grplen = sysconf(_SC_GETGR_R_SIZE_MAX);
|
|
- if (tmplen < 0) {
|
|
- error(ap->logopt, "failed to get buffer size for getgrgid_r");
|
|
- free(tsv->user);
|
|
- free(tsv->home);
|
|
- free(tsv);
|
|
- goto cont;
|
|
- }
|
|
-
|
|
- gr_tmp = NULL;
|
|
- tmplen = grplen;
|
|
- while (1) {
|
|
- char *tmp = realloc(gr_tmp, tmplen + 1);
|
|
- if (!tmp) {
|
|
- error(ap->logopt, "failed to malloc buffer for getgrgid_r");
|
|
- if (gr_tmp)
|
|
- free(gr_tmp);
|
|
- free(tsv->user);
|
|
- free(tsv->home);
|
|
- free(tsv);
|
|
- goto cont;
|
|
- }
|
|
- gr_tmp = tmp;
|
|
- pgr = &gr;
|
|
- ppgr = &pgr;
|
|
- status = getgrgid_r(tsv->gid, pgr, gr_tmp, tmplen, ppgr);
|
|
- if (status != ERANGE)
|
|
- break;
|
|
- tmplen += grplen;
|
|
- }
|
|
-
|
|
- if (status || !pgr) {
|
|
- error(ap->logopt, "failed to get group info from getgrgid_r");
|
|
- free(tsv->user);
|
|
- free(tsv->home);
|
|
- free(tsv);
|
|
- free(gr_tmp);
|
|
- goto cont;
|
|
- }
|
|
-
|
|
- tsv->group = strdup(gr.gr_name);
|
|
- if (!tsv->group) {
|
|
- error(ap->logopt, "failed to malloc buffer for group");
|
|
- free(tsv->user);
|
|
- free(tsv->home);
|
|
- free(tsv);
|
|
- free(gr_tmp);
|
|
- goto cont;
|
|
- }
|
|
-
|
|
- free(gr_tmp);
|
|
-
|
|
- status = pthread_setspecific(key_thread_stdenv_vars, tsv);
|
|
- if (status) {
|
|
- error(ap->logopt, "failed to set stdenv thread var");
|
|
- free(tsv->group);
|
|
- free(tsv->user);
|
|
- free(tsv->home);
|
|
- free(tsv);
|
|
- }
|
|
-cont:
|
|
status = lookup_nss_mount(ap, NULL, mt.name, mt.len);
|
|
pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &state);
|
|
if (status) {
|
|
diff --git a/include/automount.h b/include/automount.h
|
|
index 72e2457..da1bf8f 100644
|
|
--- a/include/automount.h
|
|
+++ b/include/automount.h
|
|
@@ -28,6 +28,7 @@
|
|
#include "macros.h"
|
|
#include "log.h"
|
|
#include "rpc_subs.h"
|
|
+#include "mounts.h"
|
|
#include "parse_subs.h"
|
|
|
|
#ifdef WITH_DMALLOC
|
|
@@ -323,61 +324,6 @@ int cat_path(char *buf, size_t len, const char *dir, const char *base);
|
|
int ncat_path(char *buf, size_t len,
|
|
const char *dir, const char *base, size_t blen);
|
|
|
|
-/* mount table utilities */
|
|
-
|
|
-#define MNTS_ALL 0x0001
|
|
-#define MNTS_REAL 0x0002
|
|
-#define MNTS_AUTOFS 0x0004
|
|
-
|
|
-struct mnt_list {
|
|
- char *path;
|
|
- char *fs_name;
|
|
- char *fs_type;
|
|
- char *opts;
|
|
- pid_t owner;
|
|
- /*
|
|
- * List operations ie. get_mnt_list.
|
|
- */
|
|
- struct mnt_list *next;
|
|
- /*
|
|
- * Tree operations ie. tree_make_tree,
|
|
- * tree_get_mnt_list etc.
|
|
- */
|
|
- struct mnt_list *left;
|
|
- struct mnt_list *right;
|
|
- struct list_head self;
|
|
- struct list_head list;
|
|
- struct list_head entries;
|
|
- struct list_head sublist;
|
|
- /*
|
|
- * Offset mount handling ie. add_ordered_list
|
|
- * and get_offset.
|
|
- */
|
|
- struct list_head ordered;
|
|
-};
|
|
-
|
|
-unsigned int query_kproto_ver(void);
|
|
-unsigned int get_kver_major(void);
|
|
-unsigned int get_kver_minor(void);
|
|
-char *make_options_string(char *path, int kernel_pipefd, char *extra);
|
|
-char *make_mnt_name_string(char *path);
|
|
-struct mnt_list *get_mnt_list(const char *table, const char *path, int include);
|
|
-struct mnt_list *reverse_mnt_list(struct mnt_list *list);
|
|
-void free_mnt_list(struct mnt_list *list);
|
|
-int contained_in_local_fs(const char *path);
|
|
-int is_mounted(const char *table, const char *path, unsigned int type);
|
|
-int has_fstab_option(const char *opt);
|
|
-char *find_mnt_ino(const char *table, dev_t dev, ino_t ino);
|
|
-char *get_offset(const char *prefix, char *offset,
|
|
- struct list_head *head, struct list_head **pos);
|
|
-void add_ordered_list(struct mnt_list *ent, struct list_head *head);
|
|
-void tree_free_mnt_tree(struct mnt_list *tree);
|
|
-struct mnt_list *tree_make_mnt_tree(const char *table, const char *path);
|
|
-int tree_get_mnt_list(struct mnt_list *mnts, struct list_head *list, const char *path, int include);
|
|
-int tree_get_mnt_sublist(struct mnt_list *mnts, struct list_head *list, const char *path, int include);
|
|
-int tree_find_mnt_ents(struct mnt_list *mnts, struct list_head *list, const char *path);
|
|
-int tree_is_mounted(struct mnt_list *mnts, const char *path, unsigned int type);
|
|
-
|
|
/* Core automount definitions */
|
|
|
|
#define MNT_DETACH 0x00000002 /* Just detach from the tree */
|
|
diff --git a/include/mounts.h b/include/mounts.h
|
|
new file mode 100644
|
|
index 0000000..7120351
|
|
--- /dev/null
|
|
+++ b/include/mounts.h
|
|
@@ -0,0 +1,91 @@
|
|
+/* ----------------------------------------------------------------------- *
|
|
+ *
|
|
+ * mounts.h - header file for mount utilities module.
|
|
+ *
|
|
+ * Copyright 2008 Red Hat, Inc. All rights reserved.
|
|
+ * Copyright 2004-2006 Ian Kent <raven@themaw.net> - All Rights Reserved.
|
|
+ *
|
|
+ * This program is free software; you can redistribute it and/or modify
|
|
+ * it under the terms of the GNU General Public License as published by
|
|
+ * the Free Software Foundation, Inc., 675 Mass Ave, Cambridge MA 02139,
|
|
+ * USA; either version 2 of the License, or (at your option) any later
|
|
+ * version; incorporated herein by reference.
|
|
+ *
|
|
+ * ----------------------------------------------------------------------- */
|
|
+
|
|
+#ifndef MOUNTS_H
|
|
+#define MOUNTS_H
|
|
+
|
|
+#define AUTOFS_TYPE_ANY 0x0000
|
|
+#define AUTOFS_TYPE_INDIRECT 0x0001
|
|
+#define AUTOFS_TYPE_DIRECT 0x0002
|
|
+#define AUTOFS_TYPE_OFFSET 0x0004
|
|
+
|
|
+#define MNTS_ALL 0x0001
|
|
+#define MNTS_REAL 0x0002
|
|
+#define MNTS_AUTOFS 0x0004
|
|
+
|
|
+#define REMOUNT_SUCCESS 0x0000
|
|
+#define REMOUNT_OPEN_FAIL 0x0001
|
|
+#define REMOUNT_STAT_FAIL 0x0002
|
|
+#define REMOUNT_READ_MAP 0x0004
|
|
+
|
|
+extern const unsigned int indirect;
|
|
+extern const unsigned int direct;
|
|
+extern const unsigned int offset;
|
|
+
|
|
+struct mapent;
|
|
+
|
|
+struct mnt_list {
|
|
+ char *path;
|
|
+ char *fs_name;
|
|
+ char *fs_type;
|
|
+ char *opts;
|
|
+ pid_t owner;
|
|
+ /*
|
|
+ * List operations ie. get_mnt_list.
|
|
+ */
|
|
+ struct mnt_list *next;
|
|
+ /*
|
|
+ * Tree operations ie. tree_make_tree,
|
|
+ * tree_get_mnt_list etc.
|
|
+ */
|
|
+ struct mnt_list *left;
|
|
+ struct mnt_list *right;
|
|
+ struct list_head self;
|
|
+ struct list_head list;
|
|
+ struct list_head entries;
|
|
+ struct list_head sublist;
|
|
+ /*
|
|
+ * Offset mount handling ie. add_ordered_list
|
|
+ * and get_offset.
|
|
+ */
|
|
+ struct list_head ordered;
|
|
+};
|
|
+
|
|
+unsigned int query_kproto_ver(void);
|
|
+unsigned int get_kver_major(void);
|
|
+unsigned int get_kver_minor(void);
|
|
+char *make_options_string(char *path, int kernel_pipefd, const char *extra);
|
|
+char *make_mnt_name_string(char *path);
|
|
+struct mnt_list *get_mnt_list(const char *table, const char *path, int include);
|
|
+struct mnt_list *reverse_mnt_list(struct mnt_list *list);
|
|
+void free_mnt_list(struct mnt_list *list);
|
|
+int contained_in_local_fs(const char *path);
|
|
+int is_mounted(const char *table, const char *path, unsigned int type);
|
|
+int has_fstab_option(const char *opt);
|
|
+char *get_offset(const char *prefix, char *offset,
|
|
+ struct list_head *head, struct list_head **pos);
|
|
+void add_ordered_list(struct mnt_list *ent, struct list_head *head);
|
|
+void tree_free_mnt_tree(struct mnt_list *tree);
|
|
+struct mnt_list *tree_make_mnt_tree(const char *table, const char *path);
|
|
+int tree_get_mnt_list(struct mnt_list *mnts, struct list_head *list, const char *path, int include);
|
|
+int tree_get_mnt_sublist(struct mnt_list *mnts, struct list_head *list, const char *path, int include);
|
|
+int tree_find_mnt_ents(struct mnt_list *mnts, struct list_head *list, const char *path);
|
|
+int tree_is_mounted(struct mnt_list *mnts, const char *path, unsigned int type);
|
|
+void set_tsd_user_vars(unsigned int, uid_t, gid_t);
|
|
+int umount_ent(struct autofs_point *, const char *);
|
|
+int mount_multi_triggers(struct autofs_point *, char *, struct mapent *, const char *);
|
|
+int umount_multi_triggers(struct autofs_point *, char *, struct mapent *, const char *);
|
|
+
|
|
+#endif
|
|
diff --git a/include/parse_subs.h b/include/parse_subs.h
|
|
index 10c6083..643ad68 100644
|
|
--- a/include/parse_subs.h
|
|
+++ b/include/parse_subs.h
|
|
@@ -27,8 +27,5 @@ int strmcmp(const char *, const char *, int);
|
|
char *dequote(const char *, int, unsigned int);
|
|
int span_space(const char *, unsigned int);
|
|
char *sanitize_path(const char *, int, unsigned int, unsigned int);
|
|
-int umount_ent(struct autofs_point *, const char *);
|
|
-int mount_multi_triggers(struct autofs_point *, char *, struct mapent *, const char *);
|
|
-int umount_multi_triggers(struct autofs_point *, char *, struct mapent *, const char *);
|
|
|
|
#endif
|
|
diff --git a/lib/mounts.c b/lib/mounts.c
|
|
index b987fbb..a4bf86c 100644
|
|
--- a/lib/mounts.c
|
|
+++ b/lib/mounts.c
|
|
@@ -1,6 +1,6 @@
|
|
/* ----------------------------------------------------------------------- *
|
|
*
|
|
- * mounts.c - module for Linux automount mount table lookup functions
|
|
+ * mounts.c - module for mount utilities.
|
|
*
|
|
* Copyright 2002-2005 Ian Kent <raven@themaw.net> - All Rights Reserved
|
|
*
|
|
@@ -23,12 +23,21 @@
|
|
#include <fcntl.h>
|
|
#include <sys/mount.h>
|
|
#include <stdio.h>
|
|
+#include <dirent.h>
|
|
+#include <sys/vfs.h>
|
|
+#include <pwd.h>
|
|
+#include <grp.h>
|
|
|
|
#include "automount.h"
|
|
|
|
#define MAX_OPTIONS_LEN 80
|
|
#define MAX_MNT_NAME_LEN 30
|
|
|
|
+const unsigned int indirect = AUTOFS_TYPE_INDIRECT;
|
|
+const unsigned int direct = AUTOFS_TYPE_DIRECT;
|
|
+const unsigned int offset = AUTOFS_TYPE_OFFSET;
|
|
+const unsigned int type_count = 3;
|
|
+
|
|
static const char options_template[] = "fd=%d,pgrp=%u,minproto=5,maxproto=%d";
|
|
static const char options_template_extra[] = "fd=%d,pgrp=%u,minproto=5,maxproto=%d,%s";
|
|
static const char mnt_name_template[] = "automount(pid%u)";
|
|
@@ -119,7 +128,7 @@ unsigned int get_kver_minor(void)
|
|
/*
|
|
* Make common autofs mount options string
|
|
*/
|
|
-char *make_options_string(char *path, int pipefd, char *extra)
|
|
+char *make_options_string(char *path, int pipefd, const char *extra)
|
|
{
|
|
char *options;
|
|
int len;
|
|
@@ -462,51 +471,6 @@ int has_fstab_option(const char *opt)
|
|
return ret;
|
|
}
|
|
|
|
-char *find_mnt_ino(const char *table, dev_t dev, ino_t ino)
|
|
-{
|
|
- struct mntent mnt_wrk;
|
|
- struct mntent *mnt;
|
|
- char buf[PATH_MAX * 3];
|
|
- char *path = NULL;
|
|
- unsigned long l_dev = (unsigned long) dev;
|
|
- unsigned long l_ino = (unsigned long) ino;
|
|
- FILE *tab;
|
|
-
|
|
- tab = setmntent(table, "r");
|
|
- if (!tab) {
|
|
- char *estr = strerror_r(errno, buf, (size_t) PATH_MAX - 1);
|
|
- logerr("setmntent: %s", estr);
|
|
- return 0;
|
|
- }
|
|
-
|
|
- while ((mnt = getmntent_r(tab, &mnt_wrk, buf, PATH_MAX * 3))) {
|
|
- char *p_dev, *p_ino;
|
|
- unsigned long m_dev, m_ino;
|
|
-
|
|
- if (strcmp(mnt->mnt_type, "autofs"))
|
|
- continue;
|
|
-
|
|
- p_dev = strstr(mnt->mnt_opts, "dev=");
|
|
- if (!p_dev)
|
|
- continue;
|
|
- sscanf(p_dev, "dev=%lu", &m_dev);
|
|
- if (m_dev != l_dev)
|
|
- continue;
|
|
-
|
|
- p_ino = strstr(mnt->mnt_opts, "ino=");
|
|
- if (!p_ino)
|
|
- continue;
|
|
- sscanf(p_ino, "ino=%lu", &m_ino);
|
|
- if (m_ino == l_ino) {
|
|
- path = strdup(mnt->mnt_dir);
|
|
- break;
|
|
- }
|
|
- }
|
|
- endmntent(tab);
|
|
-
|
|
- return path;
|
|
-}
|
|
-
|
|
char *get_offset(const char *prefix, char *offset,
|
|
struct list_head *head, struct list_head **pos)
|
|
{
|
|
@@ -982,3 +946,355 @@ int tree_is_mounted(struct mnt_list *mnts, const char *path, unsigned int type)
|
|
return mounted;
|
|
}
|
|
|
|
+void set_tsd_user_vars(unsigned int logopt, uid_t uid, gid_t gid)
|
|
+{
|
|
+ struct thread_stdenv_vars *tsv;
|
|
+ struct passwd pw;
|
|
+ struct passwd *ppw = &pw;
|
|
+ struct passwd **pppw = &ppw;
|
|
+ struct group gr;
|
|
+ struct group *pgr;
|
|
+ struct group **ppgr;
|
|
+ char *pw_tmp, *gr_tmp;
|
|
+ int status, tmplen, grplen;
|
|
+
|
|
+ /*
|
|
+ * Setup thread specific data values for macro
|
|
+ * substution in map entries during the mount.
|
|
+ * Best effort only as it must go ahead.
|
|
+ */
|
|
+
|
|
+ tsv = malloc(sizeof(struct thread_stdenv_vars));
|
|
+ if (!tsv) {
|
|
+ error(logopt, "failed alloc tsv storage");
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ tsv->uid = uid;
|
|
+ tsv->gid = gid;
|
|
+
|
|
+ /* Try to get passwd info */
|
|
+
|
|
+ tmplen = sysconf(_SC_GETPW_R_SIZE_MAX);
|
|
+ if (tmplen < 0) {
|
|
+ error(logopt, "failed to get buffer size for getpwuid_r");
|
|
+ goto free_tsv;
|
|
+ }
|
|
+
|
|
+ pw_tmp = malloc(tmplen + 1);
|
|
+ if (!pw_tmp) {
|
|
+ error(logopt, "failed to malloc buffer for getpwuid_r");
|
|
+ goto free_tsv;
|
|
+ }
|
|
+
|
|
+ status = getpwuid_r(uid, ppw, pw_tmp, tmplen, pppw);
|
|
+ if (status || !ppw) {
|
|
+ error(logopt, "failed to get passwd info from getpwuid_r");
|
|
+ free(pw_tmp);
|
|
+ goto free_tsv;
|
|
+ }
|
|
+
|
|
+ tsv->user = strdup(pw.pw_name);
|
|
+ if (!tsv->user) {
|
|
+ error(logopt, "failed to malloc buffer for user");
|
|
+ free(pw_tmp);
|
|
+ goto free_tsv;
|
|
+ }
|
|
+
|
|
+ tsv->home = strdup(pw.pw_dir);
|
|
+ if (!tsv->home) {
|
|
+ error(logopt, "failed to malloc buffer for home");
|
|
+ free(pw_tmp);
|
|
+ goto free_tsv_user;
|
|
+ }
|
|
+
|
|
+ free(pw_tmp);
|
|
+
|
|
+ /* Try to get group info */
|
|
+
|
|
+ grplen = sysconf(_SC_GETGR_R_SIZE_MAX);
|
|
+ if (tmplen < 0) {
|
|
+ error(logopt, "failed to get buffer size for getgrgid_r");
|
|
+ goto free_tsv_home;
|
|
+ }
|
|
+
|
|
+ gr_tmp = NULL;
|
|
+ tmplen = grplen;
|
|
+ while (1) {
|
|
+ char *tmp = realloc(gr_tmp, tmplen + 1);
|
|
+ if (!tmp) {
|
|
+ error(logopt, "failed to malloc buffer for getgrgid_r");
|
|
+ if (gr_tmp)
|
|
+ free(gr_tmp);
|
|
+ goto free_tsv_home;
|
|
+ }
|
|
+ gr_tmp = tmp;
|
|
+ pgr = &gr;
|
|
+ ppgr = &pgr;
|
|
+ status = getgrgid_r(gid, pgr, gr_tmp, tmplen, ppgr);
|
|
+ if (status != ERANGE)
|
|
+ break;
|
|
+ tmplen += grplen;
|
|
+ }
|
|
+
|
|
+ if (status || !pgr) {
|
|
+ error(logopt, "failed to get group info from getgrgid_r");
|
|
+ free(gr_tmp);
|
|
+ goto free_tsv_home;
|
|
+ }
|
|
+
|
|
+ tsv->group = strdup(gr.gr_name);
|
|
+ if (!tsv->group) {
|
|
+ error(logopt, "failed to malloc buffer for group");
|
|
+ free(gr_tmp);
|
|
+ goto free_tsv_home;
|
|
+ }
|
|
+
|
|
+ free(gr_tmp);
|
|
+
|
|
+ status = pthread_setspecific(key_thread_stdenv_vars, tsv);
|
|
+ if (status) {
|
|
+ error(logopt, "failed to set stdenv thread var");
|
|
+ goto free_tsv_group;
|
|
+ }
|
|
+
|
|
+ return;
|
|
+
|
|
+free_tsv_group:
|
|
+ free(tsv->group);
|
|
+free_tsv_home:
|
|
+ free(tsv->home);
|
|
+free_tsv_user:
|
|
+ free(tsv->user);
|
|
+free_tsv:
|
|
+ free(tsv);
|
|
+ return;
|
|
+}
|
|
+
|
|
+int umount_ent(struct autofs_point *ap, const char *path)
|
|
+{
|
|
+ struct stat st;
|
|
+ struct statfs fs;
|
|
+ int sav_errno;
|
|
+ int status, is_smbfs = 0;
|
|
+ int ret, rv = 1;
|
|
+
|
|
+ ret = statfs(path, &fs);
|
|
+ if (ret == -1) {
|
|
+ warn(ap->logopt, "could not stat fs of %s", path);
|
|
+ is_smbfs = 0;
|
|
+ } else {
|
|
+ int cifsfs = fs.f_type == (__SWORD_TYPE) CIFS_MAGIC_NUMBER;
|
|
+ int smbfs = fs.f_type == (__SWORD_TYPE) SMB_SUPER_MAGIC;
|
|
+ is_smbfs = (cifsfs | smbfs) ? 1 : 0;
|
|
+ }
|
|
+
|
|
+ status = lstat(path, &st);
|
|
+ sav_errno = errno;
|
|
+
|
|
+ if (status < 0)
|
|
+ warn(ap->logopt, "lstat of %s failed with %d", path, status);
|
|
+
|
|
+ /*
|
|
+ * lstat failed and we're an smbfs fs returning an error that is not
|
|
+ * EIO or EBADSLT or the lstat failed so it's a bad path. Return
|
|
+ * a fail.
|
|
+ *
|
|
+ * EIO appears to correspond to an smb mount that has gone away
|
|
+ * and EBADSLT relates to CD changer not responding.
|
|
+ */
|
|
+ if (!status && (S_ISDIR(st.st_mode) && st.st_dev != ap->dev)) {
|
|
+ rv = spawn_umount(ap->logopt, path, NULL);
|
|
+ } else if (is_smbfs && (sav_errno == EIO || sav_errno == EBADSLT)) {
|
|
+ rv = spawn_umount(ap->logopt, path, NULL);
|
|
+ }
|
|
+
|
|
+ /* We are doing a forced shutcwdown down so unlink busy mounts */
|
|
+ if (rv && (ap->state == ST_SHUTDOWN_FORCE || ap->state == ST_SHUTDOWN)) {
|
|
+ ret = stat(path, &st);
|
|
+ if (ret == -1 && errno == ENOENT) {
|
|
+ warn(ap->logopt, "mount point does not exist");
|
|
+ return 0;
|
|
+ }
|
|
+
|
|
+ if (ret == 0 && !S_ISDIR(st.st_mode)) {
|
|
+ warn(ap->logopt, "mount point is not a directory");
|
|
+ return 0;
|
|
+ }
|
|
+
|
|
+ if (ap->state == ST_SHUTDOWN_FORCE) {
|
|
+ info(ap->logopt, "forcing umount of %s", path);
|
|
+ rv = spawn_umount(ap->logopt, "-l", path, NULL);
|
|
+ }
|
|
+
|
|
+ /*
|
|
+ * Verify that we actually unmounted the thing. This is a
|
|
+ * belt and suspenders approach to not eating user data.
|
|
+ * We have seen cases where umount succeeds, but there is
|
|
+ * still a file system mounted on the mount point. How
|
|
+ * this happens has not yet been determined, but we want to
|
|
+ * make sure to return failure here, if that is the case,
|
|
+ * so that we do not try to call rmdir_path on the
|
|
+ * directory.
|
|
+ */
|
|
+ if (!rv && is_mounted(_PATH_MOUNTED, path, MNTS_REAL)) {
|
|
+ crit(ap->logopt,
|
|
+ "the umount binary reported that %s was "
|
|
+ "unmounted, but there is still something "
|
|
+ "mounted on this path.", path);
|
|
+ rv = -1;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ return rv;
|
|
+}
|
|
+
|
|
+int mount_multi_triggers(struct autofs_point *ap, char *root, struct mapent *me, const char *base)
|
|
+{
|
|
+ char path[PATH_MAX + 1];
|
|
+ char *offset = path;
|
|
+ struct mapent *oe;
|
|
+ struct list_head *pos = NULL;
|
|
+ unsigned int fs_path_len;
|
|
+ unsigned int mounted;
|
|
+ int ret, start;
|
|
+
|
|
+ fs_path_len = strlen(root) + strlen(base);
|
|
+ if (fs_path_len > PATH_MAX)
|
|
+ return -1;
|
|
+
|
|
+ strcpy(path, root);
|
|
+ strcat(path, base);
|
|
+
|
|
+ mounted = 0;
|
|
+ start = strlen(root);
|
|
+ offset = cache_get_offset(base, offset, start, &me->multi_list, &pos);
|
|
+ while (offset) {
|
|
+ int plen = fs_path_len + strlen(offset);
|
|
+
|
|
+ if (plen > PATH_MAX) {
|
|
+ warn(ap->logopt, "path loo long");
|
|
+ goto cont;
|
|
+ }
|
|
+
|
|
+ oe = cache_lookup_offset(base, offset, start, &me->multi_list);
|
|
+ if (!oe || !oe->mapent)
|
|
+ goto cont;
|
|
+
|
|
+ debug(ap->logopt, "mount offset %s", oe->key);
|
|
+
|
|
+ ret = mount_autofs_offset(ap, oe);
|
|
+ if (ret >= MOUNT_OFFSET_OK)
|
|
+ mounted++;
|
|
+ else {
|
|
+ if (ret != MOUNT_OFFSET_IGNORE)
|
|
+ warn(ap->logopt, "failed to mount offset");
|
|
+ else {
|
|
+ debug(ap->logopt,
|
|
+ "ignoring \"nohide\" trigger %s",
|
|
+ oe->key);
|
|
+ free(oe->mapent);
|
|
+ oe->mapent = NULL;
|
|
+ }
|
|
+ }
|
|
+cont:
|
|
+ offset = cache_get_offset(base,
|
|
+ offset, start, &me->multi_list, &pos);
|
|
+ }
|
|
+
|
|
+ return mounted;
|
|
+}
|
|
+
|
|
+int umount_multi_triggers(struct autofs_point *ap, char *root, struct mapent *me, const char *base)
|
|
+{
|
|
+ char path[PATH_MAX + 1];
|
|
+ char *offset;
|
|
+ struct mapent *oe;
|
|
+ struct list_head *mm_root, *pos;
|
|
+ const char o_root[] = "/";
|
|
+ const char *mm_base;
|
|
+ int left, start;
|
|
+
|
|
+ left = 0;
|
|
+ start = strlen(root);
|
|
+
|
|
+ mm_root = &me->multi->multi_list;
|
|
+
|
|
+ if (!base)
|
|
+ mm_base = o_root;
|
|
+ else
|
|
+ mm_base = base;
|
|
+
|
|
+ pos = NULL;
|
|
+ offset = path;
|
|
+
|
|
+ /* Make sure "none" of the offsets have an active mount. */
|
|
+ while ((offset = cache_get_offset(mm_base, offset, start, mm_root, &pos))) {
|
|
+ char *oe_base;
|
|
+
|
|
+ oe = cache_lookup_offset(mm_base, offset, start, &me->multi_list);
|
|
+ /* root offset is a special case */
|
|
+ if (!oe || !oe->mapent || (strlen(oe->key) - start) == 1)
|
|
+ continue;
|
|
+
|
|
+ /*
|
|
+ * Check for and umount subtree offsets resulting from
|
|
+ * nonstrict mount fail.
|
|
+ */
|
|
+ oe_base = oe->key + strlen(root);
|
|
+ left += umount_multi_triggers(ap, root, oe, oe_base);
|
|
+
|
|
+ if (oe->ioctlfd != -1)
|
|
+ left++;
|
|
+ }
|
|
+
|
|
+ if (left)
|
|
+ return left;
|
|
+
|
|
+ pos = NULL;
|
|
+ offset = path;
|
|
+
|
|
+ /* Make sure "none" of the offsets have an active mount. */
|
|
+ while ((offset = cache_get_offset(mm_base, offset, start, mm_root, &pos))) {
|
|
+ oe = cache_lookup_offset(mm_base, offset, start, &me->multi_list);
|
|
+ /* root offset is a special case */
|
|
+ if (!oe || !oe->mapent || (strlen(oe->key) - start) == 1)
|
|
+ continue;
|
|
+
|
|
+ debug(ap->logopt, "umount offset %s", oe->key);
|
|
+
|
|
+ if (umount_autofs_offset(ap, oe)) {
|
|
+ warn(ap->logopt, "failed to umount offset");
|
|
+ left++;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ if (!left && me->multi == me) {
|
|
+ struct mapent_cache *mc = me->mc;
|
|
+ int status;
|
|
+
|
|
+ /*
|
|
+ * Special case.
|
|
+ * If we can't umount the root container then we can't
|
|
+ * delete the offsets from the cache and we need to put
|
|
+ * the offset triggers back.
|
|
+ */
|
|
+ if (is_mounted(_PATH_MOUNTED, root, MNTS_REAL)) {
|
|
+ info(ap->logopt, "unmounting dir = %s", root);
|
|
+ if (umount_ent(ap, root)) {
|
|
+ if (mount_multi_triggers(ap, root, me, "/") < 0)
|
|
+ warn(ap->logopt,
|
|
+ "failed to remount offset triggers");
|
|
+ return left++;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ /* We're done - clean out the offsets */
|
|
+ status = cache_delete_offset_list(mc, me->key);
|
|
+ if (status != CHE_OK)
|
|
+ warn(ap->logopt, "couldn't delete offset list");
|
|
+ }
|
|
+
|
|
+ return left;
|
|
+}
|
|
+
|
|
diff --git a/lib/parse_subs.c b/lib/parse_subs.c
|
|
index 27cb0fc..3a04dd6 100644
|
|
--- a/lib/parse_subs.c
|
|
+++ b/lib/parse_subs.c
|
|
@@ -18,10 +18,7 @@
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <ctype.h>
|
|
-#include <sys/types.h>
|
|
-#include <sys/stat.h>
|
|
#include <unistd.h>
|
|
-#include <sys/vfs.h>
|
|
#include "automount.h"
|
|
|
|
/*
|
|
@@ -304,230 +301,3 @@ char *sanitize_path(const char *path, int origlen, unsigned int type, unsigned i
|
|
return s_path;
|
|
}
|
|
|
|
-int umount_ent(struct autofs_point *ap, const char *path)
|
|
-{
|
|
- struct stat st;
|
|
- struct statfs fs;
|
|
- int sav_errno;
|
|
- int status, is_smbfs = 0;
|
|
- int ret, rv = 1;
|
|
-
|
|
- ret = statfs(path, &fs);
|
|
- if (ret == -1) {
|
|
- warn(ap->logopt, "could not stat fs of %s", path);
|
|
- is_smbfs = 0;
|
|
- } else {
|
|
- int cifsfs = fs.f_type == (__SWORD_TYPE) CIFS_MAGIC_NUMBER;
|
|
- int smbfs = fs.f_type == (__SWORD_TYPE) SMB_SUPER_MAGIC;
|
|
- is_smbfs = (cifsfs | smbfs) ? 1 : 0;
|
|
- }
|
|
-
|
|
- status = lstat(path, &st);
|
|
- sav_errno = errno;
|
|
-
|
|
- if (status < 0)
|
|
- warn(ap->logopt, "lstat of %s failed with %d", path, status);
|
|
-
|
|
- /*
|
|
- * lstat failed and we're an smbfs fs returning an error that is not
|
|
- * EIO or EBADSLT or the lstat failed so it's a bad path. Return
|
|
- * a fail.
|
|
- *
|
|
- * EIO appears to correspond to an smb mount that has gone away
|
|
- * and EBADSLT relates to CD changer not responding.
|
|
- */
|
|
- if (!status && (S_ISDIR(st.st_mode) && st.st_dev != ap->dev)) {
|
|
- rv = spawn_umount(ap->logopt, path, NULL);
|
|
- } else if (is_smbfs && (sav_errno == EIO || sav_errno == EBADSLT)) {
|
|
- rv = spawn_umount(ap->logopt, path, NULL);
|
|
- }
|
|
-
|
|
- /* We are doing a forced shutcwdown down so unlink busy mounts */
|
|
- if (rv && (ap->state == ST_SHUTDOWN_FORCE || ap->state == ST_SHUTDOWN)) {
|
|
- ret = stat(path, &st);
|
|
- if (ret == -1 && errno == ENOENT) {
|
|
- warn(ap->logopt, "mount point does not exist");
|
|
- return 0;
|
|
- }
|
|
-
|
|
- if (ret == 0 && !S_ISDIR(st.st_mode)) {
|
|
- warn(ap->logopt, "mount point is not a directory");
|
|
- return 0;
|
|
- }
|
|
-
|
|
- if (ap->state == ST_SHUTDOWN_FORCE) {
|
|
- info(ap->logopt, "forcing umount of %s", path);
|
|
- rv = spawn_umount(ap->logopt, "-l", path, NULL);
|
|
- }
|
|
-
|
|
- /*
|
|
- * Verify that we actually unmounted the thing. This is a
|
|
- * belt and suspenders approach to not eating user data.
|
|
- * We have seen cases where umount succeeds, but there is
|
|
- * still a file system mounted on the mount point. How
|
|
- * this happens has not yet been determined, but we want to
|
|
- * make sure to return failure here, if that is the case,
|
|
- * so that we do not try to call rmdir_path on the
|
|
- * directory.
|
|
- */
|
|
- if (!rv && is_mounted(_PATH_MOUNTED, path, MNTS_REAL)) {
|
|
- crit(ap->logopt,
|
|
- "the umount binary reported that %s was "
|
|
- "unmounted, but there is still something "
|
|
- "mounted on this path.", path);
|
|
- rv = -1;
|
|
- }
|
|
- }
|
|
-
|
|
- return rv;
|
|
-}
|
|
-
|
|
-int mount_multi_triggers(struct autofs_point *ap, char *root, struct mapent *me, const char *base)
|
|
-{
|
|
- char path[PATH_MAX + 1];
|
|
- char *offset = path;
|
|
- struct mapent *oe;
|
|
- struct list_head *pos = NULL;
|
|
- unsigned int fs_path_len;
|
|
- unsigned int mounted;
|
|
- int ret, start;
|
|
-
|
|
- fs_path_len = strlen(root) + strlen(base);
|
|
- if (fs_path_len > PATH_MAX)
|
|
- return -1;
|
|
-
|
|
- strcpy(path, root);
|
|
- strcat(path, base);
|
|
-
|
|
- mounted = 0;
|
|
- start = strlen(root);
|
|
- offset = cache_get_offset(base, offset, start, &me->multi_list, &pos);
|
|
- while (offset) {
|
|
- int plen = fs_path_len + strlen(offset);
|
|
-
|
|
- if (plen > PATH_MAX) {
|
|
- warn(ap->logopt, "path loo long");
|
|
- goto cont;
|
|
- }
|
|
-
|
|
- oe = cache_lookup_offset(base, offset, start, &me->multi_list);
|
|
- if (!oe || !oe->mapent)
|
|
- goto cont;
|
|
-
|
|
- debug(ap->logopt, "mount offset %s", oe->key);
|
|
-
|
|
- ret = mount_autofs_offset(ap, oe);
|
|
- if (ret >= MOUNT_OFFSET_OK)
|
|
- mounted++;
|
|
- else {
|
|
- if (ret != MOUNT_OFFSET_IGNORE)
|
|
- warn(ap->logopt, "failed to mount offset");
|
|
- else {
|
|
- debug(ap->logopt,
|
|
- "ignoring \"nohide\" trigger %s",
|
|
- oe->key);
|
|
- free(oe->mapent);
|
|
- oe->mapent = NULL;
|
|
- }
|
|
- }
|
|
-cont:
|
|
- offset = cache_get_offset(base,
|
|
- offset, start, &me->multi_list, &pos);
|
|
- }
|
|
-
|
|
- return mounted;
|
|
-}
|
|
-
|
|
-int umount_multi_triggers(struct autofs_point *ap, char *root, struct mapent *me, const char *base)
|
|
-{
|
|
- char path[PATH_MAX + 1];
|
|
- char *offset;
|
|
- struct mapent *oe;
|
|
- struct list_head *mm_root, *pos;
|
|
- const char o_root[] = "/";
|
|
- const char *mm_base;
|
|
- int left, start;
|
|
-
|
|
- left = 0;
|
|
- start = strlen(root);
|
|
-
|
|
- mm_root = &me->multi->multi_list;
|
|
-
|
|
- if (!base)
|
|
- mm_base = o_root;
|
|
- else
|
|
- mm_base = base;
|
|
-
|
|
- pos = NULL;
|
|
- offset = path;
|
|
-
|
|
- /* Make sure "none" of the offsets have an active mount. */
|
|
- while ((offset = cache_get_offset(mm_base, offset, start, mm_root, &pos))) {
|
|
- char *oe_base;
|
|
-
|
|
- oe = cache_lookup_offset(mm_base, offset, start, &me->multi_list);
|
|
- /* root offset is a special case */
|
|
- if (!oe || !oe->mapent || (strlen(oe->key) - start) == 1)
|
|
- continue;
|
|
-
|
|
- /*
|
|
- * Check for and umount subtree offsets resulting from
|
|
- * nonstrict mount fail.
|
|
- */
|
|
- oe_base = oe->key + strlen(root);
|
|
- left += umount_multi_triggers(ap, root, oe, oe_base);
|
|
-
|
|
- if (oe->ioctlfd != -1)
|
|
- left++;
|
|
- }
|
|
-
|
|
- if (left)
|
|
- return left;
|
|
-
|
|
- pos = NULL;
|
|
- offset = path;
|
|
-
|
|
- /* Make sure "none" of the offsets have an active mount. */
|
|
- while ((offset = cache_get_offset(mm_base, offset, start, mm_root, &pos))) {
|
|
- oe = cache_lookup_offset(mm_base, offset, start, &me->multi_list);
|
|
- /* root offset is a special case */
|
|
- if (!oe || !oe->mapent || (strlen(oe->key) - start) == 1)
|
|
- continue;
|
|
-
|
|
- debug(ap->logopt, "umount offset %s", oe->key);
|
|
-
|
|
- if (umount_autofs_offset(ap, oe)) {
|
|
- warn(ap->logopt, "failed to umount offset");
|
|
- left++;
|
|
- }
|
|
- }
|
|
-
|
|
- if (!left && me->multi == me) {
|
|
- struct mapent_cache *mc = me->mc;
|
|
- int status;
|
|
-
|
|
- /*
|
|
- * Special case.
|
|
- * If we can't umount the root container then we can't
|
|
- * delete the offsets from the cache and we need to put
|
|
- * the offset triggers back.
|
|
- */
|
|
- if (is_mounted(_PATH_MOUNTED, root, MNTS_REAL)) {
|
|
- info(ap->logopt, "unmounting dir = %s", root);
|
|
- if (umount_ent(ap, root)) {
|
|
- if (mount_multi_triggers(ap, root, me, "/") < 0)
|
|
- warn(ap->logopt,
|
|
- "failed to remount offset triggers");
|
|
- return left++;
|
|
- }
|
|
- }
|
|
-
|
|
- /* We're done - clean out the offsets */
|
|
- status = cache_delete_offset_list(mc, me->key);
|
|
- if (status != CHE_OK)
|
|
- warn(ap->logopt, "couldn't delete offset list");
|
|
- }
|
|
-
|
|
- return left;
|
|
-}
|
|
-
|