--- autofs-4.1.3/modules/parse_sun.c.multi-over 2005-01-17 21:49:30.000000000 +0800 +++ autofs-4.1.3/modules/parse_sun.c 2005-01-17 21:51:06.000000000 +0800 @@ -55,6 +55,13 @@ int slashify_colons; /* Change colons to slashes? */ }; +struct multi_mnt { + char *path; + char *options; + char *location; + struct multi_mnt *next; +}; + struct utsname un; char processor[65]; /* Not defined on Linux, so we make our own */ @@ -609,6 +616,69 @@ } /* + * Build list of mounts in shortest -> longest order. + * Pass in list head and return list head. + */ +struct multi_mnt *multi_add_list(struct multi_mnt *list, + char *path, char *options, char *location) +{ + struct multi_mnt *mmptr, *new, *old = NULL; + int plen; + + if (!path || !options || !location) + return NULL; + + new = malloc(sizeof(struct multi_mnt)); + if (!new) + return NULL; + + new->path = path; + new->options = options; + new->location = location; + + plen = strlen(path); + mmptr = list; + while (mmptr) { + if (plen <= strlen(mmptr->path)) + break; + old = mmptr; + mmptr = mmptr->next; + } + + if (old) + old->next = new; + new->next = mmptr; + + return old ? list : new; +} + +void multi_free_list(struct multi_mnt *list) +{ + struct multi_mnt *next; + + if (!list) + return; + + next = list; + while (next) { + struct multi_mnt *this = next; + + next = this->next; + + if (this->path) + free(this->path); + + if (this->options) + free(this->options); + + if (this->location) + free(this->location); + + free(this); + } +} + +/* * syntax is: * [-options] location [location] ... * [-options] [mountpoint [-options] location [location] ... ]... @@ -661,6 +731,7 @@ debug(MODPREFIX "gathered options: %s", options); if (*p == '/') { + struct multi_mnt *list, *head = NULL, *next; int l; char *multi_root; @@ -679,16 +750,15 @@ do { char *myoptions = strdup(options); char *path, *loc; - int pathlen, loclen; if (myoptions == NULL) { error(MODPREFIX "multi strdup: %m"); free(options); + multi_free_list(head); return 1; } path = dequote(p, l = chunklen(p, 0)); - pathlen = strlen(path); p += l; p = skipspace(p); @@ -706,6 +776,7 @@ "multi concat_options: %m"); free(options); free(path); + multi_free_list(head); return 1; } p = skipspace(p); @@ -721,28 +792,42 @@ l = q - p; loc = dequote(p, l); - loclen = strlen(loc); - if (loc == NULL || path == NULL) { error(MODPREFIX "out of memory"); free(loc); free(path); free(options); + free(myoptions); + multi_free_list(head); return 1; } p += l; p = skipspace(p); + list = head; + head = multi_add_list(list, path, myoptions, loc); + if (!head) { + free(loc); + free(path); + free(options); + free(myoptions); + multi_free_list(list); + return 1; + } + } while (*p == '/'); + + next = head; + while (next) { debug(MODPREFIX "multimount: %.*s on %.*s with options %s", - loclen, loc, pathlen, path, myoptions); + strlen(next->location), next->location, + strlen(next->path), next->path, next->options); - rv = sun_mount(multi_root, path, pathlen, loc, loclen, - myoptions); - free(path); - free(loc); - free(myoptions); + rv = sun_mount(multi_root, + next->path, strlen(next->path), + next->location, strlen(next->location), + next->options); /* Convert non-strict failure into success */ if (rv < 0) { @@ -751,7 +836,10 @@ } else if (rv > 0) break; - } while (*p == '/'); + next = next->next; + } + + multi_free_list(head); free(options); return rv;