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