1 /* 2 * Copyright (c) 1989, 1993 3 * The Regents of the University of California. All rights reserved. 4 * (c) UNIX System Laboratories, Inc. 5 * All or some portions of this file are derived from material licensed 6 * to the University of California by American Telephone and Telegraph 7 * Co. or Unix System Laboratories, Inc. and are reproduced herein with 8 * the permission of UNIX System Laboratories, Inc. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. All advertising materials mentioning features or use of this software 19 * must display the following acknowledgement: 20 * This product includes software developed by the University of 21 * California, Berkeley and its contributors. 22 * 4. Neither the name of the University nor the names of its contributors 23 * may be used to endorse or promote products derived from this software 24 * without specific prior written permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 29 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 30 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 36 * SUCH DAMAGE. 37 * 38 * @(#)vfs_syscalls.c 8.13 (Berkeley) 4/15/94 39 * $Id$ 40 */ 41 42 /* 43 * XXX - The following is required because of some magic done 44 * in getdirentries() below which is only done if the translucent 45 * filesystem `UNION' is compiled into the kernel. This is broken, 46 * but I don't have time to study the code deeply enough to understand 47 * what's going on and determine an appropriate fix. -GAW 48 */ 49 #include "opt_union.h" 50 51 #include <sys/param.h> 52 #include <sys/systm.h> 53 #include <sys/sysent.h> 54 #include <sys/sysproto.h> 55 #include <sys/namei.h> 56 #include <sys/filedesc.h> 57 #include <sys/kernel.h> 58 #include <sys/file.h> 59 #include <sys/stat.h> 60 #include <sys/unistd.h> 61 #include <sys/vnode.h> 62 #include <sys/mount.h> 63 #include <sys/proc.h> 64 #include <sys/uio.h> 65 #include <sys/malloc.h> 66 #include <sys/dirent.h> 67 68 #ifdef UNION 69 #include <miscfs/union/union.h> 70 #endif 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 78 static int change_dir __P((struct nameidata *ndp, struct proc *p)); 79 static 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_ 89 struct mount_args { 90 char *type; 91 char *path; 92 int flags; 93 caddr_t data; 94 }; 95 #endif 96 /* ARGSUSED */ 97 int 98 mount(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; 248 update: 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 */ 304 static void 305 checkdirs(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_ 344 struct unmount_args { 345 char *path; 346 int flags; 347 }; 348 #endif 349 /* ARGSUSED */ 350 int 351 unmount(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 */ 403 int 404 dounmount(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_ 449 struct sync_args { 450 int dummy; 451 }; 452 #endif 453 454 #ifdef DEBUG 455 int syncprt = 0; 456 SYSCTL_INT(_debug, 0, syncprt, CTLFLAG_RW, &syncprt, 0, ""); 457 #endif 458 459 /* ARGSUSED */ 460 int 461 sync(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_ 505 struct quotactl_args { 506 char *path; 507 int cmd; 508 int uid; 509 caddr_t arg; 510 }; 511 #endif 512 /* ARGSUSED */ 513 int 514 quotactl(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_ 541 struct statfs_args { 542 char *path; 543 struct statfs *buf; 544 }; 545 #endif 546 /* ARGSUSED */ 547 int 548 statfs(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_ 578 struct fstatfs_args { 579 int fd; 580 struct statfs *buf; 581 }; 582 #endif 583 /* ARGSUSED */ 584 int 585 fstatfs(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_ 613 struct getfsstat_args { 614 struct statfs *buf; 615 long bufsize; 616 int flags; 617 }; 618 #endif 619 int 620 getfsstat(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_ 682 struct fchdir_args { 683 int fd; 684 }; 685 #endif 686 /* ARGSUSED */ 687 int 688 fchdir(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_ 734 struct chdir_args { 735 char *path; 736 }; 737 #endif 738 /* ARGSUSED */ 739 int 740 chdir(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_ 764 struct chroot_args { 765 char *path; 766 }; 767 #endif 768 /* ARGSUSED */ 769 int 770 chroot(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 */ 797 static int 798 change_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_ 825 struct open_args { 826 char *path; 827 int flags; 828 int mode; 829 }; 830 #endif 831 int 832 open(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_ 911 struct ocreat_args { 912 char *path; 913 int mode; 914 }; 915 #endif 916 int 917 ocreat(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_ 942 struct mknod_args { 943 char *path; 944 int mode; 945 int dev; 946 }; 947 #endif 948 /* ARGSUSED */ 949 int 950 mknod(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_ 1025 struct mkfifo_args { 1026 char *path; 1027 int mode; 1028 }; 1029 #endif 1030 /* ARGSUSED */ 1031 int 1032 mkfifo(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 struct vattr vattr; 1041 int error; 1042 struct nameidata nd; 1043 1044 NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, SCARG(uap, path), p); 1045 if (error = namei(&nd)) 1046 return (error); 1047 if (nd.ni_vp != NULL) { 1048 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); 1049 if (nd.ni_dvp == nd.ni_vp) 1050 vrele(nd.ni_dvp); 1051 else 1052 vput(nd.ni_dvp); 1053 vrele(nd.ni_vp); 1054 return (EEXIST); 1055 } 1056 VATTR_NULL(&vattr); 1057 vattr.va_type = VFIFO; 1058 vattr.va_mode = (SCARG(uap, mode) & ALLPERMS) &~ p->p_fd->fd_cmask; 1059 VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE); 1060 return (VOP_MKNOD(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr)); 1061 } 1062 1063 /* 1064 * Make a hard file link. 1065 */ 1066 #ifndef _SYS_SYSPROTO_H_ 1067 struct link_args { 1068 char *path; 1069 char *link; 1070 }; 1071 #endif 1072 /* ARGSUSED */ 1073 int 1074 link(p, uap, retval) 1075 struct proc *p; 1076 register struct link_args /* { 1077 syscallarg(char *) path; 1078 syscallarg(char *) link; 1079 } */ *uap; 1080 register_t *retval; 1081 { 1082 register struct vnode *vp; 1083 struct nameidata nd; 1084 int error; 1085 1086 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p); 1087 if (error = namei(&nd)) 1088 return (error); 1089 vp = nd.ni_vp; 1090 if (vp->v_type == VDIR) 1091 error = EPERM; /* POSIX */ 1092 else { 1093 NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, SCARG(uap, link), p); 1094 error = namei(&nd); 1095 if (!error) { 1096 if (nd.ni_vp != NULL) { 1097 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); 1098 if (nd.ni_dvp == nd.ni_vp) 1099 vrele(nd.ni_dvp); 1100 else 1101 vput(nd.ni_dvp); 1102 if (nd.ni_vp) 1103 vrele(nd.ni_vp); 1104 error = EEXIST; 1105 } else { 1106 VOP_LEASE(nd.ni_dvp, p, p->p_ucred, 1107 LEASE_WRITE); 1108 VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE); 1109 error = VOP_LINK(nd.ni_dvp, vp, &nd.ni_cnd); 1110 } 1111 } 1112 } 1113 vrele(vp); 1114 return (error); 1115 } 1116 1117 /* 1118 * Make a symbolic link. 1119 */ 1120 #ifndef _SYS_SYSPROTO_H_ 1121 struct symlink_args { 1122 char *path; 1123 char *link; 1124 }; 1125 #endif 1126 /* ARGSUSED */ 1127 int 1128 symlink(p, uap, retval) 1129 struct proc *p; 1130 register struct symlink_args /* { 1131 syscallarg(char *) path; 1132 syscallarg(char *) link; 1133 } */ *uap; 1134 register_t *retval; 1135 { 1136 struct vattr vattr; 1137 char *path; 1138 int error; 1139 struct nameidata nd; 1140 1141 MALLOC(path, char *, MAXPATHLEN, M_NAMEI, M_WAITOK); 1142 if (error = copyinstr(SCARG(uap, path), path, MAXPATHLEN, NULL)) 1143 goto out; 1144 NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, SCARG(uap, link), p); 1145 if (error = namei(&nd)) 1146 goto out; 1147 if (nd.ni_vp) { 1148 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); 1149 if (nd.ni_dvp == nd.ni_vp) 1150 vrele(nd.ni_dvp); 1151 else 1152 vput(nd.ni_dvp); 1153 vrele(nd.ni_vp); 1154 error = EEXIST; 1155 goto out; 1156 } 1157 VATTR_NULL(&vattr); 1158 vattr.va_mode = ACCESSPERMS &~ p->p_fd->fd_cmask; 1159 VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE); 1160 error = VOP_SYMLINK(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr, path); 1161 out: 1162 FREE(path, M_NAMEI); 1163 return (error); 1164 } 1165 1166 /* 1167 * Delete a whiteout from the filesystem. 1168 */ 1169 /* ARGSUSED */ 1170 int 1171 undelete(p, uap, retval) 1172 struct proc *p; 1173 register struct undelete_args /* { 1174 syscallarg(char *) path; 1175 } */ *uap; 1176 register_t *retval; 1177 { 1178 int error; 1179 struct nameidata nd; 1180 1181 NDINIT(&nd, DELETE, LOCKPARENT|DOWHITEOUT, UIO_USERSPACE, 1182 SCARG(uap, path), p); 1183 error = namei(&nd); 1184 if (error) 1185 return (error); 1186 1187 if (nd.ni_vp != NULLVP || !(nd.ni_cnd.cn_flags & ISWHITEOUT)) { 1188 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); 1189 if (nd.ni_dvp == nd.ni_vp) 1190 vrele(nd.ni_dvp); 1191 else 1192 vput(nd.ni_dvp); 1193 if (nd.ni_vp) 1194 vrele(nd.ni_vp); 1195 return (EEXIST); 1196 } 1197 1198 VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE); 1199 if (error = VOP_WHITEOUT(nd.ni_dvp, &nd.ni_cnd, DELETE)) 1200 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); 1201 vput(nd.ni_dvp); 1202 return (error); 1203 } 1204 1205 /* 1206 * Delete a name from the filesystem. 1207 */ 1208 #ifndef _SYS_SYSPROTO_H_ 1209 struct unlink_args { 1210 char *path; 1211 }; 1212 #endif 1213 /* ARGSUSED */ 1214 int 1215 unlink(p, uap, retval) 1216 struct proc *p; 1217 struct unlink_args /* { 1218 syscallarg(char *) path; 1219 } */ *uap; 1220 register_t *retval; 1221 { 1222 register struct vnode *vp; 1223 int error; 1224 struct nameidata nd; 1225 1226 NDINIT(&nd, DELETE, LOCKPARENT, UIO_USERSPACE, SCARG(uap, path), p); 1227 if (error = namei(&nd)) 1228 return (error); 1229 vp = nd.ni_vp; 1230 VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE); 1231 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); 1232 1233 if (vp->v_type == VDIR) 1234 error = EPERM; /* POSIX */ 1235 else { 1236 /* 1237 * The root of a mounted filesystem cannot be deleted. 1238 * 1239 * XXX: can this only be a VDIR case? 1240 */ 1241 if (vp->v_flag & VROOT) 1242 error = EBUSY; 1243 else 1244 (void) vnode_pager_uncache(vp, p); 1245 } 1246 1247 if (!error) { 1248 VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE); 1249 error = VOP_REMOVE(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd); 1250 } else { 1251 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); 1252 if (nd.ni_dvp == vp) 1253 vrele(nd.ni_dvp); 1254 else 1255 vput(nd.ni_dvp); 1256 if (vp != NULLVP) 1257 vput(vp); 1258 } 1259 return (error); 1260 } 1261 1262 /* 1263 * Reposition read/write file offset. 1264 */ 1265 #ifndef _SYS_SYSPROTO_H_ 1266 struct lseek_args { 1267 int fd; 1268 int pad; 1269 off_t offset; 1270 int whence; 1271 }; 1272 #endif 1273 int 1274 lseek(p, uap, retval) 1275 struct proc *p; 1276 register struct lseek_args /* { 1277 syscallarg(int) fd; 1278 syscallarg(int) pad; 1279 syscallarg(off_t) offset; 1280 syscallarg(int) whence; 1281 } */ *uap; 1282 register_t *retval; /* XXX */ 1283 { 1284 struct ucred *cred = p->p_ucred; 1285 register struct filedesc *fdp = p->p_fd; 1286 register struct file *fp; 1287 struct vattr vattr; 1288 int error; 1289 1290 if ((u_int)SCARG(uap, fd) >= fdp->fd_nfiles || 1291 (fp = fdp->fd_ofiles[SCARG(uap, fd)]) == NULL) 1292 return (EBADF); 1293 if (fp->f_type != DTYPE_VNODE) 1294 return (ESPIPE); 1295 switch (SCARG(uap, whence)) { 1296 case L_INCR: 1297 fp->f_offset += SCARG(uap, offset); 1298 break; 1299 case L_XTND: 1300 error=VOP_GETATTR((struct vnode *)fp->f_data, &vattr, cred, p); 1301 if (error) 1302 return (error); 1303 fp->f_offset = SCARG(uap, offset) + vattr.va_size; 1304 break; 1305 case L_SET: 1306 fp->f_offset = SCARG(uap, offset); 1307 break; 1308 default: 1309 return (EINVAL); 1310 } 1311 *(off_t *)retval = fp->f_offset; 1312 return (0); 1313 } 1314 1315 #if defined(COMPAT_43) || defined(COMPAT_SUNOS) 1316 /* 1317 * Reposition read/write file offset. 1318 */ 1319 #ifndef _SYS_SYSPROTO_H_ 1320 struct olseek_args { 1321 int fd; 1322 long offset; 1323 int whence; 1324 }; 1325 #endif 1326 int 1327 olseek(p, uap, retval) 1328 struct proc *p; 1329 register struct olseek_args /* { 1330 syscallarg(int) fd; 1331 syscallarg(long) offset; 1332 syscallarg(int) whence; 1333 } */ *uap; 1334 register_t *retval; 1335 { 1336 struct lseek_args /* { 1337 syscallarg(int) fd; 1338 syscallarg(int) pad; 1339 syscallarg(off_t) offset; 1340 syscallarg(int) whence; 1341 } */ nuap; 1342 off_t qret; 1343 int error; 1344 1345 SCARG(&nuap, fd) = SCARG(uap, fd); 1346 SCARG(&nuap, offset) = SCARG(uap, offset); 1347 SCARG(&nuap, whence) = SCARG(uap, whence); 1348 error = lseek(p, &nuap, (register_t *) &qret); 1349 *(long *)retval = qret; 1350 return (error); 1351 } 1352 #endif /* COMPAT_43 */ 1353 1354 /* 1355 * Check access permissions. 1356 */ 1357 #ifndef _SYS_SYSPROTO_H_ 1358 struct access_args { 1359 char *path; 1360 int flags; 1361 }; 1362 #endif 1363 int 1364 access(p, uap, retval) 1365 struct proc *p; 1366 register struct access_args /* { 1367 syscallarg(char *) path; 1368 syscallarg(int) flags; 1369 } */ *uap; 1370 register_t *retval; 1371 { 1372 register struct ucred *cred = p->p_ucred; 1373 register struct vnode *vp; 1374 int error, flags, t_gid, t_uid; 1375 struct nameidata nd; 1376 1377 t_uid = cred->cr_uid; 1378 t_gid = cred->cr_groups[0]; 1379 cred->cr_uid = p->p_cred->p_ruid; 1380 cred->cr_groups[0] = p->p_cred->p_rgid; 1381 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, 1382 SCARG(uap, path), p); 1383 if (error = namei(&nd)) 1384 goto out1; 1385 vp = nd.ni_vp; 1386 1387 /* Flags == 0 means only check for existence. */ 1388 if (SCARG(uap, flags)) { 1389 flags = 0; 1390 if (SCARG(uap, flags) & R_OK) 1391 flags |= VREAD; 1392 if (SCARG(uap, flags) & W_OK) 1393 flags |= VWRITE; 1394 if (SCARG(uap, flags) & X_OK) 1395 flags |= VEXEC; 1396 if ((flags & VWRITE) == 0 || (error = vn_writechk(vp)) == 0) 1397 error = VOP_ACCESS(vp, flags, cred, p); 1398 } 1399 vput(vp); 1400 out1: 1401 cred->cr_uid = t_uid; 1402 cred->cr_groups[0] = t_gid; 1403 return (error); 1404 } 1405 1406 #if defined(COMPAT_43) || defined(COMPAT_SUNOS) 1407 /* 1408 * Get file status; this version follows links. 1409 */ 1410 #ifndef _SYS_SYSPROTO_H_ 1411 struct ostat_args { 1412 char *path; 1413 struct ostat *ub; 1414 }; 1415 #endif 1416 /* ARGSUSED */ 1417 int 1418 ostat(p, uap, retval) 1419 struct proc *p; 1420 register struct ostat_args /* { 1421 syscallarg(char *) path; 1422 syscallarg(struct ostat *) ub; 1423 } */ *uap; 1424 register_t *retval; 1425 { 1426 struct stat sb; 1427 struct ostat osb; 1428 int error; 1429 struct nameidata nd; 1430 1431 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, 1432 SCARG(uap, path), p); 1433 if (error = namei(&nd)) 1434 return (error); 1435 error = vn_stat(nd.ni_vp, &sb, p); 1436 vput(nd.ni_vp); 1437 if (error) 1438 return (error); 1439 cvtstat(&sb, &osb); 1440 error = copyout((caddr_t)&osb, (caddr_t)SCARG(uap, ub), sizeof (osb)); 1441 return (error); 1442 } 1443 1444 /* 1445 * Get file status; this version does not follow links. 1446 */ 1447 #ifndef _SYS_SYSPROTO_H_ 1448 struct olstat_args { 1449 char *path; 1450 struct ostat *ub; 1451 }; 1452 #endif 1453 /* ARGSUSED */ 1454 int 1455 olstat(p, uap, retval) 1456 struct proc *p; 1457 register struct olstat_args /* { 1458 syscallarg(char *) path; 1459 syscallarg(struct ostat *) ub; 1460 } */ *uap; 1461 register_t *retval; 1462 { 1463 struct vnode *vp, *dvp; 1464 struct stat sb, sb1; 1465 struct ostat osb; 1466 int error; 1467 struct nameidata nd; 1468 1469 NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF | LOCKPARENT, UIO_USERSPACE, 1470 SCARG(uap, path), p); 1471 if (error = namei(&nd)) 1472 return (error); 1473 /* 1474 * For symbolic links, always return the attributes of its 1475 * containing directory, except for mode, size, and links. 1476 */ 1477 vp = nd.ni_vp; 1478 dvp = nd.ni_dvp; 1479 if (vp->v_type != VLNK) { 1480 if (dvp == vp) 1481 vrele(dvp); 1482 else 1483 vput(dvp); 1484 error = vn_stat(vp, &sb, p); 1485 vput(vp); 1486 if (error) 1487 return (error); 1488 } else { 1489 error = vn_stat(dvp, &sb, p); 1490 vput(dvp); 1491 if (error) { 1492 vput(vp); 1493 return (error); 1494 } 1495 error = vn_stat(vp, &sb1, p); 1496 vput(vp); 1497 if (error) 1498 return (error); 1499 sb.st_mode &= ~S_IFDIR; 1500 sb.st_mode |= S_IFLNK; 1501 sb.st_nlink = sb1.st_nlink; 1502 sb.st_size = sb1.st_size; 1503 sb.st_blocks = sb1.st_blocks; 1504 } 1505 cvtstat(&sb, &osb); 1506 error = copyout((caddr_t)&osb, (caddr_t)SCARG(uap, ub), sizeof (osb)); 1507 return (error); 1508 } 1509 1510 /* 1511 * Convert from an old to a new stat structure. 1512 */ 1513 void 1514 cvtstat(st, ost) 1515 struct stat *st; 1516 struct ostat *ost; 1517 { 1518 1519 ost->st_dev = st->st_dev; 1520 ost->st_ino = st->st_ino; 1521 ost->st_mode = st->st_mode; 1522 ost->st_nlink = st->st_nlink; 1523 ost->st_uid = st->st_uid; 1524 ost->st_gid = st->st_gid; 1525 ost->st_rdev = st->st_rdev; 1526 if (st->st_size < (quad_t)1 << 32) 1527 ost->st_size = st->st_size; 1528 else 1529 ost->st_size = -2; 1530 ost->st_atime = st->st_atime; 1531 ost->st_mtime = st->st_mtime; 1532 ost->st_ctime = st->st_ctime; 1533 ost->st_blksize = st->st_blksize; 1534 ost->st_blocks = st->st_blocks; 1535 ost->st_flags = st->st_flags; 1536 ost->st_gen = st->st_gen; 1537 } 1538 #endif /* COMPAT_43 || COMPAT_SUNOS */ 1539 1540 /* 1541 * Get file status; this version follows links. 1542 */ 1543 #ifndef _SYS_SYSPROTO_H_ 1544 struct stat_args { 1545 char *path; 1546 struct stat *ub; 1547 }; 1548 #endif 1549 /* ARGSUSED */ 1550 int 1551 stat(p, uap, retval) 1552 struct proc *p; 1553 register struct stat_args /* { 1554 syscallarg(char *) path; 1555 syscallarg(struct stat *) ub; 1556 } */ *uap; 1557 register_t *retval; 1558 { 1559 struct stat sb; 1560 int error; 1561 struct nameidata nd; 1562 1563 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, 1564 SCARG(uap, path), p); 1565 if (error = namei(&nd)) 1566 return (error); 1567 error = vn_stat(nd.ni_vp, &sb, p); 1568 vput(nd.ni_vp); 1569 if (error) 1570 return (error); 1571 error = copyout((caddr_t)&sb, (caddr_t)SCARG(uap, ub), sizeof (sb)); 1572 return (error); 1573 } 1574 1575 /* 1576 * Get file status; this version does not follow links. 1577 */ 1578 #ifndef _SYS_SYSPROTO_H_ 1579 struct lstat_args { 1580 char *path; 1581 struct stat *ub; 1582 }; 1583 #endif 1584 /* ARGSUSED */ 1585 int 1586 lstat(p, uap, retval) 1587 struct proc *p; 1588 register struct lstat_args /* { 1589 syscallarg(char *) path; 1590 syscallarg(struct stat *) ub; 1591 } */ *uap; 1592 register_t *retval; 1593 { 1594 int error; 1595 struct vnode *vp, *dvp; 1596 struct stat sb, sb1; 1597 struct nameidata nd; 1598 1599 NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF | LOCKPARENT, UIO_USERSPACE, 1600 SCARG(uap, path), p); 1601 if (error = namei(&nd)) 1602 return (error); 1603 /* 1604 * For symbolic links, always return the attributes of its containing 1605 * directory, except for mode, size, inode number, and links. 1606 */ 1607 vp = nd.ni_vp; 1608 dvp = nd.ni_dvp; 1609 if (vp->v_type != VLNK) { 1610 if (dvp == vp) 1611 vrele(dvp); 1612 else 1613 vput(dvp); 1614 error = vn_stat(vp, &sb, p); 1615 vput(vp); 1616 if (error) 1617 return (error); 1618 } else { 1619 error = vn_stat(dvp, &sb, p); 1620 vput(dvp); 1621 if (error) { 1622 vput(vp); 1623 return (error); 1624 } 1625 error = vn_stat(vp, &sb1, p); 1626 vput(vp); 1627 if (error) 1628 return (error); 1629 sb.st_mode &= ~S_IFDIR; 1630 sb.st_mode |= S_IFLNK; 1631 sb.st_nlink = sb1.st_nlink; 1632 sb.st_size = sb1.st_size; 1633 sb.st_blocks = sb1.st_blocks; 1634 sb.st_ino = sb1.st_ino; 1635 } 1636 error = copyout((caddr_t)&sb, (caddr_t)SCARG(uap, ub), sizeof (sb)); 1637 return (error); 1638 } 1639 1640 /* 1641 * Get configurable pathname variables. 1642 */ 1643 #ifndef _SYS_SYSPROTO_H_ 1644 struct pathconf_args { 1645 char *path; 1646 int name; 1647 }; 1648 #endif 1649 /* ARGSUSED */ 1650 int 1651 pathconf(p, uap, retval) 1652 struct proc *p; 1653 register struct pathconf_args /* { 1654 syscallarg(char *) path; 1655 syscallarg(int) name; 1656 } */ *uap; 1657 register_t *retval; 1658 { 1659 int error; 1660 struct nameidata nd; 1661 1662 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, 1663 SCARG(uap, path), p); 1664 if (error = namei(&nd)) 1665 return (error); 1666 error = VOP_PATHCONF(nd.ni_vp, SCARG(uap, name), retval); 1667 vput(nd.ni_vp); 1668 return (error); 1669 } 1670 1671 /* 1672 * Return target name of a symbolic link. 1673 */ 1674 #ifndef _SYS_SYSPROTO_H_ 1675 struct readlink_args { 1676 char *path; 1677 char *buf; 1678 int count; 1679 }; 1680 #endif 1681 /* ARGSUSED */ 1682 int 1683 readlink(p, uap, retval) 1684 struct proc *p; 1685 register struct readlink_args /* { 1686 syscallarg(char *) path; 1687 syscallarg(char *) buf; 1688 syscallarg(int) count; 1689 } */ *uap; 1690 register_t *retval; 1691 { 1692 register struct vnode *vp; 1693 struct iovec aiov; 1694 struct uio auio; 1695 int error; 1696 struct nameidata nd; 1697 1698 NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF, UIO_USERSPACE, 1699 SCARG(uap, path), p); 1700 if (error = namei(&nd)) 1701 return (error); 1702 vp = nd.ni_vp; 1703 if (vp->v_type != VLNK) 1704 error = EINVAL; 1705 else { 1706 aiov.iov_base = SCARG(uap, buf); 1707 aiov.iov_len = SCARG(uap, count); 1708 auio.uio_iov = &aiov; 1709 auio.uio_iovcnt = 1; 1710 auio.uio_offset = 0; 1711 auio.uio_rw = UIO_READ; 1712 auio.uio_segflg = UIO_USERSPACE; 1713 auio.uio_procp = p; 1714 auio.uio_resid = SCARG(uap, count); 1715 error = VOP_READLINK(vp, &auio, p->p_ucred); 1716 } 1717 vput(vp); 1718 *retval = SCARG(uap, count) - auio.uio_resid; 1719 return (error); 1720 } 1721 1722 /* 1723 * Change flags of a file given a path name. 1724 */ 1725 #ifndef _SYS_SYSPROTO_H_ 1726 struct chflags_args { 1727 char *path; 1728 int flags; 1729 }; 1730 #endif 1731 /* ARGSUSED */ 1732 int 1733 chflags(p, uap, retval) 1734 struct proc *p; 1735 register struct chflags_args /* { 1736 syscallarg(char *) path; 1737 syscallarg(int) flags; 1738 } */ *uap; 1739 register_t *retval; 1740 { 1741 register struct vnode *vp; 1742 struct vattr vattr; 1743 int error; 1744 struct nameidata nd; 1745 1746 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p); 1747 if (error = namei(&nd)) 1748 return (error); 1749 vp = nd.ni_vp; 1750 VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE); 1751 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); 1752 VATTR_NULL(&vattr); 1753 vattr.va_flags = SCARG(uap, flags); 1754 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); 1755 vput(vp); 1756 return (error); 1757 } 1758 1759 /* 1760 * Change flags of a file given a file descriptor. 1761 */ 1762 #ifndef _SYS_SYSPROTO_H_ 1763 struct fchflags_args { 1764 int fd; 1765 int flags; 1766 }; 1767 #endif 1768 /* ARGSUSED */ 1769 int 1770 fchflags(p, uap, retval) 1771 struct proc *p; 1772 register struct fchflags_args /* { 1773 syscallarg(int) fd; 1774 syscallarg(int) flags; 1775 } */ *uap; 1776 register_t *retval; 1777 { 1778 struct vattr vattr; 1779 struct vnode *vp; 1780 struct file *fp; 1781 int error; 1782 1783 if (error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) 1784 return (error); 1785 vp = (struct vnode *)fp->f_data; 1786 VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE); 1787 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); 1788 VATTR_NULL(&vattr); 1789 vattr.va_flags = SCARG(uap, flags); 1790 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); 1791 VOP_UNLOCK(vp, 0, p); 1792 return (error); 1793 } 1794 1795 /* 1796 * Change mode of a file given path name. 1797 */ 1798 #ifndef _SYS_SYSPROTO_H_ 1799 struct chmod_args { 1800 char *path; 1801 int mode; 1802 }; 1803 #endif 1804 /* ARGSUSED */ 1805 int 1806 chmod(p, uap, retval) 1807 struct proc *p; 1808 register struct chmod_args /* { 1809 syscallarg(char *) path; 1810 syscallarg(int) mode; 1811 } */ *uap; 1812 register_t *retval; 1813 { 1814 register struct vnode *vp; 1815 struct vattr vattr; 1816 int error; 1817 struct nameidata nd; 1818 1819 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p); 1820 if (error = namei(&nd)) 1821 return (error); 1822 vp = nd.ni_vp; 1823 VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE); 1824 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); 1825 VATTR_NULL(&vattr); 1826 vattr.va_mode = SCARG(uap, mode) & ALLPERMS; 1827 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); 1828 vput(vp); 1829 return (error); 1830 } 1831 1832 /* 1833 * Change mode of a file given a file descriptor. 1834 */ 1835 #ifndef _SYS_SYSPROTO_H_ 1836 struct fchmod_args { 1837 int fd; 1838 int mode; 1839 }; 1840 #endif 1841 /* ARGSUSED */ 1842 int 1843 fchmod(p, uap, retval) 1844 struct proc *p; 1845 register struct fchmod_args /* { 1846 syscallarg(int) fd; 1847 syscallarg(int) mode; 1848 } */ *uap; 1849 register_t *retval; 1850 { 1851 struct vattr vattr; 1852 struct vnode *vp; 1853 struct file *fp; 1854 int error; 1855 1856 if (error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) 1857 return (error); 1858 vp = (struct vnode *)fp->f_data; 1859 VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE); 1860 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); 1861 VATTR_NULL(&vattr); 1862 vattr.va_mode = SCARG(uap, mode) & ALLPERMS; 1863 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); 1864 VOP_UNLOCK(vp, 0, p); 1865 return (error); 1866 } 1867 1868 /* 1869 * Set ownership given a path name. 1870 */ 1871 #ifndef _SYS_SYSPROTO_H_ 1872 struct chown_args { 1873 char *path; 1874 int uid; 1875 int gid; 1876 }; 1877 #endif 1878 /* ARGSUSED */ 1879 int 1880 chown(p, uap, retval) 1881 struct proc *p; 1882 register struct chown_args /* { 1883 syscallarg(char *) path; 1884 syscallarg(int) uid; 1885 syscallarg(int) gid; 1886 } */ *uap; 1887 register_t *retval; 1888 { 1889 register struct vnode *vp; 1890 struct vattr vattr; 1891 int error; 1892 struct nameidata nd; 1893 1894 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p); 1895 if (error = namei(&nd)) 1896 return (error); 1897 vp = nd.ni_vp; 1898 VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE); 1899 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); 1900 VATTR_NULL(&vattr); 1901 vattr.va_uid = SCARG(uap, uid); 1902 vattr.va_gid = SCARG(uap, gid); 1903 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); 1904 vput(vp); 1905 return (error); 1906 } 1907 1908 /* 1909 * Set ownership given a file descriptor. 1910 */ 1911 #ifndef _SYS_SYSPROTO_H_ 1912 struct fchown_args { 1913 int fd; 1914 int uid; 1915 int gid; 1916 }; 1917 #endif 1918 /* ARGSUSED */ 1919 int 1920 fchown(p, uap, retval) 1921 struct proc *p; 1922 register struct fchown_args /* { 1923 syscallarg(int) fd; 1924 syscallarg(int) uid; 1925 syscallarg(int) gid; 1926 } */ *uap; 1927 register_t *retval; 1928 { 1929 struct vattr vattr; 1930 struct vnode *vp; 1931 struct file *fp; 1932 int error; 1933 1934 if (error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) 1935 return (error); 1936 vp = (struct vnode *)fp->f_data; 1937 VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE); 1938 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); 1939 VATTR_NULL(&vattr); 1940 vattr.va_uid = SCARG(uap, uid); 1941 vattr.va_gid = SCARG(uap, gid); 1942 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); 1943 VOP_UNLOCK(vp, 0, p); 1944 return (error); 1945 } 1946 1947 /* 1948 * Set the access and modification times of a file. 1949 */ 1950 #ifndef _SYS_SYSPROTO_H_ 1951 struct utimes_args { 1952 char *path; 1953 struct timeval *tptr; 1954 }; 1955 #endif 1956 /* ARGSUSED */ 1957 int 1958 utimes(p, uap, retval) 1959 struct proc *p; 1960 register struct utimes_args /* { 1961 syscallarg(char *) path; 1962 syscallarg(struct timeval *) tptr; 1963 } */ *uap; 1964 register_t *retval; 1965 { 1966 register struct vnode *vp; 1967 struct timeval tv[2]; 1968 struct vattr vattr; 1969 int error; 1970 struct nameidata nd; 1971 1972 VATTR_NULL(&vattr); 1973 if (SCARG(uap, tptr) == NULL) { 1974 microtime(&tv[0]); 1975 tv[1] = tv[0]; 1976 vattr.va_vaflags |= VA_UTIMES_NULL; 1977 } else if (error = copyin((caddr_t)SCARG(uap, tptr), (caddr_t)tv, 1978 sizeof (tv))) 1979 return (error); 1980 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p); 1981 if (error = namei(&nd)) 1982 return (error); 1983 vp = nd.ni_vp; 1984 VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE); 1985 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); 1986 vattr.va_atime.tv_sec = tv[0].tv_sec; 1987 vattr.va_atime.tv_nsec = tv[0].tv_usec * 1000; 1988 vattr.va_mtime.tv_sec = tv[1].tv_sec; 1989 vattr.va_mtime.tv_nsec = tv[1].tv_usec * 1000; 1990 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); 1991 vput(vp); 1992 return (error); 1993 } 1994 1995 /* 1996 * Truncate a file given its path name. 1997 */ 1998 #ifndef _SYS_SYSPROTO_H_ 1999 struct truncate_args { 2000 char *path; 2001 int pad; 2002 off_t length; 2003 }; 2004 #endif 2005 /* ARGSUSED */ 2006 int 2007 truncate(p, uap, retval) 2008 struct proc *p; 2009 register struct truncate_args /* { 2010 syscallarg(char *) path; 2011 syscallarg(int) pad; 2012 syscallarg(off_t) length; 2013 } */ *uap; 2014 register_t *retval; 2015 { 2016 register struct vnode *vp; 2017 struct vattr vattr; 2018 int error; 2019 struct nameidata nd; 2020 2021 if (uap->length < 0) 2022 return(EINVAL); 2023 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p); 2024 if (error = namei(&nd)) 2025 return (error); 2026 vp = nd.ni_vp; 2027 VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE); 2028 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); 2029 if (vp->v_type == VDIR) 2030 error = EISDIR; 2031 else if ((error = vn_writechk(vp)) == 0 && 2032 (error = VOP_ACCESS(vp, VWRITE, p->p_ucred, p)) == 0) { 2033 VATTR_NULL(&vattr); 2034 vattr.va_size = SCARG(uap, length); 2035 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); 2036 } 2037 vput(vp); 2038 return (error); 2039 } 2040 2041 /* 2042 * Truncate a file given a file descriptor. 2043 */ 2044 #ifndef _SYS_SYSPROTO_H_ 2045 struct ftruncate_args { 2046 int fd; 2047 int pad; 2048 off_t length; 2049 }; 2050 #endif 2051 /* ARGSUSED */ 2052 int 2053 ftruncate(p, uap, retval) 2054 struct proc *p; 2055 register struct ftruncate_args /* { 2056 syscallarg(int) fd; 2057 syscallarg(int) pad; 2058 syscallarg(off_t) length; 2059 } */ *uap; 2060 register_t *retval; 2061 { 2062 struct vattr vattr; 2063 struct vnode *vp; 2064 struct file *fp; 2065 int error; 2066 2067 if (uap->length < 0) 2068 return(EINVAL); 2069 if (error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) 2070 return (error); 2071 if ((fp->f_flag & FWRITE) == 0) 2072 return (EINVAL); 2073 vp = (struct vnode *)fp->f_data; 2074 VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE); 2075 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); 2076 if (vp->v_type == VDIR) 2077 error = EISDIR; 2078 else if ((error = vn_writechk(vp)) == 0) { 2079 VATTR_NULL(&vattr); 2080 vattr.va_size = SCARG(uap, length); 2081 error = VOP_SETATTR(vp, &vattr, fp->f_cred, p); 2082 } 2083 VOP_UNLOCK(vp, 0, p); 2084 return (error); 2085 } 2086 2087 #if defined(COMPAT_43) || defined(COMPAT_SUNOS) 2088 /* 2089 * Truncate a file given its path name. 2090 */ 2091 #ifndef _SYS_SYSPROTO_H_ 2092 struct otruncate_args { 2093 char *path; 2094 long length; 2095 }; 2096 #endif 2097 /* ARGSUSED */ 2098 int 2099 otruncate(p, uap, retval) 2100 struct proc *p; 2101 register struct otruncate_args /* { 2102 syscallarg(char *) path; 2103 syscallarg(long) length; 2104 } */ *uap; 2105 register_t *retval; 2106 { 2107 struct truncate_args /* { 2108 syscallarg(char *) path; 2109 syscallarg(int) pad; 2110 syscallarg(off_t) length; 2111 } */ nuap; 2112 2113 SCARG(&nuap, path) = SCARG(uap, path); 2114 SCARG(&nuap, length) = SCARG(uap, length); 2115 return (truncate(p, &nuap, retval)); 2116 } 2117 2118 /* 2119 * Truncate a file given a file descriptor. 2120 */ 2121 #ifndef _SYS_SYSPROTO_H_ 2122 struct oftruncate_args { 2123 int fd; 2124 long length; 2125 }; 2126 #endif 2127 /* ARGSUSED */ 2128 int 2129 oftruncate(p, uap, retval) 2130 struct proc *p; 2131 register struct oftruncate_args /* { 2132 syscallarg(int) fd; 2133 syscallarg(long) length; 2134 } */ *uap; 2135 register_t *retval; 2136 { 2137 struct ftruncate_args /* { 2138 syscallarg(int) fd; 2139 syscallarg(int) pad; 2140 syscallarg(off_t) length; 2141 } */ nuap; 2142 2143 SCARG(&nuap, fd) = SCARG(uap, fd); 2144 SCARG(&nuap, length) = SCARG(uap, length); 2145 return (ftruncate(p, &nuap, retval)); 2146 } 2147 #endif /* COMPAT_43 || COMPAT_SUNOS */ 2148 2149 /* 2150 * Sync an open file. 2151 */ 2152 #ifndef _SYS_SYSPROTO_H_ 2153 struct fsync_args { 2154 int fd; 2155 }; 2156 #endif 2157 /* ARGSUSED */ 2158 int 2159 fsync(p, uap, retval) 2160 struct proc *p; 2161 struct fsync_args /* { 2162 syscallarg(int) fd; 2163 } */ *uap; 2164 register_t *retval; 2165 { 2166 register struct vnode *vp; 2167 struct file *fp; 2168 int error; 2169 2170 if (error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) 2171 return (error); 2172 vp = (struct vnode *)fp->f_data; 2173 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); 2174 if (vp->v_object) { 2175 vm_object_page_clean(vp->v_object, 0, 0 ,0, FALSE); 2176 } 2177 error = VOP_FSYNC(vp, fp->f_cred, 2178 (vp->v_mount->mnt_flag & MNT_ASYNC) ? MNT_NOWAIT : MNT_WAIT, p); 2179 VOP_UNLOCK(vp, 0, p); 2180 return (error); 2181 } 2182 2183 /* 2184 * Rename files. Source and destination must either both be directories, 2185 * or both not be directories. If target is a directory, it must be empty. 2186 */ 2187 #ifndef _SYS_SYSPROTO_H_ 2188 struct rename_args { 2189 char *from; 2190 char *to; 2191 }; 2192 #endif 2193 /* ARGSUSED */ 2194 int 2195 rename(p, uap, retval) 2196 struct proc *p; 2197 register struct rename_args /* { 2198 syscallarg(char *) from; 2199 syscallarg(char *) to; 2200 } */ *uap; 2201 register_t *retval; 2202 { 2203 register struct vnode *tvp, *fvp, *tdvp; 2204 struct nameidata fromnd, tond; 2205 int error; 2206 2207 NDINIT(&fromnd, DELETE, WANTPARENT | SAVESTART, UIO_USERSPACE, 2208 SCARG(uap, from), p); 2209 if (error = namei(&fromnd)) 2210 return (error); 2211 fvp = fromnd.ni_vp; 2212 NDINIT(&tond, RENAME, LOCKPARENT | LOCKLEAF | NOCACHE | SAVESTART, 2213 UIO_USERSPACE, SCARG(uap, to), p); 2214 if (fromnd.ni_vp->v_type == VDIR) 2215 tond.ni_cnd.cn_flags |= WILLBEDIR; 2216 if (error = namei(&tond)) { 2217 /* Translate error code for rename("dir1", "dir2/."). */ 2218 if (error == EISDIR && fvp->v_type == VDIR) 2219 error = EINVAL; 2220 VOP_ABORTOP(fromnd.ni_dvp, &fromnd.ni_cnd); 2221 vrele(fromnd.ni_dvp); 2222 vrele(fvp); 2223 goto out1; 2224 } 2225 tdvp = tond.ni_dvp; 2226 tvp = tond.ni_vp; 2227 if (tvp != NULL) { 2228 if (fvp->v_type == VDIR && tvp->v_type != VDIR) { 2229 error = ENOTDIR; 2230 goto out; 2231 } else if (fvp->v_type != VDIR && tvp->v_type == VDIR) { 2232 error = EISDIR; 2233 goto out; 2234 } 2235 } 2236 if (fvp == tdvp) 2237 error = EINVAL; 2238 /* 2239 * If source is the same as the destination (that is the 2240 * same inode number with the same name in the same directory), 2241 * then there is nothing to do. 2242 */ 2243 if (fvp == tvp && fromnd.ni_dvp == tdvp && 2244 fromnd.ni_cnd.cn_namelen == tond.ni_cnd.cn_namelen && 2245 !bcmp(fromnd.ni_cnd.cn_nameptr, tond.ni_cnd.cn_nameptr, 2246 fromnd.ni_cnd.cn_namelen)) 2247 error = -1; 2248 out: 2249 if (!error) { 2250 VOP_LEASE(tdvp, p, p->p_ucred, LEASE_WRITE); 2251 if (fromnd.ni_dvp != tdvp) 2252 VOP_LEASE(fromnd.ni_dvp, p, p->p_ucred, LEASE_WRITE); 2253 if (tvp) { 2254 VOP_LEASE(tvp, p, p->p_ucred, LEASE_WRITE); 2255 (void) vnode_pager_uncache(tvp, p); 2256 } 2257 error = VOP_RENAME(fromnd.ni_dvp, fromnd.ni_vp, &fromnd.ni_cnd, 2258 tond.ni_dvp, tond.ni_vp, &tond.ni_cnd); 2259 } else { 2260 VOP_ABORTOP(tond.ni_dvp, &tond.ni_cnd); 2261 if (tdvp == tvp) 2262 vrele(tdvp); 2263 else 2264 vput(tdvp); 2265 if (tvp) 2266 vput(tvp); 2267 VOP_ABORTOP(fromnd.ni_dvp, &fromnd.ni_cnd); 2268 vrele(fromnd.ni_dvp); 2269 vrele(fvp); 2270 } 2271 vrele(tond.ni_startdir); 2272 FREE(tond.ni_cnd.cn_pnbuf, M_NAMEI); 2273 out1: 2274 if (fromnd.ni_startdir) 2275 vrele(fromnd.ni_startdir); 2276 FREE(fromnd.ni_cnd.cn_pnbuf, M_NAMEI); 2277 if (error == -1) 2278 return (0); 2279 return (error); 2280 } 2281 2282 /* 2283 * Make a directory file. 2284 */ 2285 #ifndef _SYS_SYSPROTO_H_ 2286 struct mkdir_args { 2287 char *path; 2288 int mode; 2289 }; 2290 #endif 2291 /* ARGSUSED */ 2292 int 2293 mkdir(p, uap, retval) 2294 struct proc *p; 2295 register struct mkdir_args /* { 2296 syscallarg(char *) path; 2297 syscallarg(int) mode; 2298 } */ *uap; 2299 register_t *retval; 2300 { 2301 register struct vnode *vp; 2302 struct vattr vattr; 2303 int error; 2304 struct nameidata nd; 2305 2306 NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, SCARG(uap, path), p); 2307 nd.ni_cnd.cn_flags |= WILLBEDIR; 2308 if (error = namei(&nd)) 2309 return (error); 2310 vp = nd.ni_vp; 2311 if (vp != NULL) { 2312 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); 2313 if (nd.ni_dvp == vp) 2314 vrele(nd.ni_dvp); 2315 else 2316 vput(nd.ni_dvp); 2317 vrele(vp); 2318 return (EEXIST); 2319 } 2320 VATTR_NULL(&vattr); 2321 vattr.va_type = VDIR; 2322 vattr.va_mode = (SCARG(uap, mode) & ACCESSPERMS) &~ p->p_fd->fd_cmask; 2323 VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE); 2324 error = VOP_MKDIR(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr); 2325 if (!error) 2326 vput(nd.ni_vp); 2327 return (error); 2328 } 2329 2330 /* 2331 * Remove a directory file. 2332 */ 2333 #ifndef _SYS_SYSPROTO_H_ 2334 struct rmdir_args { 2335 char *path; 2336 }; 2337 #endif 2338 /* ARGSUSED */ 2339 int 2340 rmdir(p, uap, retval) 2341 struct proc *p; 2342 struct rmdir_args /* { 2343 syscallarg(char *) path; 2344 } */ *uap; 2345 register_t *retval; 2346 { 2347 register struct vnode *vp; 2348 int error; 2349 struct nameidata nd; 2350 2351 NDINIT(&nd, DELETE, LOCKPARENT | LOCKLEAF, UIO_USERSPACE, 2352 SCARG(uap, path), p); 2353 if (error = namei(&nd)) 2354 return (error); 2355 vp = nd.ni_vp; 2356 if (vp->v_type != VDIR) { 2357 error = ENOTDIR; 2358 goto out; 2359 } 2360 /* 2361 * No rmdir "." please. 2362 */ 2363 if (nd.ni_dvp == vp) { 2364 error = EINVAL; 2365 goto out; 2366 } 2367 /* 2368 * The root of a mounted filesystem cannot be deleted. 2369 */ 2370 if (vp->v_flag & VROOT) 2371 error = EBUSY; 2372 out: 2373 if (!error) { 2374 VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE); 2375 VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE); 2376 error = VOP_RMDIR(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd); 2377 } else { 2378 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); 2379 if (nd.ni_dvp == vp) 2380 vrele(nd.ni_dvp); 2381 else 2382 vput(nd.ni_dvp); 2383 vput(vp); 2384 } 2385 return (error); 2386 } 2387 2388 #ifdef COMPAT_43 2389 /* 2390 * Read a block of directory entries in a file system independent format. 2391 */ 2392 #ifndef _SYS_SYSPROTO_H_ 2393 struct ogetdirentries_args { 2394 int fd; 2395 char *buf; 2396 u_int count; 2397 long *basep; 2398 }; 2399 #endif 2400 int 2401 ogetdirentries(p, uap, retval) 2402 struct proc *p; 2403 register struct ogetdirentries_args /* { 2404 syscallarg(int) fd; 2405 syscallarg(char *) buf; 2406 syscallarg(u_int) count; 2407 syscallarg(long *) basep; 2408 } */ *uap; 2409 register_t *retval; 2410 { 2411 register struct vnode *vp; 2412 struct file *fp; 2413 struct uio auio, kuio; 2414 struct iovec aiov, kiov; 2415 struct dirent *dp, *edp; 2416 caddr_t dirbuf; 2417 int error, eofflag, readcnt; 2418 long loff; 2419 2420 if (error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) 2421 return (error); 2422 if ((fp->f_flag & FREAD) == 0) 2423 return (EBADF); 2424 vp = (struct vnode *)fp->f_data; 2425 unionread: 2426 if (vp->v_type != VDIR) 2427 return (EINVAL); 2428 aiov.iov_base = SCARG(uap, buf); 2429 aiov.iov_len = SCARG(uap, count); 2430 auio.uio_iov = &aiov; 2431 auio.uio_iovcnt = 1; 2432 auio.uio_rw = UIO_READ; 2433 auio.uio_segflg = UIO_USERSPACE; 2434 auio.uio_procp = p; 2435 auio.uio_resid = SCARG(uap, count); 2436 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); 2437 loff = auio.uio_offset = fp->f_offset; 2438 # if (BYTE_ORDER != LITTLE_ENDIAN) 2439 if (vp->v_mount->mnt_maxsymlinklen <= 0) { 2440 error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, 2441 NULL, NULL); 2442 fp->f_offset = auio.uio_offset; 2443 } else 2444 # endif 2445 { 2446 kuio = auio; 2447 kuio.uio_iov = &kiov; 2448 kuio.uio_segflg = UIO_SYSSPACE; 2449 kiov.iov_len = SCARG(uap, count); 2450 MALLOC(dirbuf, caddr_t, SCARG(uap, count), M_TEMP, M_WAITOK); 2451 kiov.iov_base = dirbuf; 2452 error = VOP_READDIR(vp, &kuio, fp->f_cred, &eofflag, 2453 NULL, NULL); 2454 fp->f_offset = kuio.uio_offset; 2455 if (error == 0) { 2456 readcnt = SCARG(uap, count) - kuio.uio_resid; 2457 edp = (struct dirent *)&dirbuf[readcnt]; 2458 for (dp = (struct dirent *)dirbuf; dp < edp; ) { 2459 # if (BYTE_ORDER == LITTLE_ENDIAN) 2460 /* 2461 * The expected low byte of 2462 * dp->d_namlen is our dp->d_type. 2463 * The high MBZ byte of dp->d_namlen 2464 * is our dp->d_namlen. 2465 */ 2466 dp->d_type = dp->d_namlen; 2467 dp->d_namlen = 0; 2468 # else 2469 /* 2470 * The dp->d_type is the high byte 2471 * of the expected dp->d_namlen, 2472 * so must be zero'ed. 2473 */ 2474 dp->d_type = 0; 2475 # endif 2476 if (dp->d_reclen > 0) { 2477 dp = (struct dirent *) 2478 ((char *)dp + dp->d_reclen); 2479 } else { 2480 error = EIO; 2481 break; 2482 } 2483 } 2484 if (dp >= edp) 2485 error = uiomove(dirbuf, readcnt, &auio); 2486 } 2487 FREE(dirbuf, M_TEMP); 2488 } 2489 VOP_UNLOCK(vp, 0, p); 2490 if (error) 2491 return (error); 2492 2493 #ifdef UNION 2494 { 2495 if ((SCARG(uap, count) == auio.uio_resid) && 2496 (vp->v_op == union_vnodeop_p)) { 2497 struct vnode *lvp; 2498 2499 lvp = union_dircache(vp, p); 2500 if (lvp != NULLVP) { 2501 struct vattr va; 2502 2503 /* 2504 * If the directory is opaque, 2505 * then don't show lower entries 2506 */ 2507 error = VOP_GETATTR(vp, &va, fp->f_cred, p); 2508 if (va.va_flags & OPAQUE) { 2509 vput(lvp); 2510 lvp = NULL; 2511 } 2512 } 2513 2514 if (lvp != NULLVP) { 2515 error = VOP_OPEN(lvp, FREAD, fp->f_cred, p); 2516 if (error) { 2517 vput(lvp); 2518 return (error); 2519 } 2520 VOP_UNLOCK(lvp, 0, p); 2521 fp->f_data = (caddr_t) lvp; 2522 fp->f_offset = 0; 2523 error = vn_close(vp, FREAD, fp->f_cred, p); 2524 if (error) 2525 return (error); 2526 vp = lvp; 2527 goto unionread; 2528 } 2529 } 2530 } 2531 #endif /* UNION */ 2532 2533 if ((SCARG(uap, count) == auio.uio_resid) && 2534 (vp->v_flag & VROOT) && 2535 (vp->v_mount->mnt_flag & MNT_UNION)) { 2536 struct vnode *tvp = vp; 2537 vp = vp->v_mount->mnt_vnodecovered; 2538 VREF(vp); 2539 fp->f_data = (caddr_t) vp; 2540 fp->f_offset = 0; 2541 vrele(tvp); 2542 goto unionread; 2543 } 2544 error = copyout((caddr_t)&loff, (caddr_t)SCARG(uap, basep), 2545 sizeof(long)); 2546 *retval = SCARG(uap, count) - auio.uio_resid; 2547 return (error); 2548 } 2549 #endif /* COMPAT_43 */ 2550 2551 /* 2552 * Read a block of directory entries in a file system independent format. 2553 */ 2554 #ifndef _SYS_SYSPROTO_H_ 2555 struct getdirentries_args { 2556 int fd; 2557 char *buf; 2558 u_int count; 2559 long *basep; 2560 }; 2561 #endif 2562 int 2563 getdirentries(p, uap, retval) 2564 struct proc *p; 2565 register struct getdirentries_args /* { 2566 syscallarg(int) fd; 2567 syscallarg(char *) buf; 2568 syscallarg(u_int) count; 2569 syscallarg(long *) basep; 2570 } */ *uap; 2571 register_t *retval; 2572 { 2573 register struct vnode *vp; 2574 struct file *fp; 2575 struct uio auio; 2576 struct iovec aiov; 2577 long loff; 2578 int error, eofflag; 2579 2580 if (error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) 2581 return (error); 2582 if ((fp->f_flag & FREAD) == 0) 2583 return (EBADF); 2584 vp = (struct vnode *)fp->f_data; 2585 unionread: 2586 if (vp->v_type != VDIR) 2587 return (EINVAL); 2588 aiov.iov_base = SCARG(uap, buf); 2589 aiov.iov_len = SCARG(uap, count); 2590 auio.uio_iov = &aiov; 2591 auio.uio_iovcnt = 1; 2592 auio.uio_rw = UIO_READ; 2593 auio.uio_segflg = UIO_USERSPACE; 2594 auio.uio_procp = p; 2595 auio.uio_resid = SCARG(uap, count); 2596 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p); 2597 loff = auio.uio_offset = fp->f_offset; 2598 error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, NULL, NULL); 2599 fp->f_offset = auio.uio_offset; 2600 VOP_UNLOCK(vp, 0, p); 2601 if (error) 2602 return (error); 2603 2604 #ifdef UNION 2605 { 2606 if ((SCARG(uap, count) == auio.uio_resid) && 2607 (vp->v_op == union_vnodeop_p)) { 2608 struct vnode *lvp; 2609 2610 lvp = union_dircache(vp, p); 2611 if (lvp != NULLVP) { 2612 struct vattr va; 2613 2614 /* 2615 * If the directory is opaque, 2616 * then don't show lower entries 2617 */ 2618 error = VOP_GETATTR(vp, &va, fp->f_cred, p); 2619 if (va.va_flags & OPAQUE) { 2620 vput(lvp); 2621 lvp = NULL; 2622 } 2623 } 2624 2625 if (lvp != NULLVP) { 2626 error = VOP_OPEN(lvp, FREAD, fp->f_cred, p); 2627 if (error) { 2628 vput(lvp); 2629 return (error); 2630 } 2631 VOP_UNLOCK(lvp, 0, p); 2632 fp->f_data = (caddr_t) lvp; 2633 fp->f_offset = 0; 2634 error = vn_close(vp, FREAD, fp->f_cred, p); 2635 if (error) 2636 return (error); 2637 vp = lvp; 2638 goto unionread; 2639 } 2640 } 2641 } 2642 #endif /* UNION */ 2643 2644 if ((SCARG(uap, count) == auio.uio_resid) && 2645 (vp->v_flag & VROOT) && 2646 (vp->v_mount->mnt_flag & MNT_UNION)) { 2647 struct vnode *tvp = vp; 2648 vp = vp->v_mount->mnt_vnodecovered; 2649 VREF(vp); 2650 fp->f_data = (caddr_t) vp; 2651 fp->f_offset = 0; 2652 vrele(tvp); 2653 goto unionread; 2654 } 2655 error = copyout((caddr_t)&loff, (caddr_t)SCARG(uap, basep), 2656 sizeof(long)); 2657 *retval = SCARG(uap, count) - auio.uio_resid; 2658 return (error); 2659 } 2660 2661 /* 2662 * Set the mode mask for creation of filesystem nodes. 2663 */ 2664 #ifndef _SYS_SYSPROTO_H_ 2665 struct umask_args { 2666 int newmask; 2667 }; 2668 #endif 2669 int 2670 umask(p, uap, retval) 2671 struct proc *p; 2672 struct umask_args /* { 2673 syscallarg(int) newmask; 2674 } */ *uap; 2675 int *retval; /* XXX */ 2676 { 2677 register struct filedesc *fdp; 2678 2679 fdp = p->p_fd; 2680 *retval = fdp->fd_cmask; 2681 fdp->fd_cmask = SCARG(uap, newmask) & ALLPERMS; 2682 return (0); 2683 } 2684 2685 /* 2686 * Void all references to file by ripping underlying filesystem 2687 * away from vnode. 2688 */ 2689 #ifndef _SYS_SYSPROTO_H_ 2690 struct revoke_args { 2691 char *path; 2692 }; 2693 #endif 2694 /* ARGSUSED */ 2695 int 2696 revoke(p, uap, retval) 2697 struct proc *p; 2698 register struct revoke_args /* { 2699 syscallarg(char *) path; 2700 } */ *uap; 2701 register_t *retval; 2702 { 2703 register struct vnode *vp; 2704 struct vattr vattr; 2705 int error; 2706 struct nameidata nd; 2707 2708 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p); 2709 if (error = namei(&nd)) 2710 return (error); 2711 vp = nd.ni_vp; 2712 if (error = VOP_GETATTR(vp, &vattr, p->p_ucred, p)) 2713 goto out; 2714 if (p->p_ucred->cr_uid != vattr.va_uid && 2715 (error = suser(p->p_ucred, &p->p_acflag))) 2716 goto out; 2717 if (vp->v_usecount > 1 || (vp->v_flag & VALIASED)) 2718 VOP_REVOKE(vp, REVOKEALL); 2719 out: 2720 vrele(vp); 2721 return (error); 2722 } 2723 2724 /* 2725 * Convert a user file descriptor to a kernel file entry. 2726 */ 2727 int 2728 getvnode(fdp, fd, fpp) 2729 struct filedesc *fdp; 2730 int fd; 2731 struct file **fpp; 2732 { 2733 struct file *fp; 2734 2735 if ((u_int)fd >= fdp->fd_nfiles || 2736 (fp = fdp->fd_ofiles[fd]) == NULL) 2737 return (EBADF); 2738 if (fp->f_type != DTYPE_VNODE && fp->f_type != DTYPE_FIFO) 2739 return (EINVAL); 2740 *fpp = fp; 2741 return (0); 2742 } 2743