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;
-}
-