Hi all,
I've been playing with autofs a bit, and decided I missed the "mount
everything" behaviour of Sun's automounter. Here's a patch which works well,
with a few caveats.
The key change is to allow programs started with lookup_program to return
multiple entries, and to allow them include the mountpoint. lookup_program
just reads all the output of the auto.net script and mounts all the appropriate
filesystems.
The main problems with it are:
- there's no way to make a skeleton if the host doesn't export everything from
/ down - but I'm working on a patch to the kernel portion of autofs to allow
this. I changed mount_nfs to try and make the directories leading up to the
mountpoint, so all it needs is for autofs to allow the Oz pgrp to create a
directory tree rather than just create directories in the autofs root.
- the mounts are not treated as a unit, so if some parts are not used for a
while they'll be unmounted, with no way of having them remount. This should
be pretty easy to fix.
- My test auto.net script just does stupid sed manipulation of showmount, and
doesn't bother to work out which exports this host is allowed to mount, and
whether it's rw/ro/etc. That just means the script needs improvement.
I've attached a patch against 3.1.3. It's pretty small and doesn't touch very
much. It works well here, but its still definitely prototype code.
BTW, I noticed there's some mention of this functionality in the TODO file,
which talks about how complex it is and how it needs a new multithreaded
protocol. Is there some subtlety I've missed? It doesn't seem that complex.
J
diff -r -N -u autofs-3.1.3/modules/lookup_program.c autofs-3.1.3-jsgf/modules/lo
okup_program.c
--- autofs-3.1.3/modules/lookup_program.c Tue Nov 3 13:21:14 1998
+++ autofs-3.1.3-jsgf/modules/lookup_program.c Mon Mar 15 02:44:14 1999
@@ -85,13 +85,20 @@
{
struct lookup_context *ctxt = (struct lookup_context *) context;
char mapent[MAPENT_MAX_LEN+1], *mapp;
+ char keyent[MAPENT_MAX_LEN+1], *keyp;
char errbuf[1024], *errp;
- char *p, ch;
+ char ch;
int pipefd[2], epipefd[2];
pid_t f;
int files_left;
- int status;
+ int status, errs;
fd_set readfds, ourfds;
+ struct maps {
+ const char *key;
+ const char *map;
+ struct maps *next;
+ } *maps = NULL, *mapend = NULL;
+ enum state { st_key, st_space, st_map } state;
syslog(LOG_DEBUG, MODPREFIX "looking up %s", name);
@@ -129,8 +136,10 @@
close(pipefd[1]);
close(epipefd[1]);
+ keyp = keyent;
mapp = mapent;
errp = errbuf;
+ state = st_key;
FD_ZERO(&ourfds);
FD_SET(pipefd[0],&ourfds);
@@ -148,12 +157,43 @@
if ( read(pipefd[0], &ch, 1) < 1 ) {
FD_CLR(pipefd[0], &ourfds);
files_left--;
- } else if ( mapp ) {
- if ( ch == '\n' ) {
- *mapp = '\0';
- mapp = NULL; /* End of line reached */
- } else if ( mapp-mapent < MAPENT_MAX_LEN )
- *(mapp++) = ch;
+ }
+ /* XXX deal with \-quoting */
+ switch(state)
+ {
+ case st_key:
+ if (isspace(ch)) {
+ *keyp = '\0';
+ state = st_space;
+ }
+ else if (keyp - keyent < MAPENT_MAX_LEN)
+ *keyp++ = ch;
+ break;
+ case st_space:
+ if (!isspace(ch)) {
+ *mapp++ = ch;
+ state = st_map;
+ }
+ break;
+ case st_map:
+ if (ch == '\n') {
+ struct maps *m = alloca(sizeof(*m));
+ *mapp = '\0';
+ m->map = strdup(mapent);
+ m->key = strdup(keyent);
+ m->next = NULL;
+ if (mapend != NULL)
+ mapend->next = m;
+ else
+ maps = m;
+ mapend = m;
+
+ mapp = mapent;
+ keyp = keyent;
+ state = st_key;
+ } else if (mapp - mapent < MAPENT_MAX_LEN)
+ *mapp++ = ch;
+ break;
}
}
if ( FD_ISSET(epipefd[0],&readfds) ) {
@@ -190,16 +230,26 @@
syslog(LOG_ERR, MODPREFIX "waitpid: %m");
return 1;
}
- if ( mapp == mapent || !WIFEXITED(status) || WEXITSTATUS(status) != 0 ) {
+ if ( maps == NULL || !WIFEXITED(status) || WEXITSTATUS(status) != 0 ) {
syslog(LOG_NOTICE, MODPREFIX "lookup for %s failed", name);
return 1;
}
- if ( (p = strchr(mapent,'\n')) ) *p = '\0';
-
- syslog(LOG_DEBUG, MODPREFIX "%s -> %s", name, mapent);
- return ctxt->parse->parse_mount(root,name,name_len,mapent,
- ctxt->parse->context);
+ errs = 0;
+ for(; maps != NULL; maps = maps->next)
+ {
+ int ret;
+ syslog(LOG_DEBUG, MODPREFIX "%s (%s) -> %s", name, maps->key, maps->map);
+
+ ret = ctxt->parse->parse_mount(root,maps->key,strlen(maps->key),
+ maps->map,
+ ctxt->parse->context);
+ free(maps->key);
+ free(maps->map);
+ if (ret)
+ errs++;
+ }
+ return errs;
}
int lookup_done(void *context)
diff -r -N -u autofs-3.1.3/modules/mount_nfs.c autofs-3.1.3-jsgf/modules/mount_n
fs.c
--- autofs-3.1.3/modules/mount_nfs.c Tue Nov 3 13:21:14 1998
+++ autofs-3.1.3-jsgf/modules/mount_nfs.c Mon Mar 15 02:44:21 1999
@@ -54,6 +54,25 @@
return 0;
}
+static int mkdir_path(const char *path, mode_t mode)
+{
+ char *buf = alloca(strlen(path)+1);
+ const char *cp = path, *lcp = path;
+ char *bp = buf;
+
+ do
+ if (cp != path && (*cp == '/' || *cp == '\0')) {
+ memcpy(bp, lcp, cp-lcp);
+ bp += cp-lcp;
+ lcp = cp;
+ *bp = '\0';
+ if (mkdir(buf, mode) == -1 && errno != EEXIST)
+ return -1;
+ }
+ while(*cp++ != '\0');
+ return 0;
+}
+
int mount_mount(const char *root, const char *name, int name_len,
const char *what, const char *fstype,
const char *options, void *context)
@@ -65,6 +84,9 @@
int sock, local, err;
size_t len;
+ syslog(LOG_DEBUG, MODPREFIX " root=%s name=%s what=%s, fstype=%s, options=%s"
,
+ root, name, what, fstype, options);
+
whatstr = alloca(strlen(what)+1);
if ( !whatstr ) {
syslog(LOG_NOTICE, MODPREFIX "alloca: %m");
@@ -176,8 +198,8 @@
*colon = ':';
syslog(LOG_DEBUG, MODPREFIX "calling mkdir %s", fullpath);
- if ( mkdir(fullpath, 0555) && errno != EEXIST ) {
- syslog(LOG_NOTICE, MODPREFIX "mkdir %s failed: %m", name);
+ if ( mkdir_path(fullpath, 0555)) {
+ syslog(LOG_NOTICE, MODPREFIX "mkdir_path %s failed: %m", name);
return 1;
}
diff -r -N -u autofs-3.1.3/samples/auto.net autofs-3.1.3-jsgf/samples/auto.net
--- autofs-3.1.3/samples/auto.net Wed Dec 31 16:00:00 1969
+++ autofs-3.1.3-jsgf/samples/auto.net Tue Mar 16 12:54:42 1999
@@ -0,0 +1,10 @@
+#!/bin/sh
+
+# Look at what a host is exporting to determine what we can mount.
+# This is wildly simplistic - no attempt is made to see whether we can mount
+# each filesystem, or whether its RO or RW. For the future...
+
+key="$1"
+opts="-fstype=nfs,soft,intr"
+
+showmount -e "$key" | tail +2 | sort | sed -e "s|^\([^ ]*\).*|$key\1 $opts $ke
y:\1|"