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