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