Enter the autofs.

This commit is contained in:
Alfred Perlstein 2004-08-31 16:26:01 +00:00
parent 9b56caaef4
commit acc387c393
11 changed files with 1595 additions and 0 deletions

14
lib/libautofs/Makefile Normal file
View File

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

238
lib/libautofs/libautofs.3 Normal file
View File

@ -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 .

465
lib/libautofs/libautofs.c Normal file
View File

@ -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)));
}

103
lib/libautofs/libautofs.h Normal file
View File

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

View File

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

View File

@ -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 .

View File

@ -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);
}

View File

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

View File

@ -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);
}

View File

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

58
share/man/man5/autofs.5 Normal file
View File

@ -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 .