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