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