xref: /netbsd-src/external/bsd/am-utils/dist/conf/autofs/autofs_solaris_v1.c (revision 8bae5d409deb915cf7c8f0539fae22ff2cb8a313)
1 /*	$NetBSD: autofs_solaris_v1.c,v 1.1.1.3 2015/01/17 16:34:16 christos Exp $	*/
2 
3 /*
4  * Copyright (c) 1999-2003 Ion Badulescu
5  * Copyright (c) 1997-2014 Erez Zadok
6  * Copyright (c) 1990 Jan-Simon Pendry
7  * Copyright (c) 1990 Imperial College of Science, Technology & Medicine
8  * Copyright (c) 1990 The Regents of the University of California.
9  * All rights reserved.
10  *
11  * This code is derived from software contributed to Berkeley by
12  * Jan-Simon Pendry at Imperial College, London.
13  *
14  * Redistribution and use in source and binary forms, with or without
15  * modification, are permitted provided that the following conditions
16  * are met:
17  * 1. Redistributions of source code must retain the above copyright
18  *    notice, this list of conditions and the following disclaimer.
19  * 2. Redistributions in binary form must reproduce the above copyright
20  *    notice, this list of conditions and the following disclaimer in the
21  *    documentation and/or other materials provided with the distribution.
22  * 3. Neither the name of the University nor the names of its contributors
23  *    may be used to endorse or promote products derived from this software
24  *    without specific prior written permission.
25  *
26  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
27  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
30  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36  * SUCH DAMAGE.
37  *
38  *
39  * File: am-utils/conf/autofs/autofs_solaris_v1.c
40  *
41  */
42 
43 /*
44  * Automounter filesystem
45  */
46 
47 #ifdef HAVE_CONFIG_H
48 # include <config.h>
49 #endif /* HAVE_CONFIG_H */
50 #include <am_defs.h>
51 #include <amd.h>
52 
53 #ifdef HAVE_FS_AUTOFS
54 
55 /*
56  * MACROS:
57  */
58 #ifndef AUTOFS_NULL
59 # define AUTOFS_NULL	NULLPROC
60 #endif /* not AUTOFS_NULL */
61 
62 /*
63  * STRUCTURES:
64  */
65 
66 /*
67  * VARIABLES:
68  */
69 
70 /* forward declarations */
71 # ifndef HAVE_XDR_MNTREQUEST
72 bool_t xdr_mntrequest(XDR *xdrs, mntrequest *objp);
73 # endif /* not HAVE_XDR_MNTREQUEST */
74 # ifndef HAVE_XDR_MNTRES
75 bool_t xdr_mntres(XDR *xdrs, mntres *objp);
76 # endif /* not HAVE_XDR_MNTRES */
77 # ifndef HAVE_XDR_UMNTREQUEST
78 bool_t xdr_umntrequest(XDR *xdrs, umntrequest *objp);
79 # endif /* not HAVE_XDR_UMNTREQUEST */
80 # ifndef HAVE_XDR_UMNTRES
81 bool_t xdr_umntres(XDR *xdrs, umntres *objp);
82 # endif /* not HAVE_XDR_UMNTRES */
83 static int autofs_mount_1_req(struct mntrequest *mr, struct mntres *result, struct authunix_parms *cred, SVCXPRT *transp);
84 static int autofs_unmount_1_req(struct umntrequest *ur, struct umntres *result, struct authunix_parms *cred, SVCXPRT *transp);
85 
86 /****************************************************************************
87  *** VARIABLES                                                            ***
88  ****************************************************************************/
89 
90 /****************************************************************************
91  *** FUNCTIONS                                                            ***
92  ****************************************************************************/
93 
94 /*
95  * AUTOFS XDR FUNCTIONS:
96  */
97 
98 #ifndef HAVE_XDR_MNTREQUEST
99 bool_t
xdr_mntrequest(XDR * xdrs,mntrequest * objp)100 xdr_mntrequest(XDR *xdrs, mntrequest *objp)
101 {
102   if (amuDebug(D_XDRTRACE))
103     plog(XLOG_DEBUG, "xdr_mntrequest:");
104 
105   if (!xdr_string(xdrs, &objp->name, A_MAXNAME))
106     return (FALSE);
107 
108   if (!xdr_string(xdrs, &objp->map, A_MAXNAME))
109     return (FALSE);
110 
111   if (!xdr_string(xdrs, &objp->opts, A_MAXOPTS))
112     return (FALSE);
113 
114   if (!xdr_string(xdrs, &objp->path, A_MAXPATH))
115     return (FALSE);
116 
117   return (TRUE);
118 }
119 #endif /* not HAVE_XDR_MNTREQUEST */
120 
121 
122 #ifndef HAVE_XDR_MNTRES
123 bool_t
xdr_mntres(XDR * xdrs,mntres * objp)124 xdr_mntres(XDR *xdrs, mntres *objp)
125 {
126   if (amuDebug(D_XDRTRACE))
127     plog(XLOG_DEBUG, "xdr_mntres:");
128 
129   if (!xdr_int(xdrs, &objp->status))
130     return (FALSE);
131 
132   return (TRUE);
133 }
134 # endif /* not HAVE_XDR_MNTRES */
135 
136 
137 #ifndef HAVE_XDR_UMNTREQUEST
138 bool_t
xdr_umntrequest(XDR * xdrs,umntrequest * objp)139 xdr_umntrequest(XDR *xdrs, umntrequest *objp)
140 {
141   if (amuDebug(D_XDRTRACE))
142     plog(XLOG_DEBUG, "xdr_umntrequest:");
143 
144   if (!xdr_int(xdrs, (int *) &objp->isdirect))
145     return (FALSE);
146 
147   if (!xdr_u_int(xdrs, (u_int *) &objp->devid))
148     return (FALSE);
149 
150 #ifdef HAVE_UMNTREQUEST_RDEVID
151   if (!xdr_u_long(xdrs, &objp->rdevid))
152     return (FALSE);
153 #endif /* HAVE_UMNTREQUEST_RDEVID */
154 
155   if (!xdr_pointer(xdrs, (char **) &objp->next, sizeof(umntrequest), (XDRPROC_T_TYPE) xdr_umntrequest))
156     return (FALSE);
157 
158   return (TRUE);
159 }
160 #endif /* not HAVE_XDR_UMNTREQUEST */
161 
162 
163 #ifndef HAVE_XDR_UMNTRES
164 bool_t
xdr_umntres(XDR * xdrs,umntres * objp)165 xdr_umntres(XDR *xdrs, umntres *objp)
166 {
167   if (amuDebug(D_XDRTRACE))
168     plog(XLOG_DEBUG, "xdr_mntres:");
169 
170   if (!xdr_int(xdrs, &objp->status))
171     return (FALSE);
172 
173   return (TRUE);
174 }
175 #endif /* not HAVE_XDR_UMNTRES */
176 
177 
178 /*
179  * AUTOFS RPC methods
180  */
181 
182 static int
autofs_mount_1_req(struct mntrequest * m,struct mntres * res,struct authunix_parms * cred,SVCXPRT * transp)183 autofs_mount_1_req(struct mntrequest *m,
184 		   struct mntres *res,
185 		   struct authunix_parms *cred,
186 		   SVCXPRT *transp)
187 {
188   int err = 0;
189   int isdirect = 0;
190   am_node *mp, *ap;
191   mntfs *mf;
192 
193   dlog("MOUNT REQUEST: name=%s map=%s opts=%s path=%s",
194        m->name, m->map, m->opts, m->path);
195 
196   /* find the effective uid/gid from RPC request */
197   xsnprintf(opt_uid, sizeof(uid_str), "%d", (int) cred->aup_uid);
198   xsnprintf(opt_gid, sizeof(gid_str), "%d", (int) cred->aup_gid);
199 
200   mp = find_ap(m->path);
201   if (!mp) {
202     plog(XLOG_ERROR, "map %s not found", m->path);
203     err = ENOENT;
204     goto out;
205   }
206 
207   mf = mp->am_al->al_mnt;
208   isdirect = (mf->mf_fsflags & FS_DIRECT) ? 1 : 0;
209   ap = mf->mf_ops->lookup_child(mp, m->name + isdirect, &err, VLOOK_CREATE);
210   if (ap && err < 0)
211     ap = mf->mf_ops->mount_child(ap, &err);
212   if (ap == NULL) {
213     if (err < 0) {
214       /* we're working on it */
215       amd_stats.d_drops++;
216       return 1;
217     }
218     err = ENOENT;
219     goto out;
220   }
221 
222 out:
223   if (err) {
224     if (isdirect) {
225       /* direct mount */
226       plog(XLOG_ERROR, "mount of %s failed", m->path);
227     } else {
228       /* indirect mount */
229       plog(XLOG_ERROR, "mount of %s/%s failed", m->path, m->name);
230     }
231   }
232 
233   dlog("MOUNT REPLY: status=%d (%s)", err, strerror(err));
234 
235   res->status = err;
236   return 0;
237 }
238 
239 
240 static int
autofs_unmount_1_req(struct umntrequest * ul,struct umntres * res,struct authunix_parms * cred,SVCXPRT * transp)241 autofs_unmount_1_req(struct umntrequest *ul,
242 		     struct umntres *res,
243 		     struct authunix_parms *cred,
244 		     SVCXPRT *transp)
245 {
246   int mapno, err;
247   am_node *mp = NULL;
248 
249   dlog("UNMOUNT REQUEST: dev=%lx rdev=%lx %s",
250        (u_long) ul->devid,
251        (u_long) ul->rdevid,
252        ul->isdirect ? "direct" : "indirect");
253 
254   /* by default, and if not found, succeed */
255   res->status = 0;
256 
257   for (mapno = 0; ; mapno++) {
258     mp = get_exported_ap(mapno);
259     if (!mp)
260       break;
261     if (mp->am_dev == ul->devid &&
262 	(ul->rdevid == 0 || mp->am_rdev == ul->rdevid))
263       break;
264   }
265 
266   if (mp) {
267     /* save RPC context */
268     if (!mp->am_transp && transp) {
269       mp->am_transp = (SVCXPRT *) xmalloc(sizeof(SVCXPRT));
270       *(mp->am_transp) = *transp;
271     }
272 
273     mapno = mp->am_mapno;
274     err = unmount_mp(mp);
275 
276     if (err)
277       /* backgrounded, don't reply yet */
278       return 1;
279 
280     if (get_exported_ap(mapno))
281       /* unmounting failed, tell the kernel */
282       res->status = 1;
283   }
284 
285   dlog("UNMOUNT REPLY: status=%d", res->status);
286   return 0;
287 }
288 
289 
290 /****************************************************************************/
291 /* autofs program dispatcher */
292 static void
autofs_program_1(struct svc_req * rqstp,SVCXPRT * transp)293 autofs_program_1(struct svc_req *rqstp, SVCXPRT *transp)
294 {
295   union {
296     mntrequest autofs_mount_1_arg;
297     umntrequest autofs_umount_1_arg;
298   } argument;
299   union {
300     mntres mount_res;
301     umntres umount_res;
302   } result;
303   int ret;
304 
305   bool_t (*xdr_argument)();
306   bool_t (*xdr_result)();
307   int (*local)();
308 
309   current_transp = transp;
310 
311   switch (rqstp->rq_proc) {
312 
313   case AUTOFS_NULL:
314     svc_sendreply(transp,
315 		  (XDRPROC_T_TYPE) xdr_void,
316 		  (SVC_IN_ARG_TYPE) NULL);
317     return;
318 
319   case AUTOFS_MOUNT:
320     xdr_argument = xdr_mntrequest;
321     xdr_result = xdr_mntres;
322     local = autofs_mount_1_req;
323     break;
324 
325   case AUTOFS_UNMOUNT:
326     xdr_argument = xdr_umntrequest;
327     xdr_result = xdr_umntres;
328     local = autofs_unmount_1_req;
329     break;
330 
331   default:
332     svcerr_noproc(transp);
333     return;
334   }
335 
336   memset((char *) &argument, 0, sizeof(argument));
337   if (!svc_getargs(transp,
338 		   (XDRPROC_T_TYPE) xdr_argument,
339 		   (SVC_IN_ARG_TYPE) &argument)) {
340     plog(XLOG_ERROR,
341 	 "AUTOFS xdr decode failed for %d %d %d",
342 	 (int) rqstp->rq_prog, (int) rqstp->rq_vers, (int) rqstp->rq_proc);
343     svcerr_decode(transp);
344     return;
345   }
346 
347   memset((char *)&result, 0, sizeof(result));
348   ret = (*local) (&argument, &result, rqstp, transp);
349 
350   current_transp = NULL;
351 
352   /* send reply only if the RPC method returned 0 */
353   if (!ret) {
354     if (!svc_sendreply(transp,
355 		       (XDRPROC_T_TYPE) xdr_result,
356 		       (SVC_IN_ARG_TYPE) &result)) {
357       svcerr_systemerr(transp);
358     }
359   }
360 
361   if (!svc_freeargs(transp,
362 		    (XDRPROC_T_TYPE) xdr_argument,
363 		    (SVC_IN_ARG_TYPE) &argument)) {
364     plog(XLOG_FATAL, "unable to free rpc arguments in autofs_program_1");
365   }
366 }
367 
368 
369 int
autofs_get_fh(am_node * mp)370 autofs_get_fh(am_node *mp)
371 {
372   autofs_fh_t *fh;
373   char buf[MAXHOSTNAMELEN];
374   mntfs *mf = mp->am_al->al_mnt;
375   struct utsname utsname;
376 
377   plog(XLOG_DEBUG, "autofs_get_fh for %s", mp->am_path);
378   fh = ALLOC(autofs_fh_t);
379   memset((voidp) fh, 0, sizeof(autofs_fh_t)); /* Paranoid */
380 
381   /*
382    * SET MOUNT ARGS
383    */
384   if (uname(&utsname) < 0) {
385     xstrlcpy(buf, "localhost.autofs", sizeof(buf));
386   } else {
387     xstrlcpy(buf, utsname.nodename, sizeof(buf));
388     xstrlcat(buf, ".autofs", sizeof(buf));
389   }
390 #ifdef HAVE_AUTOFS_ARGS_T_ADDR
391   fh->addr.buf = xstrdup(buf);
392   fh->addr.len = fh->addr.maxlen = strlen(buf);
393 #endif /* HAVE_AUTOFS_ARGS_T_ADDR */
394 
395   fh->direct = (mf->mf_fsflags & FS_DIRECT) ? 1 : 0;
396   fh->rpc_to = 1;		/* XXX: arbitrary */
397   fh->mount_to = mp->am_timeo;
398   fh->path = mp->am_path;
399   fh->opts = "";		/* XXX: arbitrary */
400   fh->map = mp->am_path;	/* this is what we get back in readdir */
401 
402   mp->am_autofs_fh = fh;
403   return 0;
404 }
405 
406 
407 void
autofs_mounted(am_node * mp)408 autofs_mounted(am_node *mp)
409 {
410   /* We don't want any timeouts on autofs nodes */
411   mp->am_autofs_ttl = NEVER;
412 }
413 
414 
415 void
autofs_release_fh(am_node * mp)416 autofs_release_fh(am_node *mp)
417 {
418   autofs_fh_t *fh = mp->am_autofs_fh;
419 #ifdef HAVE_AUTOFS_ARGS_T_ADDR
420   XFREE(fh->addr.buf);
421 #endif /* HAVE_AUTOFS_ARGS_T_ADDR */
422   XFREE(fh);
423   mp->am_autofs_fh = NULL;
424 }
425 
426 
427 void
autofs_get_mp(am_node * mp)428 autofs_get_mp(am_node *mp)
429 {
430   /* nothing to do */
431 }
432 
433 
434 void
autofs_release_mp(am_node * mp)435 autofs_release_mp(am_node *mp)
436 {
437   /* nothing to do */
438 }
439 
440 
441 void
autofs_add_fdset(fd_set * readfds)442 autofs_add_fdset(fd_set *readfds)
443 {
444   /* nothing to do */
445 }
446 
447 
448 int
autofs_handle_fdset(fd_set * readfds,int nsel)449 autofs_handle_fdset(fd_set *readfds, int nsel)
450 {
451   /* nothing to do */
452   return nsel;
453 }
454 
455 
456 /*
457  * Create the autofs service for amd
458  */
459 int
create_autofs_service(void)460 create_autofs_service(void)
461 {
462   dlog("creating autofs service listener");
463   return register_autofs_service(AUTOFS_CONFTYPE, autofs_program_1);
464 }
465 
466 
467 int
destroy_autofs_service(void)468 destroy_autofs_service(void)
469 {
470   dlog("destroying autofs service listener");
471   return unregister_autofs_service(AUTOFS_CONFTYPE);
472 }
473 
474 
475 int
autofs_mount_fs(am_node * mp,mntfs * mf)476 autofs_mount_fs(am_node *mp, mntfs *mf)
477 {
478   int err = 0;
479   char *target, *target2 = NULL;
480   char *space_hack = autofs_strdup_space_hack(mp->am_path);
481   struct stat buf;
482 
483   if (mf->mf_flags & MFF_ON_AUTOFS) {
484     if ((err = mkdir(space_hack, 0555)))
485       goto out;
486   }
487 
488   /*
489    * For sublinks, we could end up here with an already mounted f/s.
490    * Don't do anything in that case.
491    */
492   if (!(mf->mf_flags & MFF_MOUNTED))
493     err = mf->mf_ops->mount_fs(mp, mf);
494 
495   if (err) {
496     if (mf->mf_flags & MFF_ON_AUTOFS)
497       rmdir(space_hack);
498     errno = err;
499     goto out;
500   }
501 
502   /*
503    * Autofs v1 doesn't support symlinks,
504    * so we ignore the CFM_AUTOFS_USE_LOFS flag
505    */
506   if (mf->mf_flags & MFF_ON_AUTOFS)
507     /* Nothing to do */
508     goto out;
509 
510   if (mp->am_link)
511     target = mp->am_link;
512   else
513     target = mf->mf_mount;
514 
515   if (target[0] != '/')
516     target2 = str3cat(NULL, mp->am_parent->am_path, "/", target);
517   else
518     target2 = xstrdup(target);
519 
520   plog(XLOG_INFO, "autofs: converting from link to lofs (%s -> %s)", mp->am_path, target2);
521   /*
522    * we need to stat() the destination, because the bind mount does not
523    * follow symlinks and/or allow for non-existent destinations.
524    *
525    * WARNING: we will deadlock if this function is called from the master
526    * amd process and it happens to trigger another auto mount. Therefore,
527    * this function should be called only from a child amd process, or
528    * at the very least it should not be called from the parent unless we
529    * know for sure that it won't cause a recursive mount. We refuse to
530    * cause the recursive mount anyway if called from the parent amd.
531    */
532   if (!foreground) {
533     if ((err = stat(target2, &buf)))
534       goto out;
535   }
536   if ((err = lstat(target2, &buf)))
537     goto out;
538 
539   if ((err = mkdir(space_hack, 0555)))
540     goto out;
541 
542   if ((err = mount_lofs(mp->am_path, target2, mf->mf_mopts, 1))) {
543     errno = err;
544     goto out;
545   }
546 
547  out:
548   XFREE(space_hack);
549   if (target2)
550     XFREE(target2);
551 
552   if (err)
553     return errno;
554   return 0;
555 }
556 
557 
558 int
autofs_umount_fs(am_node * mp,mntfs * mf)559 autofs_umount_fs(am_node *mp, mntfs *mf)
560 {
561   int err = 0;
562   char *space_hack = autofs_strdup_space_hack(mp->am_path);
563 
564   /*
565    * Autofs v1 doesn't support symlinks,
566    * so we ignore the CFM_AUTOFS_USE_LOFS flag
567    */
568   if (!(mf->mf_flags & MFF_ON_AUTOFS)) {
569     err = UMOUNT_FS(mp->am_path, mnttab_file_name, 1);
570     if (err)
571       goto out;
572     rmdir(space_hack);
573   }
574 
575   /*
576    * Multiple sublinks could reference this f/s.
577    * Don't actually unmount it unless we're holding the last reference.
578    */
579   if (mf->mf_refc == 1) {
580     if ((err = mf->mf_ops->umount_fs(mp, mf)))
581       goto out;
582 
583     if (mf->mf_flags & MFF_ON_AUTOFS)
584       rmdir(space_hack);
585   }
586 
587  out:
588   XFREE(space_hack);
589   return err;
590 }
591 
592 
593 int
autofs_umount_succeeded(am_node * mp)594 autofs_umount_succeeded(am_node *mp)
595 {
596   umntres res;
597   SVCXPRT *transp = mp->am_transp;
598 
599   if (transp) {
600     res.status = 0;
601 
602     if (!svc_sendreply(transp,
603 		       (XDRPROC_T_TYPE) xdr_umntres,
604 		       (SVC_IN_ARG_TYPE) &res))
605       svcerr_systemerr(transp);
606 
607     dlog("Quick reply sent for %s", mp->am_al->al_mnt->mf_mount);
608     XFREE(transp);
609     mp->am_transp = NULL;
610   }
611 
612   plog(XLOG_INFO, "autofs: unmounting %s succeeded", mp->am_path);
613   return 0;
614 }
615 
616 
617 int
autofs_umount_failed(am_node * mp)618 autofs_umount_failed(am_node *mp)
619 {
620   umntres res;
621   SVCXPRT *transp = mp->am_transp;
622 
623   if (transp) {
624     res.status = 1;
625 
626     if (!svc_sendreply(transp,
627 		       (XDRPROC_T_TYPE) xdr_umntres,
628 		       (SVC_IN_ARG_TYPE) &res))
629       svcerr_systemerr(transp);
630 
631     dlog("Quick reply sent for %s", mp->am_al->al_mnt->mf_mount);
632     XFREE(transp);
633     mp->am_transp = NULL;
634   }
635 
636   plog(XLOG_INFO, "autofs: unmounting %s failed", mp->am_path);
637   return 0;
638 }
639 
640 
641 void
autofs_mount_succeeded(am_node * mp)642 autofs_mount_succeeded(am_node *mp)
643 {
644   SVCXPRT *transp = mp->am_transp;
645   struct stat stb;
646   char *space_hack;
647 
648   if (transp) {
649     /* this was a mount request */
650     mntres res;
651     res.status = 0;
652 
653     if (!svc_sendreply(transp,
654 		       (XDRPROC_T_TYPE) xdr_mntres,
655 		       (SVC_IN_ARG_TYPE) &res))
656       svcerr_systemerr(transp);
657 
658     dlog("Quick reply sent for %s", mp->am_al->al_mnt->mf_mount);
659     XFREE(transp);
660     mp->am_transp = NULL;
661   }
662 
663   space_hack = autofs_strdup_space_hack(mp->am_path);
664   if (!lstat(space_hack, &stb)) {
665     mp->am_dev = stb.st_dev;
666     mp->am_rdev = stb.st_rdev;
667   }
668   XFREE(space_hack);
669   /* don't expire the entries -- the kernel will do it for us */
670   mp->am_flags |= AMF_NOTIMEOUT;
671 
672   plog(XLOG_INFO, "autofs: mounting %s succeeded", mp->am_path);
673 }
674 
675 
676 void
autofs_mount_failed(am_node * mp)677 autofs_mount_failed(am_node *mp)
678 {
679   SVCXPRT *transp = mp->am_transp;
680 
681   if (transp) {
682     /* this was a mount request */
683     mntres res;
684     res.status = ENOENT;
685 
686     if (!svc_sendreply(transp,
687 		       (XDRPROC_T_TYPE) xdr_mntres,
688 		       (SVC_IN_ARG_TYPE) &res))
689       svcerr_systemerr(transp);
690 
691     dlog("Quick reply sent for %s", mp->am_al->al_mnt->mf_mount);
692     XFREE(transp);
693     mp->am_transp = NULL;
694   }
695 
696   plog(XLOG_INFO, "autofs: mounting %s failed", mp->am_path);
697 }
698 
699 
700 void
autofs_get_opts(char * opts,size_t l,autofs_fh_t * fh)701 autofs_get_opts(char *opts, size_t l, autofs_fh_t *fh)
702 {
703   xsnprintf(opts, l, "%sdirect",
704 	    fh->direct ? "" : "in");
705 }
706 
707 
708 int
autofs_compute_mount_flags(mntent_t * mntp)709 autofs_compute_mount_flags(mntent_t *mntp)
710 {
711   /* Must use overlay mounts */
712   return MNT2_GEN_OPT_OVERLAY;
713 }
714 
715 
autofs_timeout_mp(am_node * mp)716 void autofs_timeout_mp(am_node *mp)
717 {
718   /* We don't want any timeouts on autofs nodes */
719   mp->am_autofs_ttl = NEVER;
720 }
721 #endif /* HAVE_FS_AUTOFS */
722