1 /*	$NetBSD: autofs_linux.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_linux.c
40  *
41  */
42 
43 /*
44  * Automounter filesystem for Linux
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 
59 #define AUTOFS_MIN_VERSION 3
60 #if AUTOFS_MAX_PROTO_VERSION >= 5
61 /*
62  * Autofs version 5 support is experimental; change this to 5 you want
63  * to play with, it. There are reports it does not work.
64  */
65 #define AUTOFS_MAX_VERSION 4	/* we only know up to version 5 */
66 #else
67 #define AUTOFS_MAX_VERSION AUTOFS_MAX_PROTO_VERSION
68 #endif
69 
70 /*
71  * STRUCTURES:
72  */
73 
74 /*
75  * VARIABLES:
76  */
77 
78 static int autofs_max_fds;
79 static am_node **hash;
80 static int *list;
81 static int numfds = 0;
82 static int bind_works = 1;
83 
84 
85 static void
hash_init(void)86 hash_init(void)
87 {
88   int i;
89   struct rlimit rlim;
90 
91   if (getrlimit(RLIMIT_NOFILE, &rlim) < 0) {
92     plog(XLOG_ERROR, "getrlimit failed, defaulting to 256 fd's");
93     autofs_max_fds = 256;
94   } else {
95     autofs_max_fds = (rlim.rlim_cur > 1024) ? 1024 : rlim.rlim_cur;
96     plog(XLOG_INFO, "%d fd's available for autofs", autofs_max_fds);
97   }
98 
99   list = malloc(autofs_max_fds * sizeof(*list));
100   hash = malloc(autofs_max_fds * sizeof(*hash));
101 
102   for (i = 0 ; i < autofs_max_fds; i++) {
103     hash[i] = NULL;
104     list[i] = -1;
105   }
106 }
107 
108 
109 static void
hash_insert(int fd,am_node * mp)110 hash_insert(int fd, am_node *mp)
111 {
112   if (hash[fd] != 0)
113     plog(XLOG_ERROR, "file descriptor %d already in the hash", fd);
114 
115   hash[fd] = mp;
116   list[numfds] = fd;
117   numfds++;
118 }
119 
120 
121 static void
hash_delete(int fd)122 hash_delete(int fd)
123 {
124   int i;
125 
126   if (hash[fd] == 0)
127     plog(XLOG_WARNING, "file descriptor %d not in the hash", fd);
128 
129   hash[fd] = NULL;
130   numfds--;
131   for (i = 0; i < numfds; i++)
132     if (list[i] == fd) {
133       list[i] = list[numfds];
134       break;
135     }
136 }
137 
138 
139 int
autofs_get_fh(am_node * mp)140 autofs_get_fh(am_node *mp)
141 {
142   int fds[2];
143   autofs_fh_t *fh;
144 
145   plog(XLOG_DEBUG, "autofs_get_fh for %s", mp->am_path);
146   if (pipe(fds) < 0)
147     return errno;
148 
149   /* sanity check */
150   if (fds[0] > autofs_max_fds) {
151     close(fds[0]);
152     close(fds[1]);
153     return EMFILE;
154   }
155 
156   fh = ALLOC(autofs_fh_t);
157   fh->fd = fds[0];
158   fh->kernelfd = fds[1];
159   fh->ioctlfd = -1;
160   fh->pending_mounts = NULL;
161   fh->pending_umounts = NULL;
162 
163   mp->am_autofs_fh = fh;
164 
165   return 0;
166 }
167 
168 
169 void
autofs_mounted(am_node * mp)170 autofs_mounted(am_node *mp)
171 {
172   autofs_fh_t *fh = mp->am_autofs_fh;
173   unsigned long timeout = gopt.am_timeo;
174 
175   close(fh->kernelfd);
176   fh->kernelfd = -1;
177 
178   autofs_get_mp(mp);
179 
180   /* Get autofs protocol version */
181   if (ioctl(fh->ioctlfd, AUTOFS_IOC_PROTOVER, &fh->version) < 0) {
182     plog(XLOG_ERROR, "AUTOFS_IOC_PROTOVER: %s", strerror(errno));
183     fh->version = AUTOFS_MIN_VERSION;
184     plog(XLOG_ERROR, "autofs: assuming protocol version %d", fh->version);
185   } else
186     plog(XLOG_INFO, "autofs: using protocol version %d", fh->version);
187 
188   /* set expiration timeout */
189   if (ioctl(fh->ioctlfd, AUTOFS_IOC_SETTIMEOUT, &timeout) < 0)
190     plog(XLOG_ERROR, "AUTOFS_IOC_SETTIMEOUT: %s", strerror(errno));
191 
192   /* tell the daemon to call us for expirations */
193   mp->am_autofs_ttl = clocktime(NULL) + gopt.am_timeo_w;
194 }
195 
196 
197 void
autofs_get_mp(am_node * mp)198 autofs_get_mp(am_node *mp)
199 {
200   autofs_fh_t *fh = mp->am_autofs_fh;
201   dlog("autofs: getting mount point");
202   if (fh->ioctlfd < 0)
203     fh->ioctlfd = open(mp->am_path, O_RDONLY);
204   hash_insert(fh->fd, mp);
205 }
206 
207 
208 void
autofs_release_mp(am_node * mp)209 autofs_release_mp(am_node *mp)
210 {
211   autofs_fh_t *fh = mp->am_autofs_fh;
212   dlog("autofs: releasing mount point");
213   if (fh->ioctlfd >= 0) {
214     close(fh->ioctlfd);
215     fh->ioctlfd = -1;
216   }
217   /*
218    * take the kernel fd out of the hash/fdset
219    * so select() doesn't go crazy if the umount succeeds
220    */
221   if (fh->fd >= 0)
222     hash_delete(fh->fd);
223 }
224 
225 
226 void
autofs_release_fh(am_node * mp)227 autofs_release_fh(am_node *mp)
228 {
229   autofs_fh_t *fh = mp->am_autofs_fh;
230   struct autofs_pending_mount **pp, *p;
231   struct autofs_pending_umount **upp, *up;
232 
233   dlog("autofs: releasing file handle");
234   if (fh) {
235     /*
236      * if a mount succeeded, the kernel fd was closed on
237      * the amd side, so it might have been reused.
238      * we set it to -1 after closing it, to avoid the problem.
239      */
240     if (fh->kernelfd >= 0)
241       close(fh->kernelfd);
242 
243     if (fh->ioctlfd >= 0)
244       close(fh->ioctlfd);
245 
246     if (fh->fd >= 0)
247       close(fh->fd);
248 
249     pp = &fh->pending_mounts;
250     while (*pp) {
251       p = *pp;
252       XFREE(p->name);
253       *pp = p->next;
254       XFREE(p);
255     }
256 
257     upp = &fh->pending_umounts;
258     while (*upp) {
259       up = *upp;
260       XFREE(up->name);
261       *upp = up->next;
262       XFREE(up);
263     }
264 
265     XFREE(fh);
266     mp->am_autofs_fh = NULL;
267   }
268 }
269 
270 
271 void
autofs_add_fdset(fd_set * readfds)272 autofs_add_fdset(fd_set *readfds)
273 {
274   int i;
275   for (i = 0; i < numfds; i++)
276     FD_SET(list[i], readfds);
277 }
278 
279 
280 static ssize_t
autofs_get_pkt(int fd,void * buf,size_t bytes)281 autofs_get_pkt(int fd, void *buf, size_t bytes)
282 {
283   ssize_t i;
284 
285   do {
286     i = read(fd, buf, bytes);
287 
288     if (i <= 0)
289       break;
290 
291     buf = (char *)buf + i;
292     bytes -= i;
293   } while (bytes);
294 
295   return bytes;
296 }
297 
298 
299 static void
send_fail(int fd,autofs_wqt_t token)300 send_fail(int fd, autofs_wqt_t token)
301 {
302   if (token == 0)
303     return;
304   if (ioctl(fd, AUTOFS_IOC_FAIL, token) < 0)
305     plog(XLOG_ERROR, "AUTOFS_IOC_FAIL: %s", strerror(errno));
306 }
307 
308 
309 static void
send_ready(int fd,autofs_wqt_t token)310 send_ready(int fd, autofs_wqt_t token)
311 {
312   if (token == 0)
313     return;
314   if (ioctl(fd, AUTOFS_IOC_READY, token) < 0)
315     plog(XLOG_ERROR, "AUTOFS_IOC_READY: %s", strerror(errno));
316 }
317 
318 
319 static void
autofs_lookup_failed(am_node * mp,char * name)320 autofs_lookup_failed(am_node *mp, char *name)
321 {
322   autofs_fh_t *fh = mp->am_autofs_fh;
323   struct autofs_pending_mount **pp, *p;
324 
325   pp = &fh->pending_mounts;
326   while (*pp && !STREQ((*pp)->name, name))
327     pp = &(*pp)->next;
328 
329   /* sanity check */
330   if (*pp == NULL)
331     return;
332 
333   p = *pp;
334   plog(XLOG_INFO, "autofs: lookup of %s failed", name);
335   send_fail(fh->ioctlfd, p->wait_queue_token);
336 
337   XFREE(p->name);
338   *pp = p->next;
339   XFREE(p);
340 }
341 
342 
343 static void
autofs_expire_one(am_node * mp,char * name,autofs_wqt_t token)344 autofs_expire_one(am_node *mp, char *name, autofs_wqt_t token)
345 {
346   autofs_fh_t *fh;
347   am_node *ap;
348   struct autofs_pending_umount *p;
349   char *ap_path;
350 
351   fh = mp->am_autofs_fh;
352 
353   ap_path = str3cat(NULL, mp->am_path, "/", name);
354   if (amuDebug(D_TRACE))
355     plog(XLOG_DEBUG, "\tumount(%s)", ap_path);
356 
357   p = fh->pending_umounts;
358   while (p && p->wait_queue_token != token)
359     p = p->next;
360 
361   if (p) {
362     /* already pending */
363     dlog("Umounting of %s already pending", ap_path);
364     amd_stats.d_drops++;
365     goto out;
366   }
367 
368   ap = find_ap(ap_path);
369   if (ap == NULL) {
370     /* not found??? not sure what to do here... */
371     send_fail(fh->ioctlfd, token);
372     goto out;
373   }
374 
375   p = ALLOC(struct autofs_pending_umount);
376   p->wait_queue_token = token;
377   p->name = xstrdup(name);
378   p->next = fh->pending_umounts;
379   fh->pending_umounts = p;
380 
381   unmount_mp(ap);
382 
383 out:
384   XFREE(ap_path);
385 }
386 
387 
388 static void
autofs_missing_one(am_node * mp,autofs_wqt_t wait_queue_token,char * name)389 autofs_missing_one(am_node *mp, autofs_wqt_t wait_queue_token, char *name)
390 {
391   autofs_fh_t *fh;
392   mntfs *mf;
393   am_node *ap;
394   struct autofs_pending_mount *p;
395   int error;
396 
397   mf = mp->am_al->al_mnt;
398   fh = mp->am_autofs_fh;
399 
400   p = fh->pending_mounts;
401   while (p && p->wait_queue_token != wait_queue_token)
402     p = p->next;
403 
404   if (p) {
405     /* already pending */
406     dlog("Mounting of %s/%s already pending",
407 	 mp->am_path, name);
408     amd_stats.d_drops++;
409     return;
410   }
411 
412   p = ALLOC(struct autofs_pending_mount);
413   p->wait_queue_token = wait_queue_token;
414   p->name = xstrdup(name);
415   p->next = fh->pending_mounts;
416   fh->pending_mounts = p;
417 
418   if (amuDebug(D_TRACE))
419     plog(XLOG_DEBUG, "\tlookup(%s, %s)", mp->am_path, name);
420   ap = mf->mf_ops->lookup_child(mp, name, &error, VLOOK_CREATE);
421   if (ap && error < 0)
422     ap = mf->mf_ops->mount_child(ap, &error);
423 
424   /* some of the rest can be done in amfs_auto_cont */
425 
426   if (ap == 0) {
427     if (error < 0) {
428       dlog("Mount still pending, not sending autofs reply yet");
429       return;
430     }
431     autofs_lookup_failed(mp, name);
432   }
433   mp->am_stats.s_lookup++;
434 }
435 
436 
437 static void
autofs_handle_expire(am_node * mp,struct autofs_packet_expire * pkt)438 autofs_handle_expire(am_node *mp, struct autofs_packet_expire *pkt)
439 {
440   autofs_expire_one(mp, pkt->name, 0);
441 }
442 
443 
444 static void
autofs_handle_missing(am_node * mp,struct autofs_packet_missing * pkt)445 autofs_handle_missing(am_node *mp, struct autofs_packet_missing *pkt)
446 {
447   autofs_missing_one(mp, pkt->wait_queue_token, pkt->name);
448 }
449 
450 
451 #if AUTOFS_MAX_PROTO_VERSION >= 4
452 static void
autofs_handle_expire_multi(am_node * mp,struct autofs_packet_expire_multi * pkt)453 autofs_handle_expire_multi(am_node *mp, struct autofs_packet_expire_multi *pkt)
454 {
455   autofs_expire_one(mp, pkt->name, pkt->wait_queue_token);
456 }
457 #endif /* AUTOFS_MAX_PROTO_VERSION >= 4 */
458 
459 
460 #if AUTOFS_MAX_PROTO_VERSION >= 5
461 static void
autofs_handle_expire_direct(am_node * mp,autofs_packet_expire_direct_t * pkt)462 autofs_handle_expire_direct(am_node *mp,
463   autofs_packet_expire_direct_t *pkt)
464 {
465   autofs_expire_one(mp, pkt->name, 0);
466 }
467 
468 static void
autofs_handle_expire_indirect(am_node * mp,autofs_packet_expire_indirect_t * pkt)469 autofs_handle_expire_indirect(am_node *mp,
470   autofs_packet_expire_indirect_t *pkt)
471 {
472   autofs_expire_one(mp, pkt->name, 0);
473 }
474 
475 
476 static void
autofs_handle_missing_direct(am_node * mp,autofs_packet_missing_direct_t * pkt)477 autofs_handle_missing_direct(am_node *mp,
478   autofs_packet_missing_direct_t *pkt)
479 {
480   autofs_missing_one(mp, pkt->wait_queue_token, pkt->name);
481 }
482 
483 
484 static void
autofs_handle_missing_indirect(am_node * mp,autofs_packet_missing_indirect_t * pkt)485 autofs_handle_missing_indirect(am_node *mp,
486   autofs_packet_missing_indirect_t *pkt)
487 {
488   autofs_missing_one(mp, pkt->wait_queue_token, pkt->name);
489 }
490 #endif /* AUTOFS_MAX_PROTO_VERSION >= 5 */
491 
492 
493 int
autofs_handle_fdset(fd_set * readfds,int nsel)494 autofs_handle_fdset(fd_set *readfds, int nsel)
495 {
496   int i;
497   union {
498 #if AUTOFS_MAX_PROTO_VERSION >= 5
499     union autofs_v5_packet_union pkt5;
500 #endif
501     union autofs_packet_union pkt;
502   } p;
503   autofs_fh_t *fh;
504   am_node *mp;
505   size_t len;
506 
507   for (i = 0; nsel && i < numfds; i++) {
508     if (!FD_ISSET(list[i], readfds))
509       continue;
510 
511     nsel--;
512     FD_CLR(list[i], readfds);
513     mp = hash[list[i]];
514     fh = mp->am_autofs_fh;
515 
516 #if AUTOFS_MAX_PROTO_VERSION >= 5
517     if (fh->version < 5) {
518       len = sizeof(p.pkt);
519     } else {
520       len = sizeof(p.pkt5);
521     }
522 #else
523     len = sizeof(p.pkt);
524 #endif /* AUTOFS_MAX_PROTO_VERSION >= 5 */
525 
526     if (autofs_get_pkt(fh->fd, &p, len))
527       continue;
528 
529     switch (p.pkt.hdr.type) {
530     case autofs_ptype_missing:
531       autofs_handle_missing(mp, &p.pkt.missing);
532       break;
533     case autofs_ptype_expire:
534       autofs_handle_expire(mp, &p.pkt.expire);
535       break;
536 #if AUTOFS_MAX_PROTO_VERSION >= 4
537     case autofs_ptype_expire_multi:
538       autofs_handle_expire_multi(mp, &p.pkt.expire_multi);
539       break;
540 #endif /* AUTOFS_MAX_PROTO_VERSION >= 4 */
541 #if AUTOFS_MAX_PROTO_VERSION >= 5
542     case autofs_ptype_expire_indirect:
543       autofs_handle_expire_indirect(mp, &p.pkt5.expire_direct);
544       break;
545     case autofs_ptype_expire_direct:
546       autofs_handle_expire_direct(mp, &p.pkt5.expire_direct);
547       break;
548     case autofs_ptype_missing_indirect:
549       autofs_handle_missing_indirect(mp, &p.pkt5.missing_direct);
550       break;
551     case autofs_ptype_missing_direct:
552       autofs_handle_missing_direct(mp, &p.pkt5.missing_direct);
553       break;
554 #endif /* AUTOFS_MAX_PROTO_VERSION >= 5 */
555     default:
556       plog(XLOG_ERROR, "Unknown autofs packet type %d",
557 	   p.pkt.hdr.type);
558     }
559   }
560   return nsel;
561 }
562 
563 
564 int
create_autofs_service(void)565 create_autofs_service(void)
566 {
567   hash_init();
568 
569   /* not the best place, but... */
570   if (linux_version_code() < KERNEL_VERSION(2,4,0))
571     bind_works = 0;
572 
573   return 0;
574 }
575 
576 
577 int
destroy_autofs_service(void)578 destroy_autofs_service(void)
579 {
580   /* Nothing to do */
581   return 0;
582 }
583 
584 
585 static int
autofs_bind_umount(char * mountpoint)586 autofs_bind_umount(char *mountpoint)
587 {
588   int err = 1;
589 #ifdef MNT2_GEN_OPT_BIND
590   if (bind_works && gopt.flags & CFM_AUTOFS_USE_LOFS) {
591     struct stat buf;
592 
593     if ((err = lstat(mountpoint, &buf)))
594       return errno;
595     if (S_ISLNK(buf.st_mode))
596       goto use_symlink;
597 
598     plog(XLOG_INFO, "autofs: un-bind-mounting %s", mountpoint);
599     err = umount_fs(mountpoint, mnttab_file_name, 1);
600     if (err)
601       plog(XLOG_INFO, "autofs: unmounting %s failed: %m", mountpoint);
602     else
603       err = rmdir(mountpoint);
604     goto out;
605   }
606 #endif /* MNT2_GEN_OPT_BIND */
607  use_symlink:
608   plog(XLOG_INFO, "autofs: deleting symlink %s", mountpoint);
609   err = unlink(mountpoint);
610 
611  out:
612   if (err)
613     return errno;
614   return 0;
615 }
616 
617 
618 int
autofs_mount_fs(am_node * mp,mntfs * mf)619 autofs_mount_fs(am_node *mp, mntfs *mf)
620 {
621   char *target, *target2 = NULL;
622   int err = 0;
623 
624   if (mf->mf_flags & MFF_ON_AUTOFS) {
625     if ((err = mkdir(mp->am_path, 0555)))
626       return errno;
627   }
628 
629   /*
630    * For sublinks, we could end up here with an already mounted f/s.
631    * Don't do anything in that case.
632    */
633   if (!(mf->mf_flags & MFF_MOUNTED))
634     err = mf->mf_ops->mount_fs(mp, mf);
635 
636   if (err) {
637     if (mf->mf_flags & MFF_ON_AUTOFS)
638       rmdir(mp->am_path);
639     return err;
640   }
641 
642   if (mf->mf_flags & MFF_ON_AUTOFS)
643     /* Nothing else to do */
644     return 0;
645 
646   if (mp->am_link)
647     target = mp->am_link;
648   else
649     target = mf->mf_fo->opt_fs;
650 
651 #ifdef MNT2_GEN_OPT_BIND
652   if (bind_works && gopt.flags & CFM_AUTOFS_USE_LOFS) {
653     struct stat buf;
654 
655     /*
656      * HACK ALERT!
657      *
658      * Since the bind mount mechanism doesn't allow mountpoint crossing,
659      * we _must_ use symlinks for the host mount case. Otherwise we end up
660      * with a bunch of empty mountpoints...
661      */
662     if (mf->mf_ops == &amfs_host_ops)
663       goto use_symlink;
664 
665     if (target[0] != '/')
666       target2 = str3cat(NULL, mp->am_parent->am_path, "/", target);
667     else
668       target2 = xstrdup(target);
669 
670     /*
671      * We need to stat() the destination, because the bind mount does not
672      * follow symlinks and/or allow for non-existent destinations.
673      * We fall back to symlinks if there are problems.
674      *
675      * We also need to temporarily change pgrp, otherwise our stat() won't
676      * trigger whatever cascading mounts are needed.
677      *
678      * WARNING: we will deadlock if this function is called from the master
679      * amd process and it happens to trigger another auto mount. Therefore,
680      * this function should be called only from a child amd process, or
681      * at the very least it should not be called from the parent unless we
682      * know for sure that it won't cause a recursive mount. We refuse to
683      * cause the recursive mount anyway if called from the parent amd.
684      */
685     if (!foreground) {
686       pid_t pgrp = getpgrp();
687       setpgrp();
688       err = stat(target2, &buf);
689       if ((err = setpgid(0, pgrp))) {
690 	plog(XLOG_ERROR, "autofs: cannot restore pgrp: %s", strerror(errno));
691 	plog(XLOG_ERROR, "autofs: aborting the mount");
692 	goto out;
693       }
694       if (err)
695 	goto use_symlink;
696     }
697     if ((err = lstat(target2, &buf)))
698       goto use_symlink;
699     if (S_ISLNK(buf.st_mode))
700       goto use_symlink;
701 
702     plog(XLOG_INFO, "autofs: bind-mounting %s -> %s", mp->am_path, target2);
703     mkdir(mp->am_path, 0555);
704     err = mount_lofs(mp->am_path, target2, mf->mf_mopts, 1);
705     if (err) {
706       rmdir(mp->am_path);
707       plog(XLOG_INFO, "autofs: bind-mounting %s -> %s failed", mp->am_path, target2);
708       goto use_symlink;
709     }
710     goto out;
711   }
712 #endif /* MNT2_GEN_OPT_BIND */
713  use_symlink:
714   plog(XLOG_INFO, "autofs: symlinking %s -> %s", mp->am_path, target);
715   err = symlink(target, mp->am_path);
716 
717  out:
718   if (target2)
719     XFREE(target2);
720 
721   if (err)
722     return errno;
723   return 0;
724 }
725 
726 
727 int
autofs_umount_fs(am_node * mp,mntfs * mf)728 autofs_umount_fs(am_node *mp, mntfs *mf)
729 {
730   int err = 0;
731   if (!(mf->mf_flags & MFF_ON_AUTOFS)) {
732     err = autofs_bind_umount(mp->am_path);
733     if (err)
734       return err;
735   }
736 
737   /*
738    * Multiple sublinks could reference this f/s.
739    * Don't actually unmount it unless we're holding the last reference.
740    */
741   if (mf->mf_refc == 1) {
742     err = mf->mf_ops->umount_fs(mp, mf);
743     if (err)
744       return err;
745     if (mf->mf_flags & MFF_ON_AUTOFS)
746       rmdir(mp->am_path);
747   }
748   return 0;
749 }
750 
751 
752 int
autofs_umount_succeeded(am_node * mp)753 autofs_umount_succeeded(am_node *mp)
754 {
755   autofs_fh_t *fh = mp->am_parent->am_autofs_fh;
756   struct autofs_pending_umount **pp, *p;
757 
758   /* Already gone? */
759   if (fh == NULL)
760 	return 0;
761 
762   pp = &fh->pending_umounts;
763   while (*pp && !STREQ((*pp)->name, mp->am_name))
764     pp = &(*pp)->next;
765 
766   /* sanity check */
767   if (*pp == NULL)
768     return -1;
769 
770   p = *pp;
771   plog(XLOG_INFO, "autofs: unmounting %s succeeded", mp->am_path);
772   send_ready(fh->ioctlfd, p->wait_queue_token);
773 
774   XFREE(p->name);
775   *pp = p->next;
776   XFREE(p);
777   return 0;
778 }
779 
780 
781 int
autofs_umount_failed(am_node * mp)782 autofs_umount_failed(am_node *mp)
783 {
784   autofs_fh_t *fh = mp->am_parent->am_autofs_fh;
785   struct autofs_pending_umount **pp, *p;
786 
787   pp = &fh->pending_umounts;
788   while (*pp && !STREQ((*pp)->name, mp->am_name))
789     pp = &(*pp)->next;
790 
791   /* sanity check */
792   if (*pp == NULL)
793     return -1;
794 
795   p = *pp;
796   plog(XLOG_INFO, "autofs: unmounting %s failed", mp->am_path);
797   send_fail(fh->ioctlfd, p->wait_queue_token);
798 
799   XFREE(p->name);
800   *pp = p->next;
801   XFREE(p);
802   return 0;
803 }
804 
805 
806 void
autofs_mount_succeeded(am_node * mp)807 autofs_mount_succeeded(am_node *mp)
808 {
809   autofs_fh_t *fh = mp->am_parent->am_autofs_fh;
810   struct autofs_pending_mount **pp, *p;
811 
812   /*
813    * don't expire the entries -- the kernel will do it for us.
814    *
815    * but it won't do autofs filesystems, so we expire them the old
816    * fashioned way instead.
817    */
818   if (!(mp->am_al->al_mnt->mf_flags & MFF_IS_AUTOFS))
819     mp->am_flags |= AMF_NOTIMEOUT;
820 
821   pp = &fh->pending_mounts;
822   while (*pp && !STREQ((*pp)->name, mp->am_name))
823     pp = &(*pp)->next;
824 
825   /* sanity check */
826   if (*pp == NULL)
827     return;
828 
829   p = *pp;
830   plog(XLOG_INFO, "autofs: mounting %s succeeded", mp->am_path);
831   send_ready(fh->ioctlfd, p->wait_queue_token);
832 
833   XFREE(p->name);
834   *pp = p->next;
835   XFREE(p);
836 }
837 
838 
839 void
autofs_mount_failed(am_node * mp)840 autofs_mount_failed(am_node *mp)
841 {
842   autofs_fh_t *fh = mp->am_parent->am_autofs_fh;
843   struct autofs_pending_mount **pp, *p;
844 
845   pp = &fh->pending_mounts;
846   while (*pp && !STREQ((*pp)->name, mp->am_name))
847     pp = &(*pp)->next;
848 
849   /* sanity check */
850   if (*pp == NULL)
851     return;
852 
853   p = *pp;
854   plog(XLOG_INFO, "autofs: mounting %s failed", mp->am_path);
855   send_fail(fh->ioctlfd, p->wait_queue_token);
856 
857   XFREE(p->name);
858   *pp = p->next;
859   XFREE(p);
860 }
861 
862 
863 void
autofs_get_opts(char * opts,size_t l,autofs_fh_t * fh)864 autofs_get_opts(char *opts, size_t l, autofs_fh_t *fh)
865 {
866   xsnprintf(opts, l, "fd=%d,minproto=%d,maxproto=%d",
867 	    fh->kernelfd, AUTOFS_MIN_VERSION, AUTOFS_MAX_VERSION);
868 }
869 
870 
871 int
autofs_compute_mount_flags(mntent_t * mnt)872 autofs_compute_mount_flags(mntent_t *mnt)
873 {
874   return 0;
875 }
876 
877 
878 #if AUTOFS_MAX_PROTO_VERSION >= 4
autofs_timeout_mp_task(void * arg)879 static int autofs_timeout_mp_task(void *arg)
880 {
881   am_node *mp = (am_node *)arg;
882   autofs_fh_t *fh = mp->am_autofs_fh;
883   int now = 0;
884 
885   while (ioctl(fh->ioctlfd, AUTOFS_IOC_EXPIRE_MULTI, &now) == 0);
886   return 0;
887 }
888 #endif /* AUTOFS_MAX_PROTO_VERSION >= 4 */
889 
890 
autofs_timeout_mp(am_node * mp)891 void autofs_timeout_mp(am_node *mp)
892 {
893   autofs_fh_t *fh = mp->am_autofs_fh;
894   time_t now = clocktime(NULL);
895 
896   /* update the ttl */
897   mp->am_autofs_ttl = now + gopt.am_timeo_w;
898 
899   if (fh->version < 4) {
900     struct autofs_packet_expire pkt;
901     while (ioctl(fh->ioctlfd, AUTOFS_IOC_EXPIRE, &pkt) == 0)
902       autofs_handle_expire(mp, &pkt);
903     return;
904   }
905 
906 #if AUTOFS_MAX_PROTO_VERSION >= 4
907   run_task(autofs_timeout_mp_task, mp, NULL, NULL);
908 #endif /* AUTOFS_MAX_PROTO_VERSION >= 4 */
909 }
910 
911 #endif /* HAVE_FS_AUTOFS */
912