1 /* 2 * Copyright (c) 1989, 1993 3 * The Regents of the University of California. All rights reserved. 4 * (c) UNIX System Laboratories, Inc. 5 * All or some portions of this file are derived from material licensed 6 * to the University of California by American Telephone and Telegraph 7 * Co. or Unix System Laboratories, Inc. and are reproduced herein with 8 * the permission of UNIX System Laboratories, Inc. 9 * 10 * %sccs.include.redist.c% 11 * 12 * @(#)vfs_syscalls.c 8.38 (Berkeley) 05/18/95 13 */ 14 15 #include <sys/param.h> 16 #include <sys/systm.h> 17 #include <sys/namei.h> 18 #include <sys/filedesc.h> 19 #include <sys/kernel.h> 20 #include <sys/file.h> 21 #include <sys/stat.h> 22 #include <sys/vnode.h> 23 #include <sys/mount.h> 24 #include <sys/proc.h> 25 #include <sys/uio.h> 26 #include <sys/malloc.h> 27 #include <sys/dirent.h> 28 29 #include <sys/syscallargs.h> 30 31 #include <vm/vm.h> 32 #include <sys/sysctl.h> 33 34 static int change_dir __P((struct nameidata *ndp, struct proc *p)); 35 static void checkdirs __P((struct vnode *olddp)); 36 37 /* 38 * Virtual File System System Calls 39 */ 40 41 /* 42 * Mount a file system. 43 */ 44 /* ARGSUSED */ 45 int 46 mount(p, uap, retval) 47 struct proc *p; 48 register struct mount_args /* { 49 syscallarg(char *) type; 50 syscallarg(char *) path; 51 syscallarg(int) flags; 52 syscallarg(caddr_t) data; 53 } */ *uap; 54 register_t *retval; 55 { 56 struct vnode *vp; 57 struct mount *mp; 58 struct vfsconf *vfsp; 59 int error, flag; 60 struct vattr va; 61 u_long fstypenum; 62 struct nameidata nd; 63 char fstypename[MFSNAMELEN]; 64 65 /* 66 * Get vnode to be covered 67 */ 68 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, 69 SCARG(uap, path), p); 70 if (error = namei(&nd)) 71 return (error); 72 vp = nd.ni_vp; 73 if (SCARG(uap, flags) & MNT_UPDATE) { 74 if ((vp->v_flag & VROOT) == 0) { 75 vput(vp); 76 return (EINVAL); 77 } 78 mp = vp->v_mount; 79 flag = mp->mnt_flag; 80 /* 81 * We only allow the filesystem to be reloaded if it 82 * is currently mounted read-only. 83 */ 84 if ((SCARG(uap, flags) & MNT_RELOAD) && 85 ((mp->mnt_flag & MNT_RDONLY) == 0)) { 86 vput(vp); 87 return (EOPNOTSUPP); /* Needs translation */ 88 } 89 mp->mnt_flag |= 90 SCARG(uap, flags) & (MNT_RELOAD | MNT_FORCE | MNT_UPDATE); 91 /* 92 * Only root, or the user that did the original mount is 93 * permitted to update it. 94 */ 95 if (mp->mnt_stat.f_owner != p->p_ucred->cr_uid && 96 (error = suser(p->p_ucred, &p->p_acflag))) { 97 vput(vp); 98 return (error); 99 } 100 /* 101 * Do not allow NFS export by non-root users. Silently 102 * enforce MNT_NOSUID and MNT_NODEV for non-root users. 103 */ 104 if (p->p_ucred->cr_uid != 0) { 105 if (SCARG(uap, flags) & MNT_EXPORTED) { 106 vput(vp); 107 return (EPERM); 108 } 109 SCARG(uap, flags) |= MNT_NOSUID | MNT_NODEV; 110 } 111 VOP_UNLOCK(vp, 0, p); 112 goto update; 113 } 114 /* 115 * If the user is not root, ensure that they own the directory 116 * onto which we are attempting to mount. 117 */ 118 if ((error = VOP_GETATTR(vp, &va, p->p_ucred, p)) || 119 (va.va_uid != p->p_ucred->cr_uid && 120 (error = suser(p->p_ucred, &p->p_acflag)))) { 121 vput(vp); 122 return (error); 123 } 124 /* 125 * Do not allow NFS export by non-root users. Silently 126 * enforce MNT_NOSUID and MNT_NODEV for non-root users. 127 */ 128 if (p->p_ucred->cr_uid != 0) { 129 if (SCARG(uap, flags) & MNT_EXPORTED) { 130 vput(vp); 131 return (EPERM); 132 } 133 SCARG(uap, flags) |= MNT_NOSUID | MNT_NODEV; 134 } 135 if (error = vinvalbuf(vp, V_SAVE, p->p_ucred, p, 0, 0)) 136 return (error); 137 if (vp->v_type != VDIR) { 138 vput(vp); 139 return (ENOTDIR); 140 } 141 #ifdef COMPAT_43 142 /* 143 * Historically filesystem types were identified by number. If we 144 * get an integer for the filesystem type instead of a string, we 145 * check to see if it matches one of the historic filesystem types. 146 */ 147 fstypenum = (u_long)SCARG(uap, type); 148 if (fstypenum < maxvfsconf) { 149 for (vfsp = vfsconf; vfsp; vfsp = vfsp->vfc_next) 150 if (vfsp->vfc_typenum == fstypenum) 151 break; 152 if (vfsp == NULL) { 153 vput(vp); 154 return (ENODEV); 155 } 156 strncpy(fstypename, vfsp->vfc_name, MFSNAMELEN); 157 } else 158 #endif /* COMPAT_43 */ 159 if (error = copyinstr(SCARG(uap, type), fstypename, MFSNAMELEN, NULL)) { 160 vput(vp); 161 return (error); 162 } 163 for (vfsp = vfsconf; vfsp; vfsp = vfsp->vfc_next) 164 if (!strcmp(vfsp->vfc_name, fstypename)) 165 break; 166 if (vfsp == NULL) { 167 vput(vp); 168 return (ENODEV); 169 } 170 if (vp->v_mountedhere != NULL) { 171 vput(vp); 172 return (EBUSY); 173 } 174 175 /* 176 * Allocate and initialize the filesystem. 177 */ 178 mp = (struct mount *)malloc((u_long)sizeof(struct mount), 179 M_MOUNT, M_WAITOK); 180 bzero((char *)mp, (u_long)sizeof(struct mount)); 181 mp->mnt_op = vfsp->vfc_vfsops; 182 if (error = vfs_lock(mp)) { 183 free((caddr_t)mp, M_MOUNT); 184 vput(vp); 185 return (error); 186 } 187 mp->mnt_vfc = vfsp; 188 vfsp->vfc_refcount++; 189 mp->mnt_stat.f_type = vfsp->vfc_typenum; 190 mp->mnt_flag |= vfsp->vfc_flags & MNT_VISFLAGMASK; 191 strncpy(mp->mnt_stat.f_fstypename, vfsp->vfc_name, MFSNAMELEN); 192 vp->v_mountedhere = mp; 193 mp->mnt_vnodecovered = vp; 194 mp->mnt_stat.f_owner = p->p_ucred->cr_uid; 195 update: 196 /* 197 * Set the mount level flags. 198 */ 199 if (SCARG(uap, flags) & MNT_RDONLY) 200 mp->mnt_flag |= MNT_RDONLY; 201 else if (mp->mnt_flag & MNT_RDONLY) 202 mp->mnt_flag |= MNT_WANTRDWR; 203 mp->mnt_flag &=~ (MNT_NOSUID | MNT_NOEXEC | MNT_NODEV | 204 MNT_SYNCHRONOUS | MNT_UNION | MNT_ASYNC); 205 mp->mnt_flag |= SCARG(uap, flags) & (MNT_NOSUID | MNT_NOEXEC | 206 MNT_NODEV | MNT_SYNCHRONOUS | MNT_UNION | MNT_ASYNC); 207 /* 208 * Mount the filesystem. 209 */ 210 error = VFS_MOUNT(mp, SCARG(uap, path), SCARG(uap, data), &nd, p); 211 if (mp->mnt_flag & MNT_UPDATE) { 212 vrele(vp); 213 if (mp->mnt_flag & MNT_WANTRDWR) 214 mp->mnt_flag &= ~MNT_RDONLY; 215 mp->mnt_flag &=~ 216 (MNT_UPDATE | MNT_RELOAD | MNT_FORCE | MNT_WANTRDWR); 217 if (error) 218 mp->mnt_flag = flag; 219 return (error); 220 } 221 /* 222 * Put the new filesystem on the mount list after root. 223 */ 224 cache_purge(vp); 225 if (!error) { 226 CIRCLEQ_INSERT_TAIL(&mountlist, mp, mnt_list); 227 checkdirs(vp); 228 VOP_UNLOCK(vp, 0, p); 229 vfs_unlock(mp); 230 error = VFS_START(mp, 0, p); 231 } else { 232 mp->mnt_vnodecovered->v_mountedhere = (struct mount *)0; 233 mp->mnt_vfc->vfc_refcount--; 234 vfs_unlock(mp); 235 free((caddr_t)mp, M_MOUNT); 236 vput(vp); 237 } 238 return (error); 239 } 240 241 /* 242 * Scan all active processes to see if any of them have a current 243 * or root directory onto which the new filesystem has just been 244 * mounted. If so, replace them with the new mount point. 245 */ 246 static void 247 checkdirs(olddp) 248 struct vnode *olddp; 249 { 250 struct filedesc *fdp; 251 struct vnode *newdp; 252 struct proc *p; 253 254 if (olddp->v_usecount == 1) 255 return; 256 if (VFS_ROOT(olddp->v_mountedhere, &newdp)) 257 panic("mount: lost mount"); 258 for (p = allproc.lh_first; p != 0; p = p->p_list.le_next) { 259 fdp = p->p_fd; 260 if (fdp->fd_cdir == olddp) { 261 vrele(fdp->fd_cdir); 262 VREF(newdp); 263 fdp->fd_cdir = newdp; 264 } 265 if (fdp->fd_rdir == olddp) { 266 vrele(fdp->fd_rdir); 267 VREF(newdp); 268 fdp->fd_rdir = newdp; 269 } 270 } 271 if (rootvnode == olddp) { 272 vrele(rootvnode); 273 VREF(newdp); 274 rootvnode = newdp; 275 } 276 vput(newdp); 277 } 278 279 /* 280 * Unmount a file system. 281 * 282 * Note: unmount takes a path to the vnode mounted on as argument, 283 * not special file (as before). 284 */ 285 /* ARGSUSED */ 286 int 287 unmount(p, uap, retval) 288 struct proc *p; 289 register struct unmount_args /* { 290 syscallarg(char *) path; 291 syscallarg(int) flags; 292 } */ *uap; 293 register_t *retval; 294 { 295 register struct vnode *vp; 296 struct mount *mp; 297 int error; 298 struct nameidata nd; 299 300 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, 301 SCARG(uap, path), p); 302 if (error = namei(&nd)) 303 return (error); 304 vp = nd.ni_vp; 305 mp = vp->v_mount; 306 307 /* 308 * Only root, or the user that did the original mount is 309 * permitted to unmount this filesystem. 310 */ 311 if ((mp->mnt_stat.f_owner != p->p_ucred->cr_uid) && 312 (error = suser(p->p_ucred, &p->p_acflag))) { 313 vput(vp); 314 return (error); 315 } 316 317 /* 318 * Don't allow unmounting the root file system. 319 */ 320 if (mp->mnt_flag & MNT_ROOTFS) { 321 vput(vp); 322 return (EINVAL); 323 } 324 325 /* 326 * Must be the root of the filesystem 327 */ 328 if ((vp->v_flag & VROOT) == 0) { 329 vput(vp); 330 return (EINVAL); 331 } 332 vput(vp); 333 return (dounmount(mp, SCARG(uap, flags), p)); 334 } 335 336 /* 337 * Do the actual file system unmount. 338 */ 339 int 340 dounmount(mp, flags, p) 341 register struct mount *mp; 342 int flags; 343 struct proc *p; 344 { 345 struct vnode *coveredvp; 346 int error; 347 348 coveredvp = mp->mnt_vnodecovered; 349 if (vfs_busy(mp)) 350 return (EBUSY); 351 mp->mnt_flag |= MNT_UNMOUNT; 352 if (error = vfs_lock(mp)) 353 return (error); 354 355 mp->mnt_flag &=~ MNT_ASYNC; 356 vnode_pager_umount(mp); /* release cached vnodes */ 357 cache_purgevfs(mp); /* remove cache entries for this file sys */ 358 if (((mp->mnt_flag & MNT_RDONLY) || 359 (error = VFS_SYNC(mp, MNT_WAIT, p->p_ucred, p)) == 0) || 360 (flags & MNT_FORCE)) 361 error = VFS_UNMOUNT(mp, flags, p); 362 mp->mnt_flag &= ~MNT_UNMOUNT; 363 vfs_unbusy(mp); 364 if (error) { 365 vfs_unlock(mp); 366 } else { 367 CIRCLEQ_REMOVE(&mountlist, mp, mnt_list); 368 if (coveredvp != NULLVP) { 369 vrele(coveredvp); 370 mp->mnt_vnodecovered->v_mountedhere = (struct mount *)0; 371 } 372 mp->mnt_vfc->vfc_refcount--; 373 vfs_unlock(mp); 374 if (mp->mnt_vnodelist.lh_first != NULL) 375 panic("unmount: dangling vnode"); 376 free((caddr_t)mp, M_MOUNT); 377 } 378 return (error); 379 } 380 381 /* 382 * Sync each mounted filesystem. 383 */ 384 #ifdef DEBUG 385 int syncprt = 0; 386 struct ctldebug debug0 = { "syncprt", &syncprt }; 387 #endif 388 389 /* ARGSUSED */ 390 int 391 sync(p, uap, retval) 392 struct proc *p; 393 void *uap; 394 register_t *retval; 395 { 396 register struct mount *mp, *nmp; 397 int asyncflag; 398 399 for (mp = mountlist.cqh_first; mp != (void *)&mountlist; mp = nmp) { 400 /* 401 * Get the next pointer in case we hang on vfs_busy 402 * while we are being unmounted. 403 */ 404 nmp = mp->mnt_list.cqe_next; 405 /* 406 * The lock check below is to avoid races with mount 407 * and unmount. 408 */ 409 if ((mp->mnt_flag & (MNT_MLOCK|MNT_RDONLY|MNT_MPBUSY)) == 0 && 410 !vfs_busy(mp)) { 411 asyncflag = mp->mnt_flag & MNT_ASYNC; 412 mp->mnt_flag &= ~MNT_ASYNC; 413 VFS_SYNC(mp, MNT_NOWAIT, p->p_ucred, p); 414 if (asyncflag) 415 mp->mnt_flag |= MNT_ASYNC; 416 /* 417 * Get the next pointer again, as the next filesystem 418 * might have been unmounted while we were sync'ing. 419 */ 420 nmp = mp->mnt_list.cqe_next; 421 vfs_unbusy(mp); 422 } 423 } 424 #ifdef DIAGNOSTIC 425 if (syncprt) 426 vfs_bufstats(); 427 #endif /* DIAGNOSTIC */ 428 return (0); 429 } 430 431 /* 432 * Change filesystem quotas. 433 */ 434 /* ARGSUSED */ 435 int 436 quotactl(p, uap, retval) 437 struct proc *p; 438 register struct quotactl_args /* { 439 syscallarg(char *) path; 440 syscallarg(int) cmd; 441 syscallarg(int) uid; 442 syscallarg(caddr_t) arg; 443 } */ *uap; 444 register_t *retval; 445 { 446 register struct mount *mp; 447 int error; 448 struct nameidata nd; 449 450 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p); 451 if (error = namei(&nd)) 452 return (error); 453 mp = nd.ni_vp->v_mount; 454 vrele(nd.ni_vp); 455 return (VFS_QUOTACTL(mp, SCARG(uap, cmd), SCARG(uap, uid), 456 SCARG(uap, arg), p)); 457 } 458 459 /* 460 * Get filesystem statistics. 461 */ 462 /* ARGSUSED */ 463 int 464 statfs(p, uap, retval) 465 struct proc *p; 466 register struct statfs_args /* { 467 syscallarg(char *) path; 468 syscallarg(struct statfs *) buf; 469 } */ *uap; 470 register_t *retval; 471 { 472 register struct mount *mp; 473 register struct statfs *sp; 474 int error; 475 struct nameidata nd; 476 477 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p); 478 if (error = namei(&nd)) 479 return (error); 480 mp = nd.ni_vp->v_mount; 481 sp = &mp->mnt_stat; 482 vrele(nd.ni_vp); 483 if (error = VFS_STATFS(mp, sp, p)) 484 return (error); 485 sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK; 486 return (copyout((caddr_t)sp, (caddr_t)SCARG(uap, buf), sizeof(*sp))); 487 } 488 489 /* 490 * Get filesystem statistics. 491 */ 492 /* ARGSUSED */ 493 int 494 fstatfs(p, uap, retval) 495 struct proc *p; 496 register struct fstatfs_args /* { 497 syscallarg(int) fd; 498 syscallarg(struct statfs *) buf; 499 } */ *uap; 500 register_t *retval; 501 { 502 struct file *fp; 503 struct mount *mp; 504 register struct statfs *sp; 505 int error; 506 507 if (error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) 508 return (error); 509 mp = ((struct vnode *)fp->f_data)->v_mount; 510 sp = &mp->mnt_stat; 511 if (error = VFS_STATFS(mp, sp, p)) 512 return (error); 513 sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK; 514 return (copyout((caddr_t)sp, (caddr_t)SCARG(uap, buf), sizeof(*sp))); 515 } 516 517 /* 518 * Get statistics on all filesystems. 519 */ 520 int 521 getfsstat(p, uap, retval) 522 struct proc *p; 523 register struct getfsstat_args /* { 524 syscallarg(struct statfs *) buf; 525 syscallarg(long) bufsize; 526 syscallarg(int) flags; 527 } */ *uap; 528 register_t *retval; 529 { 530 register struct mount *mp, *nmp; 531 register struct statfs *sp; 532 caddr_t sfsp; 533 long count, maxcount, error; 534 535 maxcount = SCARG(uap, bufsize) / sizeof(struct statfs); 536 sfsp = (caddr_t)SCARG(uap, buf); 537 count = 0; 538 for (mp = mountlist.cqh_first; mp != (void *)&mountlist; mp = nmp) { 539 nmp = mp->mnt_list.cqe_next; 540 if (sfsp && count < maxcount && 541 ((mp->mnt_flag & MNT_MLOCK) == 0)) { 542 sp = &mp->mnt_stat; 543 /* 544 * If MNT_NOWAIT is specified, do not refresh the 545 * fsstat cache. MNT_WAIT overrides MNT_NOWAIT. 546 */ 547 if (((SCARG(uap, flags) & MNT_NOWAIT) == 0 || 548 (SCARG(uap, flags) & MNT_WAIT)) && 549 (error = VFS_STATFS(mp, sp, p))) 550 continue; 551 sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK; 552 if (error = copyout((caddr_t)sp, sfsp, sizeof(*sp))) 553 return (error); 554 sfsp += sizeof(*sp); 555 } 556 count++; 557 } 558 if (sfsp && count > maxcount) 559 *retval = maxcount; 560 else 561 *retval = count; 562 return (0); 563 } 564 565 /* 566 * Change current working directory to a given file descriptor. 567 */ 568 /* ARGSUSED */ 569 int 570 fchdir(p, uap, retval) 571 struct proc *p; 572 struct fchdir_args /* { 573 syscallarg(int) fd; 574 } */ *uap; 575 register_t *retval; 576 { 577 register struct filedesc *fdp = p->p_fd; 578 struct vnode *vp, *tdp; 579 struct mount *mp; 580 struct file *fp; 581 int error; 582 583 if (error = getvnode(fdp, SCARG(uap, fd), &fp)) 584 return (error); 585 vp = (struct vnode *)fp->f_data; 586 VREF(vp); 587 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); 588 if (vp->v_type != VDIR) 589 error = ENOTDIR; 590 else 591 error = VOP_ACCESS(vp, VEXEC, p->p_ucred, p); 592 while (!error && (mp = vp->v_mountedhere) != NULL) { 593 if (mp->mnt_flag & MNT_MLOCK) { 594 mp->mnt_flag |= MNT_MWAIT; 595 sleep((caddr_t)mp, PVFS); 596 continue; 597 } 598 if (error = VFS_ROOT(mp, &tdp)) 599 break; 600 vput(vp); 601 vp = tdp; 602 } 603 if (error) { 604 vput(vp); 605 return (error); 606 } 607 VOP_UNLOCK(vp, 0, p); 608 vrele(fdp->fd_cdir); 609 fdp->fd_cdir = vp; 610 return (0); 611 } 612 613 /* 614 * Change current working directory (``.''). 615 */ 616 /* ARGSUSED */ 617 int 618 chdir(p, uap, retval) 619 struct proc *p; 620 struct chdir_args /* { 621 syscallarg(char *) path; 622 } */ *uap; 623 register_t *retval; 624 { 625 register struct filedesc *fdp = p->p_fd; 626 int error; 627 struct nameidata nd; 628 629 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, 630 SCARG(uap, path), p); 631 if (error = change_dir(&nd, p)) 632 return (error); 633 vrele(fdp->fd_cdir); 634 fdp->fd_cdir = nd.ni_vp; 635 return (0); 636 } 637 638 /* 639 * Change notion of root (``/'') directory. 640 */ 641 /* ARGSUSED */ 642 int 643 chroot(p, uap, retval) 644 struct proc *p; 645 struct chroot_args /* { 646 syscallarg(char *) path; 647 } */ *uap; 648 register_t *retval; 649 { 650 register struct filedesc *fdp = p->p_fd; 651 int error; 652 struct nameidata nd; 653 654 if (error = suser(p->p_ucred, &p->p_acflag)) 655 return (error); 656 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, 657 SCARG(uap, path), p); 658 if (error = change_dir(&nd, p)) 659 return (error); 660 if (fdp->fd_rdir != NULL) 661 vrele(fdp->fd_rdir); 662 fdp->fd_rdir = nd.ni_vp; 663 return (0); 664 } 665 666 /* 667 * Common routine for chroot and chdir. 668 */ 669 static int 670 change_dir(ndp, p) 671 register struct nameidata *ndp; 672 struct proc *p; 673 { 674 struct vnode *vp; 675 int error; 676 677 if (error = namei(ndp)) 678 return (error); 679 vp = ndp->ni_vp; 680 if (vp->v_type != VDIR) 681 error = ENOTDIR; 682 else 683 error = VOP_ACCESS(vp, VEXEC, p->p_ucred, p); 684 if (error) 685 vput(vp); 686 else 687 VOP_UNLOCK(vp, 0, p); 688 return (error); 689 } 690 691 /* 692 * Check permissions, allocate an open file structure, 693 * and call the device open routine if any. 694 */ 695 int 696 open(p, uap, retval) 697 struct proc *p; 698 register struct open_args /* { 699 syscallarg(char *) path; 700 syscallarg(int) flags; 701 syscallarg(int) mode; 702 } */ *uap; 703 register_t *retval; 704 { 705 register struct filedesc *fdp = p->p_fd; 706 register struct file *fp; 707 register struct vnode *vp; 708 int flags, cmode; 709 struct file *nfp; 710 int type, indx, error; 711 struct flock lf; 712 struct nameidata nd; 713 extern struct fileops vnops; 714 715 if (error = falloc(p, &nfp, &indx)) 716 return (error); 717 fp = nfp; 718 flags = FFLAGS(SCARG(uap, flags)); 719 cmode = ((SCARG(uap, mode) &~ fdp->fd_cmask) & ALLPERMS) &~ S_ISTXT; 720 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p); 721 p->p_dupfd = -indx - 1; /* XXX check for fdopen */ 722 if (error = vn_open(&nd, flags, cmode)) { 723 ffree(fp); 724 if ((error == ENODEV || error == ENXIO) && 725 p->p_dupfd >= 0 && /* XXX from fdopen */ 726 (error = 727 dupfdopen(fdp, indx, p->p_dupfd, flags, error)) == 0) { 728 *retval = indx; 729 return (0); 730 } 731 if (error == ERESTART) 732 error = EINTR; 733 fdp->fd_ofiles[indx] = NULL; 734 return (error); 735 } 736 p->p_dupfd = 0; 737 vp = nd.ni_vp; 738 fp->f_flag = flags & FMASK; 739 fp->f_type = DTYPE_VNODE; 740 fp->f_ops = &vnops; 741 fp->f_data = (caddr_t)vp; 742 if (flags & (O_EXLOCK | O_SHLOCK)) { 743 lf.l_whence = SEEK_SET; 744 lf.l_start = 0; 745 lf.l_len = 0; 746 if (flags & O_EXLOCK) 747 lf.l_type = F_WRLCK; 748 else 749 lf.l_type = F_RDLCK; 750 type = F_FLOCK; 751 if ((flags & FNONBLOCK) == 0) 752 type |= F_WAIT; 753 VOP_UNLOCK(vp, 0, p); 754 if (error = VOP_ADVLOCK(vp, (caddr_t)fp, F_SETLK, &lf, type)) { 755 (void) vn_close(vp, fp->f_flag, fp->f_cred, p); 756 ffree(fp); 757 fdp->fd_ofiles[indx] = NULL; 758 return (error); 759 } 760 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); 761 fp->f_flag |= FHASLOCK; 762 } 763 VOP_UNLOCK(vp, 0, p); 764 *retval = indx; 765 return (0); 766 } 767 768 #ifdef COMPAT_43 769 /* 770 * Create a file. 771 */ 772 int 773 compat_43_creat(p, uap, retval) 774 struct proc *p; 775 register struct compat_43_creat_args /* { 776 syscallarg(char *) path; 777 syscallarg(int) mode; 778 } */ *uap; 779 register_t *retval; 780 { 781 struct open_args /* { 782 syscallarg(char *) path; 783 syscallarg(int) flags; 784 syscallarg(int) mode; 785 } */ nuap; 786 787 SCARG(&nuap, path) = SCARG(uap, path); 788 SCARG(&nuap, mode) = SCARG(uap, mode); 789 SCARG(&nuap, flags) = O_WRONLY | O_CREAT | O_TRUNC; 790 return (open(p, &nuap, retval)); 791 } 792 #endif /* COMPAT_43 */ 793 794 /* 795 * Create a special file. 796 */ 797 /* ARGSUSED */ 798 int 799 mknod(p, uap, retval) 800 struct proc *p; 801 register struct mknod_args /* { 802 syscallarg(char *) path; 803 syscallarg(int) mode; 804 syscallarg(int) dev; 805 } */ *uap; 806 register_t *retval; 807 { 808 register struct vnode *vp; 809 struct vattr vattr; 810 int error; 811 int whiteout; 812 struct nameidata nd; 813 814 if (error = suser(p->p_ucred, &p->p_acflag)) 815 return (error); 816 NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, SCARG(uap, path), p); 817 if (error = namei(&nd)) 818 return (error); 819 vp = nd.ni_vp; 820 if (vp != NULL) 821 error = EEXIST; 822 else { 823 VATTR_NULL(&vattr); 824 vattr.va_mode = (SCARG(uap, mode) & ALLPERMS) &~ p->p_fd->fd_cmask; 825 vattr.va_rdev = SCARG(uap, dev); 826 whiteout = 0; 827 828 switch (SCARG(uap, mode) & S_IFMT) { 829 case S_IFMT: /* used by badsect to flag bad sectors */ 830 vattr.va_type = VBAD; 831 break; 832 case S_IFCHR: 833 vattr.va_type = VCHR; 834 break; 835 case S_IFBLK: 836 vattr.va_type = VBLK; 837 break; 838 case S_IFWHT: 839 whiteout = 1; 840 break; 841 default: 842 error = EINVAL; 843 break; 844 } 845 } 846 if (!error) { 847 VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE); 848 if (whiteout) { 849 error = VOP_WHITEOUT(nd.ni_dvp, &nd.ni_cnd, CREATE); 850 if (error) 851 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); 852 vput(nd.ni_dvp); 853 } else { 854 error = VOP_MKNOD(nd.ni_dvp, &nd.ni_vp, 855 &nd.ni_cnd, &vattr); 856 } 857 } else { 858 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); 859 if (nd.ni_dvp == vp) 860 vrele(nd.ni_dvp); 861 else 862 vput(nd.ni_dvp); 863 if (vp) 864 vrele(vp); 865 } 866 return (error); 867 } 868 869 /* 870 * Create a named pipe. 871 */ 872 /* ARGSUSED */ 873 int 874 mkfifo(p, uap, retval) 875 struct proc *p; 876 register struct mkfifo_args /* { 877 syscallarg(char *) path; 878 syscallarg(int) mode; 879 } */ *uap; 880 register_t *retval; 881 { 882 struct vattr vattr; 883 int error; 884 struct nameidata nd; 885 886 #ifndef FIFO 887 return (EOPNOTSUPP); 888 #else 889 NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, SCARG(uap, path), p); 890 if (error = namei(&nd)) 891 return (error); 892 if (nd.ni_vp != NULL) { 893 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); 894 if (nd.ni_dvp == nd.ni_vp) 895 vrele(nd.ni_dvp); 896 else 897 vput(nd.ni_dvp); 898 vrele(nd.ni_vp); 899 return (EEXIST); 900 } 901 VATTR_NULL(&vattr); 902 vattr.va_type = VFIFO; 903 vattr.va_mode = (SCARG(uap, mode) & ALLPERMS) &~ p->p_fd->fd_cmask; 904 VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE); 905 return (VOP_MKNOD(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr)); 906 #endif /* FIFO */ 907 } 908 909 /* 910 * Make a hard file link. 911 */ 912 /* ARGSUSED */ 913 int 914 link(p, uap, retval) 915 struct proc *p; 916 register struct link_args /* { 917 syscallarg(char *) path; 918 syscallarg(char *) link; 919 } */ *uap; 920 register_t *retval; 921 { 922 register struct vnode *vp; 923 struct nameidata nd; 924 int error; 925 926 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p); 927 if (error = namei(&nd)) 928 return (error); 929 vp = nd.ni_vp; 930 if (vp->v_type != VDIR || 931 (error = suser(p->p_ucred, &p->p_acflag)) == 0) { 932 nd.ni_cnd.cn_nameiop = CREATE; 933 nd.ni_cnd.cn_flags = LOCKPARENT; 934 nd.ni_dirp = SCARG(uap, link); 935 if ((error = namei(&nd)) == 0) { 936 if (nd.ni_vp != NULL) 937 error = EEXIST; 938 if (!error) { 939 VOP_LEASE(nd.ni_dvp, p, p->p_ucred, 940 LEASE_WRITE); 941 VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE); 942 error = VOP_LINK(vp, nd.ni_dvp, &nd.ni_cnd); 943 } else { 944 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); 945 if (nd.ni_dvp == nd.ni_vp) 946 vrele(nd.ni_dvp); 947 else 948 vput(nd.ni_dvp); 949 if (nd.ni_vp) 950 vrele(nd.ni_vp); 951 } 952 } 953 } 954 vrele(vp); 955 return (error); 956 } 957 958 /* 959 * Make a symbolic link. 960 */ 961 /* ARGSUSED */ 962 int 963 symlink(p, uap, retval) 964 struct proc *p; 965 register struct symlink_args /* { 966 syscallarg(char *) path; 967 syscallarg(char *) link; 968 } */ *uap; 969 register_t *retval; 970 { 971 struct vattr vattr; 972 char *path; 973 int error; 974 struct nameidata nd; 975 976 MALLOC(path, char *, MAXPATHLEN, M_NAMEI, M_WAITOK); 977 if (error = copyinstr(SCARG(uap, path), path, MAXPATHLEN, NULL)) 978 goto out; 979 NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, SCARG(uap, link), p); 980 if (error = namei(&nd)) 981 goto out; 982 if (nd.ni_vp) { 983 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); 984 if (nd.ni_dvp == nd.ni_vp) 985 vrele(nd.ni_dvp); 986 else 987 vput(nd.ni_dvp); 988 vrele(nd.ni_vp); 989 error = EEXIST; 990 goto out; 991 } 992 VATTR_NULL(&vattr); 993 vattr.va_mode = ACCESSPERMS &~ p->p_fd->fd_cmask; 994 VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE); 995 error = VOP_SYMLINK(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr, path); 996 out: 997 FREE(path, M_NAMEI); 998 return (error); 999 } 1000 1001 /* 1002 * Delete a whiteout from the filesystem. 1003 */ 1004 /* ARGSUSED */ 1005 int 1006 undelete(p, uap, retval) 1007 struct proc *p; 1008 register struct undelete_args /* { 1009 syscallarg(char *) path; 1010 } */ *uap; 1011 register_t *retval; 1012 { 1013 int error; 1014 struct nameidata nd; 1015 1016 NDINIT(&nd, DELETE, LOCKPARENT|DOWHITEOUT, UIO_USERSPACE, 1017 SCARG(uap, path), p); 1018 error = namei(&nd); 1019 if (error) 1020 return (error); 1021 1022 if (nd.ni_vp != NULLVP || !(nd.ni_cnd.cn_flags & ISWHITEOUT)) { 1023 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); 1024 if (nd.ni_dvp == nd.ni_vp) 1025 vrele(nd.ni_dvp); 1026 else 1027 vput(nd.ni_dvp); 1028 if (nd.ni_vp) 1029 vrele(nd.ni_vp); 1030 return (EEXIST); 1031 } 1032 1033 VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE); 1034 if (error = VOP_WHITEOUT(nd.ni_dvp, &nd.ni_cnd, DELETE)) 1035 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); 1036 vput(nd.ni_dvp); 1037 return (error); 1038 } 1039 1040 /* 1041 * Delete a name from the filesystem. 1042 */ 1043 /* ARGSUSED */ 1044 int 1045 unlink(p, uap, retval) 1046 struct proc *p; 1047 struct unlink_args /* { 1048 syscallarg(char *) path; 1049 } */ *uap; 1050 register_t *retval; 1051 { 1052 register struct vnode *vp; 1053 int error; 1054 struct nameidata nd; 1055 1056 NDINIT(&nd, DELETE, LOCKPARENT, UIO_USERSPACE, SCARG(uap, path), p); 1057 if (error = namei(&nd)) 1058 return (error); 1059 vp = nd.ni_vp; 1060 VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE); 1061 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); 1062 1063 if (vp->v_type != VDIR || 1064 (error = suser(p->p_ucred, &p->p_acflag)) == 0) { 1065 /* 1066 * The root of a mounted filesystem cannot be deleted. 1067 */ 1068 if (vp->v_flag & VROOT) 1069 error = EBUSY; 1070 else 1071 (void)vnode_pager_uncache(vp); 1072 } 1073 1074 if (!error) { 1075 VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE); 1076 error = VOP_REMOVE(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd); 1077 } else { 1078 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); 1079 if (nd.ni_dvp == vp) 1080 vrele(nd.ni_dvp); 1081 else 1082 vput(nd.ni_dvp); 1083 if (vp != NULLVP) 1084 vput(vp); 1085 } 1086 return (error); 1087 } 1088 1089 /* 1090 * Reposition read/write file offset. 1091 */ 1092 int 1093 lseek(p, uap, retval) 1094 struct proc *p; 1095 register struct lseek_args /* { 1096 syscallarg(int) fd; 1097 syscallarg(int) pad; 1098 syscallarg(off_t) offset; 1099 syscallarg(int) whence; 1100 } */ *uap; 1101 register_t *retval; 1102 { 1103 struct ucred *cred = p->p_ucred; 1104 register struct filedesc *fdp = p->p_fd; 1105 register struct file *fp; 1106 struct vattr vattr; 1107 int error; 1108 1109 if ((u_int)SCARG(uap, fd) >= fdp->fd_nfiles || 1110 (fp = fdp->fd_ofiles[SCARG(uap, fd)]) == NULL) 1111 return (EBADF); 1112 if (fp->f_type != DTYPE_VNODE) 1113 return (ESPIPE); 1114 switch (SCARG(uap, whence)) { 1115 case L_INCR: 1116 fp->f_offset += SCARG(uap, offset); 1117 break; 1118 case L_XTND: 1119 if (error = 1120 VOP_GETATTR((struct vnode *)fp->f_data, &vattr, cred, p)) 1121 return (error); 1122 fp->f_offset = SCARG(uap, offset) + vattr.va_size; 1123 break; 1124 case L_SET: 1125 fp->f_offset = SCARG(uap, offset); 1126 break; 1127 default: 1128 return (EINVAL); 1129 } 1130 *(off_t *)retval = fp->f_offset; 1131 return (0); 1132 } 1133 1134 #if defined(COMPAT_43) || defined(COMPAT_SUNOS) 1135 /* 1136 * Reposition read/write file offset. 1137 */ 1138 int 1139 compat_43_lseek(p, uap, retval) 1140 struct proc *p; 1141 register struct compat_43_lseek_args /* { 1142 syscallarg(int) fd; 1143 syscallarg(long) offset; 1144 syscallarg(int) whence; 1145 } */ *uap; 1146 register_t *retval; 1147 { 1148 struct lseek_args /* { 1149 syscallarg(int) fd; 1150 syscallarg(int) pad; 1151 syscallarg(off_t) offset; 1152 syscallarg(int) whence; 1153 } */ nuap; 1154 off_t qret; 1155 int error; 1156 1157 SCARG(&nuap, fd) = SCARG(uap, fd); 1158 SCARG(&nuap, offset) = SCARG(uap, offset); 1159 SCARG(&nuap, whence) = SCARG(uap, whence); 1160 error = lseek(p, &nuap, &qret); 1161 *(long *)retval = qret; 1162 return (error); 1163 } 1164 #endif /* COMPAT_43 */ 1165 1166 /* 1167 * Check access permissions. 1168 */ 1169 int 1170 access(p, uap, retval) 1171 struct proc *p; 1172 register struct access_args /* { 1173 syscallarg(char *) path; 1174 syscallarg(int) flags; 1175 } */ *uap; 1176 register_t *retval; 1177 { 1178 register struct ucred *cred = p->p_ucred; 1179 register struct vnode *vp; 1180 int error, flags, t_gid, t_uid; 1181 struct nameidata nd; 1182 1183 t_uid = cred->cr_uid; 1184 t_gid = cred->cr_groups[0]; 1185 cred->cr_uid = p->p_cred->p_ruid; 1186 cred->cr_groups[0] = p->p_cred->p_rgid; 1187 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, 1188 SCARG(uap, path), p); 1189 if (error = namei(&nd)) 1190 goto out1; 1191 vp = nd.ni_vp; 1192 1193 /* Flags == 0 means only check for existence. */ 1194 if (SCARG(uap, flags)) { 1195 flags = 0; 1196 if (SCARG(uap, flags) & R_OK) 1197 flags |= VREAD; 1198 if (SCARG(uap, flags) & W_OK) 1199 flags |= VWRITE; 1200 if (SCARG(uap, flags) & X_OK) 1201 flags |= VEXEC; 1202 if ((flags & VWRITE) == 0 || (error = vn_writechk(vp)) == 0) 1203 error = VOP_ACCESS(vp, flags, cred, p); 1204 } 1205 vput(vp); 1206 out1: 1207 cred->cr_uid = t_uid; 1208 cred->cr_groups[0] = t_gid; 1209 return (error); 1210 } 1211 1212 #if defined(COMPAT_43) || defined(COMPAT_SUNOS) 1213 /* 1214 * Get file status; this version follows links. 1215 */ 1216 /* ARGSUSED */ 1217 int 1218 compat_43_stat(p, uap, retval) 1219 struct proc *p; 1220 register struct compat_43_stat_args /* { 1221 syscallarg(char *) path; 1222 syscallarg(struct ostat *) ub; 1223 } */ *uap; 1224 register_t *retval; 1225 { 1226 struct stat sb; 1227 struct ostat osb; 1228 int error; 1229 struct nameidata nd; 1230 1231 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, 1232 SCARG(uap, path), p); 1233 if (error = namei(&nd)) 1234 return (error); 1235 error = vn_stat(nd.ni_vp, &sb, p); 1236 vput(nd.ni_vp); 1237 if (error) 1238 return (error); 1239 cvtstat(&sb, &osb); 1240 error = copyout((caddr_t)&osb, (caddr_t)SCARG(uap, ub), sizeof (osb)); 1241 return (error); 1242 } 1243 1244 /* 1245 * Get file status; this version does not follow links. 1246 */ 1247 /* ARGSUSED */ 1248 int 1249 compat_43_lstat(p, uap, retval) 1250 struct proc *p; 1251 register struct compat_43_lstat_args /* { 1252 syscallarg(char *) path; 1253 syscallarg(struct ostat *) ub; 1254 } */ *uap; 1255 register_t *retval; 1256 { 1257 struct vnode *vp, *dvp; 1258 struct stat sb, sb1; 1259 struct ostat osb; 1260 int error; 1261 struct nameidata nd; 1262 1263 NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF | LOCKPARENT, UIO_USERSPACE, 1264 SCARG(uap, path), p); 1265 if (error = namei(&nd)) 1266 return (error); 1267 /* 1268 * For symbolic links, always return the attributes of its 1269 * containing directory, except for mode, size, and links. 1270 */ 1271 vp = nd.ni_vp; 1272 dvp = nd.ni_dvp; 1273 if (vp->v_type != VLNK) { 1274 if (dvp == vp) 1275 vrele(dvp); 1276 else 1277 vput(dvp); 1278 error = vn_stat(vp, &sb, p); 1279 vput(vp); 1280 if (error) 1281 return (error); 1282 } else { 1283 error = vn_stat(dvp, &sb, p); 1284 vput(dvp); 1285 if (error) { 1286 vput(vp); 1287 return (error); 1288 } 1289 error = vn_stat(vp, &sb1, p); 1290 vput(vp); 1291 if (error) 1292 return (error); 1293 sb.st_mode &= ~S_IFDIR; 1294 sb.st_mode |= S_IFLNK; 1295 sb.st_nlink = sb1.st_nlink; 1296 sb.st_size = sb1.st_size; 1297 sb.st_blocks = sb1.st_blocks; 1298 } 1299 cvtstat(&sb, &osb); 1300 error = copyout((caddr_t)&osb, (caddr_t)SCARG(uap, ub), sizeof (osb)); 1301 return (error); 1302 } 1303 1304 /* 1305 * Convert from an old to a new stat structure. 1306 */ 1307 void 1308 cvtstat(st, ost) 1309 struct stat *st; 1310 struct ostat *ost; 1311 { 1312 1313 ost->st_dev = st->st_dev; 1314 ost->st_ino = st->st_ino; 1315 ost->st_mode = st->st_mode; 1316 ost->st_nlink = st->st_nlink; 1317 ost->st_uid = st->st_uid; 1318 ost->st_gid = st->st_gid; 1319 ost->st_rdev = st->st_rdev; 1320 if (st->st_size < (quad_t)1 << 32) 1321 ost->st_size = st->st_size; 1322 else 1323 ost->st_size = -2; 1324 ost->st_atime = st->st_atime; 1325 ost->st_mtime = st->st_mtime; 1326 ost->st_ctime = st->st_ctime; 1327 ost->st_blksize = st->st_blksize; 1328 ost->st_blocks = st->st_blocks; 1329 ost->st_flags = st->st_flags; 1330 ost->st_gen = st->st_gen; 1331 } 1332 #endif /* COMPAT_43 || COMPAT_SUNOS */ 1333 1334 /* 1335 * Get file status; this version follows links. 1336 */ 1337 /* ARGSUSED */ 1338 int 1339 stat(p, uap, retval) 1340 struct proc *p; 1341 register struct stat_args /* { 1342 syscallarg(char *) path; 1343 syscallarg(struct stat *) ub; 1344 } */ *uap; 1345 register_t *retval; 1346 { 1347 struct stat sb; 1348 int error; 1349 struct nameidata nd; 1350 1351 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, 1352 SCARG(uap, path), p); 1353 if (error = namei(&nd)) 1354 return (error); 1355 error = vn_stat(nd.ni_vp, &sb, p); 1356 vput(nd.ni_vp); 1357 if (error) 1358 return (error); 1359 error = copyout((caddr_t)&sb, (caddr_t)SCARG(uap, ub), sizeof (sb)); 1360 return (error); 1361 } 1362 1363 /* 1364 * Get file status; this version does not follow links. 1365 */ 1366 /* ARGSUSED */ 1367 int 1368 lstat(p, uap, retval) 1369 struct proc *p; 1370 register struct lstat_args /* { 1371 syscallarg(char *) path; 1372 syscallarg(struct stat *) ub; 1373 } */ *uap; 1374 register_t *retval; 1375 { 1376 int error; 1377 struct vnode *vp, *dvp; 1378 struct stat sb, sb1; 1379 struct nameidata nd; 1380 1381 NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF | LOCKPARENT, UIO_USERSPACE, 1382 SCARG(uap, path), p); 1383 if (error = namei(&nd)) 1384 return (error); 1385 /* 1386 * For symbolic links, always return the attributes of its containing 1387 * directory, except for mode, size, inode number, and links. 1388 */ 1389 vp = nd.ni_vp; 1390 dvp = nd.ni_dvp; 1391 if (vp->v_type != VLNK) { 1392 if (dvp == vp) 1393 vrele(dvp); 1394 else 1395 vput(dvp); 1396 error = vn_stat(vp, &sb, p); 1397 vput(vp); 1398 if (error) 1399 return (error); 1400 } else { 1401 error = vn_stat(dvp, &sb, p); 1402 vput(dvp); 1403 if (error) { 1404 vput(vp); 1405 return (error); 1406 } 1407 error = vn_stat(vp, &sb1, p); 1408 vput(vp); 1409 if (error) 1410 return (error); 1411 sb.st_mode &= ~S_IFDIR; 1412 sb.st_mode |= S_IFLNK; 1413 sb.st_nlink = sb1.st_nlink; 1414 sb.st_size = sb1.st_size; 1415 sb.st_blocks = sb1.st_blocks; 1416 sb.st_ino = sb1.st_ino; 1417 } 1418 error = copyout((caddr_t)&sb, (caddr_t)SCARG(uap, ub), sizeof (sb)); 1419 return (error); 1420 } 1421 1422 /* 1423 * Get configurable pathname variables. 1424 */ 1425 /* ARGSUSED */ 1426 int 1427 pathconf(p, uap, retval) 1428 struct proc *p; 1429 register struct pathconf_args /* { 1430 syscallarg(char *) path; 1431 syscallarg(int) name; 1432 } */ *uap; 1433 register_t *retval; 1434 { 1435 int error; 1436 struct nameidata nd; 1437 1438 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, 1439 SCARG(uap, path), p); 1440 if (error = namei(&nd)) 1441 return (error); 1442 error = VOP_PATHCONF(nd.ni_vp, SCARG(uap, name), retval); 1443 vput(nd.ni_vp); 1444 return (error); 1445 } 1446 1447 /* 1448 * Return target name of a symbolic link. 1449 */ 1450 /* ARGSUSED */ 1451 int 1452 readlink(p, uap, retval) 1453 struct proc *p; 1454 register struct readlink_args /* { 1455 syscallarg(char *) path; 1456 syscallarg(char *) buf; 1457 syscallarg(int) count; 1458 } */ *uap; 1459 register_t *retval; 1460 { 1461 register struct vnode *vp; 1462 struct iovec aiov; 1463 struct uio auio; 1464 int error; 1465 struct nameidata nd; 1466 1467 NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF, UIO_USERSPACE, 1468 SCARG(uap, path), p); 1469 if (error = namei(&nd)) 1470 return (error); 1471 vp = nd.ni_vp; 1472 if (vp->v_type != VLNK) 1473 error = EINVAL; 1474 else { 1475 aiov.iov_base = SCARG(uap, buf); 1476 aiov.iov_len = SCARG(uap, count); 1477 auio.uio_iov = &aiov; 1478 auio.uio_iovcnt = 1; 1479 auio.uio_offset = 0; 1480 auio.uio_rw = UIO_READ; 1481 auio.uio_segflg = UIO_USERSPACE; 1482 auio.uio_procp = p; 1483 auio.uio_resid = SCARG(uap, count); 1484 error = VOP_READLINK(vp, &auio, p->p_ucred); 1485 } 1486 vput(vp); 1487 *retval = SCARG(uap, count) - auio.uio_resid; 1488 return (error); 1489 } 1490 1491 /* 1492 * Change flags of a file given a path name. 1493 */ 1494 /* ARGSUSED */ 1495 int 1496 chflags(p, uap, retval) 1497 struct proc *p; 1498 register struct chflags_args /* { 1499 syscallarg(char *) path; 1500 syscallarg(int) flags; 1501 } */ *uap; 1502 register_t *retval; 1503 { 1504 register struct vnode *vp; 1505 struct vattr vattr; 1506 int error; 1507 struct nameidata nd; 1508 1509 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p); 1510 if (error = namei(&nd)) 1511 return (error); 1512 vp = nd.ni_vp; 1513 VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE); 1514 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); 1515 if (vp->v_mount->mnt_flag & MNT_RDONLY) 1516 error = EROFS; 1517 else { 1518 VATTR_NULL(&vattr); 1519 vattr.va_flags = SCARG(uap, flags); 1520 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); 1521 } 1522 vput(vp); 1523 return (error); 1524 } 1525 1526 /* 1527 * Change flags of a file given a file descriptor. 1528 */ 1529 /* ARGSUSED */ 1530 int 1531 fchflags(p, uap, retval) 1532 struct proc *p; 1533 register struct fchflags_args /* { 1534 syscallarg(int) fd; 1535 syscallarg(int) flags; 1536 } */ *uap; 1537 register_t *retval; 1538 { 1539 struct vattr vattr; 1540 struct vnode *vp; 1541 struct file *fp; 1542 int error; 1543 1544 if (error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) 1545 return (error); 1546 vp = (struct vnode *)fp->f_data; 1547 VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE); 1548 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); 1549 if (vp->v_mount->mnt_flag & MNT_RDONLY) 1550 error = EROFS; 1551 else { 1552 VATTR_NULL(&vattr); 1553 vattr.va_flags = SCARG(uap, flags); 1554 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); 1555 } 1556 VOP_UNLOCK(vp, 0, p); 1557 return (error); 1558 } 1559 1560 /* 1561 * Change mode of a file given path name. 1562 */ 1563 /* ARGSUSED */ 1564 int 1565 chmod(p, uap, retval) 1566 struct proc *p; 1567 register struct chmod_args /* { 1568 syscallarg(char *) path; 1569 syscallarg(int) mode; 1570 } */ *uap; 1571 register_t *retval; 1572 { 1573 register struct vnode *vp; 1574 struct vattr vattr; 1575 int error; 1576 struct nameidata nd; 1577 1578 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p); 1579 if (error = namei(&nd)) 1580 return (error); 1581 vp = nd.ni_vp; 1582 VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE); 1583 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); 1584 if (vp->v_mount->mnt_flag & MNT_RDONLY) 1585 error = EROFS; 1586 else { 1587 VATTR_NULL(&vattr); 1588 vattr.va_mode = SCARG(uap, mode) & ALLPERMS; 1589 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); 1590 } 1591 vput(vp); 1592 return (error); 1593 } 1594 1595 /* 1596 * Change mode of a file given a file descriptor. 1597 */ 1598 /* ARGSUSED */ 1599 int 1600 fchmod(p, uap, retval) 1601 struct proc *p; 1602 register struct fchmod_args /* { 1603 syscallarg(int) fd; 1604 syscallarg(int) mode; 1605 } */ *uap; 1606 register_t *retval; 1607 { 1608 struct vattr vattr; 1609 struct vnode *vp; 1610 struct file *fp; 1611 int error; 1612 1613 if (error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) 1614 return (error); 1615 vp = (struct vnode *)fp->f_data; 1616 VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE); 1617 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); 1618 if (vp->v_mount->mnt_flag & MNT_RDONLY) 1619 error = EROFS; 1620 else { 1621 VATTR_NULL(&vattr); 1622 vattr.va_mode = SCARG(uap, mode) & ALLPERMS; 1623 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); 1624 } 1625 VOP_UNLOCK(vp, 0, p); 1626 return (error); 1627 } 1628 1629 /* 1630 * Set ownership given a path name. 1631 */ 1632 /* ARGSUSED */ 1633 int 1634 chown(p, uap, retval) 1635 struct proc *p; 1636 register struct chown_args /* { 1637 syscallarg(char *) path; 1638 syscallarg(int) uid; 1639 syscallarg(int) gid; 1640 } */ *uap; 1641 register_t *retval; 1642 { 1643 register struct vnode *vp; 1644 struct vattr vattr; 1645 int error; 1646 struct nameidata nd; 1647 1648 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p); 1649 if (error = namei(&nd)) 1650 return (error); 1651 vp = nd.ni_vp; 1652 VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE); 1653 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); 1654 if (vp->v_mount->mnt_flag & MNT_RDONLY) 1655 error = EROFS; 1656 else { 1657 VATTR_NULL(&vattr); 1658 vattr.va_uid = SCARG(uap, uid); 1659 vattr.va_gid = SCARG(uap, gid); 1660 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); 1661 } 1662 vput(vp); 1663 return (error); 1664 } 1665 1666 /* 1667 * Set ownership given a file descriptor. 1668 */ 1669 /* ARGSUSED */ 1670 int 1671 fchown(p, uap, retval) 1672 struct proc *p; 1673 register struct fchown_args /* { 1674 syscallarg(int) fd; 1675 syscallarg(int) uid; 1676 syscallarg(int) gid; 1677 } */ *uap; 1678 register_t *retval; 1679 { 1680 struct vattr vattr; 1681 struct vnode *vp; 1682 struct file *fp; 1683 int error; 1684 1685 if (error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) 1686 return (error); 1687 vp = (struct vnode *)fp->f_data; 1688 VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE); 1689 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); 1690 if (vp->v_mount->mnt_flag & MNT_RDONLY) 1691 error = EROFS; 1692 else { 1693 VATTR_NULL(&vattr); 1694 vattr.va_uid = SCARG(uap, uid); 1695 vattr.va_gid = SCARG(uap, gid); 1696 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); 1697 } 1698 VOP_UNLOCK(vp, 0, p); 1699 return (error); 1700 } 1701 1702 /* 1703 * Set the access and modification times of a file. 1704 */ 1705 /* ARGSUSED */ 1706 int 1707 utimes(p, uap, retval) 1708 struct proc *p; 1709 register struct utimes_args /* { 1710 syscallarg(char *) path; 1711 syscallarg(struct timeval *) tptr; 1712 } */ *uap; 1713 register_t *retval; 1714 { 1715 register struct vnode *vp; 1716 struct timeval tv[2]; 1717 struct vattr vattr; 1718 int error; 1719 struct nameidata nd; 1720 1721 VATTR_NULL(&vattr); 1722 if (SCARG(uap, tptr) == NULL) { 1723 microtime(&tv[0]); 1724 tv[1] = tv[0]; 1725 vattr.va_vaflags |= VA_UTIMES_NULL; 1726 } else if (error = copyin((caddr_t)SCARG(uap, tptr), (caddr_t)tv, 1727 sizeof (tv))) 1728 return (error); 1729 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p); 1730 if (error = namei(&nd)) 1731 return (error); 1732 vp = nd.ni_vp; 1733 VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE); 1734 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); 1735 if (vp->v_mount->mnt_flag & MNT_RDONLY) 1736 error = EROFS; 1737 else { 1738 vattr.va_atime.ts_sec = tv[0].tv_sec; 1739 vattr.va_atime.ts_nsec = tv[0].tv_usec * 1000; 1740 vattr.va_mtime.ts_sec = tv[1].tv_sec; 1741 vattr.va_mtime.ts_nsec = tv[1].tv_usec * 1000; 1742 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); 1743 } 1744 vput(vp); 1745 return (error); 1746 } 1747 1748 /* 1749 * Truncate a file given its path name. 1750 */ 1751 /* ARGSUSED */ 1752 int 1753 truncate(p, uap, retval) 1754 struct proc *p; 1755 register struct truncate_args /* { 1756 syscallarg(char *) path; 1757 syscallarg(int) pad; 1758 syscallarg(off_t) length; 1759 } */ *uap; 1760 register_t *retval; 1761 { 1762 register struct vnode *vp; 1763 struct vattr vattr; 1764 int error; 1765 struct nameidata nd; 1766 1767 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p); 1768 if (error = namei(&nd)) 1769 return (error); 1770 vp = nd.ni_vp; 1771 VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE); 1772 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); 1773 if (vp->v_type == VDIR) 1774 error = EISDIR; 1775 else if ((error = vn_writechk(vp)) == 0 && 1776 (error = VOP_ACCESS(vp, VWRITE, p->p_ucred, p)) == 0) { 1777 VATTR_NULL(&vattr); 1778 vattr.va_size = SCARG(uap, length); 1779 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); 1780 } 1781 vput(vp); 1782 return (error); 1783 } 1784 1785 /* 1786 * Truncate a file given a file descriptor. 1787 */ 1788 /* ARGSUSED */ 1789 int 1790 ftruncate(p, uap, retval) 1791 struct proc *p; 1792 register struct ftruncate_args /* { 1793 syscallarg(int) fd; 1794 syscallarg(int) pad; 1795 syscallarg(off_t) length; 1796 } */ *uap; 1797 register_t *retval; 1798 { 1799 struct vattr vattr; 1800 struct vnode *vp; 1801 struct file *fp; 1802 int error; 1803 1804 if (error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) 1805 return (error); 1806 if ((fp->f_flag & FWRITE) == 0) 1807 return (EINVAL); 1808 vp = (struct vnode *)fp->f_data; 1809 VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE); 1810 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); 1811 if (vp->v_type == VDIR) 1812 error = EISDIR; 1813 else if ((error = vn_writechk(vp)) == 0) { 1814 VATTR_NULL(&vattr); 1815 vattr.va_size = SCARG(uap, length); 1816 error = VOP_SETATTR(vp, &vattr, fp->f_cred, p); 1817 } 1818 VOP_UNLOCK(vp, 0, p); 1819 return (error); 1820 } 1821 1822 #if defined(COMPAT_43) || defined(COMPAT_SUNOS) 1823 /* 1824 * Truncate a file given its path name. 1825 */ 1826 /* ARGSUSED */ 1827 int 1828 compat_43_truncate(p, uap, retval) 1829 struct proc *p; 1830 register struct compat_43_truncate_args /* { 1831 syscallarg(char *) path; 1832 syscallarg(long) length; 1833 } */ *uap; 1834 register_t *retval; 1835 { 1836 struct truncate_args /* { 1837 syscallarg(char *) path; 1838 syscallarg(int) pad; 1839 syscallarg(off_t) length; 1840 } */ nuap; 1841 1842 SCARG(&nuap, path) = SCARG(uap, path); 1843 SCARG(&nuap, length) = SCARG(uap, length); 1844 return (truncate(p, &nuap, retval)); 1845 } 1846 1847 /* 1848 * Truncate a file given a file descriptor. 1849 */ 1850 /* ARGSUSED */ 1851 int 1852 compat_43_ftruncate(p, uap, retval) 1853 struct proc *p; 1854 register struct compat_43_ftruncate_args /* { 1855 syscallarg(int) fd; 1856 syscallarg(long) length; 1857 } */ *uap; 1858 register_t *retval; 1859 { 1860 struct ftruncate_args /* { 1861 syscallarg(int) fd; 1862 syscallarg(int) pad; 1863 syscallarg(off_t) length; 1864 } */ nuap; 1865 1866 SCARG(&nuap, fd) = SCARG(uap, fd); 1867 SCARG(&nuap, length) = SCARG(uap, length); 1868 return (ftruncate(p, &nuap, retval)); 1869 } 1870 #endif /* COMPAT_43 || COMPAT_SUNOS */ 1871 1872 /* 1873 * Sync an open file. 1874 */ 1875 /* ARGSUSED */ 1876 int 1877 fsync(p, uap, retval) 1878 struct proc *p; 1879 struct fsync_args /* { 1880 syscallarg(int) fd; 1881 } */ *uap; 1882 register_t *retval; 1883 { 1884 register struct vnode *vp; 1885 struct file *fp; 1886 int error; 1887 1888 if (error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) 1889 return (error); 1890 vp = (struct vnode *)fp->f_data; 1891 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); 1892 error = VOP_FSYNC(vp, fp->f_cred, MNT_WAIT, p); 1893 VOP_UNLOCK(vp, 0, p); 1894 return (error); 1895 } 1896 1897 /* 1898 * Rename files. Source and destination must either both be directories, 1899 * or both not be directories. If target is a directory, it must be empty. 1900 */ 1901 /* ARGSUSED */ 1902 int 1903 rename(p, uap, retval) 1904 struct proc *p; 1905 register struct rename_args /* { 1906 syscallarg(char *) from; 1907 syscallarg(char *) to; 1908 } */ *uap; 1909 register_t *retval; 1910 { 1911 register struct vnode *tvp, *fvp, *tdvp; 1912 struct nameidata fromnd, tond; 1913 int error; 1914 1915 NDINIT(&fromnd, DELETE, WANTPARENT | SAVESTART, UIO_USERSPACE, 1916 SCARG(uap, from), p); 1917 if (error = namei(&fromnd)) 1918 return (error); 1919 fvp = fromnd.ni_vp; 1920 NDINIT(&tond, RENAME, LOCKPARENT | LOCKLEAF | NOCACHE | SAVESTART, 1921 UIO_USERSPACE, SCARG(uap, to), p); 1922 if (error = namei(&tond)) { 1923 VOP_ABORTOP(fromnd.ni_dvp, &fromnd.ni_cnd); 1924 vrele(fromnd.ni_dvp); 1925 vrele(fvp); 1926 goto out1; 1927 } 1928 tdvp = tond.ni_dvp; 1929 tvp = tond.ni_vp; 1930 if (tvp != NULL) { 1931 if (fvp->v_type == VDIR && tvp->v_type != VDIR) { 1932 error = ENOTDIR; 1933 goto out; 1934 } else if (fvp->v_type != VDIR && tvp->v_type == VDIR) { 1935 error = EISDIR; 1936 goto out; 1937 } 1938 } 1939 if (fvp == tdvp) 1940 error = EINVAL; 1941 /* 1942 * If source is the same as the destination (that is the 1943 * same inode number with the same name in the same directory), 1944 * then there is nothing to do. 1945 */ 1946 if (fvp == tvp && fromnd.ni_dvp == tdvp && 1947 fromnd.ni_cnd.cn_namelen == tond.ni_cnd.cn_namelen && 1948 !bcmp(fromnd.ni_cnd.cn_nameptr, tond.ni_cnd.cn_nameptr, 1949 fromnd.ni_cnd.cn_namelen)) 1950 error = -1; 1951 out: 1952 if (!error) { 1953 VOP_LEASE(tdvp, p, p->p_ucred, LEASE_WRITE); 1954 if (fromnd.ni_dvp != tdvp) 1955 VOP_LEASE(fromnd.ni_dvp, p, p->p_ucred, LEASE_WRITE); 1956 if (tvp) 1957 VOP_LEASE(tvp, p, p->p_ucred, LEASE_WRITE); 1958 error = VOP_RENAME(fromnd.ni_dvp, fromnd.ni_vp, &fromnd.ni_cnd, 1959 tond.ni_dvp, tond.ni_vp, &tond.ni_cnd); 1960 } else { 1961 VOP_ABORTOP(tond.ni_dvp, &tond.ni_cnd); 1962 if (tdvp == tvp) 1963 vrele(tdvp); 1964 else 1965 vput(tdvp); 1966 if (tvp) 1967 vput(tvp); 1968 VOP_ABORTOP(fromnd.ni_dvp, &fromnd.ni_cnd); 1969 vrele(fromnd.ni_dvp); 1970 vrele(fvp); 1971 } 1972 vrele(tond.ni_startdir); 1973 FREE(tond.ni_cnd.cn_pnbuf, M_NAMEI); 1974 out1: 1975 if (fromnd.ni_startdir) 1976 vrele(fromnd.ni_startdir); 1977 FREE(fromnd.ni_cnd.cn_pnbuf, M_NAMEI); 1978 if (error == -1) 1979 return (0); 1980 return (error); 1981 } 1982 1983 /* 1984 * Make a directory file. 1985 */ 1986 /* ARGSUSED */ 1987 int 1988 mkdir(p, uap, retval) 1989 struct proc *p; 1990 register struct mkdir_args /* { 1991 syscallarg(char *) path; 1992 syscallarg(int) mode; 1993 } */ *uap; 1994 register_t *retval; 1995 { 1996 register struct vnode *vp; 1997 struct vattr vattr; 1998 int error; 1999 struct nameidata nd; 2000 2001 NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, SCARG(uap, path), p); 2002 if (error = namei(&nd)) 2003 return (error); 2004 vp = nd.ni_vp; 2005 if (vp != NULL) { 2006 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); 2007 if (nd.ni_dvp == vp) 2008 vrele(nd.ni_dvp); 2009 else 2010 vput(nd.ni_dvp); 2011 vrele(vp); 2012 return (EEXIST); 2013 } 2014 VATTR_NULL(&vattr); 2015 vattr.va_type = VDIR; 2016 vattr.va_mode = (SCARG(uap, mode) & ACCESSPERMS) &~ p->p_fd->fd_cmask; 2017 VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE); 2018 error = VOP_MKDIR(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr); 2019 if (!error) 2020 vput(nd.ni_vp); 2021 return (error); 2022 } 2023 2024 /* 2025 * Remove a directory file. 2026 */ 2027 /* ARGSUSED */ 2028 int 2029 rmdir(p, uap, retval) 2030 struct proc *p; 2031 struct rmdir_args /* { 2032 syscallarg(char *) path; 2033 } */ *uap; 2034 register_t *retval; 2035 { 2036 register struct vnode *vp; 2037 int error; 2038 struct nameidata nd; 2039 2040 NDINIT(&nd, DELETE, LOCKPARENT | LOCKLEAF, UIO_USERSPACE, 2041 SCARG(uap, path), p); 2042 if (error = namei(&nd)) 2043 return (error); 2044 vp = nd.ni_vp; 2045 if (vp->v_type != VDIR) { 2046 error = ENOTDIR; 2047 goto out; 2048 } 2049 /* 2050 * No rmdir "." please. 2051 */ 2052 if (nd.ni_dvp == vp) { 2053 error = EINVAL; 2054 goto out; 2055 } 2056 /* 2057 * The root of a mounted filesystem cannot be deleted. 2058 */ 2059 if (vp->v_flag & VROOT) 2060 error = EBUSY; 2061 out: 2062 if (!error) { 2063 VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE); 2064 VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE); 2065 error = VOP_RMDIR(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd); 2066 } else { 2067 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); 2068 if (nd.ni_dvp == vp) 2069 vrele(nd.ni_dvp); 2070 else 2071 vput(nd.ni_dvp); 2072 vput(vp); 2073 } 2074 return (error); 2075 } 2076 2077 #ifdef COMPAT_43 2078 /* 2079 * Read a block of directory entries in a file system independent format. 2080 */ 2081 int 2082 compat_43_getdirentries(p, uap, retval) 2083 struct proc *p; 2084 register struct compat_43_getdirentries_args /* { 2085 syscallarg(int) fd; 2086 syscallarg(char *) buf; 2087 syscallarg(u_int) count; 2088 syscallarg(long *) basep; 2089 } */ *uap; 2090 register_t *retval; 2091 { 2092 register struct vnode *vp; 2093 struct file *fp; 2094 struct uio auio, kuio; 2095 struct iovec aiov, kiov; 2096 struct dirent *dp, *edp; 2097 caddr_t dirbuf; 2098 int error, eofflag, readcnt; 2099 long loff; 2100 2101 if (error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) 2102 return (error); 2103 if ((fp->f_flag & FREAD) == 0) 2104 return (EBADF); 2105 vp = (struct vnode *)fp->f_data; 2106 unionread: 2107 if (vp->v_type != VDIR) 2108 return (EINVAL); 2109 aiov.iov_base = SCARG(uap, buf); 2110 aiov.iov_len = SCARG(uap, count); 2111 auio.uio_iov = &aiov; 2112 auio.uio_iovcnt = 1; 2113 auio.uio_rw = UIO_READ; 2114 auio.uio_segflg = UIO_USERSPACE; 2115 auio.uio_procp = p; 2116 auio.uio_resid = SCARG(uap, count); 2117 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); 2118 loff = auio.uio_offset = fp->f_offset; 2119 # if (BYTE_ORDER != LITTLE_ENDIAN) 2120 if (vp->v_mount->mnt_maxsymlinklen <= 0) { 2121 error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, 2122 (int *)0, (u_long *)0); 2123 fp->f_offset = auio.uio_offset; 2124 } else 2125 # endif 2126 { 2127 kuio = auio; 2128 kuio.uio_iov = &kiov; 2129 kuio.uio_segflg = UIO_SYSSPACE; 2130 kiov.iov_len = SCARG(uap, count); 2131 MALLOC(dirbuf, caddr_t, SCARG(uap, count), M_TEMP, M_WAITOK); 2132 kiov.iov_base = dirbuf; 2133 error = VOP_READDIR(vp, &kuio, fp->f_cred, &eofflag, 2134 (int *)0, (u_long *)0); 2135 fp->f_offset = kuio.uio_offset; 2136 if (error == 0) { 2137 readcnt = SCARG(uap, count) - kuio.uio_resid; 2138 edp = (struct dirent *)&dirbuf[readcnt]; 2139 for (dp = (struct dirent *)dirbuf; dp < edp; ) { 2140 # if (BYTE_ORDER == LITTLE_ENDIAN) 2141 /* 2142 * The expected low byte of 2143 * dp->d_namlen is our dp->d_type. 2144 * The high MBZ byte of dp->d_namlen 2145 * is our dp->d_namlen. 2146 */ 2147 dp->d_type = dp->d_namlen; 2148 dp->d_namlen = 0; 2149 # else 2150 /* 2151 * The dp->d_type is the high byte 2152 * of the expected dp->d_namlen, 2153 * so must be zero'ed. 2154 */ 2155 dp->d_type = 0; 2156 # endif 2157 if (dp->d_reclen > 0) { 2158 dp = (struct dirent *) 2159 ((char *)dp + dp->d_reclen); 2160 } else { 2161 error = EIO; 2162 break; 2163 } 2164 } 2165 if (dp >= edp) 2166 error = uiomove(dirbuf, readcnt, &auio); 2167 } 2168 FREE(dirbuf, M_TEMP); 2169 } 2170 VOP_UNLOCK(vp, 0, p); 2171 if (error) 2172 return (error); 2173 2174 #ifdef UNION 2175 { 2176 extern int (**union_vnodeop_p)(); 2177 extern struct vnode *union_dircache __P((struct vnode*, struct proc*)); 2178 2179 if ((SCARG(uap, count) == auio.uio_resid) && 2180 (vp->v_op == union_vnodeop_p)) { 2181 struct vnode *lvp; 2182 2183 lvp = union_dircache(vp, p); 2184 if (lvp != NULLVP) { 2185 struct vattr va; 2186 2187 /* 2188 * If the directory is opaque, 2189 * then don't show lower entries 2190 */ 2191 error = VOP_GETATTR(vp, &va, fp->f_cred, p); 2192 if (va.va_flags & OPAQUE) { 2193 vput(lvp); 2194 lvp = NULL; 2195 } 2196 } 2197 2198 if (lvp != NULLVP) { 2199 error = VOP_OPEN(lvp, FREAD, fp->f_cred, p); 2200 if (error) { 2201 vput(lvp); 2202 return (error); 2203 } 2204 VOP_UNLOCK(lvp, 0, p); 2205 fp->f_data = (caddr_t) lvp; 2206 fp->f_offset = 0; 2207 error = vn_close(vp, FREAD, fp->f_cred, p); 2208 if (error) 2209 return (error); 2210 vp = lvp; 2211 goto unionread; 2212 } 2213 } 2214 } 2215 #endif /* UNION */ 2216 2217 if ((SCARG(uap, count) == auio.uio_resid) && 2218 (vp->v_flag & VROOT) && 2219 (vp->v_mount->mnt_flag & MNT_UNION)) { 2220 struct vnode *tvp = vp; 2221 vp = vp->v_mount->mnt_vnodecovered; 2222 VREF(vp); 2223 fp->f_data = (caddr_t) vp; 2224 fp->f_offset = 0; 2225 vrele(tvp); 2226 goto unionread; 2227 } 2228 error = copyout((caddr_t)&loff, (caddr_t)SCARG(uap, basep), 2229 sizeof(long)); 2230 *retval = SCARG(uap, count) - auio.uio_resid; 2231 return (error); 2232 } 2233 #endif /* COMPAT_43 */ 2234 2235 /* 2236 * Read a block of directory entries in a file system independent format. 2237 */ 2238 int 2239 getdirentries(p, uap, retval) 2240 struct proc *p; 2241 register struct getdirentries_args /* { 2242 syscallarg(int) fd; 2243 syscallarg(char *) buf; 2244 syscallarg(u_int) count; 2245 syscallarg(long *) basep; 2246 } */ *uap; 2247 register_t *retval; 2248 { 2249 register struct vnode *vp; 2250 struct file *fp; 2251 struct uio auio; 2252 struct iovec aiov; 2253 long loff; 2254 int error, eofflag; 2255 2256 if (error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) 2257 return (error); 2258 if ((fp->f_flag & FREAD) == 0) 2259 return (EBADF); 2260 vp = (struct vnode *)fp->f_data; 2261 unionread: 2262 if (vp->v_type != VDIR) 2263 return (EINVAL); 2264 aiov.iov_base = SCARG(uap, buf); 2265 aiov.iov_len = SCARG(uap, count); 2266 auio.uio_iov = &aiov; 2267 auio.uio_iovcnt = 1; 2268 auio.uio_rw = UIO_READ; 2269 auio.uio_segflg = UIO_USERSPACE; 2270 auio.uio_procp = p; 2271 auio.uio_resid = SCARG(uap, count); 2272 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); 2273 loff = auio.uio_offset = fp->f_offset; 2274 error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, 2275 (int *)0, (u_long *)0); 2276 fp->f_offset = auio.uio_offset; 2277 VOP_UNLOCK(vp, 0, p); 2278 if (error) 2279 return (error); 2280 2281 #ifdef UNION 2282 { 2283 extern int (**union_vnodeop_p)(); 2284 extern struct vnode *union_dircache __P((struct vnode*, struct proc*)); 2285 2286 if ((SCARG(uap, count) == auio.uio_resid) && 2287 (vp->v_op == union_vnodeop_p)) { 2288 struct vnode *lvp; 2289 2290 lvp = union_dircache(vp, p); 2291 if (lvp != NULLVP) { 2292 struct vattr va; 2293 2294 /* 2295 * If the directory is opaque, 2296 * then don't show lower entries 2297 */ 2298 error = VOP_GETATTR(vp, &va, fp->f_cred, p); 2299 if (va.va_flags & OPAQUE) { 2300 vput(lvp); 2301 lvp = NULL; 2302 } 2303 } 2304 2305 if (lvp != NULLVP) { 2306 error = VOP_OPEN(lvp, FREAD, fp->f_cred, p); 2307 if (error) { 2308 vput(lvp); 2309 return (error); 2310 } 2311 VOP_UNLOCK(lvp, 0, p); 2312 fp->f_data = (caddr_t) lvp; 2313 fp->f_offset = 0; 2314 error = vn_close(vp, FREAD, fp->f_cred, p); 2315 if (error) 2316 return (error); 2317 vp = lvp; 2318 goto unionread; 2319 } 2320 } 2321 } 2322 #endif /* UNION */ 2323 2324 if ((SCARG(uap, count) == auio.uio_resid) && 2325 (vp->v_flag & VROOT) && 2326 (vp->v_mount->mnt_flag & MNT_UNION)) { 2327 struct vnode *tvp = vp; 2328 vp = vp->v_mount->mnt_vnodecovered; 2329 VREF(vp); 2330 fp->f_data = (caddr_t) vp; 2331 fp->f_offset = 0; 2332 vrele(tvp); 2333 goto unionread; 2334 } 2335 error = copyout((caddr_t)&loff, (caddr_t)SCARG(uap, basep), 2336 sizeof(long)); 2337 *retval = SCARG(uap, count) - auio.uio_resid; 2338 return (error); 2339 } 2340 2341 /* 2342 * Set the mode mask for creation of filesystem nodes. 2343 */ 2344 int 2345 umask(p, uap, retval) 2346 struct proc *p; 2347 struct umask_args /* { 2348 syscallarg(int) newmask; 2349 } */ *uap; 2350 register_t *retval; 2351 { 2352 register struct filedesc *fdp; 2353 2354 fdp = p->p_fd; 2355 *retval = fdp->fd_cmask; 2356 fdp->fd_cmask = SCARG(uap, newmask) & ALLPERMS; 2357 return (0); 2358 } 2359 2360 /* 2361 * Void all references to file by ripping underlying filesystem 2362 * away from vnode. 2363 */ 2364 /* ARGSUSED */ 2365 int 2366 revoke(p, uap, retval) 2367 struct proc *p; 2368 register struct revoke_args /* { 2369 syscallarg(char *) path; 2370 } */ *uap; 2371 register_t *retval; 2372 { 2373 register struct vnode *vp; 2374 struct vattr vattr; 2375 int error; 2376 struct nameidata nd; 2377 2378 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p); 2379 if (error = namei(&nd)) 2380 return (error); 2381 vp = nd.ni_vp; 2382 if (error = VOP_GETATTR(vp, &vattr, p->p_ucred, p)) 2383 goto out; 2384 if (p->p_ucred->cr_uid != vattr.va_uid && 2385 (error = suser(p->p_ucred, &p->p_acflag))) 2386 goto out; 2387 if (vp->v_usecount > 1 || (vp->v_flag & VALIASED)) 2388 VOP_REVOKE(vp, REVOKEALL); 2389 out: 2390 vrele(vp); 2391 return (error); 2392 } 2393 2394 /* 2395 * Convert a user file descriptor to a kernel file entry. 2396 */ 2397 int 2398 getvnode(fdp, fd, fpp) 2399 struct filedesc *fdp; 2400 struct file **fpp; 2401 int fd; 2402 { 2403 struct file *fp; 2404 2405 if ((u_int)fd >= fdp->fd_nfiles || 2406 (fp = fdp->fd_ofiles[fd]) == NULL) 2407 return (EBADF); 2408 if (fp->f_type != DTYPE_VNODE) 2409 return (EINVAL); 2410 *fpp = fp; 2411 return (0); 2412 } 2413