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