2 * Copyright (c) 2004 Alfred Perlstein <alfred@FreeBSD.org>
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * $Id: libautofs.c,v 1.5 2004/09/08 08:44:12 bright Exp $
39 #include <sys/types.h>
40 #include <sys/param.h>
41 #include <sys/mount.h>
44 #include <sys/sysctl.h>
46 #ifdef AUTOFSSTANDALONE
47 #include "../autofs/autofs.h"
49 #include <fs/autofs/autofs.h>
52 #include "libautofs.h"
60 static int autofs_sysctl(int, fsid_t
*, void *, size_t *, void *, size_t);
61 static void safe_free(void *ptr
);
62 static int getmntlst(struct statfs
**sfsp
, int *cntp
);
75 getmntlst(struct statfs
**sfsp
, int *cntp
)
81 cnt
= getfsstat(NULL
, 0, MNT_NOWAIT
);
82 bufsize
= cnt
* sizeof(**sfsp
);
83 /*fprintf(stderr, "getmntlst bufsize %ld, cnt %d\n", bufsize, cnt);*/
84 *sfsp
= malloc(bufsize
);
87 cnt
= getfsstat(*sfsp
, bufsize
, MNT_NOWAIT
);
91 /*fprintf(stderr, "getmntlst ok, cnt %d\n", cnt);*/
96 /*fprintf(stderr, "getmntlst bad\n");*/
100 /* get a handle based on a path. */
102 autoh_get(const char *path
, autoh_t
*ahp
)
104 struct statfs
*sfsp
, *sp
;
110 * We use getfsstat to prevent avoid the lookups on the mountpoints
111 * that statfs(2) would do.
113 if (getmntlst(&sfsp
, &cnt
))
115 for (i
= 0; i
< cnt
; i
++) {
116 if (strcmp(sfsp
[i
].f_mntonname
, path
) == 0)
120 /*fprintf(stderr, "autoh_get bad %d %d\n", i, cnt);*/
125 if (strcmp(sp
->f_fstypename
, "autofs")) {
129 fd
= open(sp
->f_mntonname
, O_RDONLY
);
132 ret
= malloc(sizeof(*ret
));
136 ret
->ah_fsid
= sp
->f_fsid
;
138 strlcpy(ret
->ah_mp
, sp
->f_mntonname
, sizeof(ret
->ah_mp
));
150 autoh_free(autoh_t ah
)
161 * Get an array of pointers to all the currently mounted autofs
165 autoh_getall(autoh_t
**arrayp
, int *cntp
)
173 * We use getfsstat to prevent avoid the lookups on the mountpoints
174 * that statfs(2) would do.
176 if (getmntlst(&sfsp
, &cnt
))
178 array
= *arrayp
= calloc(cnt
+ 1, sizeof(**arrayp
));
181 for (i
= 0, pos
= 0; i
< cnt
; i
++) {
182 if (autoh_get(sfsp
[i
].f_mntonname
, &array
[pos
]) == -1) {
183 /* not an autofs entry, that's ok, otherwise bail */
201 autoh_freeall(array
);
207 autoh_freeall(autoh_t
*ah
)
213 while (*ahp
!= NULL
) {
220 /* return fd to select on. */
235 static int do_autoreq_get(autoh_t ah
, autoreq_t
*reqp
, int *cntp
);
237 /* get an array of pending requests */
239 autoreq_get(autoh_t ah
, autoreq_t
**reqpp
, int *cntp
)
242 autoreq_t req
, *reqp
;
244 if (do_autoreq_get(ah
, &req
, &cnt
))
247 reqp
= calloc(cnt
+ 1, sizeof(*reqp
));
252 for (i
= 0; i
< cnt
; i
++)
260 do_autoreq_get(autoh_t ah
, autoreq_t
*reqp
, int *cntp
)
263 struct autofs_userreq
*reqs
;
267 vers
= AUTOFS_PROTOVERS
;
273 error
= autofs_sysctl(AUTOFS_CTL_GETREQS
, &ah
->ah_fsid
, NULL
, &olen
,
274 &vers
, sizeof(vers
));
283 error
= autofs_sysctl(AUTOFS_CTL_GETREQS
, &ah
->ah_fsid
, reqs
, &olen
,
284 &vers
, sizeof(vers
));
292 cnt
= olen
/ sizeof(*reqs
);
298 /* free an array of requests */
300 autoreq_free(autoh_t ah __unused
, autoreq_t
*req
)
307 /* serve a request */
309 autoreq_serv(autoh_t ah
, autoreq_t req
)
313 error
= autofs_sysctl(AUTOFS_CTL_SERVREQ
, &ah
->ah_fsid
, NULL
, NULL
,
319 autoreq_getop(autoreq_t req
)
322 switch (req
->au_op
) {
324 return (AUTOREQ_OP_LOOKUP
);
326 return (AUTOREQ_OP_STAT
);
328 return (AUTOREQ_OP_READDIR
);
330 return (AUTOREQ_OP_UNKNOWN
);
334 /* get a request's file name. */
336 autoreq_getpath(autoreq_t req
)
339 return (req
->au_name
);
342 /* get a request's inode. a indirect mount may return AUTO_INODE_NONE. */
344 autoreq_getino(autoreq_t req
)
347 return (req
->au_ino
);
351 autoreq_setino(autoreq_t req
, autoino_t ino
)
357 /* get a request's directory inode. */
359 autoreq_getdirino(autoreq_t req
)
362 return (req
->au_dino
);
366 autoreq_seterrno(autoreq_t req
, int error
)
369 req
->au_errno
= error
;
373 autoreq_setaux(autoreq_t req
, void *auxdata
, size_t auxlen
)
376 req
->au_auxdata
= auxdata
;
377 req
->au_auxlen
= auxlen
;
381 autoreq_getaux(autoreq_t req
, void **auxdatap
, size_t *auxlenp
)
384 *auxdatap
= req
->au_auxdata
;
385 *auxlenp
= req
->au_auxlen
;
389 autoreq_seteof(autoreq_t req
, int eof
)
392 req
->au_eofflag
= eof
;
396 autoreq_getoffset(autoreq_t req
, off_t
*offp
)
399 *offp
= req
->au_offset
- AUTOFS_USEROFF
;
403 autoreq_getxid(autoreq_t req
, int *xid
)
409 /* toggle by path. args = handle, AUTO_?, pid (-1 to disable), path. */
411 autoh_togglepath(autoh_t ah
, int op
, pid_t pid
, const char *path
)
415 fd
= open(path
, O_RDONLY
);
418 ret
= autoh_togglefd(ah
, op
, pid
, fd
);
423 /* toggle by fd. args = handle, AUTO_?, pid (-1 to disable), fd. */
425 autoh_togglefd(autoh_t ah
, int op
, pid_t pid
, int fd
)
428 struct autofs_mounterreq mr
;
433 realop
= AUTOFS_CTL_TRIGGER
;
436 realop
= AUTOFS_CTL_SUBTRIGGER
;
439 realop
= AUTOFS_CTL_MOUNTER
;
442 realop
= AUTOFS_CTL_BROWSE
;
451 bzero(&mr
, sizeof(mr
));
452 mr
.amu_ino
= sb
.st_ino
;
454 error
= autofs_sysctl(realop
, &ah
->ah_fsid
, NULL
, NULL
,
460 autofs_sysctl(op
, fsid
, oldp
, oldlenp
, newp
, newlen
)
470 bzero(&vc
, sizeof(vc
));
472 strcpy(vc
.vc_fstypename
, "*");
473 vc
.vc_vers
= VFS_CTL_VERS1
;
477 return (sysctlbyname("vfs.autofs.ctl", oldp
, oldlenp
, &vc
, sizeof(vc
)));