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.39 (Berkeley) 05/20/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 if (vp->v_mount->mnt_flag & MNT_RDONLY) 1519 error = EROFS; 1520 else { 1521 VATTR_NULL(&vattr); 1522 vattr.va_flags = SCARG(uap, flags); 1523 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); 1524 } 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 if (vp->v_mount->mnt_flag & MNT_RDONLY) 1553 error = EROFS; 1554 else { 1555 VATTR_NULL(&vattr); 1556 vattr.va_flags = SCARG(uap, flags); 1557 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); 1558 } 1559 VOP_UNLOCK(vp, 0, p); 1560 return (error); 1561 } 1562 1563 /* 1564 * Change mode of a file given path name. 1565 */ 1566 /* ARGSUSED */ 1567 int 1568 chmod(p, uap, retval) 1569 struct proc *p; 1570 register struct chmod_args /* { 1571 syscallarg(char *) path; 1572 syscallarg(int) mode; 1573 } */ *uap; 1574 register_t *retval; 1575 { 1576 register struct vnode *vp; 1577 struct vattr vattr; 1578 int error; 1579 struct nameidata nd; 1580 1581 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p); 1582 if (error = namei(&nd)) 1583 return (error); 1584 vp = nd.ni_vp; 1585 VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE); 1586 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); 1587 if (vp->v_mount->mnt_flag & MNT_RDONLY) 1588 error = EROFS; 1589 else { 1590 VATTR_NULL(&vattr); 1591 vattr.va_mode = SCARG(uap, mode) & ALLPERMS; 1592 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); 1593 } 1594 vput(vp); 1595 return (error); 1596 } 1597 1598 /* 1599 * Change mode of a file given a file descriptor. 1600 */ 1601 /* ARGSUSED */ 1602 int 1603 fchmod(p, uap, retval) 1604 struct proc *p; 1605 register struct fchmod_args /* { 1606 syscallarg(int) fd; 1607 syscallarg(int) mode; 1608 } */ *uap; 1609 register_t *retval; 1610 { 1611 struct vattr vattr; 1612 struct vnode *vp; 1613 struct file *fp; 1614 int error; 1615 1616 if (error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) 1617 return (error); 1618 vp = (struct vnode *)fp->f_data; 1619 VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE); 1620 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); 1621 if (vp->v_mount->mnt_flag & MNT_RDONLY) 1622 error = EROFS; 1623 else { 1624 VATTR_NULL(&vattr); 1625 vattr.va_mode = SCARG(uap, mode) & ALLPERMS; 1626 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); 1627 } 1628 VOP_UNLOCK(vp, 0, p); 1629 return (error); 1630 } 1631 1632 /* 1633 * Set ownership given a path name. 1634 */ 1635 /* ARGSUSED */ 1636 int 1637 chown(p, uap, retval) 1638 struct proc *p; 1639 register struct chown_args /* { 1640 syscallarg(char *) path; 1641 syscallarg(int) uid; 1642 syscallarg(int) gid; 1643 } */ *uap; 1644 register_t *retval; 1645 { 1646 register struct vnode *vp; 1647 struct vattr vattr; 1648 int error; 1649 struct nameidata nd; 1650 1651 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p); 1652 if (error = namei(&nd)) 1653 return (error); 1654 vp = nd.ni_vp; 1655 VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE); 1656 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); 1657 if (vp->v_mount->mnt_flag & MNT_RDONLY) 1658 error = EROFS; 1659 else { 1660 VATTR_NULL(&vattr); 1661 vattr.va_uid = SCARG(uap, uid); 1662 vattr.va_gid = SCARG(uap, gid); 1663 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); 1664 } 1665 vput(vp); 1666 return (error); 1667 } 1668 1669 /* 1670 * Set ownership given a file descriptor. 1671 */ 1672 /* ARGSUSED */ 1673 int 1674 fchown(p, uap, retval) 1675 struct proc *p; 1676 register struct fchown_args /* { 1677 syscallarg(int) fd; 1678 syscallarg(int) uid; 1679 syscallarg(int) gid; 1680 } */ *uap; 1681 register_t *retval; 1682 { 1683 struct vattr vattr; 1684 struct vnode *vp; 1685 struct file *fp; 1686 int error; 1687 1688 if (error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) 1689 return (error); 1690 vp = (struct vnode *)fp->f_data; 1691 VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE); 1692 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); 1693 if (vp->v_mount->mnt_flag & MNT_RDONLY) 1694 error = EROFS; 1695 else { 1696 VATTR_NULL(&vattr); 1697 vattr.va_uid = SCARG(uap, uid); 1698 vattr.va_gid = SCARG(uap, gid); 1699 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); 1700 } 1701 VOP_UNLOCK(vp, 0, p); 1702 return (error); 1703 } 1704 1705 /* 1706 * Set the access and modification times of a file. 1707 */ 1708 /* ARGSUSED */ 1709 int 1710 utimes(p, uap, retval) 1711 struct proc *p; 1712 register struct utimes_args /* { 1713 syscallarg(char *) path; 1714 syscallarg(struct timeval *) tptr; 1715 } */ *uap; 1716 register_t *retval; 1717 { 1718 register struct vnode *vp; 1719 struct timeval tv[2]; 1720 struct vattr vattr; 1721 int error; 1722 struct nameidata nd; 1723 1724 VATTR_NULL(&vattr); 1725 if (SCARG(uap, tptr) == NULL) { 1726 microtime(&tv[0]); 1727 tv[1] = tv[0]; 1728 vattr.va_vaflags |= VA_UTIMES_NULL; 1729 } else if (error = copyin((caddr_t)SCARG(uap, tptr), (caddr_t)tv, 1730 sizeof (tv))) 1731 return (error); 1732 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p); 1733 if (error = namei(&nd)) 1734 return (error); 1735 vp = nd.ni_vp; 1736 VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE); 1737 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); 1738 if (vp->v_mount->mnt_flag & MNT_RDONLY) 1739 error = EROFS; 1740 else { 1741 vattr.va_atime.ts_sec = tv[0].tv_sec; 1742 vattr.va_atime.ts_nsec = tv[0].tv_usec * 1000; 1743 vattr.va_mtime.ts_sec = tv[1].tv_sec; 1744 vattr.va_mtime.ts_nsec = tv[1].tv_usec * 1000; 1745 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); 1746 } 1747 vput(vp); 1748 return (error); 1749 } 1750 1751 /* 1752 * Truncate a file given its path name. 1753 */ 1754 /* ARGSUSED */ 1755 int 1756 truncate(p, uap, retval) 1757 struct proc *p; 1758 register struct truncate_args /* { 1759 syscallarg(char *) path; 1760 syscallarg(int) pad; 1761 syscallarg(off_t) length; 1762 } */ *uap; 1763 register_t *retval; 1764 { 1765 register struct vnode *vp; 1766 struct vattr vattr; 1767 int error; 1768 struct nameidata nd; 1769 1770 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p); 1771 if (error = namei(&nd)) 1772 return (error); 1773 vp = nd.ni_vp; 1774 VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE); 1775 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); 1776 if (vp->v_type == VDIR) 1777 error = EISDIR; 1778 else if ((error = vn_writechk(vp)) == 0 && 1779 (error = VOP_ACCESS(vp, VWRITE, p->p_ucred, p)) == 0) { 1780 VATTR_NULL(&vattr); 1781 vattr.va_size = SCARG(uap, length); 1782 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); 1783 } 1784 vput(vp); 1785 return (error); 1786 } 1787 1788 /* 1789 * Truncate a file given a file descriptor. 1790 */ 1791 /* ARGSUSED */ 1792 int 1793 ftruncate(p, uap, retval) 1794 struct proc *p; 1795 register struct ftruncate_args /* { 1796 syscallarg(int) fd; 1797 syscallarg(int) pad; 1798 syscallarg(off_t) length; 1799 } */ *uap; 1800 register_t *retval; 1801 { 1802 struct vattr vattr; 1803 struct vnode *vp; 1804 struct file *fp; 1805 int error; 1806 1807 if (error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) 1808 return (error); 1809 if ((fp->f_flag & FWRITE) == 0) 1810 return (EINVAL); 1811 vp = (struct vnode *)fp->f_data; 1812 VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE); 1813 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); 1814 if (vp->v_type == VDIR) 1815 error = EISDIR; 1816 else if ((error = vn_writechk(vp)) == 0) { 1817 VATTR_NULL(&vattr); 1818 vattr.va_size = SCARG(uap, length); 1819 error = VOP_SETATTR(vp, &vattr, fp->f_cred, p); 1820 } 1821 VOP_UNLOCK(vp, 0, p); 1822 return (error); 1823 } 1824 1825 #if defined(COMPAT_43) || defined(COMPAT_SUNOS) 1826 /* 1827 * Truncate a file given its path name. 1828 */ 1829 /* ARGSUSED */ 1830 int 1831 compat_43_truncate(p, uap, retval) 1832 struct proc *p; 1833 register struct compat_43_truncate_args /* { 1834 syscallarg(char *) path; 1835 syscallarg(long) length; 1836 } */ *uap; 1837 register_t *retval; 1838 { 1839 struct truncate_args /* { 1840 syscallarg(char *) path; 1841 syscallarg(int) pad; 1842 syscallarg(off_t) length; 1843 } */ nuap; 1844 1845 SCARG(&nuap, path) = SCARG(uap, path); 1846 SCARG(&nuap, length) = SCARG(uap, length); 1847 return (truncate(p, &nuap, retval)); 1848 } 1849 1850 /* 1851 * Truncate a file given a file descriptor. 1852 */ 1853 /* ARGSUSED */ 1854 int 1855 compat_43_ftruncate(p, uap, retval) 1856 struct proc *p; 1857 register struct compat_43_ftruncate_args /* { 1858 syscallarg(int) fd; 1859 syscallarg(long) length; 1860 } */ *uap; 1861 register_t *retval; 1862 { 1863 struct ftruncate_args /* { 1864 syscallarg(int) fd; 1865 syscallarg(int) pad; 1866 syscallarg(off_t) length; 1867 } */ nuap; 1868 1869 SCARG(&nuap, fd) = SCARG(uap, fd); 1870 SCARG(&nuap, length) = SCARG(uap, length); 1871 return (ftruncate(p, &nuap, retval)); 1872 } 1873 #endif /* COMPAT_43 || COMPAT_SUNOS */ 1874 1875 /* 1876 * Sync an open file. 1877 */ 1878 /* ARGSUSED */ 1879 int 1880 fsync(p, uap, retval) 1881 struct proc *p; 1882 struct fsync_args /* { 1883 syscallarg(int) fd; 1884 } */ *uap; 1885 register_t *retval; 1886 { 1887 register struct vnode *vp; 1888 struct file *fp; 1889 int error; 1890 1891 if (error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) 1892 return (error); 1893 vp = (struct vnode *)fp->f_data; 1894 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); 1895 error = VOP_FSYNC(vp, fp->f_cred, MNT_WAIT, p); 1896 VOP_UNLOCK(vp, 0, p); 1897 return (error); 1898 } 1899 1900 /* 1901 * Rename files. Source and destination must either both be directories, 1902 * or both not be directories. If target is a directory, it must be empty. 1903 */ 1904 /* ARGSUSED */ 1905 int 1906 rename(p, uap, retval) 1907 struct proc *p; 1908 register struct rename_args /* { 1909 syscallarg(char *) from; 1910 syscallarg(char *) to; 1911 } */ *uap; 1912 register_t *retval; 1913 { 1914 register struct vnode *tvp, *fvp, *tdvp; 1915 struct nameidata fromnd, tond; 1916 int error; 1917 1918 NDINIT(&fromnd, DELETE, WANTPARENT | SAVESTART, UIO_USERSPACE, 1919 SCARG(uap, from), p); 1920 if (error = namei(&fromnd)) 1921 return (error); 1922 fvp = fromnd.ni_vp; 1923 NDINIT(&tond, RENAME, LOCKPARENT | LOCKLEAF | NOCACHE | SAVESTART, 1924 UIO_USERSPACE, SCARG(uap, to), p); 1925 if (error = namei(&tond)) { 1926 VOP_ABORTOP(fromnd.ni_dvp, &fromnd.ni_cnd); 1927 vrele(fromnd.ni_dvp); 1928 vrele(fvp); 1929 goto out1; 1930 } 1931 tdvp = tond.ni_dvp; 1932 tvp = tond.ni_vp; 1933 if (tvp != NULL) { 1934 if (fvp->v_type == VDIR && tvp->v_type != VDIR) { 1935 error = ENOTDIR; 1936 goto out; 1937 } else if (fvp->v_type != VDIR && tvp->v_type == VDIR) { 1938 error = EISDIR; 1939 goto out; 1940 } 1941 } 1942 if (fvp == tdvp) 1943 error = EINVAL; 1944 /* 1945 * If source is the same as the destination (that is the 1946 * same inode number with the same name in the same directory), 1947 * then there is nothing to do. 1948 */ 1949 if (fvp == tvp && fromnd.ni_dvp == tdvp && 1950 fromnd.ni_cnd.cn_namelen == tond.ni_cnd.cn_namelen && 1951 !bcmp(fromnd.ni_cnd.cn_nameptr, tond.ni_cnd.cn_nameptr, 1952 fromnd.ni_cnd.cn_namelen)) 1953 error = -1; 1954 out: 1955 if (!error) { 1956 VOP_LEASE(tdvp, p, p->p_ucred, LEASE_WRITE); 1957 if (fromnd.ni_dvp != tdvp) 1958 VOP_LEASE(fromnd.ni_dvp, p, p->p_ucred, LEASE_WRITE); 1959 if (tvp) 1960 VOP_LEASE(tvp, p, p->p_ucred, LEASE_WRITE); 1961 error = VOP_RENAME(fromnd.ni_dvp, fromnd.ni_vp, &fromnd.ni_cnd, 1962 tond.ni_dvp, tond.ni_vp, &tond.ni_cnd); 1963 } else { 1964 VOP_ABORTOP(tond.ni_dvp, &tond.ni_cnd); 1965 if (tdvp == tvp) 1966 vrele(tdvp); 1967 else 1968 vput(tdvp); 1969 if (tvp) 1970 vput(tvp); 1971 VOP_ABORTOP(fromnd.ni_dvp, &fromnd.ni_cnd); 1972 vrele(fromnd.ni_dvp); 1973 vrele(fvp); 1974 } 1975 vrele(tond.ni_startdir); 1976 FREE(tond.ni_cnd.cn_pnbuf, M_NAMEI); 1977 out1: 1978 if (fromnd.ni_startdir) 1979 vrele(fromnd.ni_startdir); 1980 FREE(fromnd.ni_cnd.cn_pnbuf, M_NAMEI); 1981 if (error == -1) 1982 return (0); 1983 return (error); 1984 } 1985 1986 /* 1987 * Make a directory file. 1988 */ 1989 /* ARGSUSED */ 1990 int 1991 mkdir(p, uap, retval) 1992 struct proc *p; 1993 register struct mkdir_args /* { 1994 syscallarg(char *) path; 1995 syscallarg(int) mode; 1996 } */ *uap; 1997 register_t *retval; 1998 { 1999 register struct vnode *vp; 2000 struct vattr vattr; 2001 int error; 2002 struct nameidata nd; 2003 2004 NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, SCARG(uap, path), p); 2005 if (error = namei(&nd)) 2006 return (error); 2007 vp = nd.ni_vp; 2008 if (vp != NULL) { 2009 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); 2010 if (nd.ni_dvp == vp) 2011 vrele(nd.ni_dvp); 2012 else 2013 vput(nd.ni_dvp); 2014 vrele(vp); 2015 return (EEXIST); 2016 } 2017 VATTR_NULL(&vattr); 2018 vattr.va_type = VDIR; 2019 vattr.va_mode = (SCARG(uap, mode) & ACCESSPERMS) &~ p->p_fd->fd_cmask; 2020 VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE); 2021 error = VOP_MKDIR(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr); 2022 if (!error) 2023 vput(nd.ni_vp); 2024 return (error); 2025 } 2026 2027 /* 2028 * Remove a directory file. 2029 */ 2030 /* ARGSUSED */ 2031 int 2032 rmdir(p, uap, retval) 2033 struct proc *p; 2034 struct rmdir_args /* { 2035 syscallarg(char *) path; 2036 } */ *uap; 2037 register_t *retval; 2038 { 2039 register struct vnode *vp; 2040 int error; 2041 struct nameidata nd; 2042 2043 NDINIT(&nd, DELETE, LOCKPARENT | LOCKLEAF, UIO_USERSPACE, 2044 SCARG(uap, path), p); 2045 if (error = namei(&nd)) 2046 return (error); 2047 vp = nd.ni_vp; 2048 if (vp->v_type != VDIR) { 2049 error = ENOTDIR; 2050 goto out; 2051 } 2052 /* 2053 * No rmdir "." please. 2054 */ 2055 if (nd.ni_dvp == vp) { 2056 error = EINVAL; 2057 goto out; 2058 } 2059 /* 2060 * The root of a mounted filesystem cannot be deleted. 2061 */ 2062 if (vp->v_flag & VROOT) 2063 error = EBUSY; 2064 out: 2065 if (!error) { 2066 VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE); 2067 VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE); 2068 error = VOP_RMDIR(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd); 2069 } else { 2070 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); 2071 if (nd.ni_dvp == vp) 2072 vrele(nd.ni_dvp); 2073 else 2074 vput(nd.ni_dvp); 2075 vput(vp); 2076 } 2077 return (error); 2078 } 2079 2080 #ifdef COMPAT_43 2081 /* 2082 * Read a block of directory entries in a file system independent format. 2083 */ 2084 int 2085 compat_43_getdirentries(p, uap, retval) 2086 struct proc *p; 2087 register struct compat_43_getdirentries_args /* { 2088 syscallarg(int) fd; 2089 syscallarg(char *) buf; 2090 syscallarg(u_int) count; 2091 syscallarg(long *) basep; 2092 } */ *uap; 2093 register_t *retval; 2094 { 2095 register struct vnode *vp; 2096 struct file *fp; 2097 struct uio auio, kuio; 2098 struct iovec aiov, kiov; 2099 struct dirent *dp, *edp; 2100 caddr_t dirbuf; 2101 int error, eofflag, readcnt; 2102 long loff; 2103 2104 if (error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) 2105 return (error); 2106 if ((fp->f_flag & FREAD) == 0) 2107 return (EBADF); 2108 vp = (struct vnode *)fp->f_data; 2109 unionread: 2110 if (vp->v_type != VDIR) 2111 return (EINVAL); 2112 aiov.iov_base = SCARG(uap, buf); 2113 aiov.iov_len = SCARG(uap, count); 2114 auio.uio_iov = &aiov; 2115 auio.uio_iovcnt = 1; 2116 auio.uio_rw = UIO_READ; 2117 auio.uio_segflg = UIO_USERSPACE; 2118 auio.uio_procp = p; 2119 auio.uio_resid = SCARG(uap, count); 2120 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); 2121 loff = auio.uio_offset = fp->f_offset; 2122 # if (BYTE_ORDER != LITTLE_ENDIAN) 2123 if (vp->v_mount->mnt_maxsymlinklen <= 0) { 2124 error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, 2125 (int *)0, (u_long *)0); 2126 fp->f_offset = auio.uio_offset; 2127 } else 2128 # endif 2129 { 2130 kuio = auio; 2131 kuio.uio_iov = &kiov; 2132 kuio.uio_segflg = UIO_SYSSPACE; 2133 kiov.iov_len = SCARG(uap, count); 2134 MALLOC(dirbuf, caddr_t, SCARG(uap, count), M_TEMP, M_WAITOK); 2135 kiov.iov_base = dirbuf; 2136 error = VOP_READDIR(vp, &kuio, fp->f_cred, &eofflag, 2137 (int *)0, (u_long *)0); 2138 fp->f_offset = kuio.uio_offset; 2139 if (error == 0) { 2140 readcnt = SCARG(uap, count) - kuio.uio_resid; 2141 edp = (struct dirent *)&dirbuf[readcnt]; 2142 for (dp = (struct dirent *)dirbuf; dp < edp; ) { 2143 # if (BYTE_ORDER == LITTLE_ENDIAN) 2144 /* 2145 * The expected low byte of 2146 * dp->d_namlen is our dp->d_type. 2147 * The high MBZ byte of dp->d_namlen 2148 * is our dp->d_namlen. 2149 */ 2150 dp->d_type = dp->d_namlen; 2151 dp->d_namlen = 0; 2152 # else 2153 /* 2154 * The dp->d_type is the high byte 2155 * of the expected dp->d_namlen, 2156 * so must be zero'ed. 2157 */ 2158 dp->d_type = 0; 2159 # endif 2160 if (dp->d_reclen > 0) { 2161 dp = (struct dirent *) 2162 ((char *)dp + dp->d_reclen); 2163 } else { 2164 error = EIO; 2165 break; 2166 } 2167 } 2168 if (dp >= edp) 2169 error = uiomove(dirbuf, readcnt, &auio); 2170 } 2171 FREE(dirbuf, M_TEMP); 2172 } 2173 VOP_UNLOCK(vp, 0, p); 2174 if (error) 2175 return (error); 2176 2177 #ifdef UNION 2178 { 2179 extern int (**union_vnodeop_p)(); 2180 extern struct vnode *union_dircache __P((struct vnode*, struct proc*)); 2181 2182 if ((SCARG(uap, count) == auio.uio_resid) && 2183 (vp->v_op == union_vnodeop_p)) { 2184 struct vnode *lvp; 2185 2186 lvp = union_dircache(vp, p); 2187 if (lvp != NULLVP) { 2188 struct vattr va; 2189 2190 /* 2191 * If the directory is opaque, 2192 * then don't show lower entries 2193 */ 2194 error = VOP_GETATTR(vp, &va, fp->f_cred, p); 2195 if (va.va_flags & OPAQUE) { 2196 vput(lvp); 2197 lvp = NULL; 2198 } 2199 } 2200 2201 if (lvp != NULLVP) { 2202 error = VOP_OPEN(lvp, FREAD, fp->f_cred, p); 2203 if (error) { 2204 vput(lvp); 2205 return (error); 2206 } 2207 VOP_UNLOCK(lvp, 0, p); 2208 fp->f_data = (caddr_t) lvp; 2209 fp->f_offset = 0; 2210 error = vn_close(vp, FREAD, fp->f_cred, p); 2211 if (error) 2212 return (error); 2213 vp = lvp; 2214 goto unionread; 2215 } 2216 } 2217 } 2218 #endif /* UNION */ 2219 2220 if ((SCARG(uap, count) == auio.uio_resid) && 2221 (vp->v_flag & VROOT) && 2222 (vp->v_mount->mnt_flag & MNT_UNION)) { 2223 struct vnode *tvp = vp; 2224 vp = vp->v_mount->mnt_vnodecovered; 2225 VREF(vp); 2226 fp->f_data = (caddr_t) vp; 2227 fp->f_offset = 0; 2228 vrele(tvp); 2229 goto unionread; 2230 } 2231 error = copyout((caddr_t)&loff, (caddr_t)SCARG(uap, basep), 2232 sizeof(long)); 2233 *retval = SCARG(uap, count) - auio.uio_resid; 2234 return (error); 2235 } 2236 #endif /* COMPAT_43 */ 2237 2238 /* 2239 * Read a block of directory entries in a file system independent format. 2240 */ 2241 int 2242 getdirentries(p, uap, retval) 2243 struct proc *p; 2244 register struct getdirentries_args /* { 2245 syscallarg(int) fd; 2246 syscallarg(char *) buf; 2247 syscallarg(u_int) count; 2248 syscallarg(long *) basep; 2249 } */ *uap; 2250 register_t *retval; 2251 { 2252 register struct vnode *vp; 2253 struct file *fp; 2254 struct uio auio; 2255 struct iovec aiov; 2256 long loff; 2257 int error, eofflag; 2258 2259 if (error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) 2260 return (error); 2261 if ((fp->f_flag & FREAD) == 0) 2262 return (EBADF); 2263 vp = (struct vnode *)fp->f_data; 2264 unionread: 2265 if (vp->v_type != VDIR) 2266 return (EINVAL); 2267 aiov.iov_base = SCARG(uap, buf); 2268 aiov.iov_len = SCARG(uap, count); 2269 auio.uio_iov = &aiov; 2270 auio.uio_iovcnt = 1; 2271 auio.uio_rw = UIO_READ; 2272 auio.uio_segflg = UIO_USERSPACE; 2273 auio.uio_procp = p; 2274 auio.uio_resid = SCARG(uap, count); 2275 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); 2276 loff = auio.uio_offset = fp->f_offset; 2277 error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, 2278 (int *)0, (u_long *)0); 2279 fp->f_offset = auio.uio_offset; 2280 VOP_UNLOCK(vp, 0, p); 2281 if (error) 2282 return (error); 2283 2284 #ifdef UNION 2285 { 2286 extern int (**union_vnodeop_p)(); 2287 extern struct vnode *union_dircache __P((struct vnode*, struct proc*)); 2288 2289 if ((SCARG(uap, count) == auio.uio_resid) && 2290 (vp->v_op == union_vnodeop_p)) { 2291 struct vnode *lvp; 2292 2293 lvp = union_dircache(vp, p); 2294 if (lvp != NULLVP) { 2295 struct vattr va; 2296 2297 /* 2298 * If the directory is opaque, 2299 * then don't show lower entries 2300 */ 2301 error = VOP_GETATTR(vp, &va, fp->f_cred, p); 2302 if (va.va_flags & OPAQUE) { 2303 vput(lvp); 2304 lvp = NULL; 2305 } 2306 } 2307 2308 if (lvp != NULLVP) { 2309 error = VOP_OPEN(lvp, FREAD, fp->f_cred, p); 2310 if (error) { 2311 vput(lvp); 2312 return (error); 2313 } 2314 VOP_UNLOCK(lvp, 0, p); 2315 fp->f_data = (caddr_t) lvp; 2316 fp->f_offset = 0; 2317 error = vn_close(vp, FREAD, fp->f_cred, p); 2318 if (error) 2319 return (error); 2320 vp = lvp; 2321 goto unionread; 2322 } 2323 } 2324 } 2325 #endif /* UNION */ 2326 2327 if ((SCARG(uap, count) == auio.uio_resid) && 2328 (vp->v_flag & VROOT) && 2329 (vp->v_mount->mnt_flag & MNT_UNION)) { 2330 struct vnode *tvp = vp; 2331 vp = vp->v_mount->mnt_vnodecovered; 2332 VREF(vp); 2333 fp->f_data = (caddr_t) vp; 2334 fp->f_offset = 0; 2335 vrele(tvp); 2336 goto unionread; 2337 } 2338 error = copyout((caddr_t)&loff, (caddr_t)SCARG(uap, basep), 2339 sizeof(long)); 2340 *retval = SCARG(uap, count) - auio.uio_resid; 2341 return (error); 2342 } 2343 2344 /* 2345 * Set the mode mask for creation of filesystem nodes. 2346 */ 2347 int 2348 umask(p, uap, retval) 2349 struct proc *p; 2350 struct umask_args /* { 2351 syscallarg(int) newmask; 2352 } */ *uap; 2353 register_t *retval; 2354 { 2355 register struct filedesc *fdp; 2356 2357 fdp = p->p_fd; 2358 *retval = fdp->fd_cmask; 2359 fdp->fd_cmask = SCARG(uap, newmask) & ALLPERMS; 2360 return (0); 2361 } 2362 2363 /* 2364 * Void all references to file by ripping underlying filesystem 2365 * away from vnode. 2366 */ 2367 /* ARGSUSED */ 2368 int 2369 revoke(p, uap, retval) 2370 struct proc *p; 2371 register struct revoke_args /* { 2372 syscallarg(char *) path; 2373 } */ *uap; 2374 register_t *retval; 2375 { 2376 register struct vnode *vp; 2377 struct vattr vattr; 2378 int error; 2379 struct nameidata nd; 2380 2381 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p); 2382 if (error = namei(&nd)) 2383 return (error); 2384 vp = nd.ni_vp; 2385 if (error = VOP_GETATTR(vp, &vattr, p->p_ucred, p)) 2386 goto out; 2387 if (p->p_ucred->cr_uid != vattr.va_uid && 2388 (error = suser(p->p_ucred, &p->p_acflag))) 2389 goto out; 2390 if (vp->v_usecount > 1 || (vp->v_flag & VALIASED)) 2391 VOP_REVOKE(vp, REVOKEALL); 2392 out: 2393 vrele(vp); 2394 return (error); 2395 } 2396 2397 /* 2398 * Convert a user file descriptor to a kernel file entry. 2399 */ 2400 int 2401 getvnode(fdp, fd, fpp) 2402 struct filedesc *fdp; 2403 struct file **fpp; 2404 int fd; 2405 { 2406 struct file *fp; 2407 2408 if ((u_int)fd >= fdp->fd_nfiles || 2409 (fp = fdp->fd_ofiles[fd]) == NULL) 2410 return (EBADF); 2411 if (fp->f_type != DTYPE_VNODE) 2412 return (EINVAL); 2413 *fpp = fp; 2414 return (0); 2415 } 2416