summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authoralfred <alfred@FreeBSD.org>2004-08-31 16:26:01 +0000
committeralfred <alfred@FreeBSD.org>2004-08-31 16:26:01 +0000
commite39e879ede3eb48cca848118af6f9fb6435c7241 (patch)
tree9b36a14c0b5776cc37fcd05bce3ca649ad5374ea
parent07c612deeed1a0a85162274839c59b67c9aa472a (diff)
downloadFreeBSD-src-e39e879ede3eb48cca848118af6f9fb6435c7241.zip
FreeBSD-src-e39e879ede3eb48cca848118af6f9fb6435c7241.tar.gz
Enter the autofs.
-rw-r--r--lib/libautofs/Makefile14
-rw-r--r--lib/libautofs/libautofs.3238
-rw-r--r--lib/libautofs/libautofs.c465
-rw-r--r--lib/libautofs/libautofs.h103
-rw-r--r--sbin/mount_autofs/Makefile8
-rw-r--r--sbin/mount_autofs/mount_autofs.871
-rw-r--r--sbin/mount_autofs/mount_autofs.c103
-rw-r--r--share/examples/autofs/driver/Makefile18
-rw-r--r--share/examples/autofs/driver/autodriver.c510
-rw-r--r--share/examples/autofs/driver/autotab7
-rw-r--r--share/man/man5/autofs.558
11 files changed, 1595 insertions, 0 deletions
diff --git a/lib/libautofs/Makefile b/lib/libautofs/Makefile
new file mode 100644
index 0000000..92945c9
--- /dev/null
+++ b/lib/libautofs/Makefile
@@ -0,0 +1,14 @@
+# $Id: Makefile,v 1.3 2004/08/31 08:49:56 bright Exp $
+# $FreeBSD$
+
+LIB=autofs
+SHLIB_MAJOR= 1
+SHLIB_MINOR= 0
+WARNS=4
+CFLAGS+= -I${.CURDIR}/../autofs -Werror
+CFLAGS+= -g
+
+SRCS= libautofs.c
+MAN+= libautofs.3
+
+.include <bsd.lib.mk>
diff --git a/lib/libautofs/libautofs.3 b/lib/libautofs/libautofs.3
new file mode 100644
index 0000000..2875c06
--- /dev/null
+++ b/lib/libautofs/libautofs.3
@@ -0,0 +1,238 @@
+.\" Copyright (c) 2004 Alfred Perlstein <alfred@FreeBSD.org>
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $Id: libautofs.3,v 1.3 2004/08/31 15:58:40 bright Exp $
+.\" $FreeBSD$
+.Dd August 30, 2004
+.Dt LIBAUTOFS 3
+.Os
+.Sh NAME
+.Nm libautofs
+.Nd "procedural interface to managing an autofs filesystem"
+.Sh SYNOPSIS
+.In libautofs.h
+.Ft int
+.Fn autoh_get "const char *path" "autoh_t *hndlp"
+.Ft void
+.Fn autoh_free "autoh_t hndl"
+.Ft int
+.Fn autoh_getall "autoh_t **hndlpp" "int *cnt"
+.Ft void
+.Fn autoh_freeall "autoh_t *hndlep"
+.Ft int
+.Fn autoh_fd "autoh_t hndl"
+.Ft const char *
+.Fn autoh_mp "autoh_t hndl"
+.Ft int
+.Fn autoreq_get "autoh_t hndl" "autoreq_t **reqpp" "int *cntp"
+.Ft void
+.Fn autoreq_free "autoh_t hndl" "autoreq_t *reqp"
+.Ft int
+.Fn autoreq_serv "autoh_t hndl" "autoreq_t req"
+.Ft enum autoreq_op
+.Fn autoreq_getop "autoreq_t req"
+.Ft const char *
+.Fn autoreq_getpath "autoreq_t req"
+.Ft autoino_t
+.Fn autoreq_getino "autoreq_t req"
+.Ft autoino_t
+.Fn autoreq_getdirino "autoreq_t req"
+.Ft void
+.Fn autoreq_getaux "autoreq_t req" "void **auxdatap" "size_t *auxsizep"
+.Ft void
+.Fn autoreq_getoffset "autoreq_t req" "off_t *offp"
+.Ft void
+.Fn autoreq_setino "autoreq_t req" "autoino_t ino"
+.Ft void
+.Fn autoreq_seterrno "autoreq_t req" "int errno"
+.Ft void
+.Fn autoreq_setaux "autoreq_t req" "void *auxdata" "size_t auxsize"
+.Ft void
+.Fn autoreq_seteof "autoreq_t req" "int eof"
+.Ft int
+.Fn autoh_togglepath "autoh_t hndl" "int toggle" "pid_t pid" "const char *path"
+.Ft int
+.Fn autoh_togglefd "autoh_t hndl" "int toggle" "pid_t pid" "int fd"
+.Sh DESCRIPTION
+The
+.Nm libautofs
+libarary provides a "mostly" stable interface to the
+.Xr autofs 9
+filesystem.
+.Pp
+The inteface to
+.Xr autofs 9
+is managed via handles of type
+.Fa autoh_t
+and
+.Fa autoreq_t
+which refer to handles to
+.Xr autofs 9
+mount points and requests respectively.
+.Pp
+The
+.Fn autoh_get
+function returns a handle to an
+.Xr autofs 9
+filesystem based on the
+.Fn path
+parameter.
+The handle returned should be freed via the
+.Fn autoh_free
+function.
+.Pp
+The
+.Fn autoh_getall
+function returns an array of handles to all mounted
+.Xr autofs 9
+filesystems, each of which should be released via the
+.Fn autoh_free
+function or released en-mass via the
+.Fn autoh_freeall
+function.
+.Pp
+The
+.Fn autoh_fd
+function returns a file descriptor that can selected or polled on
+for "excecption" data to detect an
+.Xr autofs 9
+event.
+.Pp
+The
+.Fn autoh_mp
+function returns the path to the autofs filesystem that the
+.Fa hndl
+is derived from.
+.Pp
+The
+.Fn autoreq_get
+function returns an array of autofs requests in
+.Fa reqpp ,
+the number of requests is stored into
+.Fa cntp .
+Each request should be released using the
+.Fn autoreq_free
+function.
+.Pp
+Requests that are retrieved via the
+.Fn autoreq_get
+are served via the "autoreq_" functions.
+.Pp
+The following functions returns information about the request.
+.Bl -tag -width indent
+.It Fn autoreq_getop
+return the operation type of the request, that would be one of
+AUTOREQ_OP_UNKNOWN, AUTOREQ_OP_LOOKUP, AUTOREQ_OP_STAT, AUTOREQ_OP_READDIR
+depending on the type of request that
+.Xr autofs 9
+requires service from.
+.It Fn autoreq_getpath
+return the path of the mountpoint associated with the request
+.Fa req .
+.It Fn autoreq_getino
+return the inode associated with the request
+.Fa req .
+.It Fn autoreq_getdirno
+return the directory inode associated with the request
+.Fa req .
+.It Fn autoreq_getaux
+return the auxilliray data associated with the request
+.Fa req .
+.It Fn autoreq_getoffset
+return the offset request associated with the request
+.Fa req .
+(used for readdir request)
+.El
+.Pp
+The following functions allow one to set the response sent to
+.Xr autofs 9
+to the requesting userland application.
+.Bl -tag -width indent
+.It Fn autoreq_setino
+Set the request
+.Fa req
+inode to
+.Fa ino ,
+this is typically unused.
+.It Fn autoreq_seterrno
+set the error returned to the application sending the request, typically
+this is left alone, or set to ENOENT if the request is for a non-existant
+name. The default error is no error. Meaning the application will see
+a successful return.
+.It Fn autoreq_setaux
+used to set the auxilliray data for a request, currently used to set
+the dirent structures for serving a readdir request. Default is no
+auxilliary data.
+.It Fn autoreq_seteof
+used to set the eof flag for readdir requests (default is not eof.)
+.El
+.Pp
+The functions
+.Fn autoh_togglepath
+and
+.Fn autoh_togglefd
+are used to set options on an
+.Xr autofs 9
+directory via
+.Fa path
+and
+.Fa fd
+respectively. The
+.Fa pid
+argument should be set to the pid of the process serving
+.Xr autofs 9
+requests, or -1 to disable the option. The options are
+.Bl -tag -width AUTO_INDIRECT
+.It Fa AUTO_MOUNTER
+set this process as the one responsible for the
+.Xr autofs 9
+node, if this process exits, then requests into the autofs will begin to fail.
+.It Fa AUTO_BROWSE
+dispatch directory read requests for this node to the process identified by
+.Fa pid .
+Specifically, calls to
+.Xr getdirentries 2
+and
+.Xr getdents 2
+will be routed to userland after the current actual directory contents
+are read into userland.
+.It Fa AUTO_DIRECT
+Set the directory as a mount trigger. Any request to enter the directory
+will trigger a callback into the process
+.Fa pid .
+.It Fa AUTO_INDIRECT
+Set the directory as an indirect trigger. Any request for an entry inside
+the directory will be routed to the process identified by
+.Fa pid .
+.El
+.Sh EXAMPLES
+See /usr/share/examples/autofs/driver/
+.Sh HISTORY
+The
+.Nm
+utility first appeared in
+.Fx 6.0 .
+.Sh AUTHORS
+This manual page and the autofs filesystem suite were written by
+.An Alfred Perlstein .
diff --git a/lib/libautofs/libautofs.c b/lib/libautofs/libautofs.c
new file mode 100644
index 0000000..f68e904
--- /dev/null
+++ b/lib/libautofs/libautofs.c
@@ -0,0 +1,465 @@
+/*
+ * Copyright (c) 2004 Alfred Perlstein <alfred@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ * $Id: libautofs.c,v 1.3 2004/08/31 08:49:56 bright Exp $
+ */
+#include <err.h>
+#include <ctype.h>
+#include <err.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/mount.h>
+#include <sys/poll.h>
+#include <sys/stat.h>
+#include <sys/sysctl.h>
+
+#include <autofs.h>
+
+#include "libautofs.h"
+
+struct auto_handle {
+ char ah_mp[MNAMELEN];
+ fsid_t ah_fsid;
+ int ah_fd;
+};
+
+static int autofs_sysctl(int, fsid_t *, void *, size_t *, void *, size_t);
+static void safe_free(void *ptr);
+static int getmntlst(struct statfs **sfsp, int *cntp);
+
+static void
+safe_free(void *ptr)
+{
+ int saved_errno;
+
+ saved_errno = errno;
+ free(ptr);
+ errno = saved_errno;
+}
+
+int
+getmntlst(struct statfs **sfsp, int *cntp)
+{
+ int cnt;
+ long bufsize;
+
+ *sfsp = NULL;
+ cnt = getfsstat(NULL, 0, MNT_NOWAIT);
+ bufsize = cnt * sizeof(**sfsp);
+ fprintf(stderr, "getmntlst bufsize %ld, cnt %d\n", bufsize, cnt);
+ *sfsp = malloc(bufsize);
+ if (sfsp == NULL)
+ goto err;
+ cnt = getfsstat(*sfsp, bufsize, MNT_NOWAIT);
+ if (cnt == -1)
+ goto err;
+ *cntp = cnt;
+ fprintf(stderr, "getmntlst ok, cnt %d\n", cnt);
+ return (0);
+err:
+ safe_free(sfsp);
+ *sfsp = NULL;
+ fprintf(stderr, "getmntlst bad\n");
+ return (-1);
+}
+
+/* get a handle based on a path. */
+int
+autoh_get(const char *path, autoh_t *ahp)
+{
+ struct statfs *sfsp, *sp;
+ int cnt, fd, i;
+ autoh_t ret;
+
+ ret = NULL;
+ /*
+ * We use getfsstat to prevent avoid the lookups on the mountpoints
+ * that statfs(2) would do.
+ */
+ if (getmntlst(&sfsp, &cnt))
+ goto err;
+ for (i = 0; i < cnt; i++) {
+ if (strcmp(sfsp[i].f_mntonname, path) == 0)
+ break;
+ }
+ if (i == cnt) {
+ fprintf(stderr, "autoh_get bad %d %d\n", i, cnt);
+ errno = ENOENT;
+ goto err;
+ }
+ sp = &sfsp[i];
+ if (strcmp(sp->f_fstypename, "autofs")) {
+ errno = ENOTTY;
+ goto err;
+ }
+ fd = open(sp->f_mntonname, O_RDONLY);
+ if (fd == -1)
+ goto err;
+ ret = malloc(sizeof(*ret));
+ if (ret == NULL)
+ goto err;
+
+ ret->ah_fsid = sp->f_fsid;
+ ret->ah_fd = fd;
+ strlcpy(ret->ah_mp, sp->f_mntonname, sizeof(ret->ah_mp));
+ safe_free(sfsp);
+ *ahp = ret;
+ return (0);
+err:
+ safe_free(ret);
+ safe_free(sfsp);
+ return (-1);
+}
+
+/* release. */
+void
+autoh_free(autoh_t ah)
+{
+ int saved_errno;
+
+ saved_errno = errno;
+ close(ah->ah_fd);
+ free(ah);
+ errno = saved_errno;
+}
+
+/*
+ * Get an array of pointers to all the currently mounted autofs
+ * instances.
+ */
+int
+autoh_getall(autoh_t **arrayp, int *cntp)
+{
+ struct statfs *sfsp;
+ int cnt, i, pos;
+ autoh_t *array;
+
+ array = NULL;
+ /*
+ * We use getfsstat to prevent avoid the lookups on the mountpoints
+ * that statfs(2) would do.
+ */
+ if (getmntlst(&sfsp, &cnt))
+ goto err;
+ array = *arrayp = calloc(cnt + 1, sizeof(**arrayp));
+ if (array == NULL)
+ goto err;
+ for (i = 0, pos = 0; i < cnt; i++) {
+ if (autoh_get(sfsp[i].f_mntonname, &array[pos]) == -1) {
+ /* not an autofs entry, that's ok, otherwise bail */
+ if (errno == ENOTTY)
+ continue;
+ goto err;
+ }
+ pos++;
+ }
+ if (pos == 0) {
+ errno = ENOENT;
+ goto err;
+ }
+ *arrayp = array;
+ *cntp = pos;
+ safe_free(sfsp);
+ return (0);
+err:
+ safe_free(sfsp);
+ if (array)
+ autoh_freeall(array);
+ return (-1);
+}
+
+/* release. */
+void
+autoh_freeall(autoh_t *ah)
+{
+
+ while (*ah != NULL) {
+ autoh_free(*ah);
+ ah++;
+ }
+ safe_free(ah);
+}
+
+/* return fd to select on. */
+int
+autoh_fd(autoh_t ah)
+{
+
+ return (ah->ah_fd);
+}
+
+const char *
+autoh_mp(autoh_t ah)
+{
+
+ return (ah->ah_mp);
+}
+
+static int do_autoreq_get(autoh_t ah, autoreq_t *reqp, int *cntp);
+
+/* get an array of pending requests */
+int
+autoreq_get(autoh_t ah, autoreq_t **reqpp, int *cntp)
+{
+ int cnt, i;
+ autoreq_t req, *reqp;
+
+ if (do_autoreq_get(ah, &req, &cnt))
+ return (-1);
+
+ reqp = calloc(cnt + 1, sizeof(*reqp));
+ if (reqp == NULL) {
+ safe_free(req);
+ return (-1);
+ }
+ for (i = 0; i < cnt; i++)
+ reqp[i] = &req[i];
+ *reqpp = reqp;
+ *cntp = cnt;
+ return (0);
+}
+
+int
+do_autoreq_get(autoh_t ah, autoreq_t *reqp, int *cntp)
+{
+ size_t olen;
+ struct autofs_userreq *reqs;
+ int cnt, error;
+ int vers;
+
+ vers = AUTOFS_PROTOVERS;
+
+ error = 0;
+ reqs = NULL;
+ olen = 0;
+ cnt = 0;
+ error = autofs_sysctl(AUTOFS_CTL_GETREQS, &ah->ah_fsid, NULL, &olen,
+ &vers, sizeof(vers));
+ if (error == -1)
+ goto out;
+ if (olen == 0)
+ goto out;
+
+ reqs = malloc(olen);
+ if (reqs == NULL)
+ goto out;
+ error = autofs_sysctl(AUTOFS_CTL_GETREQS, &ah->ah_fsid, reqs, &olen,
+ &vers, sizeof(vers));
+ if (error == -1)
+ goto out;
+out:
+ if (error) {
+ safe_free(reqs);
+ return (-1);
+ }
+ cnt = olen / sizeof(*reqs);
+ *cntp = cnt;
+ *reqp = reqs;
+ return (0);
+}
+
+/* free an array of requests */
+void
+autoreq_free(autoh_t ah __unused, autoreq_t *req)
+{
+
+ free(*req);
+ free(req);
+}
+
+/* serve a request */
+int
+autoreq_serv(autoh_t ah, autoreq_t req)
+{
+ int error;
+
+ error = autofs_sysctl(AUTOFS_CTL_SERVREQ, &ah->ah_fsid, NULL, NULL,
+ req, sizeof(*req));
+ return (error);
+}
+
+enum autoreq_op
+autoreq_getop(autoreq_t req)
+{
+
+ switch (req->au_op) {
+ case AREQ_LOOKUP:
+ return (AUTOREQ_OP_LOOKUP);
+ case AREQ_STAT:
+ return (AUTOREQ_OP_STAT);
+ case AREQ_READDIR:
+ return (AUTOREQ_OP_READDIR);
+ default:
+ return (AUTOREQ_OP_UNKNOWN);
+ }
+}
+
+/* get a request's file name. */
+const char *
+autoreq_getpath(autoreq_t req)
+{
+
+ return (req->au_name);
+}
+
+/* get a request's inode. a indirect mount may return AUTO_INODE_NONE. */
+autoino_t
+autoreq_getino(autoreq_t req)
+{
+
+ return (req->au_ino);
+}
+
+void
+autoreq_setino(autoreq_t req, autoino_t ino)
+{
+
+ req->au_ino = ino;
+}
+
+/* get a request's directory inode. */
+autoino_t
+autoreq_getdirino(autoreq_t req)
+{
+
+ return (req->au_dino);
+}
+
+void
+autoreq_seterrno(autoreq_t req, int error)
+{
+
+ req->au_errno = error;
+}
+
+void
+autoreq_setaux(autoreq_t req, void *auxdata, size_t auxlen)
+{
+
+ req->au_auxdata = auxdata;
+ req->au_auxlen = auxlen;
+}
+
+void
+autoreq_getaux(autoreq_t req, void **auxdatap, size_t *auxlenp)
+{
+
+ *auxdatap = req->au_auxdata;
+ *auxlenp = req->au_auxlen;
+}
+
+void
+autoreq_seteof(autoreq_t req, int eof)
+{
+
+ req->au_eofflag = eof;
+}
+
+void
+autoreq_getoffset(autoreq_t req, off_t *offp)
+{
+
+ *offp = req->au_offset - AUTOFS_USEROFF;
+}
+
+/* toggle by path. args = handle, AUTO_?, pid (-1 to disable), path. */
+int
+autoh_togglepath(autoh_t ah, int op, pid_t pid, const char *path)
+{
+ int fd, ret;
+
+ fd = open(path, O_RDONLY);
+ if (fd == -1)
+ return (-1);
+ ret = autoh_togglefd(ah, op, pid, fd);
+ close(fd);
+ return (ret);
+}
+
+/* toggle by fd. args = handle, AUTO_?, pid (-1 to disable), fd. */
+int
+autoh_togglefd(autoh_t ah, int op, pid_t pid, int fd)
+{
+ struct stat sb;
+ struct autofs_mounterreq mr;
+ int error, realop;
+
+ switch (op) {
+ case AUTO_DIRECT:
+ realop = AUTOFS_CTL_TRIGGER;
+ break;
+ case AUTO_INDIRECT:
+ realop = AUTOFS_CTL_SUBTRIGGER;
+ break;
+ case AUTO_MOUNTER:
+ realop = AUTOFS_CTL_MOUNTER;
+ break;
+ case AUTO_BROWSE:
+ realop = AUTOFS_CTL_BROWSE;
+ break;
+ default:
+ errno = ENOTTY;
+ return (-1);
+ }
+
+ if (fstat(fd, &sb))
+ return (-1);
+ bzero(&mr, sizeof(mr));
+ mr.amu_ino = sb.st_ino;
+ mr.amu_pid = pid;
+ error = autofs_sysctl(realop, &ah->ah_fsid, NULL, NULL,
+ &mr, sizeof(mr));
+ return (error);
+}
+
+int
+autofs_sysctl(op, fsid, oldp, oldlenp, newp, newlen)
+ int op;
+ fsid_t *fsid;
+ void *oldp;
+ size_t *oldlenp;
+ void *newp;
+ size_t newlen;
+{
+ struct vfsidctl vc;
+
+ bzero(&vc, sizeof(vc));
+ vc.vc_op = op;
+ strcpy(vc.vc_fstypename, "*");
+ vc.vc_vers = VFS_CTL_VERS1;
+ vc.vc_fsid = *fsid;
+ vc.vc_ptr = newp;
+ vc.vc_len = newlen;
+ return (sysctlbyname("vfs.autofs.ctl", oldp, oldlenp, &vc, sizeof(vc)));
+}
+
diff --git a/lib/libautofs/libautofs.h b/lib/libautofs/libautofs.h
new file mode 100644
index 0000000..98da2f8
--- /dev/null
+++ b/lib/libautofs/libautofs.h
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) 2004 Alfred Perlstein <alfred@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ * $Id: libautofs.h,v 1.3 2004/08/31 08:49:56 bright Exp $
+ */
+#ifndef _LIBAUTOFS_H
+#define _LIBAUTOFS_H
+
+struct auto_handle;
+typedef struct auto_handle * autoh_t;
+struct autofs_userreq;
+typedef struct autofs_userreq * autoreq_t;
+typedef uint64_t autoino_t;
+
+#define AUTO_INODE_NONE 0
+
+#define AUTO_DIRECT 1
+#define AUTO_INDIRECT 2
+#define AUTO_MOUNTER 3
+#define AUTO_BROWSE 4
+
+enum autoreq_op {
+ AUTOREQ_OP_UNKNOWN = 0,
+ AUTOREQ_OP_LOOKUP,
+ AUTOREQ_OP_STAT,
+ AUTOREQ_OP_READDIR
+};
+
+/* get a handle based on a path. */
+int autoh_get(const char *, autoh_t *);
+/* release. */
+void autoh_free(autoh_t);
+
+/*
+ * Get an array of pointers to handles for all autofs mounts, returns count
+ * or -1
+ */
+int autoh_getall(autoh_t **, int *cnt);
+/* free the array of pointers */
+void autoh_freeall(autoh_t *);
+
+/* return fd to select on. */
+int autoh_fd(autoh_t);
+
+/* returns the mount point of the autofs instance. */
+const char *autoh_mp(autoh_t);
+
+/* get an array of pending requests */
+int autoreq_get(autoh_t, autoreq_t **, int *);
+/* free an array of requests */
+void autoreq_free(autoh_t, autoreq_t *);
+/* serve a request */
+int autoreq_serv(autoh_t, autoreq_t);
+
+/* get the operation requested */
+enum autoreq_op autoreq_getop(autoreq_t);
+
+/* get a request's file name. */
+const char *autoreq_getpath(autoreq_t);
+/* get a request's inode. a indirect mount may return AUTO_INODE_NONE. */
+autoino_t autoreq_getino(autoreq_t);
+/*
+ * set a request's inode. an indirect mount may return AUTO_INODE_NONE,
+ * this is a fixup for indirect mounts.
+ */
+void autoreq_setino(autoreq_t, autoino_t);
+/* get a request's directory inode. */
+autoino_t autoreq_getdirino(autoreq_t);
+void autoreq_seterrno(autoreq_t, int);
+void autoreq_setaux(autoreq_t, void *, size_t);
+void autoreq_getaux(autoreq_t, void **, size_t *);
+void autoreq_seteof(autoreq_t req, int eof);
+void autoreq_getoffset(autoreq_t req, off_t *offp);
+
+/* toggle by path. args = handle, AUTO_?, pid (-1 to disable), path. */
+int autoh_togglepath(autoh_t, int, pid_t, const char *);
+/* toggle by fd. args = handle, AUTO_?, pid (-1 to disable), fd. */
+int autoh_togglefd(autoh_t, int, pid_t, int);
+
+#endif
diff --git a/sbin/mount_autofs/Makefile b/sbin/mount_autofs/Makefile
new file mode 100644
index 0000000..a234944
--- /dev/null
+++ b/sbin/mount_autofs/Makefile
@@ -0,0 +1,8 @@
+# $Id: Makefile,v 1.4 2004/08/31 16:27:40 bright Exp $
+# $FreeBSD$
+
+PROG=mount_autofs
+MAN=mount_autofs.8
+BINDIR?=/usr/sbin
+
+.include <bsd.prog.mk>
diff --git a/sbin/mount_autofs/mount_autofs.8 b/sbin/mount_autofs/mount_autofs.8
new file mode 100644
index 0000000..b4f0c84
--- /dev/null
+++ b/sbin/mount_autofs/mount_autofs.8
@@ -0,0 +1,71 @@
+.\" Copyright (c) 2004 Alfred Perlstein <alfred@FreeBSD.org>
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $Id: mount_autofs.8,v 1.2 2004/08/31 08:49:56 bright Exp $
+.\" $FreeBSD$
+.Dd August 30, 2004
+.Dt MOUNT_AUTOFS 8
+.Os
+.Sh NAME
+.Nm mount_autofs
+.Nd mount an autofs file system
+.Sh SYNOPSIS
+.Nm
+.Op Fl o Ar options
+.Ar dummy
+.Ar node
+.Sh DESCRIPTION
+The
+.Nm
+utility attaches an autofs file system
+device on to the file system tree at the point
+.Ar node .
+.Pp
+This command is normally executed by
+.Xr mount 8
+at boot time.
+.Pp
+The options are as follows:
+.Bl -tag -width indent
+.It Fl o
+Options are specified with a
+.Fl o
+flag followed by a comma separated string of options.
+See the
+.Xr mount 8
+man page for possible options and their meanings.
+.El
+.Sh SEE ALSO
+.Xr mount 2 ,
+.Xr unmount 2 ,
+.Xr fstab 5 ,
+.Xr mount 8
+.Sh HISTORY
+The
+.Nm
+utility first appeared in
+.Fx 6.0 .
+.Sh AUTHORS
+This manual page and the autofs filesystem suite were written by
+.An Alfred Perlstein .
diff --git a/sbin/mount_autofs/mount_autofs.c b/sbin/mount_autofs/mount_autofs.c
new file mode 100644
index 0000000..393ff06
--- /dev/null
+++ b/sbin/mount_autofs/mount_autofs.c
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) 2004 Alfred Perlstein <alfred@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $Id: mount_autofs.c,v 1.4 2004/08/31 16:28:22 bright Exp $
+ * $FreeBSD$
+ */
+#include <sys/param.h>
+#include <sys/mount.h>
+#include <sys/uio.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <err.h>
+#include <unistd.h>
+
+void usage(void);
+
+const char *progname;
+
+void
+usage(void) {
+
+ errx(1, "usage: %s node", progname);
+}
+
+#if __FreeBSD_version < 600000
+int
+mymount(const char *type, const char *dir, int flags, void *data)
+{
+
+ return (mount(type, dir, flags, data));
+}
+#else
+void
+ioset(struct iovec *iovp, char *str)
+{
+
+ iovp->iov_base = str;
+ iovp->iov_len = strlen(str) + 1;
+}
+
+int
+mymount(char *type, char *dir, int flags, void *data)
+{
+ struct iovec iov[4], *iovp;
+
+ iovp = &iov[0];
+ ioset(iovp++, "fstype");
+ ioset(iovp++, type);
+ ioset(iovp++, "fspath");
+ ioset(iovp++, dir);
+ return (nmount(iov, 4, 0));
+}
+#endif
+
+int
+main(int argc, char **argv)
+{
+ int error, i;
+ int ch;
+
+ progname = argv[0];
+
+ while ((ch = getopt(argc, argv, "o:")) != -1) {
+ /* just eat opts for now */
+ switch (ch) {
+ case '?':
+ usage();
+ }
+ }
+ argc -= optind;
+ argv += optind;
+
+ if (argc < 2) {
+ usage();
+ }
+
+ error = mymount("autofs", argv[1], 0, NULL);
+ if (error)
+ perror("mount");
+ return (error == 0 ? EXIT_SUCCESS : EXIT_FAILURE);
+}
diff --git a/share/examples/autofs/driver/Makefile b/share/examples/autofs/driver/Makefile
new file mode 100644
index 0000000..51791bb
--- /dev/null
+++ b/share/examples/autofs/driver/Makefile
@@ -0,0 +1,18 @@
+# $Id: Makefile,v 1.2 2004/07/17 11:26:51 bright Exp $
+# $FreeBSD$
+
+PROG=autodriver
+
+SRCS= autodriver.c
+NOMAN= YES
+WERROR= YES
+WARNS= 4
+CFLAGS+= -g
+
+DPADD+= ${.OBJDIR}/../libautofs/libautofs.a
+#LDADD+= -lautofs
+LDADD+= ${.OBJDIR}/../libautofs/libautofs.a
+LDFLAGS+= -L${.OBJDIR}/../libautofs
+CFLAGS+= -I${.CURDIR}/../libautofs
+
+.include <bsd.prog.mk>
diff --git a/share/examples/autofs/driver/autodriver.c b/share/examples/autofs/driver/autodriver.c
new file mode 100644
index 0000000..e2c9b05
--- /dev/null
+++ b/share/examples/autofs/driver/autodriver.c
@@ -0,0 +1,510 @@
+/*
+ * Copyright (c) 2004 Alfred Perlstein <alfred@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $Id: autodriver.c,v 1.8 2004/08/31 08:49:56 bright Exp $
+ * $FreeBSD$
+ */
+#include <ctype.h>
+#include <err.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+
+#include <sys/dirent.h>
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/mount.h>
+#include <sys/poll.h>
+#include <sys/stat.h>
+
+#include <libautofs.h>
+
+struct autoentry {
+ char *ae_mnt; /* autofs mountpoint. */
+ char *ae_path; /* path under mount. */
+ char *ae_type; /* fs to be mounted type. */
+ char *ae_opts; /* options passed to mount. */
+ char *ae_rpath; /* remote path */
+ char *ae_free; /* freeme! */
+ char *ae_fullpath; /* full path to mount */
+ int ae_line; /* line it came from in the conf. */
+ int ae_indirect; /* is this an indirect mount? */
+ int ae_direct; /* is this a direct mount? */
+ int ae_browse; /* browseable? */
+ struct autoentry *ae_next; /* next. */
+};
+
+struct autoentry *entries;
+const char *mount_prog = "mount";
+const char *fstype = "autofs";
+
+void *xmalloc(size_t);
+void *xcalloc(size_t number, size_t size);
+void parsetab(void);
+void populate_tab(void);
+void doreq(autoh_t, autoreq_t);
+void dotheneedful(autoh_t);
+void eventloop(void);
+int poll_handles(autoh_t *array, int cnt);
+int mount_indirect(struct autofs_userreq *req, struct autoentry *ent);
+int mount_direct(struct autofs_userreq *req, struct autoentry *ent);
+int mount_browse(struct autofs_userreq *req, struct autoentry *ent);
+
+#define DSTR(s) sizeof(s) - 1, s
+
+struct dirent dumbents[] = {
+ {50, sizeof(struct dirent), DT_DIR, DSTR("one") },
+ {51, sizeof(struct dirent), DT_DIR, DSTR(".") },
+ {52, sizeof(struct dirent), DT_DIR, DSTR("..") },
+ {50, sizeof(struct dirent), DT_DIR, DSTR("two") },
+};
+
+void *
+xmalloc(size_t size)
+{
+ void *ret;
+
+ ret = malloc(size);
+ if (ret == NULL)
+ err(1, "malloc %d", (int) size);
+ return (ret);
+}
+
+void *
+xcalloc(size_t number, size_t size)
+{
+ void *ret;
+
+ ret = calloc(number, size);
+ if (ret == NULL)
+ err(1, "calloc %d %d", (int)number, (int)size);
+ return (ret);
+}
+
+void
+parsetab(void)
+{
+ FILE *fp;
+ const char *tab;
+ char *cp, *p, *line, *opt;
+ size_t len;
+ struct autoentry *ent;
+ int lineno, x, gotopt;
+ const char *expecting = "expecting 'direct', 'indirect' or 'browse'";
+
+ tab = "autotab";
+ lineno = 0;
+
+ fp = fopen(tab, "r");
+ if (fp == NULL)
+ err(1, "fopen %s", tab);
+
+ while ((cp = fgetln(fp, &len)) != NULL) {
+ lineno++;
+ while (len > 0 && isspace(cp[len - 1]))
+ len--;
+ line = xmalloc(len + 1);
+ bcopy(cp, line, len);
+ line[len] = '\0';
+ cp = line;
+ if ((cp = strchr(line, '#')) != NULL)
+ *cp = '\0';
+ cp = line;
+ while (isspace(*cp))
+ cp++;
+ if (*cp == '\0') {
+ free(line);
+ continue;
+ }
+ ent = xcalloc(1, sizeof(*ent));
+ if ((p = strsep(&cp, " \t")) == NULL)
+ goto bad;
+ ent->ae_mnt = p;
+ if ((p = strsep(&cp, " \t")) == NULL)
+ goto bad;
+ ent->ae_path = p;
+ if ((p = strsep(&cp, " \t")) == NULL)
+ goto bad;
+ ent->ae_type = p;
+ if ((p = strsep(&cp, " \t")) == NULL)
+ goto bad;
+ ent->ae_opts = p;
+ if ((p = strsep(&cp, " \t")) == NULL)
+ goto bad;
+ ent->ae_rpath = p;
+ if ((p = strsep(&cp, " \t")) == NULL)
+ goto bad;
+ gotopt = 0;
+ opt = p;
+ while ((p = strsep(&opt, ",")) != NULL) {
+ if (strcmp(p, "indirect") == 0) {
+ ent->ae_indirect = 1;
+ gotopt = 1;
+ } else if (strcmp(p, "direct") == 0) {
+ ent->ae_direct = 1;
+ gotopt = 1;
+ } else if (strcmp(p, "browse") == 0) {
+ ent->ae_browse = 1;
+ gotopt = 1;
+ } else {
+ warnx("unreconized option '%s', %s",
+ p, expecting);
+ goto bad2;
+ }
+ }
+ if (!gotopt) {
+ warnx("no options specified %s", expecting);
+ goto bad2;
+ }
+ if (ent->ae_direct && ent->ae_indirect) {
+ warnx("direct and indirect are mutually exclusive");
+ goto bad2;
+
+ }
+ x = asprintf(&ent->ae_fullpath, "%s/%s",
+ ent->ae_mnt, ent->ae_path);
+ if (x == -1)
+ err(1, "asprintf");
+
+ if (strlen(ent->ae_fullpath) + 1 > PATH_MAX) {
+ warnx("Error in file %s, line %d, "
+ "mountpath (%s) exceeds PATH_MAX (%d)",
+ tab, lineno, ent->ae_fullpath, PATH_MAX);
+ goto bad2;
+ }
+ ent->ae_line = lineno;
+ ent->ae_free = line;
+ ent->ae_next = entries;
+ entries = ent;
+ continue;
+bad:
+ warnx("Parse error in file %s, line %d", tab, lineno);
+bad2:
+ free(ent->ae_fullpath);
+ free(line);
+ free(ent);
+ }
+ if (ferror(fp))
+ err(1, "error with file %s", tab);
+}
+
+void
+populate_tab(void)
+{
+ struct autoentry *ent;
+ char *path, *cmd;
+ int error;
+ autoh_t ah;
+
+ path = cmd = NULL;
+
+ for (ent = entries; ent != NULL; ent = ent->ae_next) {
+ free(path);
+ free(cmd);
+ error = asprintf(&path, "%s/%s", ent->ae_mnt, ent->ae_path);
+ if (error == -1)
+ err(1, "asprintf");
+ error = asprintf(&cmd, "mkdir -p %s", path);
+ if (error == -1)
+ err(1, "asprintf");
+ error = system(cmd);
+ if (error) {
+ warn("system: %s", cmd);
+ continue;
+ }
+ if (autoh_get(ent->ae_mnt, &ah)) {
+ warn("autoh_get %s", path);
+ continue;
+ }
+ error = autoh_togglepath(ah, AUTO_MOUNTER, getpid(), path);
+ if (error) {
+ err(1, "AUTO_MOUNTER %s", path);
+ continue;
+ }
+ if (ent->ae_browse) {
+ error = autoh_togglepath(ah, AUTO_BROWSE, getpid(),
+ path);
+ if (error)
+ err(1, "AUTO_BROWSE %s", path);
+ }
+ if (ent->ae_direct) {
+ error = autoh_togglepath(ah, AUTO_DIRECT, getpid(),
+ path);
+ if (error)
+ err(1, "AUTO_DIRECT %s", path);
+ }
+ if (ent->ae_indirect) {
+ error = autoh_togglepath(ah, AUTO_INDIRECT, getpid(),
+ path);
+ if (error)
+ err(1, "AUTO_INDIRECT %s", path);
+ }
+ autoh_free(ah);
+ }
+ free(path);
+ free(cmd);
+}
+
+/*
+ * Process an autofs request, scan the list of entries in the config
+ * looking for our node, if found mount it.
+ */
+void
+doreq(autoh_t ah, autoreq_t req)
+{
+ struct autoentry *ent;
+ int error;
+ int mcmp;
+ const char *mnt;
+
+ mnt = autoh_mp(ah);
+
+ autoreq_seterrno(req, 0);
+ for (ent = entries; ent != NULL; ent = ent->ae_next) {
+ fprintf(stderr, "comparing {%s,%s} to {%s,%s}\n",
+ mnt, ent->ae_mnt, autoreq_getpath(req), ent->ae_path);
+ fprintf(stderr, "comparing {%d,%d} to {%d,%d}\n",
+ (int)strlen(mnt),
+ (int)strlen(ent->ae_mnt),
+ (int)strlen(autoreq_getpath(req)),
+ (int)strlen(ent->ae_path));
+ if ((mcmp = strcmp(mnt, ent->ae_mnt)) != 0) {
+ fprintf(stderr, "mcmp = %d\n", mcmp);
+ continue;
+ }
+ if (mount_direct(req, ent))
+ goto serve;
+ if (mount_indirect(req, ent))
+ goto serve;
+ if (mount_browse(req, ent))
+ goto serve;
+ }
+ fprintf(stderr, "no entry found...\n");
+ autoreq_seterrno(req, ENOENT);
+serve:
+ error = autoreq_serv(ah, req);
+ if (error == -1) {
+ warn("AUTOFS_CTL_SERVREQ");
+ }
+}
+
+int
+mount_indirect(req, ent)
+ struct autofs_userreq *req;
+ struct autoentry *ent;
+{
+ struct stat sb;
+ char *path, *cmd;
+ int error, x;
+
+ if (ent->ae_indirect != 1)
+ return (0);
+ /*
+ * handle lookups, fake all stat(2) requests... this is bad,
+ * but we're a driver so we don't care...
+ * If we don't care about the type of request, then just return.
+ */
+ switch (autoreq_getop(req)) {
+ case AUTOREQ_OP_LOOKUP:
+ break;
+ case AUTOREQ_OP_STAT:
+ return (1);
+ default:
+ return (0);
+ }
+ if (stat(ent->ae_fullpath, &sb))
+ return (0);
+ if (sb.st_ino != autoreq_getdirino(req))
+ return (0);
+ x = asprintf(&path, "%s/%s", ent->ae_fullpath, autoreq_getpath(req));
+ if (x > PATH_MAX) {
+ autoreq_seterrno(req, ENAMETOOLONG);
+ return (1);
+ }
+ if (mkdir(path, 0555) == -1)
+ warn("mkdir %s", path);
+ error = asprintf(&cmd, "%s -t %s -o %s %s/%s %s", mount_prog,
+ ent->ae_type, ent->ae_opts, ent->ae_rpath, autoreq_getpath(req), path);
+ fprintf(stderr, "running:\n\t%s\n", cmd);
+ error = system(cmd);
+ fprintf(stderr, "error = %d\n", error);
+ free(cmd);
+ if (error) {
+ if (rmdir(path) == -1)
+ warn("rmdir %s", path);
+ autoreq_seterrno(req, ENOENT);
+ } else {
+ if (stat(path, &sb) != -1)
+ autoreq_setino(req, sb.st_ino);
+ /* XXX !!! */
+ /* req->au_flags = 1; */
+ }
+ free(path);
+ return (1);
+}
+
+int
+mount_direct(req, ent)
+ struct autofs_userreq *req;
+ struct autoentry *ent;
+{
+ struct stat sb;
+ char *cmd;
+ int error;
+
+ if (ent->ae_direct != 1)
+ return (0);
+ /*
+ * handle lookups, fake all stat(2) requests... this is bad,
+ * but we're a driver so we don't care...
+ * If we don't care about the type of request, then just return.
+ */
+ switch (autoreq_getop(req)) {
+ case AUTOREQ_OP_LOOKUP:
+ break;
+ case AUTOREQ_OP_STAT:
+ return (1);
+ default:
+ return (0);
+ }
+ if (stat(ent->ae_fullpath, &sb))
+ return (0);
+ if (sb.st_ino != autoreq_getino(req))
+ return (0);
+ error = asprintf(&cmd, "%s -t %s -o %s %s %s", mount_prog,
+ ent->ae_type, ent->ae_opts, ent->ae_rpath, ent->ae_fullpath);
+ if (error == -1)
+ err(1, "asprintf");
+ fprintf(stderr, "running:\n\t%s\n", cmd);
+ error = system(cmd);
+ fprintf(stderr, "error = %d\n", error);
+ free(cmd);
+ if (error) {
+ autoreq_seterrno(req, ENOENT);
+ return (1);
+ }
+ /* XXX: fix ONLIST in kernel */
+ /* req->au_flags = 1; */
+ return (1);
+}
+
+int
+mount_browse(req, ent)
+ struct autofs_userreq *req;
+ struct autoentry *ent;
+{
+ off_t off;
+
+ if (ent->ae_browse != 1)
+ return (0);
+ if (autoreq_getop(req) != AUTOREQ_OP_READDIR)
+ return (0);
+ autoreq_getoffset(req, &off);
+ if (off < sizeof(dumbents))
+ autoreq_setaux(req, dumbents, sizeof(dumbents));
+ fprintf(stderr, "mount_browse: offset %d, size %d\n",
+ (int)off, (int)sizeof(dumbents));
+ autoreq_seteof(req, 1);
+ return (1);
+}
+
+/*
+ * Ask the filesystem passed in if it has a pending request.
+ * if so process them.
+ */
+void
+dotheneedful(autoh_t ah)
+{
+ int cnt, i;
+ autoreq_t *reqs;
+
+ if (autoreq_get(ah, &reqs, &cnt))
+ err(1, "autoreq_get");
+
+ for (i = 0; i < cnt; i++) {
+ fprintf(stderr, "processing request for '%s' '%s'\n",
+ autoh_mp(ah), autoreq_getpath(reqs[i]));
+ doreq(ah, reqs[i]);
+ }
+ free(reqs);
+}
+
+int
+poll_handles(autoh_t *array, int cnt)
+{
+ int i, saved_errno, x;
+ static struct pollfd *pfd = NULL;
+
+ pfd = reallocf(pfd, cnt * sizeof(*pfd));
+ if (pfd == NULL)
+ return (-1);
+ for (i = 0; i < cnt; i++) {
+ pfd[i].fd = autoh_fd(array[i]);
+ pfd[i].events = POLLPRI;
+ pfd[i].revents = 0;
+ }
+ fprintf(stderr, "start polling...\n");
+ x = poll(pfd, cnt, 10000);
+ saved_errno = errno;
+ fprintf(stderr, "done polling...\n");
+ errno = saved_errno;
+ if (x == -1)
+ return (-1);
+ /* at least one fs is ready... */
+ if (x > 0)
+ return (0);
+ return (0);
+}
+
+void
+eventloop(void)
+{
+ autoh_t *array;
+ int cnt, i;
+
+ fprintf(stderr, "starting event loop...\n");
+ for ( ;; ) {
+ if (autoh_getall(&array, &cnt))
+ err(1, "autoh_getall");
+ if (poll_handles(array, cnt))
+ err(1, "poll_handles");
+ for (i = 0; i < cnt; i++) {
+ dotheneedful(array[i]);
+ }
+ }
+}
+
+int
+main(int argc __unused, char **argv __unused)
+{
+
+ parsetab();
+ populate_tab();
+ eventloop();
+ return (0);
+}
diff --git a/share/examples/autofs/driver/autotab b/share/examples/autofs/driver/autotab
new file mode 100644
index 0000000..e2f8569
--- /dev/null
+++ b/share/examples/autofs/driver/autotab
@@ -0,0 +1,7 @@
+# $Id: autotab,v 1.7 2004/08/31 15:59:44 bright Exp $
+# $FreeBSD$
+# autofs, directory, fstype, opts, path
+/auto share nfs ro,-R=1 big:/vol/share direct
+#/auto src nfs ro,-R=1 big:/vol/share/src indirect
+/auto src nfs ro,-R=1 big:/vol/share/src direct
+/auto browse nfs ro,-R=1 big:/vol/share/src browse,indirect
diff --git a/share/man/man5/autofs.5 b/share/man/man5/autofs.5
new file mode 100644
index 0000000..40eacde
--- /dev/null
+++ b/share/man/man5/autofs.5
@@ -0,0 +1,58 @@
+.\" Copyright (c) 2004 Alfred Perlstein <alfred@FreeBSD.org>
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $Id: autofs.5,v 1.1 2004/08/31 16:05:39 bright Exp $
+.\" $FreeBSD$
+.Dd August 30, 2004
+.Dt AUTOFS 5
+.Os
+.Sh NAME
+.Nm autofs
+.Nd auto file system
+.Sh SYNOPSIS
+.Bd -literal
+autofs /auto autofs rw 0 0
+.Ed
+.Sh DESCRIPTION
+The auto file system, or
+.Nm ,
+provides a method to dynamically graft mountpoints into the filesystem
+namespace.
+.Sh SEE ALSO
+.Xr mount_autofs 8
+.Xr libautofs 3
+.Sh HISTORY
+The
+.Nm
+file system first appeared in
+.Fx 6.0 .
+The
+.Nm
+manual page first appeared in
+.Fx 6.0 .
+.Sh AUTHORS
+The
+.Nm
+manual page was written by
+.An Alfred Perlstein Aq alfred@FreeBSD.org .
OpenPOWER on IntegriCloud