implements VMCB_EXIT_MSR
[freebsd-src/fkvm-freebsd.git] / lib / libautofs / libautofs.c
blob459b32d2048baf8941522430f3353f1908f28d84
1 /*
2 * Copyright (c) 2004 Alfred Perlstein <alfred@FreeBSD.org>
3 * All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
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
24 * SUCH DAMAGE.
26 * $FreeBSD$
27 * $Id: libautofs.c,v 1.5 2004/09/08 08:44:12 bright Exp $
29 #include <err.h>
30 #include <ctype.h>
31 #include <err.h>
32 #include <errno.h>
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <string.h>
36 #include <unistd.h>
37 #include <fcntl.h>
39 #include <sys/types.h>
40 #include <sys/param.h>
41 #include <sys/mount.h>
42 #include <sys/poll.h>
43 #include <sys/stat.h>
44 #include <sys/sysctl.h>
46 #ifdef AUTOFSSTANDALONE
47 #include "../autofs/autofs.h"
48 #else
49 #include <fs/autofs/autofs.h>
50 #endif
52 #include "libautofs.h"
54 struct auto_handle {
55 char ah_mp[MNAMELEN];
56 fsid_t ah_fsid;
57 int ah_fd;
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);
64 static void
65 safe_free(void *ptr)
67 int saved_errno;
69 saved_errno = errno;
70 free(ptr);
71 errno = saved_errno;
74 int
75 getmntlst(struct statfs **sfsp, int *cntp)
77 int cnt;
78 long bufsize;
80 *sfsp = NULL;
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);
85 if (sfsp == NULL)
86 goto err;
87 cnt = getfsstat(*sfsp, bufsize, MNT_NOWAIT);
88 if (cnt == -1)
89 goto err;
90 *cntp = cnt;
91 /*fprintf(stderr, "getmntlst ok, cnt %d\n", cnt);*/
92 return (0);
93 err:
94 safe_free(sfsp);
95 *sfsp = NULL;
96 /*fprintf(stderr, "getmntlst bad\n");*/
97 return (-1);
100 /* get a handle based on a path. */
102 autoh_get(const char *path, autoh_t *ahp)
104 struct statfs *sfsp, *sp;
105 int cnt, fd, i;
106 autoh_t ret;
108 ret = NULL;
110 * We use getfsstat to prevent avoid the lookups on the mountpoints
111 * that statfs(2) would do.
113 if (getmntlst(&sfsp, &cnt))
114 goto err;
115 for (i = 0; i < cnt; i++) {
116 if (strcmp(sfsp[i].f_mntonname, path) == 0)
117 break;
119 if (i == cnt) {
120 /*fprintf(stderr, "autoh_get bad %d %d\n", i, cnt);*/
121 errno = ENOENT;
122 goto err;
124 sp = &sfsp[i];
125 if (strcmp(sp->f_fstypename, "autofs")) {
126 errno = ENOTTY;
127 goto err;
129 fd = open(sp->f_mntonname, O_RDONLY);
130 if (fd == -1)
131 goto err;
132 ret = malloc(sizeof(*ret));
133 if (ret == NULL)
134 goto err;
136 ret->ah_fsid = sp->f_fsid;
137 ret->ah_fd = fd;
138 strlcpy(ret->ah_mp, sp->f_mntonname, sizeof(ret->ah_mp));
139 safe_free(sfsp);
140 *ahp = ret;
141 return (0);
142 err:
143 safe_free(ret);
144 safe_free(sfsp);
145 return (-1);
148 /* release. */
149 void
150 autoh_free(autoh_t ah)
152 int saved_errno;
154 saved_errno = errno;
155 close(ah->ah_fd);
156 free(ah);
157 errno = saved_errno;
161 * Get an array of pointers to all the currently mounted autofs
162 * instances.
165 autoh_getall(autoh_t **arrayp, int *cntp)
167 struct statfs *sfsp;
168 int cnt, i, pos;
169 autoh_t *array;
171 array = NULL;
173 * We use getfsstat to prevent avoid the lookups on the mountpoints
174 * that statfs(2) would do.
176 if (getmntlst(&sfsp, &cnt))
177 goto err;
178 array = *arrayp = calloc(cnt + 1, sizeof(**arrayp));
179 if (array == NULL)
180 goto err;
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 */
184 if (errno == ENOTTY)
185 continue;
186 goto err;
188 pos++;
190 if (pos == 0) {
191 errno = ENOENT;
192 goto err;
194 *arrayp = array;
195 *cntp = pos;
196 safe_free(sfsp);
197 return (0);
198 err:
199 safe_free(sfsp);
200 if (array)
201 autoh_freeall(array);
202 return (-1);
205 /* release. */
206 void
207 autoh_freeall(autoh_t *ah)
209 autoh_t *ahp;
211 ahp = ah;
213 while (*ahp != NULL) {
214 autoh_free(*ahp);
215 ahp++;
217 safe_free(ah);
220 /* return fd to select on. */
222 autoh_fd(autoh_t ah)
225 return (ah->ah_fd);
228 const char *
229 autoh_mp(autoh_t ah)
232 return (ah->ah_mp);
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)
241 int cnt, i;
242 autoreq_t req, *reqp;
244 if (do_autoreq_get(ah, &req, &cnt))
245 return (-1);
247 reqp = calloc(cnt + 1, sizeof(*reqp));
248 if (reqp == NULL) {
249 safe_free(req);
250 return (-1);
252 for (i = 0; i < cnt; i++)
253 reqp[i] = &req[i];
254 *reqpp = reqp;
255 *cntp = cnt;
256 return (0);
260 do_autoreq_get(autoh_t ah, autoreq_t *reqp, int *cntp)
262 size_t olen;
263 struct autofs_userreq *reqs;
264 int cnt, error;
265 int vers;
267 vers = AUTOFS_PROTOVERS;
269 error = 0;
270 reqs = NULL;
271 olen = 0;
272 cnt = 0;
273 error = autofs_sysctl(AUTOFS_CTL_GETREQS, &ah->ah_fsid, NULL, &olen,
274 &vers, sizeof(vers));
275 if (error == -1)
276 goto out;
277 if (olen == 0)
278 goto out;
280 reqs = malloc(olen);
281 if (reqs == NULL)
282 goto out;
283 error = autofs_sysctl(AUTOFS_CTL_GETREQS, &ah->ah_fsid, reqs, &olen,
284 &vers, sizeof(vers));
285 if (error == -1)
286 goto out;
287 out:
288 if (error) {
289 safe_free(reqs);
290 return (-1);
292 cnt = olen / sizeof(*reqs);
293 *cntp = cnt;
294 *reqp = reqs;
295 return (0);
298 /* free an array of requests */
299 void
300 autoreq_free(autoh_t ah __unused, autoreq_t *req)
303 free(*req);
304 free(req);
307 /* serve a request */
309 autoreq_serv(autoh_t ah, autoreq_t req)
311 int error;
313 error = autofs_sysctl(AUTOFS_CTL_SERVREQ, &ah->ah_fsid, NULL, NULL,
314 req, sizeof(*req));
315 return (error);
318 enum autoreq_op
319 autoreq_getop(autoreq_t req)
322 switch (req->au_op) {
323 case AREQ_LOOKUP:
324 return (AUTOREQ_OP_LOOKUP);
325 case AREQ_STAT:
326 return (AUTOREQ_OP_STAT);
327 case AREQ_READDIR:
328 return (AUTOREQ_OP_READDIR);
329 default:
330 return (AUTOREQ_OP_UNKNOWN);
334 /* get a request's file name. */
335 const char *
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. */
343 autoino_t
344 autoreq_getino(autoreq_t req)
347 return (req->au_ino);
350 void
351 autoreq_setino(autoreq_t req, autoino_t ino)
354 req->au_ino = ino;
357 /* get a request's directory inode. */
358 autoino_t
359 autoreq_getdirino(autoreq_t req)
362 return (req->au_dino);
365 void
366 autoreq_seterrno(autoreq_t req, int error)
369 req->au_errno = error;
372 void
373 autoreq_setaux(autoreq_t req, void *auxdata, size_t auxlen)
376 req->au_auxdata = auxdata;
377 req->au_auxlen = auxlen;
380 void
381 autoreq_getaux(autoreq_t req, void **auxdatap, size_t *auxlenp)
384 *auxdatap = req->au_auxdata;
385 *auxlenp = req->au_auxlen;
388 void
389 autoreq_seteof(autoreq_t req, int eof)
392 req->au_eofflag = eof;
395 void
396 autoreq_getoffset(autoreq_t req, off_t *offp)
399 *offp = req->au_offset - AUTOFS_USEROFF;
402 void
403 autoreq_getxid(autoreq_t req, int *xid)
406 *xid = req->au_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)
413 int fd, ret;
415 fd = open(path, O_RDONLY);
416 if (fd == -1)
417 return (-1);
418 ret = autoh_togglefd(ah, op, pid, fd);
419 close(fd);
420 return (ret);
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)
427 struct stat sb;
428 struct autofs_mounterreq mr;
429 int error, realop;
431 switch (op) {
432 case AUTO_DIRECT:
433 realop = AUTOFS_CTL_TRIGGER;
434 break;
435 case AUTO_INDIRECT:
436 realop = AUTOFS_CTL_SUBTRIGGER;
437 break;
438 case AUTO_MOUNTER:
439 realop = AUTOFS_CTL_MOUNTER;
440 break;
441 case AUTO_BROWSE:
442 realop = AUTOFS_CTL_BROWSE;
443 break;
444 default:
445 errno = ENOTTY;
446 return (-1);
449 if (fstat(fd, &sb))
450 return (-1);
451 bzero(&mr, sizeof(mr));
452 mr.amu_ino = sb.st_ino;
453 mr.amu_pid = pid;
454 error = autofs_sysctl(realop, &ah->ah_fsid, NULL, NULL,
455 &mr, sizeof(mr));
456 return (error);
460 autofs_sysctl(op, fsid, oldp, oldlenp, newp, newlen)
461 int op;
462 fsid_t *fsid;
463 void *oldp;
464 size_t *oldlenp;
465 void *newp;
466 size_t newlen;
468 struct vfsidctl vc;
470 bzero(&vc, sizeof(vc));
471 vc.vc_op = op;
472 strcpy(vc.vc_fstypename, "*");
473 vc.vc_vers = VFS_CTL_VERS1;
474 vc.vc_fsid = *fsid;
475 vc.vc_ptr = newp;
476 vc.vc_len = newlen;
477 return (sysctlbyname("vfs.autofs.ctl", oldp, oldlenp, &vc, sizeof(vc)));