Ian Kent 890377
autofs-5.0.5 - dir map-type patch v2
Ian Kent 890377
Ian Kent 890377
From: Masatake YAMATO <yamato@redhat.com>
Ian Kent 890377
Ian Kent 890377
This is the second post of "dir map-type" patch.
Ian Kent 890377
Ian Kent 890377
Changes since last post:
Ian Kent 890377
Ian Kent 890377
	- Don't use auto. as prefix for included map.
Ian Kent 890377
          Use .autofs suffix instead. Suggested by Steve Linn.
Ian Kent 890377
Ian Kent 890377
	- Use scandir instead of using opendir/readdir/closedir.
Ian Kent 890377
Ian Kent 890377
Ian Kent 890377
What is dir map-type?
Ian Kent 890377
Ian Kent 890377
Ian Kent 890377
`dir' map-type is for including files under a directory into master
Ian Kent 890377
map.
Ian Kent 890377
`file' map-type can be used for including a file with + notation like:
Ian Kent 890377
Ian Kent 890377
       +/etc/auto.mine
Ian Kent 890377
Ian Kent 890377
in auto.master. However, for specifying a new file to be included you
Ian Kent 890377
have to edit auto.master file. Editing is also needed when you want to
Ian Kent 890377
remove the included file. When you have to do this with your shell
Ian Kent 890377
script you may have to use sed or awk.
Ian Kent 890377
Ian Kent 890377
`dir' map-type permits you adding new master map entries with cp
Ian Kent 890377
command and removing the entries with rm command. `dir' map-type is
Ian Kent 890377
inspired from /etc/httpd/conf.d and /etc/modprobe.d.
Ian Kent 890377
Ian Kent 890377
`dir' map-type can be used for included files under a directory
Ian Kent 890377
(e.g. /etc/auto.master.d) with + notation like:
Ian Kent 890377
Ian Kent 890377
      +dir:/etc/auto.master.d
Ian Kent 890377
Ian Kent 890377
in auto.master. With this notation /etc/auto.master.d/*.autofs files
Ian Kent 890377
are included except a file which name is started with ".".  With the
Ian Kent 890377
name of the file you can control whether a file under the directory is
Ian Kent 890377
included or not: the file which name ends with ".autofs" is included.
Ian Kent 890377
Ian Kent 890377
Ian Kent 890377
Signed-off-by: Masatake YAMATO <yamato@redhat.com>
Ian Kent 890377
---
Ian Kent 890377
Ian Kent ca38f0
 CHANGELOG            |    1 
Ian Kent 890377
 autofs.spec          |    2 
Ian Kent 890377
 daemon/lookup.c      |    3 -
Ian Kent 890377
 man/auto.master.5.in |   10 ++
Ian Kent 890377
 modules/Makefile     |    6 +
Ian Kent 890377
 modules/lookup_dir.c |  219 ++++++++++++++++++++++++++++++++++++++++++++++++++
Ian Kent 890377
 samples/auto.master  |    4 +
Ian Kent ca38f0
 7 files changed, 240 insertions(+), 5 deletions(-)
Ian Kent 890377
 create mode 100644 modules/lookup_dir.c
Ian Kent 890377
Ian Kent 890377
Ian Kent ca38f0
diff --git a/CHANGELOG b/CHANGELOG
Ian Kent ca38f0
index 7e86c84..5b988d4 100644
Ian Kent ca38f0
--- a/CHANGELOG
Ian Kent ca38f0
+++ b/CHANGELOG
Ian Kent ca38f0
@@ -8,6 +8,7 @@
Ian Kent ca38f0
 - fix LDAP result leaks on error paths.
Ian Kent ca38f0
 - code analysis fixes part 1.
Ian Kent ca38f0
 - fix not bind mounting local filesystem.
Ian Kent ca38f0
+- add "dir" map-type.
Ian Kent ca38f0
 
Ian Kent ca38f0
 28/06/2011 autofs-5.0.6
Ian Kent ca38f0
 -----------------------
Ian Kent 890377
diff --git a/autofs.spec b/autofs.spec
Ian Kent 890377
index 91d4f8b..82edd1e 100644
Ian Kent 890377
--- a/autofs.spec
Ian Kent 890377
+++ b/autofs.spec
Ian Kent 890377
@@ -67,6 +67,7 @@ mkdir -p -m755 $RPM_BUILD_ROOT%{_sbindir}
Ian Kent 890377
 mkdir -p -m755 $RPM_BUILD_ROOT%{_libdir}/autofs
Ian Kent 890377
 mkdir -p -m755 $RPM_BUILD_ROOT%{_mandir}/{man5,man8}
Ian Kent 890377
 mkdir -p -m755 $RPM_BUILD_ROOT/etc/sysconfig
Ian Kent 890377
+mkdir -p -m755 $RPM_BUILD_ROOT/etc/auto.master.d
Ian Kent 890377
 
Ian Kent 890377
 make install mandir=%{_mandir} initdir=/etc/rc.d/init.d INSTALLROOT=$RPM_BUILD_ROOT
Ian Kent 890377
 make -C redhat
Ian Kent 890377
@@ -104,6 +105,7 @@ fi
Ian Kent 890377
 %dir %{_libdir}/autofs
Ian Kent 890377
 %{_libdir}/autofs/*
Ian Kent 890377
 %{_mandir}/*/*
Ian Kent 890377
+%dir /etc/auto.master.d
Ian Kent 890377
 
Ian Kent 890377
 %changelog
Ian Kent 890377
 * Tue Jun 3 2011 Ian Kent <raven@themaw.net>
Ian Kent 890377
diff --git a/daemon/lookup.c b/daemon/lookup.c
Ian Kent 890377
index 958d8cc..098588c 100644
Ian Kent 890377
--- a/daemon/lookup.c
Ian Kent 890377
+++ b/daemon/lookup.c
Ian Kent 890377
@@ -176,7 +176,8 @@ int lookup_nss_read_master(struct master *master, time_t age)
Ian Kent 890377
 			    !strncmp(name, "nis:", 4) ||
Ian Kent 890377
 			    !strncmp(name, "nisplus:", 8) ||
Ian Kent 890377
 			    !strncmp(name, "ldap:", 5) ||
Ian Kent 890377
-			    !strncmp(name, "ldaps:", 6)) {
Ian Kent 890377
+			    !strncmp(name, "ldaps:", 6) ||
Ian Kent 890377
+			    !strncmp(name, "dir:", 4)) {
Ian Kent 890377
 				strncpy(source, name, tmp - name);
Ian Kent 890377
 
Ian Kent 890377
 				/*
Ian Kent 890377
diff --git a/man/auto.master.5.in b/man/auto.master.5.in
Ian Kent 890377
index de692d2..fff9943 100644
Ian Kent 890377
--- a/man/auto.master.5.in
Ian Kent 890377
+++ b/man/auto.master.5.in
Ian Kent 890377
@@ -107,6 +107,14 @@ appropriate certificate must be configured in the LDAP client.
Ian Kent 890377
 .B multi
Ian Kent 890377
 This map type allows the specification of multiple maps separated
Ian Kent 890377
 by "--". These maps are searched in order to resolve key lookups.
Ian Kent 890377
+.TP
Ian Kent 890377
+.B dir
Ian Kent 890377
+This map type can be used at
Ian Kent 890377
+.BR +
Ian Kent 890377
+master map including notation. The contents of files under given directory are included
Ian Kent 890377
+to the master map. The name of file to be included must be ended with ".autofs". A file
Ian Kent 890377
+will be ignored if its name is not ended with the suffix. In addition a dot file, a file
Ian Kent 890377
+which name is started with "." is also ignored.
Ian Kent 890377
 .RE
Ian Kent 890377
 .TP
Ian Kent 890377
 \fBformat\fP
Ian Kent 890377
@@ -118,7 +126,7 @@ left unspecified, it defaults to \fBsun\fP for all map types except
Ian Kent 890377
 .TP
Ian Kent 890377
 \fBmap\fP
Ian Kent 890377
 Name of the map to use.  This is an absolute UNIX pathname
Ian Kent 890377
-for maps of types \fBfile\fP or \fBprogram\fP, and the name of a database
Ian Kent 890377
+for maps of types \fBfile\fP, \fBdir\fP, or \fBprogram\fP, and the name of a database
Ian Kent 890377
 in the case for maps of type \fByp\fP, \fBnisplus\fP, or \fBhesiod\fP or
Ian Kent 890377
 the \fBdn\fP of an LDAP entry for maps of type \fBldap\fP.
Ian Kent 890377
 .TP
Ian Kent 890377
diff --git a/modules/Makefile b/modules/Makefile
Ian Kent 890377
index a35c0a5..6090127 100644
Ian Kent 890377
--- a/modules/Makefile
Ian Kent 890377
+++ b/modules/Makefile
Ian Kent 890377
@@ -5,14 +5,14 @@
Ian Kent 890377
 -include ../Makefile.conf
Ian Kent 890377
 include ../Makefile.rules
Ian Kent 890377
 
Ian Kent 890377
-SRCS :=	lookup_yp.c  lookup_file.c  lookup_program.c  lookup_userhome.c \
Ian Kent 890377
-	lookup_multi.c lookup_hosts.c \
Ian Kent 890377
+SRCS :=	lookup_yp.c  lookup_file.c lookup_program.c  lookup_userhome.c \
Ian Kent 890377
+	lookup_multi.c lookup_hosts.c lookup_dir.c \
Ian Kent 890377
 	parse_sun.c    \
Ian Kent 890377
 	mount_generic.c  mount_nfs.c  mount_afs.c  mount_autofs.c \
Ian Kent 890377
 	mount_changer.c  mount_bind.c
Ian Kent 890377
 
Ian Kent 890377
 MODS :=	lookup_yp.so lookup_file.so lookup_program.so lookup_userhome.so \
Ian Kent 890377
-	lookup_multi.so lookup_hosts.so \
Ian Kent 890377
+	lookup_multi.so lookup_hosts.so lookup_dir.so \
Ian Kent 890377
 	parse_sun.so \
Ian Kent 890377
 	mount_generic.so mount_nfs.so mount_afs.so mount_autofs.so \
Ian Kent 890377
 	mount_changer.so mount_bind.so
Ian Kent 890377
diff --git a/modules/lookup_dir.c b/modules/lookup_dir.c
Ian Kent 890377
new file mode 100644
Ian Kent 890377
index 0000000..658cc29
Ian Kent 890377
--- /dev/null
Ian Kent 890377
+++ b/modules/lookup_dir.c
Ian Kent 890377
@@ -0,0 +1,219 @@
Ian Kent 890377
+/* ----------------------------------------------------------------------- *
Ian Kent 890377
+ *
Ian Kent 890377
+ *  lookup_dir.c - module for including master files in a directory.
Ian Kent 890377
+ *
Ian Kent 890377
+ * Copyright 2011 Red Hat, Inc. All rights reserved.
Ian Kent 890377
+ * Copyright 2011 Masatake YAMATO <yamato@redhat.com>
Ian Kent 890377
+ *
Ian Kent 890377
+ * This program is free software; you can redistribute it and/or modify
Ian Kent 890377
+ * it under the terms of the GNU General Public License as published by
Ian Kent 890377
+ * the Free Software Foundation, Inc., 675 Mass Ave, Cambridge MA 02139,
Ian Kent 890377
+ * USA; either version 2 of the License, or (at your option) any later
Ian Kent 890377
+ * version.
Ian Kent 890377
+ *
Ian Kent 890377
+ * This program is distributed in the hope that it will be useful,
Ian Kent 890377
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
Ian Kent 890377
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Ian Kent 890377
+ * GNU General Public License for more details.
Ian Kent 890377
+ *
Ian Kent 890377
+ * ----------------------------------------------------------------------- */
Ian Kent 890377
+
Ian Kent 890377
+#include <stdio.h>
Ian Kent 890377
+#include <malloc.h>
Ian Kent 890377
+#include <pwd.h>
Ian Kent 890377
+#include <string.h>
Ian Kent 890377
+#include <sys/param.h>
Ian Kent 890377
+#include <sys/types.h>
Ian Kent 890377
+#include <sys/stat.h>
Ian Kent 890377
+#include <dirent.h>
Ian Kent 890377
+
Ian Kent 890377
+
Ian Kent 890377
+#define MODULE_LOOKUP
Ian Kent 890377
+#include "automount.h"
Ian Kent 890377
+#include "nsswitch.h"
Ian Kent 890377
+
Ian Kent 890377
+#define MODPREFIX "lookup(dir): "
Ian Kent 890377
+
Ian Kent 890377
+#define MAX_INCLUDE_DEPTH	16
Ian Kent 890377
+
Ian Kent 890377
+#define AUTOFS_DIR_EXT ".autofs"
Ian Kent 890377
+#define AUTOFS_DIR_EXTSIZ (sizeof(AUTOFS_DIR_EXT) - 1)
Ian Kent 890377
+
Ian Kent 890377
+struct lookup_context {
Ian Kent 890377
+  const char *mapname;
Ian Kent 890377
+};
Ian Kent 890377
+
Ian Kent 890377
+int lookup_version = AUTOFS_LOOKUP_VERSION;	/* Required by protocol */
Ian Kent 890377
+
Ian Kent 890377
+
Ian Kent 890377
+int lookup_init(const char *mapfmt, int argc, const char *const *argv, void **context)
Ian Kent 890377
+{
Ian Kent 890377
+	struct lookup_context *ctxt;
Ian Kent 890377
+	char buf[MAX_ERR_BUF];
Ian Kent 890377
+	struct stat st;
Ian Kent 890377
+
Ian Kent 890377
+	*context = NULL;
Ian Kent 890377
+	ctxt = malloc(sizeof(struct lookup_context));
Ian Kent 890377
+	if (!ctxt) {
Ian Kent 890377
+		char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
Ian Kent 890377
+		logerr(MODPREFIX "malloc: %s", estr);
Ian Kent 890377
+		return 1;
Ian Kent 890377
+	}
Ian Kent 890377
+
Ian Kent 890377
+	if (argc < 1) {
Ian Kent 890377
+		free(ctxt);
Ian Kent 890377
+		logerr(MODPREFIX "No map name");
Ian Kent 890377
+		return 1;
Ian Kent 890377
+	}
Ian Kent 890377
+
Ian Kent 890377
+	ctxt->mapname = argv[0];
Ian Kent 890377
+
Ian Kent 890377
+	if (ctxt->mapname[0] != '/') {
Ian Kent 890377
+		free(ctxt);
Ian Kent 890377
+		logmsg(MODPREFIX
Ian Kent 890377
+		     "dir map %s is not an absolute pathname", argv[0]);
Ian Kent 890377
+		return 1;
Ian Kent 890377
+	}
Ian Kent 890377
+
Ian Kent 890377
+	if (access(ctxt->mapname, R_OK)) {
Ian Kent 890377
+		free(ctxt);
Ian Kent 890377
+		warn(LOGOPT_NONE, MODPREFIX
Ian Kent 890377
+		     "dir map %s missing or not readable", argv[0]);
Ian Kent 890377
+		return 1;
Ian Kent 890377
+	}
Ian Kent 890377
+
Ian Kent 890377
+	if (stat(ctxt->mapname, &st)) {
Ian Kent 890377
+		free(ctxt);
Ian Kent 890377
+		warn(LOGOPT_NONE, MODPREFIX
Ian Kent 890377
+		     "dir map %s, could not stat", argv[0]);
Ian Kent 890377
+		return 1;
Ian Kent 890377
+	}
Ian Kent 890377
+
Ian Kent 890377
+	if ( (!S_ISDIR(st.st_mode)) && (!S_ISLNK(st.st_mode)) ) {
Ian Kent 890377
+		free(ctxt);
Ian Kent 890377
+		warn(LOGOPT_NONE, MODPREFIX
Ian Kent 890377
+		     "dir map %s, is not a directory", argv[0]);
Ian Kent 890377
+	}
Ian Kent 890377
+
Ian Kent 890377
+	*context = ctxt;
Ian Kent 890377
+	return 0;
Ian Kent 890377
+}
Ian Kent 890377
+
Ian Kent 890377
+static int acceptable_dirent_p(const struct dirent *e)
Ian Kent 890377
+{
Ian Kent 890377
+  size_t namesz;
Ian Kent 890377
+
Ian Kent 890377
+
Ian Kent 890377
+  if (!(e->d_type == DT_REG || e->d_type == DT_LNK))
Ian Kent 890377
+	  return 0;
Ian Kent 890377
+
Ian Kent 890377
+  namesz = strlen(e->d_name);
Ian Kent 890377
+  if (!namesz)
Ian Kent 890377
+	  return 0;
Ian Kent 890377
+
Ian Kent 890377
+  if (e->d_name[0] == '.')
Ian Kent 890377
+	  return 0;
Ian Kent 890377
+
Ian Kent 890377
+  if (namesz < AUTOFS_DIR_EXTSIZ + 1 ||
Ian Kent 890377
+      strcmp(e->d_name + (namesz - AUTOFS_DIR_EXTSIZ),
Ian Kent 890377
+	     AUTOFS_DIR_EXT))
Ian Kent 890377
+	  return 0;
Ian Kent 890377
+
Ian Kent 890377
+  return 1;
Ian Kent 890377
+}
Ian Kent 890377
+
Ian Kent 890377
+
Ian Kent 890377
+static int include_file(struct master *master, time_t age, struct lookup_context* ctxt, struct dirent *e)
Ian Kent 890377
+{
Ian Kent 890377
+	unsigned int logopt = master->logopt;
Ian Kent 890377
+	char included_path[PATH_MAX + 1];
Ian Kent 890377
+	int included_path_len;
Ian Kent 890377
+	char *save_name;
Ian Kent 890377
+	int status;
Ian Kent 890377
+
Ian Kent 890377
+	included_path_len = snprintf(included_path,
Ian Kent 890377
+				     PATH_MAX + 1,
Ian Kent 890377
+				     "%s/%s",
Ian Kent 890377
+				     ctxt->mapname,
Ian Kent 890377
+				     e->d_name);
Ian Kent 890377
+	if (included_path_len > PATH_MAX)
Ian Kent 890377
+		return NSS_STATUS_NOTFOUND;
Ian Kent 890377
+
Ian Kent 890377
+	save_name = master->name;
Ian Kent 890377
+	master->name = included_path;
Ian Kent 890377
+
Ian Kent 890377
+	master->depth++;
Ian Kent 890377
+	debug(logopt, MODPREFIX "include: %s", master->name);
Ian Kent 890377
+	status = lookup_nss_read_master(master, age);
Ian Kent 890377
+	if (!status) {
Ian Kent 890377
+		warn(logopt,
Ian Kent 890377
+		     MODPREFIX
Ian Kent 890377
+		     "failed to read included master map %s",
Ian Kent 890377
+		     master->name);
Ian Kent 890377
+	}
Ian Kent 890377
+	master->depth--;
Ian Kent 890377
+
Ian Kent 890377
+	master->name = save_name;
Ian Kent 890377
+	return NSS_STATUS_SUCCESS;
Ian Kent 890377
+}
Ian Kent 890377
+
Ian Kent 890377
+
Ian Kent 890377
+int lookup_read_master(struct master *master, time_t age, void *context)
Ian Kent 890377
+{
Ian Kent 890377
+        int n, i;
Ian Kent 890377
+	struct dirent **namelist = NULL;
Ian Kent 890377
+	struct lookup_context *ctxt = (struct lookup_context *) context;
Ian Kent 890377
+	unsigned int logopt = master->logopt;
Ian Kent 890377
+	char buf[MAX_ERR_BUF];
Ian Kent 890377
+
Ian Kent 890377
+
Ian Kent 890377
+	if (master->depth > MAX_INCLUDE_DEPTH) {
Ian Kent 890377
+		error(logopt, MODPREFIX
Ian Kent 890377
+		      "maximum include depth exceeded %s", master->name);
Ian Kent 890377
+		return NSS_STATUS_UNAVAIL;
Ian Kent 890377
+	}
Ian Kent 890377
+
Ian Kent 890377
+	debug(logopt, MODPREFIX "scandir: %s", ctxt->mapname);
Ian Kent 890377
+	n = scandir(ctxt->mapname, &namelist, acceptable_dirent_p, versionsort);
Ian Kent 890377
+	if (n < 0) {
Ian Kent 890377
+	       char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
Ian Kent 890377
+
Ian Kent 890377
+		error(logopt,
Ian Kent 890377
+		      MODPREFIX "could not scan master map dir %s: %s",
Ian Kent 890377
+		      ctxt->mapname,
Ian Kent 890377
+		      estr);
Ian Kent 890377
+		return NSS_STATUS_UNAVAIL;
Ian Kent 890377
+	}
Ian Kent 890377
+
Ian Kent 890377
+	for (i = 0; i < n; i++) {
Ian Kent 890377
+		struct dirent *e = namelist[i];
Ian Kent 890377
+
Ian Kent 890377
+		include_file(master, age, ctxt, e);
Ian Kent 890377
+		free(e);
Ian Kent 890377
+	}
Ian Kent 890377
+	free(namelist);
Ian Kent 890377
+
Ian Kent 890377
+	return NSS_STATUS_SUCCESS;
Ian Kent 890377
+}
Ian Kent 890377
+
Ian Kent 890377
+int lookup_read_map(struct autofs_point *ap, time_t age, void *context)
Ian Kent 890377
+{
Ian Kent 890377
+	ap->entry->current = NULL;
Ian Kent 890377
+	master_source_current_signal(ap->entry);
Ian Kent 890377
+	return NSS_STATUS_UNKNOWN;
Ian Kent 890377
+}
Ian Kent 890377
+
Ian Kent 890377
+int lookup_mount(struct autofs_point *ap, const char *name, int name_len, void *context)
Ian Kent 890377
+{
Ian Kent 890377
+	ap->entry->current = NULL;
Ian Kent 890377
+	master_source_current_signal(ap->entry);
Ian Kent 890377
+	return NSS_STATUS_UNKNOWN;
Ian Kent 890377
+}
Ian Kent 890377
+
Ian Kent 890377
+int lookup_done(void *context)
Ian Kent 890377
+{
Ian Kent 890377
+	struct lookup_context *ctxt = (struct lookup_context *) context;
Ian Kent 890377
+
Ian Kent 890377
+	free(ctxt);
Ian Kent 890377
+	return 0;
Ian Kent 890377
+}
Ian Kent 890377
diff --git a/samples/auto.master b/samples/auto.master
Ian Kent 890377
index 9fe5609..72f086c 100644
Ian Kent 890377
--- a/samples/auto.master
Ian Kent 890377
+++ b/samples/auto.master
Ian Kent 890377
@@ -12,6 +12,10 @@
Ian Kent 890377
 #
Ian Kent 890377
 /net	-hosts
Ian Kent 890377
 #
Ian Kent 890377
+# Include /etc/auto.master.d/*.autofs
Ian Kent 890377
+#
Ian Kent 890377
++dir:/etc/auto.master.d
Ian Kent 890377
+#
Ian Kent 890377
 # Include central master map if it can be found using
Ian Kent 890377
 # nsswitch sources.
Ian Kent 890377
 #