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