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