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