1 /* 2 * Copyright (c) 1992, 1993 3 * The Regents of the University of California. All rights reserved. 4 * Copyright (c) 2000 5 * Poul-Henning Kamp. All rights reserved. 6 * 7 * This code is derived from software donated to Berkeley by 8 * Jan-Simon Pendry. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Neither the name of the University nor the names of its contributors 16 * may be used to endorse or promote products derived from this software 17 * without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 * SUCH DAMAGE. 30 * 31 * @(#)kernfs_vnops.c 8.15 (Berkeley) 5/21/95 32 * From: FreeBSD: src/sys/miscfs/kernfs/kernfs_vnops.c 1.43 33 * 34 * $FreeBSD$ 35 */ 36 37 /* 38 * TODO: 39 * remove empty directories 40 * mknod: hunt down DE_DELETED, compare name, reinstantiate. 41 * mkdir: want it ? 42 */ 43 44 #include <opt_devfs.h> 45 #include <opt_mac.h> 46 47 #include <sys/param.h> 48 #include <sys/systm.h> 49 #include <sys/conf.h> 50 #include <sys/dirent.h> 51 #include <sys/kernel.h> 52 #include <sys/lock.h> 53 #include <sys/mac.h> 54 #include <sys/malloc.h> 55 #include <sys/mount.h> 56 #include <sys/namei.h> 57 #include <sys/proc.h> 58 #include <sys/time.h> 59 #include <sys/unistd.h> 60 #include <sys/vnode.h> 61 62 #include <fs/devfs/devfs.h> 63 64 static int devfs_access(struct vop_access_args *ap); 65 static int devfs_getattr(struct vop_getattr_args *ap); 66 static int devfs_ioctl(struct vop_ioctl_args *ap); 67 static int devfs_lookupx(struct vop_lookup_args *ap); 68 static int devfs_mknod(struct vop_mknod_args *ap); 69 static int devfs_pathconf(struct vop_pathconf_args *ap); 70 static int devfs_read(struct vop_read_args *ap); 71 static int devfs_readdir(struct vop_readdir_args *ap); 72 static int devfs_readlink(struct vop_readlink_args *ap); 73 static int devfs_reclaim(struct vop_reclaim_args *ap); 74 static int devfs_remove(struct vop_remove_args *ap); 75 static int devfs_revoke(struct vop_revoke_args *ap); 76 static int devfs_setattr(struct vop_setattr_args *ap); 77 #ifdef MAC 78 static int devfs_setlabel(struct vop_setlabel_args *ap); 79 #endif 80 static int devfs_symlink(struct vop_symlink_args *ap); 81 82 static vop_t **devfs_vnodeop_p; 83 static vop_t **devfs_specop_p; 84 85 /* 86 * Construct the fully qualified path name relative to the mountpoint 87 */ 88 static char * 89 devfs_fqpn(char *buf, struct vnode *dvp, struct componentname *cnp) 90 { 91 int i; 92 struct devfs_dirent *de, *dd; 93 struct devfs_mount *dmp; 94 95 dmp = VFSTODEVFS(dvp->v_mount); 96 dd = dvp->v_data; 97 i = SPECNAMELEN; 98 buf[i] = '\0'; 99 i -= cnp->cn_namelen; 100 if (i < 0) 101 return (NULL); 102 bcopy(cnp->cn_nameptr, buf + i, cnp->cn_namelen); 103 de = dd; 104 while (de != dmp->dm_basedir) { 105 i--; 106 if (i < 0) 107 return (NULL); 108 buf[i] = '/'; 109 i -= de->de_dirent->d_namlen; 110 if (i < 0) 111 return (NULL); 112 bcopy(de->de_dirent->d_name, buf + i, 113 de->de_dirent->d_namlen); 114 de = TAILQ_FIRST(&de->de_dlist); /* "." */ 115 de = TAILQ_NEXT(de, de_list); /* ".." */ 116 de = de->de_dir; 117 } 118 return (buf + i); 119 } 120 121 int 122 devfs_allocv(struct devfs_dirent *de, struct mount *mp, struct vnode **vpp, struct thread *td) 123 { 124 int error; 125 struct vnode *vp; 126 struct cdev *dev; 127 128 KASSERT(td == curthread, ("devfs_allocv: td != curthread")); 129 loop: 130 vp = de->de_vnode; 131 if (vp != NULL) { 132 if (vget(vp, LK_EXCLUSIVE, td)) 133 goto loop; 134 *vpp = vp; 135 return (0); 136 } 137 if (de->de_dirent->d_type == DT_CHR) { 138 dev = *devfs_itod(de->de_inode); 139 if (dev == NULL) 140 return (ENOENT); 141 } else { 142 dev = NULL; 143 } 144 error = getnewvnode("devfs", mp, devfs_vnodeop_p, &vp); 145 if (error != 0) { 146 printf("devfs_allocv: failed to allocate new vnode\n"); 147 return (error); 148 } 149 150 if (de->de_dirent->d_type == DT_CHR) { 151 vp->v_type = VCHR; 152 vp = addaliasu(vp, dev->si_udev); 153 vp->v_op = devfs_specop_p; 154 } else if (de->de_dirent->d_type == DT_DIR) { 155 vp->v_type = VDIR; 156 } else if (de->de_dirent->d_type == DT_LNK) { 157 vp->v_type = VLNK; 158 } else { 159 vp->v_type = VBAD; 160 } 161 vp->v_data = de; 162 de->de_vnode = vp; 163 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 164 #ifdef MAC 165 mac_associate_vnode_devfs(mp, de, vp); 166 #endif 167 *vpp = vp; 168 return (0); 169 } 170 171 static int 172 devfs_access(ap) 173 struct vop_access_args /* { 174 struct vnode *a_vp; 175 int a_mode; 176 struct ucred *a_cred; 177 struct thread *a_td; 178 } */ *ap; 179 { 180 struct vnode *vp = ap->a_vp; 181 struct devfs_dirent *de; 182 int error; 183 184 de = vp->v_data; 185 if (vp->v_type == VDIR) 186 de = de->de_dir; 187 188 error = vaccess(vp->v_type, de->de_mode, de->de_uid, de->de_gid, 189 ap->a_mode, ap->a_cred, NULL); 190 if (!error) 191 return (error); 192 if (error != EACCES) 193 return (error); 194 /* We do, however, allow access to the controlling terminal */ 195 if (!(ap->a_td->td_proc->p_flag & P_CONTROLT)) 196 return (error); 197 if (ap->a_td->td_proc->p_session->s_ttyvp == de->de_vnode) 198 return (0); 199 return (error); 200 } 201 202 static int 203 devfs_getattr(ap) 204 struct vop_getattr_args /* { 205 struct vnode *a_vp; 206 struct vattr *a_vap; 207 struct ucred *a_cred; 208 struct thread *a_td; 209 } */ *ap; 210 { 211 struct vnode *vp = ap->a_vp; 212 struct vattr *vap = ap->a_vap; 213 int error = 0; 214 struct devfs_dirent *de; 215 struct cdev *dev; 216 217 de = vp->v_data; 218 if (vp->v_type == VDIR) 219 de = de->de_dir; 220 bzero((caddr_t) vap, sizeof(*vap)); 221 vattr_null(vap); 222 vap->va_uid = de->de_uid; 223 vap->va_gid = de->de_gid; 224 vap->va_mode = de->de_mode; 225 if (vp->v_type == VLNK) 226 vap->va_size = strlen(de->de_symlink); 227 else if (vp->v_type == VDIR) 228 vap->va_size = vap->va_bytes = DEV_BSIZE; 229 else 230 vap->va_size = 0; 231 if (vp->v_type != VDIR) 232 vap->va_bytes = 0; 233 vap->va_blocksize = DEV_BSIZE; 234 vap->va_type = vp->v_type; 235 236 #define fix(aa) \ 237 do { \ 238 if ((aa).tv_sec == 0) { \ 239 (aa).tv_sec = boottime.tv_sec; \ 240 (aa).tv_nsec = boottime.tv_usec * 1000; \ 241 } \ 242 } while (0) 243 244 if (vp->v_type != VCHR) { 245 fix(de->de_atime); 246 vap->va_atime = de->de_atime; 247 fix(de->de_mtime); 248 vap->va_mtime = de->de_mtime; 249 fix(de->de_ctime); 250 vap->va_ctime = de->de_ctime; 251 } else { 252 dev = vp->v_rdev; 253 fix(dev->si_atime); 254 vap->va_atime = dev->si_atime; 255 fix(dev->si_mtime); 256 vap->va_mtime = dev->si_mtime; 257 fix(dev->si_ctime); 258 vap->va_ctime = dev->si_ctime; 259 vap->va_rdev = dev->si_udev; 260 } 261 vap->va_gen = 0; 262 vap->va_flags = 0; 263 vap->va_nlink = de->de_links; 264 vap->va_fileid = de->de_inode; 265 266 return (error); 267 } 268 269 static int 270 devfs_ioctl(ap) 271 struct vop_ioctl_args /* { 272 struct vnode *a_vp; 273 u_long a_command; 274 caddr_t a_data; 275 int a_fflag; 276 struct ucred *a_cred; 277 struct thread *a_td; 278 } */ *ap; 279 { 280 int error; 281 struct devfs_mount *dmp; 282 283 dmp = VFSTODEVFS(ap->a_vp->v_mount); 284 lockmgr(&dmp->dm_lock, LK_SHARED, 0, curthread); 285 devfs_populate(dmp); 286 lockmgr(&dmp->dm_lock, LK_RELEASE, 0, curthread); 287 error = devfs_rules_ioctl(ap->a_vp->v_mount, ap->a_command, ap->a_data, 288 ap->a_td); 289 return (error); 290 } 291 292 static int 293 devfs_lookupx(ap) 294 struct vop_lookup_args /* { 295 struct vnode * a_dvp; 296 struct vnode ** a_vpp; 297 struct componentname * a_cnp; 298 } */ *ap; 299 { 300 struct componentname *cnp; 301 struct vnode *dvp, **vpp; 302 struct thread *td; 303 struct devfs_dirent *de, *dd; 304 struct devfs_dirent **dde; 305 struct devfs_mount *dmp; 306 struct cdev *cdev; 307 int error, flags, nameiop; 308 char specname[SPECNAMELEN + 1], *pname; 309 310 cnp = ap->a_cnp; 311 vpp = ap->a_vpp; 312 dvp = ap->a_dvp; 313 pname = cnp->cn_nameptr; 314 td = cnp->cn_thread; 315 flags = cnp->cn_flags; 316 nameiop = cnp->cn_nameiop; 317 dmp = VFSTODEVFS(dvp->v_mount); 318 dd = dvp->v_data; 319 320 *vpp = NULLVP; 321 cnp->cn_flags &= ~PDIRUNLOCK; 322 323 if ((flags & ISLASTCN) && nameiop == RENAME) 324 return (EOPNOTSUPP); 325 326 if (dvp->v_type != VDIR) 327 return (ENOTDIR); 328 329 if ((flags & ISDOTDOT) && (dvp->v_vflag & VV_ROOT)) 330 return (EIO); 331 332 error = VOP_ACCESS(dvp, VEXEC, cnp->cn_cred, td); 333 if (error) 334 return (error); 335 336 if (cnp->cn_namelen == 1 && *pname == '.') { 337 if ((flags & ISLASTCN) && nameiop != LOOKUP) 338 return (EINVAL); 339 *vpp = dvp; 340 VREF(dvp); 341 return (0); 342 } 343 344 if (flags & ISDOTDOT) { 345 if ((flags & ISLASTCN) && nameiop != LOOKUP) 346 return (EINVAL); 347 VOP_UNLOCK(dvp, 0, td); 348 cnp->cn_flags |= PDIRUNLOCK; 349 de = TAILQ_FIRST(&dd->de_dlist); /* "." */ 350 de = TAILQ_NEXT(de, de_list); /* ".." */ 351 de = de->de_dir; 352 error = devfs_allocv(de, dvp->v_mount, vpp, td); 353 if (error || ((flags & LOCKPARENT) && (flags & ISLASTCN))) { 354 vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY, td); 355 cnp->cn_flags &= ~PDIRUNLOCK; 356 } 357 return (error); 358 } 359 360 devfs_populate(dmp); 361 dd = dvp->v_data; 362 TAILQ_FOREACH(de, &dd->de_dlist, de_list) { 363 if (cnp->cn_namelen != de->de_dirent->d_namlen) 364 continue; 365 if (bcmp(cnp->cn_nameptr, de->de_dirent->d_name, 366 de->de_dirent->d_namlen) != 0) 367 continue; 368 if (de->de_flags & DE_WHITEOUT) 369 goto notfound; 370 goto found; 371 } 372 373 if (nameiop == DELETE) 374 goto notfound; 375 376 /* 377 * OK, we didn't have an entry for the name we were asked for 378 * so we try to see if anybody can create it on demand. 379 */ 380 pname = devfs_fqpn(specname, dvp, cnp); 381 if (pname == NULL) 382 goto notfound; 383 384 cdev = NULL; 385 EVENTHANDLER_INVOKE(dev_clone, pname, strlen(pname), &cdev); 386 if (cdev == NULL) 387 goto notfound; 388 389 devfs_populate(dmp); 390 391 dde = devfs_itode(dmp, cdev->si_inode); 392 393 if (dde == NULL || *dde == NULL || *dde == DE_DELETED) 394 goto notfound; 395 396 if ((*dde)->de_flags & DE_WHITEOUT) 397 goto notfound; 398 399 de = *dde; 400 goto found; 401 402 notfound: 403 404 if ((nameiop == CREATE || nameiop == RENAME) && 405 (flags & (LOCKPARENT | WANTPARENT)) && (flags & ISLASTCN)) { 406 cnp->cn_flags |= SAVENAME; 407 if (!(flags & LOCKPARENT)) { 408 VOP_UNLOCK(dvp, 0, td); 409 cnp->cn_flags |= PDIRUNLOCK; 410 } 411 return (EJUSTRETURN); 412 } 413 return (ENOENT); 414 415 416 found: 417 418 if ((cnp->cn_nameiop == DELETE) && (flags & ISLASTCN)) { 419 error = VOP_ACCESS(dvp, VWRITE, cnp->cn_cred, td); 420 if (error) 421 return (error); 422 if (*vpp == dvp) { 423 VREF(dvp); 424 *vpp = dvp; 425 return (0); 426 } 427 error = devfs_allocv(de, dvp->v_mount, vpp, td); 428 if (error) 429 return (error); 430 if (!(flags & LOCKPARENT)) { 431 VOP_UNLOCK(dvp, 0, td); 432 cnp->cn_flags |= PDIRUNLOCK; 433 } 434 return (0); 435 } 436 error = devfs_allocv(de, dvp->v_mount, vpp, td); 437 if (error) 438 return (error); 439 if (!(flags & LOCKPARENT) || !(flags & ISLASTCN)) { 440 VOP_UNLOCK(dvp, 0, td); 441 cnp->cn_flags |= PDIRUNLOCK; 442 } 443 return (0); 444 } 445 446 static int 447 devfs_lookup(struct vop_lookup_args *ap) 448 { 449 int j; 450 struct devfs_mount *dmp; 451 452 dmp = VFSTODEVFS(ap->a_dvp->v_mount); 453 lockmgr(&dmp->dm_lock, LK_SHARED, 0, curthread); 454 j = devfs_lookupx(ap); 455 lockmgr(&dmp->dm_lock, LK_RELEASE, 0, curthread); 456 return (j); 457 } 458 459 static int 460 devfs_mknod(struct vop_mknod_args *ap) 461 /* 462 struct vop_mknod_args { 463 struct vnodeop_desc *a_desc; 464 struct vnode *a_dvp; 465 struct vnode **a_vpp; 466 struct componentname *a_cnp; 467 struct vattr *a_vap; 468 }; 469 */ 470 { 471 struct componentname *cnp; 472 struct vnode *dvp, **vpp; 473 struct thread *td; 474 struct devfs_dirent *dd, *de; 475 struct devfs_mount *dmp; 476 int error; 477 478 dvp = ap->a_dvp; 479 dmp = VFSTODEVFS(dvp->v_mount); 480 lockmgr(&dmp->dm_lock, LK_EXCLUSIVE, 0, curthread); 481 482 cnp = ap->a_cnp; 483 vpp = ap->a_vpp; 484 td = cnp->cn_thread; 485 dd = dvp->v_data; 486 487 error = ENOENT; 488 TAILQ_FOREACH(de, &dd->de_dlist, de_list) { 489 if (cnp->cn_namelen != de->de_dirent->d_namlen) 490 continue; 491 if (bcmp(cnp->cn_nameptr, de->de_dirent->d_name, 492 de->de_dirent->d_namlen) != 0) 493 continue; 494 if (de->de_flags & DE_WHITEOUT) 495 break; 496 goto notfound; 497 } 498 if (de == NULL) 499 goto notfound; 500 de->de_flags &= ~DE_WHITEOUT; 501 error = devfs_allocv(de, dvp->v_mount, vpp, td); 502 notfound: 503 lockmgr(&dmp->dm_lock, LK_RELEASE, 0, curthread); 504 return (error); 505 } 506 507 508 static int 509 devfs_pathconf(ap) 510 struct vop_pathconf_args /* { 511 struct vnode *a_vp; 512 int a_name; 513 int *a_retval; 514 } */ *ap; 515 { 516 517 switch (ap->a_name) { 518 case _PC_NAME_MAX: 519 *ap->a_retval = NAME_MAX; 520 return (0); 521 case _PC_PATH_MAX: 522 *ap->a_retval = PATH_MAX; 523 return (0); 524 case _PC_MAC_PRESENT: 525 #ifdef MAC 526 /* 527 * If MAC is enabled, devfs automatically supports 528 * trivial non-persistant label storage. 529 */ 530 *ap->a_retval = 1; 531 #else 532 *ap->a_retval = 0; 533 #endif 534 return (0); 535 default: 536 return (vop_stdpathconf(ap)); 537 } 538 /* NOTREACHED */ 539 } 540 541 static int 542 devfs_read(ap) 543 struct vop_read_args /* { 544 struct vnode *a_vp; 545 struct uio *a_uio; 546 int a_ioflag; 547 struct ucred *a_cred; 548 } */ *ap; 549 { 550 551 if (ap->a_vp->v_type != VDIR) 552 return (EINVAL); 553 return (VOP_READDIR(ap->a_vp, ap->a_uio, ap->a_cred, NULL, NULL, NULL)); 554 } 555 556 static int 557 devfs_readdir(ap) 558 struct vop_readdir_args /* { 559 struct vnode *a_vp; 560 struct uio *a_uio; 561 struct ucred *a_cred; 562 int *a_eofflag; 563 int *a_ncookies; 564 u_long **a_cookies; 565 } */ *ap; 566 { 567 int error; 568 struct uio *uio; 569 struct dirent *dp; 570 struct devfs_dirent *dd; 571 struct devfs_dirent *de; 572 struct devfs_mount *dmp; 573 off_t off, oldoff; 574 int ncookies = 0; 575 u_long *cookiebuf, *cookiep; 576 struct dirent *dps, *dpe; 577 578 if (ap->a_vp->v_type != VDIR) 579 return (ENOTDIR); 580 581 uio = ap->a_uio; 582 if (uio->uio_offset < 0) 583 return (EINVAL); 584 585 dmp = VFSTODEVFS(ap->a_vp->v_mount); 586 lockmgr(&dmp->dm_lock, LK_SHARED, 0, curthread); 587 devfs_populate(dmp); 588 error = 0; 589 de = ap->a_vp->v_data; 590 off = 0; 591 oldoff = uio->uio_offset; 592 TAILQ_FOREACH(dd, &de->de_dlist, de_list) { 593 if (dd->de_flags & DE_WHITEOUT) 594 continue; 595 if (dd->de_dirent->d_type == DT_DIR) 596 de = dd->de_dir; 597 else 598 de = dd; 599 dp = dd->de_dirent; 600 if (dp->d_reclen > uio->uio_resid) 601 break; 602 dp->d_fileno = de->de_inode; 603 if (off >= uio->uio_offset) { 604 ncookies++; 605 error = uiomove(dp, dp->d_reclen, uio); 606 if (error) 607 break; 608 } 609 off += dp->d_reclen; 610 } 611 if( !error && ap->a_ncookies != NULL && ap->a_cookies != NULL ) { 612 MALLOC(cookiebuf, u_long *, ncookies * sizeof(u_long), 613 M_TEMP, M_WAITOK); 614 cookiep = cookiebuf; 615 dps = (struct dirent *)((char *)uio->uio_iov->iov_base - 616 (uio->uio_offset - oldoff)); 617 dpe = (struct dirent *) uio->uio_iov->iov_base; 618 for( dp = dps; 619 dp < dpe; 620 dp = (struct dirent *)((caddr_t) dp + dp->d_reclen)) { 621 oldoff += dp->d_reclen; 622 *cookiep++ = (u_long) oldoff; 623 } 624 *ap->a_ncookies = ncookies; 625 *ap->a_cookies = cookiebuf; 626 } 627 lockmgr(&dmp->dm_lock, LK_RELEASE, 0, curthread); 628 uio->uio_offset = off; 629 return (error); 630 } 631 632 static int 633 devfs_readlink(ap) 634 struct vop_readlink_args /* { 635 struct vnode *a_vp; 636 struct uio *a_uio; 637 struct ucred *a_cead; 638 } */ *ap; 639 { 640 int error; 641 struct devfs_dirent *de; 642 643 de = ap->a_vp->v_data; 644 error = uiomove(de->de_symlink, strlen(de->de_symlink), ap->a_uio); 645 return (error); 646 } 647 648 static int 649 devfs_reclaim(ap) 650 struct vop_reclaim_args /* { 651 struct vnode *a_vp; 652 } */ *ap; 653 { 654 struct vnode *vp = ap->a_vp; 655 struct devfs_dirent *de; 656 int i; 657 658 de = vp->v_data; 659 if (de != NULL) 660 de->de_vnode = NULL; 661 vp->v_data = NULL; 662 if (vp->v_rdev != NULL && vp->v_rdev != NULL) { 663 i = vcount(vp); 664 if ((vp->v_rdev->si_flags & SI_CHEAPCLONE) && i == 0 && 665 (vp->v_rdev->si_flags & SI_NAMED)) 666 destroy_dev(vp->v_rdev); 667 } 668 return (0); 669 } 670 671 static int 672 devfs_remove(ap) 673 struct vop_remove_args /* { 674 struct vnode *a_dvp; 675 struct vnode *a_vp; 676 struct componentname *a_cnp; 677 } */ *ap; 678 { 679 struct vnode *vp = ap->a_vp; 680 struct devfs_dirent *dd; 681 struct devfs_dirent *de; 682 struct devfs_mount *dmp = VFSTODEVFS(vp->v_mount); 683 684 lockmgr(&dmp->dm_lock, LK_EXCLUSIVE, 0, curthread); 685 dd = ap->a_dvp->v_data; 686 de = vp->v_data; 687 if (de->de_dirent->d_type == DT_LNK) { 688 TAILQ_REMOVE(&dd->de_dlist, de, de_list); 689 if (de->de_vnode) 690 de->de_vnode->v_data = NULL; 691 #ifdef MAC 692 mac_destroy_devfsdirent(de); 693 #endif 694 FREE(de, M_DEVFS); 695 } else { 696 de->de_flags |= DE_WHITEOUT; 697 } 698 lockmgr(&dmp->dm_lock, LK_RELEASE, 0, curthread); 699 return (0); 700 } 701 702 /* 703 * Revoke is called on a tty when a terminal session ends. The vnode 704 * is orphaned by setting v_op to deadfs so we need to let go of it 705 * as well so that we create a new one next time around. 706 */ 707 static int 708 devfs_revoke(ap) 709 struct vop_revoke_args /* { 710 struct vnode *a_vp; 711 int a_flags; 712 } */ *ap; 713 { 714 struct vnode *vp = ap->a_vp; 715 struct devfs_dirent *de; 716 717 de = vp->v_data; 718 de->de_vnode = NULL; 719 vop_revoke(ap); 720 return (0); 721 } 722 723 static int 724 devfs_setattr(ap) 725 struct vop_setattr_args /* { 726 struct vnode *a_vp; 727 struct vattr *a_vap; 728 struct ucred *a_cred; 729 struct proc *a_p; 730 } */ *ap; 731 { 732 struct devfs_dirent *de; 733 struct vattr *vap; 734 struct vnode *vp; 735 int c, error; 736 uid_t uid; 737 gid_t gid; 738 739 vap = ap->a_vap; 740 vp = ap->a_vp; 741 if ((vap->va_type != VNON) || 742 (vap->va_nlink != VNOVAL) || 743 (vap->va_fsid != VNOVAL) || 744 (vap->va_fileid != VNOVAL) || 745 (vap->va_blocksize != VNOVAL) || 746 (vap->va_flags != VNOVAL && vap->va_flags != 0) || 747 (vap->va_rdev != VNOVAL) || 748 ((int)vap->va_bytes != VNOVAL) || 749 (vap->va_gen != VNOVAL)) { 750 return (EINVAL); 751 } 752 753 de = vp->v_data; 754 if (vp->v_type == VDIR) 755 de = de->de_dir; 756 757 error = c = 0; 758 if (vap->va_uid == (uid_t)VNOVAL) 759 uid = de->de_uid; 760 else 761 uid = vap->va_uid; 762 if (vap->va_gid == (gid_t)VNOVAL) 763 gid = de->de_gid; 764 else 765 gid = vap->va_gid; 766 if (uid != de->de_uid || gid != de->de_gid) { 767 if (((ap->a_cred->cr_uid != de->de_uid) || uid != de->de_uid || 768 (gid != de->de_gid && !groupmember(gid, ap->a_cred))) && 769 (error = suser_cred(ap->a_td->td_ucred, SUSER_ALLOWJAIL)) != 0) 770 return (error); 771 de->de_uid = uid; 772 de->de_gid = gid; 773 c = 1; 774 } 775 776 if (vap->va_mode != (mode_t)VNOVAL) { 777 if ((ap->a_cred->cr_uid != de->de_uid) && 778 (error = suser_cred(ap->a_td->td_ucred, SUSER_ALLOWJAIL))) 779 return (error); 780 de->de_mode = vap->va_mode; 781 c = 1; 782 } 783 784 if (vap->va_atime.tv_sec != VNOVAL || vap->va_mtime.tv_sec != VNOVAL) { 785 /* See the comment in ufs_vnops::ufs_setattr(). */ 786 if ((error = VOP_ACCESS(vp, VADMIN, ap->a_cred, ap->a_td)) && 787 ((vap->va_vaflags & VA_UTIMES_NULL) == 0 || 788 (error = VOP_ACCESS(vp, VWRITE, ap->a_cred, ap->a_td)))) 789 return (error); 790 if (vap->va_atime.tv_sec != VNOVAL) { 791 if (vp->v_type == VCHR) 792 vp->v_rdev->si_atime = vap->va_atime; 793 else 794 de->de_atime = vap->va_atime; 795 } 796 if (vap->va_mtime.tv_sec != VNOVAL) { 797 if (vp->v_type == VCHR) 798 vp->v_rdev->si_mtime = vap->va_mtime; 799 else 800 de->de_mtime = vap->va_mtime; 801 } 802 c = 1; 803 } 804 805 if (c) { 806 if (vp->v_type == VCHR) 807 vfs_timestamp(&vp->v_rdev->si_ctime); 808 else 809 vfs_timestamp(&de->de_mtime); 810 } 811 return (0); 812 } 813 814 #ifdef MAC 815 static int 816 devfs_setlabel(ap) 817 struct vop_setlabel_args /* { 818 struct vnode *a_vp; 819 struct mac *a_label; 820 struct ucred *a_cred; 821 struct thread *a_td; 822 } */ *ap; 823 { 824 struct vnode *vp; 825 struct devfs_dirent *de; 826 827 vp = ap->a_vp; 828 de = vp->v_data; 829 830 mac_relabel_vnode(ap->a_cred, vp, ap->a_label); 831 mac_update_devfsdirent(vp->v_mount, de, vp); 832 833 return (0); 834 } 835 #endif 836 837 static int 838 devfs_symlink(ap) 839 struct vop_symlink_args /* { 840 struct vnode *a_dvp; 841 struct vnode **a_vpp; 842 struct componentname *a_cnp; 843 struct vattr *a_vap; 844 char *a_target; 845 } */ *ap; 846 { 847 int i, error; 848 struct devfs_dirent *dd; 849 struct devfs_dirent *de; 850 struct devfs_mount *dmp; 851 struct thread *td; 852 853 td = ap->a_cnp->cn_thread; 854 KASSERT(td == curthread, ("devfs_symlink: td != curthread")); 855 error = suser(td); 856 if (error) 857 return(error); 858 dmp = VFSTODEVFS(ap->a_dvp->v_mount); 859 dd = ap->a_dvp->v_data; 860 de = devfs_newdirent(ap->a_cnp->cn_nameptr, ap->a_cnp->cn_namelen); 861 de->de_uid = 0; 862 de->de_gid = 0; 863 de->de_mode = 0755; 864 de->de_inode = dmp->dm_inode++; 865 de->de_dirent->d_type = DT_LNK; 866 i = strlen(ap->a_target) + 1; 867 MALLOC(de->de_symlink, char *, i, M_DEVFS, M_WAITOK); 868 bcopy(ap->a_target, de->de_symlink, i); 869 lockmgr(&dmp->dm_lock, LK_EXCLUSIVE, 0, td); 870 #ifdef MAC 871 mac_create_devfs_symlink(ap->a_cnp->cn_cred, dmp->dm_mount, dd, de); 872 #endif 873 TAILQ_INSERT_TAIL(&dd->de_dlist, de, de_list); 874 devfs_allocv(de, ap->a_dvp->v_mount, ap->a_vpp, td); 875 lockmgr(&dmp->dm_lock, LK_RELEASE, 0, td); 876 return (0); 877 } 878 879 static struct vnodeopv_entry_desc devfs_vnodeop_entries[] = { 880 { &vop_default_desc, (vop_t *) vop_defaultop }, 881 { &vop_access_desc, (vop_t *) devfs_access }, 882 { &vop_getattr_desc, (vop_t *) devfs_getattr }, 883 { &vop_ioctl_desc, (vop_t *) devfs_ioctl }, 884 { &vop_lookup_desc, (vop_t *) devfs_lookup }, 885 { &vop_mknod_desc, (vop_t *) devfs_mknod }, 886 { &vop_pathconf_desc, (vop_t *) devfs_pathconf }, 887 { &vop_read_desc, (vop_t *) devfs_read }, 888 { &vop_readdir_desc, (vop_t *) devfs_readdir }, 889 { &vop_readlink_desc, (vop_t *) devfs_readlink }, 890 { &vop_reclaim_desc, (vop_t *) devfs_reclaim }, 891 { &vop_remove_desc, (vop_t *) devfs_remove }, 892 { &vop_revoke_desc, (vop_t *) devfs_revoke }, 893 { &vop_setattr_desc, (vop_t *) devfs_setattr }, 894 #ifdef MAC 895 { &vop_setlabel_desc, (vop_t *) devfs_setlabel }, 896 #endif 897 { &vop_symlink_desc, (vop_t *) devfs_symlink }, 898 { NULL, NULL } 899 }; 900 static struct vnodeopv_desc devfs_vnodeop_opv_desc = 901 { &devfs_vnodeop_p, devfs_vnodeop_entries }; 902 903 VNODEOP_SET(devfs_vnodeop_opv_desc); 904 905 static struct vnodeopv_entry_desc devfs_specop_entries[] = { 906 { &vop_default_desc, (vop_t *) spec_vnoperate }, 907 { &vop_access_desc, (vop_t *) devfs_access }, 908 { &vop_getattr_desc, (vop_t *) devfs_getattr }, 909 { &vop_pathconf_desc, (vop_t *) devfs_pathconf }, 910 { &vop_reclaim_desc, (vop_t *) devfs_reclaim }, 911 { &vop_remove_desc, (vop_t *) devfs_remove }, 912 { &vop_revoke_desc, (vop_t *) devfs_revoke }, 913 { &vop_setattr_desc, (vop_t *) devfs_setattr }, 914 #ifdef MAC 915 { &vop_setlabel_desc, (vop_t *) devfs_setlabel }, 916 #endif 917 { NULL, NULL } 918 }; 919 static struct vnodeopv_desc devfs_specop_opv_desc = 920 { &devfs_specop_p, devfs_specop_entries }; 921 922 VNODEOP_SET(devfs_specop_opv_desc); 923