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|"

Reply via email to