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