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 * $FreeBSD$ 40 */ 41 42 /* For 4.3 integer FS ID compatibility */ 43 #include "opt_compat.h" 44 #include "opt_ffs.h" 45 46 #include <sys/param.h> 47 #include <sys/systm.h> 48 #include <sys/bio.h> 49 #include <sys/buf.h> 50 #include <sys/sysent.h> 51 #include <sys/malloc.h> 52 #include <sys/mount.h> 53 #include <sys/mutex.h> 54 #include <sys/sysproto.h> 55 #include <sys/namei.h> 56 #include <sys/filedesc.h> 57 #include <sys/kernel.h> 58 #include <sys/fcntl.h> 59 #include <sys/file.h> 60 #include <sys/linker.h> 61 #include <sys/stat.h> 62 #include <sys/sx.h> 63 #include <sys/unistd.h> 64 #include <sys/vnode.h> 65 #include <sys/proc.h> 66 #include <sys/dirent.h> 67 #include <sys/extattr.h> 68 #include <sys/jail.h> 69 #include <sys/sysctl.h> 70 71 #include <machine/limits.h> 72 73 #include <vm/vm.h> 74 #include <vm/vm_object.h> 75 #include <vm/vm_zone.h> 76 #include <vm/vm_page.h> 77 78 static int change_dir __P((struct nameidata *ndp, struct thread *td)); 79 static void checkdirs __P((struct vnode *olddp, struct vnode *newdp)); 80 static int chroot_refuse_vdir_fds __P((struct filedesc *fdp)); 81 static int getutimes __P((const struct timeval *, struct timespec *)); 82 static int setfown __P((struct thread *td, struct vnode *, uid_t, gid_t)); 83 static int setfmode __P((struct thread *td, struct vnode *, int)); 84 static int setfflags __P((struct thread *td, struct vnode *, int)); 85 static int setutimes __P((struct thread *td, struct vnode *, 86 const struct timespec *, int)); 87 static int vn_access __P((struct vnode *vp, int user_flags, struct ucred *cred, 88 struct thread *td)); 89 90 static int usermount = 0; /* if 1, non-root can mount fs. */ 91 92 int (*union_dircheckp) __P((struct thread *td, struct vnode **, struct file *)); 93 94 SYSCTL_INT(_vfs, OID_AUTO, usermount, CTLFLAG_RW, &usermount, 0, ""); 95 96 /* 97 * Virtual File System System Calls 98 */ 99 100 #ifndef _SYS_SYSPROTO_H_ 101 struct nmount_args { 102 struct iovec *iovp; 103 unsigned int iovcnt; 104 int flags; 105 }; 106 #endif 107 /* ARGSUSED */ 108 int 109 nmount(td, uap) 110 struct thread *td; 111 struct nmount_args /* { 112 syscallarg(struct iovec *) iovp; 113 syscallarg(unsigned int) iovcnt; 114 syscallarg(int) flags; 115 } */ *uap; 116 { 117 118 return(EOPNOTSUPP); 119 } 120 121 /* 122 * Mount a file system. 123 */ 124 #ifndef _SYS_SYSPROTO_H_ 125 struct mount_args { 126 char *type; 127 char *path; 128 int flags; 129 caddr_t data; 130 }; 131 #endif 132 /* ARGSUSED */ 133 int 134 mount(td, uap) 135 struct thread *td; 136 struct mount_args /* { 137 syscallarg(char *) type; 138 syscallarg(char *) path; 139 syscallarg(int) flags; 140 syscallarg(caddr_t) data; 141 } */ *uap; 142 { 143 char *fstype; 144 char *fspath; 145 int error; 146 147 fstype = malloc(MFSNAMELEN, M_TEMP, M_WAITOK | M_ZERO); 148 fspath = malloc(MNAMELEN, M_TEMP, M_WAITOK | M_ZERO); 149 150 /* 151 * vfs_mount() actually takes a kernel string for `type' and 152 * `path' now, so extract them. 153 */ 154 error = copyinstr(SCARG(uap, type), fstype, MFSNAMELEN, NULL); 155 if (error) 156 goto finish; 157 error = copyinstr(SCARG(uap, path), fspath, MNAMELEN, NULL); 158 if (error) 159 goto finish; 160 error = vfs_mount(td, fstype, fspath, SCARG(uap, flags), 161 SCARG(uap, data)); 162 finish: 163 free(fstype, M_TEMP); 164 free(fspath, M_TEMP); 165 return (error); 166 } 167 168 /* 169 * vfs_mount(): actually attempt a filesystem mount. 170 * 171 * This routine is designed to be a "generic" entry point for routines 172 * that wish to mount a filesystem. All parameters except `fsdata' are 173 * pointers into kernel space. `fsdata' is currently still a pointer 174 * into userspace. 175 */ 176 int 177 vfs_mount(td, fstype, fspath, fsflags, fsdata) 178 struct thread *td; 179 const char *fstype; 180 char *fspath; 181 int fsflags; 182 void *fsdata; 183 { 184 struct vnode *vp; 185 struct mount *mp; 186 struct vfsconf *vfsp; 187 int error, flag = 0, flag2 = 0; 188 struct vattr va; 189 struct nameidata nd; 190 191 /* 192 * Be ultra-paranoid about making sure the type and fspath 193 * variables will fit in our mp buffers, including the 194 * terminating NUL. 195 */ 196 if ((strlen(fstype) >= MFSNAMELEN - 1) || 197 (strlen(fspath) >= MNAMELEN - 1)) 198 return (ENAMETOOLONG); 199 200 if (usermount == 0) { 201 error = suser_td(td); 202 if (error) 203 return (error); 204 } 205 /* 206 * Do not allow NFS export by non-root users. 207 */ 208 if (fsflags & MNT_EXPORTED) { 209 error = suser_td(td); 210 if (error) 211 return (error); 212 } 213 /* 214 * Silently enforce MNT_NOSUID and MNT_NODEV for non-root users 215 */ 216 if (suser_xxx(td->td_proc->p_ucred, 0, 0)) 217 fsflags |= MNT_NOSUID | MNT_NODEV; 218 /* 219 * Get vnode to be covered 220 */ 221 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_SYSSPACE, fspath, td); 222 if ((error = namei(&nd)) != 0) 223 return (error); 224 NDFREE(&nd, NDF_ONLY_PNBUF); 225 vp = nd.ni_vp; 226 if (fsflags & MNT_UPDATE) { 227 if ((vp->v_flag & VROOT) == 0) { 228 vput(vp); 229 return (EINVAL); 230 } 231 mp = vp->v_mount; 232 flag = mp->mnt_flag; 233 flag2 = mp->mnt_kern_flag; 234 /* 235 * We only allow the filesystem to be reloaded if it 236 * is currently mounted read-only. 237 */ 238 if ((fsflags & MNT_RELOAD) && 239 ((mp->mnt_flag & MNT_RDONLY) == 0)) { 240 vput(vp); 241 return (EOPNOTSUPP); /* Needs translation */ 242 } 243 /* 244 * Only root, or the user that did the original mount is 245 * permitted to update it. 246 */ 247 if (mp->mnt_stat.f_owner != td->td_proc->p_ucred->cr_uid) { 248 error = suser_td(td); 249 if (error) { 250 vput(vp); 251 return (error); 252 } 253 } 254 if (vfs_busy(mp, LK_NOWAIT, 0, td)) { 255 vput(vp); 256 return (EBUSY); 257 } 258 mtx_lock(&vp->v_interlock); 259 if ((vp->v_flag & VMOUNT) != 0 || 260 vp->v_mountedhere != NULL) { 261 mtx_unlock(&vp->v_interlock); 262 vfs_unbusy(mp, td); 263 vput(vp); 264 return (EBUSY); 265 } 266 vp->v_flag |= VMOUNT; 267 mtx_unlock(&vp->v_interlock); 268 mp->mnt_flag |= fsflags & 269 (MNT_RELOAD | MNT_FORCE | MNT_UPDATE | MNT_SNAPSHOT); 270 VOP_UNLOCK(vp, 0, td); 271 goto update; 272 } 273 /* 274 * If the user is not root, ensure that they own the directory 275 * onto which we are attempting to mount. 276 */ 277 error = VOP_GETATTR(vp, &va, td->td_proc->p_ucred, td); 278 if (error) { 279 vput(vp); 280 return (error); 281 } 282 if (va.va_uid != td->td_proc->p_ucred->cr_uid) { 283 error = suser_td(td); 284 if (error) { 285 vput(vp); 286 return (error); 287 } 288 } 289 if ((error = vinvalbuf(vp, V_SAVE, td->td_proc->p_ucred, td, 0, 0)) 290 != 0) { 291 vput(vp); 292 return (error); 293 } 294 if (vp->v_type != VDIR) { 295 vput(vp); 296 return (ENOTDIR); 297 } 298 for (vfsp = vfsconf; vfsp; vfsp = vfsp->vfc_next) 299 if (!strcmp(vfsp->vfc_name, fstype)) 300 break; 301 if (vfsp == NULL) { 302 linker_file_t lf; 303 304 /* Only load modules for root (very important!) */ 305 error = suser_td(td); 306 if (error) { 307 vput(vp); 308 return error; 309 } 310 error = linker_load_file(fstype, &lf); 311 if (error || lf == NULL) { 312 vput(vp); 313 if (lf == NULL) 314 error = ENODEV; 315 return error; 316 } 317 lf->userrefs++; 318 /* lookup again, see if the VFS was loaded */ 319 for (vfsp = vfsconf; vfsp; vfsp = vfsp->vfc_next) 320 if (!strcmp(vfsp->vfc_name, fstype)) 321 break; 322 if (vfsp == NULL) { 323 lf->userrefs--; 324 linker_file_unload(lf); 325 vput(vp); 326 return (ENODEV); 327 } 328 } 329 mtx_lock(&vp->v_interlock); 330 if ((vp->v_flag & VMOUNT) != 0 || 331 vp->v_mountedhere != NULL) { 332 mtx_unlock(&vp->v_interlock); 333 vput(vp); 334 return (EBUSY); 335 } 336 vp->v_flag |= VMOUNT; 337 mtx_unlock(&vp->v_interlock); 338 339 /* 340 * Allocate and initialize the filesystem. 341 */ 342 mp = malloc(sizeof(struct mount), M_MOUNT, M_WAITOK | M_ZERO); 343 TAILQ_INIT(&mp->mnt_nvnodelist); 344 TAILQ_INIT(&mp->mnt_reservedvnlist); 345 lockinit(&mp->mnt_lock, PVFS, "vfslock", 0, LK_NOPAUSE); 346 (void)vfs_busy(mp, LK_NOWAIT, 0, td); 347 mp->mnt_op = vfsp->vfc_vfsops; 348 mp->mnt_vfc = vfsp; 349 vfsp->vfc_refcount++; 350 mp->mnt_stat.f_type = vfsp->vfc_typenum; 351 mp->mnt_flag |= vfsp->vfc_flags & MNT_VISFLAGMASK; 352 strncpy(mp->mnt_stat.f_fstypename, fstype, MFSNAMELEN); 353 mp->mnt_stat.f_fstypename[MFSNAMELEN - 1] = '\0'; 354 mp->mnt_vnodecovered = vp; 355 mp->mnt_stat.f_owner = td->td_proc->p_ucred->cr_uid; 356 strncpy(mp->mnt_stat.f_mntonname, fspath, MNAMELEN); 357 mp->mnt_stat.f_mntonname[MNAMELEN - 1] = '\0'; 358 mp->mnt_iosize_max = DFLTPHYS; 359 VOP_UNLOCK(vp, 0, td); 360 update: 361 /* 362 * Set the mount level flags. 363 */ 364 if (fsflags & MNT_RDONLY) 365 mp->mnt_flag |= MNT_RDONLY; 366 else if (mp->mnt_flag & MNT_RDONLY) 367 mp->mnt_kern_flag |= MNTK_WANTRDWR; 368 mp->mnt_flag &=~ MNT_UPDATEMASK; 369 mp->mnt_flag |= fsflags & (MNT_UPDATEMASK | MNT_FORCE); 370 /* 371 * Mount the filesystem. 372 * XXX The final recipients of VFS_MOUNT just overwrite the ndp they 373 * get. No freeing of cn_pnbuf. 374 */ 375 error = VFS_MOUNT(mp, fspath, fsdata, &nd, td); 376 if (mp->mnt_flag & MNT_UPDATE) { 377 if (mp->mnt_kern_flag & MNTK_WANTRDWR) 378 mp->mnt_flag &= ~MNT_RDONLY; 379 mp->mnt_flag &=~ 380 (MNT_UPDATE | MNT_RELOAD | MNT_FORCE | MNT_SNAPSHOT); 381 mp->mnt_kern_flag &=~ MNTK_WANTRDWR; 382 if (error) { 383 mp->mnt_flag = flag; 384 mp->mnt_kern_flag = flag2; 385 } 386 if ((mp->mnt_flag & MNT_RDONLY) == 0) { 387 if (mp->mnt_syncer == NULL) 388 error = vfs_allocate_syncvnode(mp); 389 } else { 390 if (mp->mnt_syncer != NULL) 391 vrele(mp->mnt_syncer); 392 mp->mnt_syncer = NULL; 393 } 394 vfs_unbusy(mp, td); 395 mtx_lock(&vp->v_interlock); 396 vp->v_flag &= ~VMOUNT; 397 mtx_unlock(&vp->v_interlock); 398 vrele(vp); 399 return (error); 400 } 401 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 402 /* 403 * Put the new filesystem on the mount list after root. 404 */ 405 cache_purge(vp); 406 if (!error) { 407 struct vnode *newdp; 408 409 mtx_lock(&vp->v_interlock); 410 vp->v_flag &= ~VMOUNT; 411 vp->v_mountedhere = mp; 412 mtx_unlock(&vp->v_interlock); 413 mtx_lock(&mountlist_mtx); 414 TAILQ_INSERT_TAIL(&mountlist, mp, mnt_list); 415 mtx_unlock(&mountlist_mtx); 416 if (VFS_ROOT(mp, &newdp)) 417 panic("mount: lost mount"); 418 checkdirs(vp, newdp); 419 vput(newdp); 420 VOP_UNLOCK(vp, 0, td); 421 if ((mp->mnt_flag & MNT_RDONLY) == 0) 422 error = vfs_allocate_syncvnode(mp); 423 vfs_unbusy(mp, td); 424 if ((error = VFS_START(mp, 0, td)) != 0) 425 vrele(vp); 426 } else { 427 mtx_lock(&vp->v_interlock); 428 vp->v_flag &= ~VMOUNT; 429 mtx_unlock(&vp->v_interlock); 430 mp->mnt_vfc->vfc_refcount--; 431 vfs_unbusy(mp, td); 432 free((caddr_t)mp, M_MOUNT); 433 vput(vp); 434 } 435 return (error); 436 } 437 438 /* 439 * Scan all active processes to see if any of them have a current 440 * or root directory of `olddp'. If so, replace them with the new 441 * mount point. 442 */ 443 static void 444 checkdirs(olddp, newdp) 445 struct vnode *olddp, *newdp; 446 { 447 struct filedesc *fdp; 448 struct proc *p; 449 450 if (olddp->v_usecount == 1) 451 return; 452 sx_slock(&allproc_lock); 453 LIST_FOREACH(p, &allproc, p_list) { 454 fdp = p->p_fd; 455 if (fdp == NULL) 456 continue; 457 FILEDESC_LOCK(fdp); 458 if (fdp->fd_cdir == olddp) { 459 VREF(newdp); 460 fdp->fd_cdir = newdp; 461 FILEDESC_UNLOCK(fdp); 462 vrele(olddp); 463 FILEDESC_LOCK(fdp); 464 } 465 if (fdp->fd_rdir == olddp) { 466 VREF(newdp); 467 fdp->fd_rdir = newdp; 468 FILEDESC_UNLOCK(fdp); 469 vrele(olddp); 470 } else 471 FILEDESC_UNLOCK(fdp); 472 } 473 sx_sunlock(&allproc_lock); 474 if (rootvnode == olddp) { 475 vrele(rootvnode); 476 VREF(newdp); 477 rootvnode = newdp; 478 } 479 } 480 481 /* 482 * Unmount a file system. 483 * 484 * Note: unmount takes a path to the vnode mounted on as argument, 485 * not special file (as before). 486 */ 487 #ifndef _SYS_SYSPROTO_H_ 488 struct unmount_args { 489 char *path; 490 int flags; 491 }; 492 #endif 493 /* ARGSUSED */ 494 int 495 unmount(td, uap) 496 struct thread *td; 497 register struct unmount_args /* { 498 syscallarg(char *) path; 499 syscallarg(int) flags; 500 } */ *uap; 501 { 502 register struct vnode *vp; 503 struct mount *mp; 504 int error; 505 struct nameidata nd; 506 507 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, 508 SCARG(uap, path), td); 509 if ((error = namei(&nd)) != 0) 510 return (error); 511 vp = nd.ni_vp; 512 NDFREE(&nd, NDF_ONLY_PNBUF); 513 mp = vp->v_mount; 514 515 /* 516 * Only root, or the user that did the original mount is 517 * permitted to unmount this filesystem. 518 */ 519 if (mp->mnt_stat.f_owner != td->td_proc->p_ucred->cr_uid) { 520 error = suser_td(td); 521 if (error) { 522 vput(vp); 523 return (error); 524 } 525 } 526 527 /* 528 * Don't allow unmounting the root file system. 529 */ 530 if (mp->mnt_flag & MNT_ROOTFS) { 531 vput(vp); 532 return (EINVAL); 533 } 534 535 /* 536 * Must be the root of the filesystem 537 */ 538 if ((vp->v_flag & VROOT) == 0) { 539 vput(vp); 540 return (EINVAL); 541 } 542 vput(vp); 543 return (dounmount(mp, SCARG(uap, flags), td)); 544 } 545 546 /* 547 * Do the actual file system unmount. 548 */ 549 int 550 dounmount(mp, flags, td) 551 struct mount *mp; 552 int flags; 553 struct thread *td; 554 { 555 struct vnode *coveredvp, *fsrootvp; 556 int error; 557 int async_flag; 558 559 mtx_lock(&mountlist_mtx); 560 mp->mnt_kern_flag |= MNTK_UNMOUNT; 561 error = lockmgr(&mp->mnt_lock, LK_DRAIN | LK_INTERLOCK | 562 ((flags & MNT_FORCE) ? 0 : LK_NOWAIT), &mountlist_mtx, td); 563 if (error) { 564 mp->mnt_kern_flag &= ~MNTK_UNMOUNT; 565 if (mp->mnt_kern_flag & MNTK_MWAIT) 566 wakeup((caddr_t)mp); 567 return (error); 568 } 569 vn_start_write(NULL, &mp, V_WAIT); 570 571 if (mp->mnt_flag & MNT_EXPUBLIC) 572 vfs_setpublicfs(NULL, NULL, NULL); 573 574 vfs_msync(mp, MNT_WAIT); 575 async_flag = mp->mnt_flag & MNT_ASYNC; 576 mp->mnt_flag &=~ MNT_ASYNC; 577 cache_purgevfs(mp); /* remove cache entries for this file sys */ 578 if (mp->mnt_syncer != NULL) 579 vrele(mp->mnt_syncer); 580 /* Move process cdir/rdir refs on fs root to underlying vnode. */ 581 if (VFS_ROOT(mp, &fsrootvp) == 0) { 582 if (mp->mnt_vnodecovered != NULL) 583 checkdirs(fsrootvp, mp->mnt_vnodecovered); 584 if (fsrootvp == rootvnode) { 585 vrele(rootvnode); 586 rootvnode = NULL; 587 } 588 vput(fsrootvp); 589 } 590 if (((mp->mnt_flag & MNT_RDONLY) || 591 (error = VFS_SYNC(mp, MNT_WAIT, td->td_proc->p_ucred, td)) == 0) || 592 (flags & MNT_FORCE)) { 593 error = VFS_UNMOUNT(mp, flags, td); 594 } 595 vn_finished_write(mp); 596 if (error) { 597 /* Undo cdir/rdir and rootvnode changes made above. */ 598 if (VFS_ROOT(mp, &fsrootvp) == 0) { 599 if (mp->mnt_vnodecovered != NULL) 600 checkdirs(mp->mnt_vnodecovered, fsrootvp); 601 if (rootvnode == NULL) { 602 rootvnode = fsrootvp; 603 vref(rootvnode); 604 } 605 vput(fsrootvp); 606 } 607 if ((mp->mnt_flag & MNT_RDONLY) == 0 && mp->mnt_syncer == NULL) 608 (void) vfs_allocate_syncvnode(mp); 609 mtx_lock(&mountlist_mtx); 610 mp->mnt_kern_flag &= ~MNTK_UNMOUNT; 611 mp->mnt_flag |= async_flag; 612 lockmgr(&mp->mnt_lock, LK_RELEASE | LK_INTERLOCK, 613 &mountlist_mtx, td); 614 if (mp->mnt_kern_flag & MNTK_MWAIT) 615 wakeup((caddr_t)mp); 616 return (error); 617 } 618 mtx_lock(&mountlist_mtx); 619 TAILQ_REMOVE(&mountlist, mp, mnt_list); 620 if ((coveredvp = mp->mnt_vnodecovered) != NULL) 621 coveredvp->v_mountedhere = NULL; 622 mp->mnt_vfc->vfc_refcount--; 623 if (!TAILQ_EMPTY(&mp->mnt_nvnodelist)) 624 panic("unmount: dangling vnode"); 625 lockmgr(&mp->mnt_lock, LK_RELEASE | LK_INTERLOCK, &mountlist_mtx, td); 626 lockdestroy(&mp->mnt_lock); 627 if (coveredvp != NULL) 628 vrele(coveredvp); 629 if (mp->mnt_kern_flag & MNTK_MWAIT) 630 wakeup((caddr_t)mp); 631 free((caddr_t)mp, M_MOUNT); 632 return (0); 633 } 634 635 /* 636 * Sync each mounted filesystem. 637 */ 638 #ifndef _SYS_SYSPROTO_H_ 639 struct sync_args { 640 int dummy; 641 }; 642 #endif 643 644 #ifdef DEBUG 645 static int syncprt = 0; 646 SYSCTL_INT(_debug, OID_AUTO, syncprt, CTLFLAG_RW, &syncprt, 0, ""); 647 #endif 648 649 /* ARGSUSED */ 650 int 651 sync(td, uap) 652 struct thread *td; 653 struct sync_args *uap; 654 { 655 struct mount *mp, *nmp; 656 int asyncflag; 657 658 mtx_lock(&mountlist_mtx); 659 for (mp = TAILQ_FIRST(&mountlist); mp != NULL; mp = nmp) { 660 if (vfs_busy(mp, LK_NOWAIT, &mountlist_mtx, td)) { 661 nmp = TAILQ_NEXT(mp, mnt_list); 662 continue; 663 } 664 if ((mp->mnt_flag & MNT_RDONLY) == 0 && 665 vn_start_write(NULL, &mp, V_NOWAIT) == 0) { 666 asyncflag = mp->mnt_flag & MNT_ASYNC; 667 mp->mnt_flag &= ~MNT_ASYNC; 668 vfs_msync(mp, MNT_NOWAIT); 669 VFS_SYNC(mp, MNT_NOWAIT, 670 ((td != NULL) ? td->td_proc->p_ucred : NOCRED), td); 671 mp->mnt_flag |= asyncflag; 672 vn_finished_write(mp); 673 } 674 mtx_lock(&mountlist_mtx); 675 nmp = TAILQ_NEXT(mp, mnt_list); 676 vfs_unbusy(mp, td); 677 } 678 mtx_unlock(&mountlist_mtx); 679 #if 0 680 /* 681 * XXX don't call vfs_bufstats() yet because that routine 682 * was not imported in the Lite2 merge. 683 */ 684 #ifdef DIAGNOSTIC 685 if (syncprt) 686 vfs_bufstats(); 687 #endif /* DIAGNOSTIC */ 688 #endif 689 return (0); 690 } 691 692 /* XXX PRISON: could be per prison flag */ 693 static int prison_quotas; 694 #if 0 695 SYSCTL_INT(_kern_prison, OID_AUTO, quotas, CTLFLAG_RW, &prison_quotas, 0, ""); 696 #endif 697 698 /* 699 * Change filesystem quotas. 700 */ 701 #ifndef _SYS_SYSPROTO_H_ 702 struct quotactl_args { 703 char *path; 704 int cmd; 705 int uid; 706 caddr_t arg; 707 }; 708 #endif 709 /* ARGSUSED */ 710 int 711 quotactl(td, uap) 712 struct thread *td; 713 register struct quotactl_args /* { 714 syscallarg(char *) path; 715 syscallarg(int) cmd; 716 syscallarg(int) uid; 717 syscallarg(caddr_t) arg; 718 } */ *uap; 719 { 720 struct mount *mp; 721 int error; 722 struct nameidata nd; 723 724 if (jailed(td->td_proc->p_ucred) && !prison_quotas) 725 return (EPERM); 726 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), td); 727 if ((error = namei(&nd)) != 0) 728 return (error); 729 NDFREE(&nd, NDF_ONLY_PNBUF); 730 error = vn_start_write(nd.ni_vp, &mp, V_WAIT | PCATCH); 731 vrele(nd.ni_vp); 732 if (error) 733 return (error); 734 error = VFS_QUOTACTL(mp, SCARG(uap, cmd), SCARG(uap, uid), 735 SCARG(uap, arg), td); 736 vn_finished_write(mp); 737 return (error); 738 } 739 740 /* 741 * Get filesystem statistics. 742 */ 743 #ifndef _SYS_SYSPROTO_H_ 744 struct statfs_args { 745 char *path; 746 struct statfs *buf; 747 }; 748 #endif 749 /* ARGSUSED */ 750 int 751 statfs(td, uap) 752 struct thread *td; 753 register struct statfs_args /* { 754 syscallarg(char *) path; 755 syscallarg(struct statfs *) buf; 756 } */ *uap; 757 { 758 register struct mount *mp; 759 register struct statfs *sp; 760 int error; 761 struct nameidata nd; 762 struct statfs sb; 763 764 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), td); 765 if ((error = namei(&nd)) != 0) 766 return (error); 767 mp = nd.ni_vp->v_mount; 768 sp = &mp->mnt_stat; 769 NDFREE(&nd, NDF_ONLY_PNBUF); 770 vrele(nd.ni_vp); 771 error = VFS_STATFS(mp, sp, td); 772 if (error) 773 return (error); 774 sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK; 775 if (suser_xxx(td->td_proc->p_ucred, 0, 0)) { 776 bcopy((caddr_t)sp, (caddr_t)&sb, sizeof(sb)); 777 sb.f_fsid.val[0] = sb.f_fsid.val[1] = 0; 778 sp = &sb; 779 } 780 return (copyout((caddr_t)sp, (caddr_t)SCARG(uap, buf), sizeof(*sp))); 781 } 782 783 /* 784 * Get filesystem statistics. 785 */ 786 #ifndef _SYS_SYSPROTO_H_ 787 struct fstatfs_args { 788 int fd; 789 struct statfs *buf; 790 }; 791 #endif 792 /* ARGSUSED */ 793 int 794 fstatfs(td, uap) 795 struct thread *td; 796 register struct fstatfs_args /* { 797 syscallarg(int) fd; 798 syscallarg(struct statfs *) buf; 799 } */ *uap; 800 { 801 struct file *fp; 802 struct mount *mp; 803 register struct statfs *sp; 804 int error; 805 struct statfs sb; 806 807 if ((error = getvnode(td->td_proc->p_fd, SCARG(uap, fd), &fp)) != 0) 808 return (error); 809 mp = ((struct vnode *)fp->f_data)->v_mount; 810 fdrop(fp, td); 811 if (mp == NULL) 812 return (EBADF); 813 sp = &mp->mnt_stat; 814 error = VFS_STATFS(mp, sp, td); 815 if (error) 816 return (error); 817 sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK; 818 if (suser_xxx(td->td_proc->p_ucred, 0, 0)) { 819 bcopy((caddr_t)sp, (caddr_t)&sb, sizeof(sb)); 820 sb.f_fsid.val[0] = sb.f_fsid.val[1] = 0; 821 sp = &sb; 822 } 823 return (copyout((caddr_t)sp, (caddr_t)SCARG(uap, buf), sizeof(*sp))); 824 } 825 826 /* 827 * Get statistics on all filesystems. 828 */ 829 #ifndef _SYS_SYSPROTO_H_ 830 struct getfsstat_args { 831 struct statfs *buf; 832 long bufsize; 833 int flags; 834 }; 835 #endif 836 int 837 getfsstat(td, uap) 838 struct thread *td; 839 register struct getfsstat_args /* { 840 syscallarg(struct statfs *) buf; 841 syscallarg(long) bufsize; 842 syscallarg(int) flags; 843 } */ *uap; 844 { 845 register struct mount *mp, *nmp; 846 register struct statfs *sp; 847 caddr_t sfsp; 848 long count, maxcount, error; 849 850 maxcount = SCARG(uap, bufsize) / sizeof(struct statfs); 851 sfsp = (caddr_t)SCARG(uap, buf); 852 count = 0; 853 mtx_lock(&mountlist_mtx); 854 for (mp = TAILQ_FIRST(&mountlist); mp != NULL; mp = nmp) { 855 if (vfs_busy(mp, LK_NOWAIT, &mountlist_mtx, td)) { 856 nmp = TAILQ_NEXT(mp, mnt_list); 857 continue; 858 } 859 if (sfsp && count < maxcount) { 860 sp = &mp->mnt_stat; 861 /* 862 * If MNT_NOWAIT or MNT_LAZY is specified, do not 863 * refresh the fsstat cache. MNT_NOWAIT or MNT_LAZY 864 * overrides MNT_WAIT. 865 */ 866 if (((SCARG(uap, flags) & (MNT_LAZY|MNT_NOWAIT)) == 0 || 867 (SCARG(uap, flags) & MNT_WAIT)) && 868 (error = VFS_STATFS(mp, sp, td))) { 869 mtx_lock(&mountlist_mtx); 870 nmp = TAILQ_NEXT(mp, mnt_list); 871 vfs_unbusy(mp, td); 872 continue; 873 } 874 sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK; 875 error = copyout((caddr_t)sp, sfsp, sizeof(*sp)); 876 if (error) { 877 vfs_unbusy(mp, td); 878 return (error); 879 } 880 sfsp += sizeof(*sp); 881 } 882 count++; 883 mtx_lock(&mountlist_mtx); 884 nmp = TAILQ_NEXT(mp, mnt_list); 885 vfs_unbusy(mp, td); 886 } 887 mtx_unlock(&mountlist_mtx); 888 if (sfsp && count > maxcount) 889 td->td_retval[0] = maxcount; 890 else 891 td->td_retval[0] = count; 892 return (0); 893 } 894 895 /* 896 * Change current working directory to a given file descriptor. 897 */ 898 #ifndef _SYS_SYSPROTO_H_ 899 struct fchdir_args { 900 int fd; 901 }; 902 #endif 903 /* ARGSUSED */ 904 int 905 fchdir(td, uap) 906 struct thread *td; 907 struct fchdir_args /* { 908 syscallarg(int) fd; 909 } */ *uap; 910 { 911 register struct filedesc *fdp = td->td_proc->p_fd; 912 struct vnode *vp, *tdp, *vpold; 913 struct mount *mp; 914 struct file *fp; 915 int error; 916 917 if ((error = getvnode(fdp, SCARG(uap, fd), &fp)) != 0) 918 return (error); 919 vp = (struct vnode *)fp->f_data; 920 VREF(vp); 921 fdrop(fp, td); 922 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 923 if (vp->v_type != VDIR) 924 error = ENOTDIR; 925 else 926 error = VOP_ACCESS(vp, VEXEC, td->td_proc->p_ucred, td); 927 while (!error && (mp = vp->v_mountedhere) != NULL) { 928 if (vfs_busy(mp, 0, 0, td)) 929 continue; 930 error = VFS_ROOT(mp, &tdp); 931 vfs_unbusy(mp, td); 932 if (error) 933 break; 934 vput(vp); 935 vp = tdp; 936 } 937 if (error) { 938 vput(vp); 939 return (error); 940 } 941 VOP_UNLOCK(vp, 0, td); 942 FILEDESC_LOCK(fdp); 943 vpold = fdp->fd_cdir; 944 fdp->fd_cdir = vp; 945 FILEDESC_UNLOCK(fdp); 946 vrele(vpold); 947 return (0); 948 } 949 950 /* 951 * Change current working directory (``.''). 952 */ 953 #ifndef _SYS_SYSPROTO_H_ 954 struct chdir_args { 955 char *path; 956 }; 957 #endif 958 /* ARGSUSED */ 959 int 960 chdir(td, uap) 961 struct thread *td; 962 struct chdir_args /* { 963 syscallarg(char *) path; 964 } */ *uap; 965 { 966 register struct filedesc *fdp = td->td_proc->p_fd; 967 int error; 968 struct nameidata nd; 969 struct vnode *vp; 970 971 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, 972 SCARG(uap, path), td); 973 if ((error = change_dir(&nd, td)) != 0) 974 return (error); 975 NDFREE(&nd, NDF_ONLY_PNBUF); 976 FILEDESC_LOCK(fdp); 977 vp = fdp->fd_cdir; 978 fdp->fd_cdir = nd.ni_vp; 979 FILEDESC_UNLOCK(fdp); 980 vrele(vp); 981 return (0); 982 } 983 984 /* 985 * Helper function for raised chroot(2) security function: Refuse if 986 * any filedescriptors are open directories. 987 */ 988 static int 989 chroot_refuse_vdir_fds(fdp) 990 struct filedesc *fdp; 991 { 992 struct vnode *vp; 993 struct file *fp; 994 struct thread *td = curthread; 995 int error; 996 int fd; 997 998 FILEDESC_LOCK(fdp); 999 for (fd = 0; fd < fdp->fd_nfiles ; fd++) { 1000 error = getvnode(fdp, fd, &fp); 1001 if (error) 1002 continue; 1003 vp = (struct vnode *)fp->f_data; 1004 fdrop(fp, td); 1005 if (vp->v_type != VDIR) 1006 continue; 1007 FILEDESC_UNLOCK(fdp); 1008 return(EPERM); 1009 } 1010 FILEDESC_UNLOCK(fdp); 1011 return (0); 1012 } 1013 1014 /* 1015 * This sysctl determines if we will allow a process to chroot(2) if it 1016 * has a directory open: 1017 * 0: disallowed for all processes. 1018 * 1: allowed for processes that were not already chroot(2)'ed. 1019 * 2: allowed for all processes. 1020 */ 1021 1022 static int chroot_allow_open_directories = 1; 1023 1024 SYSCTL_INT(_kern, OID_AUTO, chroot_allow_open_directories, CTLFLAG_RW, 1025 &chroot_allow_open_directories, 0, ""); 1026 1027 /* 1028 * Change notion of root (``/'') directory. 1029 */ 1030 #ifndef _SYS_SYSPROTO_H_ 1031 struct chroot_args { 1032 char *path; 1033 }; 1034 #endif 1035 /* ARGSUSED */ 1036 int 1037 chroot(td, uap) 1038 struct thread *td; 1039 struct chroot_args /* { 1040 syscallarg(char *) path; 1041 } */ *uap; 1042 { 1043 register struct filedesc *fdp = td->td_proc->p_fd; 1044 int error; 1045 struct nameidata nd; 1046 struct vnode *vp; 1047 1048 error = suser_xxx(0, td->td_proc, PRISON_ROOT); 1049 if (error) 1050 return (error); 1051 FILEDESC_LOCK(fdp); 1052 if (chroot_allow_open_directories == 0 || 1053 (chroot_allow_open_directories == 1 && fdp->fd_rdir != rootvnode)) { 1054 FILEDESC_UNLOCK(fdp); 1055 error = chroot_refuse_vdir_fds(fdp); 1056 } else 1057 FILEDESC_UNLOCK(fdp); 1058 if (error) 1059 return (error); 1060 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, 1061 SCARG(uap, path), td); 1062 if ((error = change_dir(&nd, td)) != 0) 1063 return (error); 1064 NDFREE(&nd, NDF_ONLY_PNBUF); 1065 FILEDESC_LOCK(fdp); 1066 vp = fdp->fd_rdir; 1067 fdp->fd_rdir = nd.ni_vp; 1068 if (!fdp->fd_jdir) { 1069 fdp->fd_jdir = nd.ni_vp; 1070 VREF(fdp->fd_jdir); 1071 } 1072 FILEDESC_UNLOCK(fdp); 1073 vrele(vp); 1074 return (0); 1075 } 1076 1077 /* 1078 * Common routine for chroot and chdir. 1079 */ 1080 static int 1081 change_dir(ndp, td) 1082 register struct nameidata *ndp; 1083 struct thread *td; 1084 { 1085 struct vnode *vp; 1086 int error; 1087 1088 error = namei(ndp); 1089 if (error) 1090 return (error); 1091 vp = ndp->ni_vp; 1092 if (vp->v_type != VDIR) 1093 error = ENOTDIR; 1094 else 1095 error = VOP_ACCESS(vp, VEXEC, td->td_proc->p_ucred, td); 1096 if (error) 1097 vput(vp); 1098 else 1099 VOP_UNLOCK(vp, 0, td); 1100 return (error); 1101 } 1102 1103 /* 1104 * Check permissions, allocate an open file structure, 1105 * and call the device open routine if any. 1106 */ 1107 #ifndef _SYS_SYSPROTO_H_ 1108 struct open_args { 1109 char *path; 1110 int flags; 1111 int mode; 1112 }; 1113 #endif 1114 int 1115 open(td, uap) 1116 struct thread *td; 1117 register struct open_args /* { 1118 syscallarg(char *) path; 1119 syscallarg(int) flags; 1120 syscallarg(int) mode; 1121 } */ *uap; 1122 { 1123 struct proc *p = td->td_proc; 1124 struct filedesc *fdp = p->p_fd; 1125 struct file *fp; 1126 struct vnode *vp; 1127 struct vattr vat; 1128 struct mount *mp; 1129 int cmode, flags, oflags; 1130 struct file *nfp; 1131 int type, indx, error; 1132 struct flock lf; 1133 struct nameidata nd; 1134 1135 oflags = SCARG(uap, flags); 1136 if ((oflags & O_ACCMODE) == O_ACCMODE) 1137 return (EINVAL); 1138 flags = FFLAGS(oflags); 1139 error = falloc(td, &nfp, &indx); 1140 if (error) 1141 return (error); 1142 fp = nfp; 1143 FILEDESC_LOCK(fdp); 1144 cmode = ((SCARG(uap, mode) &~ fdp->fd_cmask) & ALLPERMS) &~ S_ISTXT; 1145 FILEDESC_UNLOCK(fdp); 1146 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), td); 1147 td->td_dupfd = -indx - 1; /* XXX check for fdopen */ 1148 /* 1149 * Bump the ref count to prevent another process from closing 1150 * the descriptor while we are blocked in vn_open() 1151 */ 1152 fhold(fp); 1153 error = vn_open(&nd, &flags, cmode); 1154 if (error) { 1155 /* 1156 * release our own reference 1157 */ 1158 fdrop(fp, td); 1159 1160 /* 1161 * handle special fdopen() case. bleh. dupfdopen() is 1162 * responsible for dropping the old contents of ofiles[indx] 1163 * if it succeeds. 1164 */ 1165 if ((error == ENODEV || error == ENXIO) && 1166 td->td_dupfd >= 0 && /* XXX from fdopen */ 1167 (error = 1168 dupfdopen(td, fdp, indx, td->td_dupfd, flags, error)) == 0) { 1169 td->td_retval[0] = indx; 1170 return (0); 1171 } 1172 /* 1173 * Clean up the descriptor, but only if another thread hadn't 1174 * replaced or closed it. 1175 */ 1176 FILEDESC_LOCK(fdp); 1177 if (fdp->fd_ofiles[indx] == fp) { 1178 fdp->fd_ofiles[indx] = NULL; 1179 FILEDESC_UNLOCK(fdp); 1180 fdrop(fp, td); 1181 } else 1182 FILEDESC_UNLOCK(fdp); 1183 1184 if (error == ERESTART) 1185 error = EINTR; 1186 return (error); 1187 } 1188 td->td_dupfd = 0; 1189 NDFREE(&nd, NDF_ONLY_PNBUF); 1190 vp = nd.ni_vp; 1191 1192 /* 1193 * There should be 2 references on the file, one from the descriptor 1194 * table, and one for us. 1195 * 1196 * Handle the case where someone closed the file (via its file 1197 * descriptor) while we were blocked. The end result should look 1198 * like opening the file succeeded but it was immediately closed. 1199 */ 1200 FILEDESC_LOCK(fdp); 1201 FILE_LOCK(fp); 1202 if (fp->f_count == 1) { 1203 KASSERT(fdp->fd_ofiles[indx] != fp, 1204 ("Open file descriptor lost all refs")); 1205 FILEDESC_UNLOCK(fdp); 1206 FILE_UNLOCK(fp); 1207 VOP_UNLOCK(vp, 0, td); 1208 vn_close(vp, flags & FMASK, fp->f_cred, td); 1209 fdrop(fp, td); 1210 td->td_retval[0] = indx; 1211 return 0; 1212 } 1213 1214 fp->f_data = (caddr_t)vp; 1215 fp->f_flag = flags & FMASK; 1216 fp->f_ops = &vnops; 1217 fp->f_type = (vp->v_type == VFIFO ? DTYPE_FIFO : DTYPE_VNODE); 1218 FILEDESC_UNLOCK(fdp); 1219 FILE_UNLOCK(fp); 1220 VOP_UNLOCK(vp, 0, td); 1221 if (flags & (O_EXLOCK | O_SHLOCK)) { 1222 lf.l_whence = SEEK_SET; 1223 lf.l_start = 0; 1224 lf.l_len = 0; 1225 if (flags & O_EXLOCK) 1226 lf.l_type = F_WRLCK; 1227 else 1228 lf.l_type = F_RDLCK; 1229 type = F_FLOCK; 1230 if ((flags & FNONBLOCK) == 0) 1231 type |= F_WAIT; 1232 if ((error = VOP_ADVLOCK(vp, (caddr_t)fp, F_SETLK, &lf, type)) != 0) 1233 goto bad; 1234 fp->f_flag |= FHASLOCK; 1235 } 1236 if (flags & O_TRUNC) { 1237 if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0) 1238 goto bad; 1239 VOP_LEASE(vp, td, p->p_ucred, LEASE_WRITE); 1240 VATTR_NULL(&vat); 1241 vat.va_size = 0; 1242 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 1243 error = VOP_SETATTR(vp, &vat, p->p_ucred, td); 1244 VOP_UNLOCK(vp, 0, td); 1245 vn_finished_write(mp); 1246 if (error) 1247 goto bad; 1248 } 1249 /* assert that vn_open created a backing object if one is needed */ 1250 KASSERT(!vn_canvmio(vp) || VOP_GETVOBJECT(vp, NULL) == 0, 1251 ("open: vmio vnode has no backing object after vn_open")); 1252 /* 1253 * Release our private reference, leaving the one associated with 1254 * the descriptor table intact. 1255 */ 1256 fdrop(fp, td); 1257 td->td_retval[0] = indx; 1258 return (0); 1259 bad: 1260 FILEDESC_LOCK(fdp); 1261 if (fdp->fd_ofiles[indx] == fp) { 1262 fdp->fd_ofiles[indx] = NULL; 1263 FILEDESC_UNLOCK(fdp); 1264 fdrop(fp, td); 1265 } else 1266 FILEDESC_UNLOCK(fdp); 1267 return (error); 1268 } 1269 1270 #ifdef COMPAT_43 1271 /* 1272 * Create a file. 1273 */ 1274 #ifndef _SYS_SYSPROTO_H_ 1275 struct ocreat_args { 1276 char *path; 1277 int mode; 1278 }; 1279 #endif 1280 int 1281 ocreat(td, uap) 1282 struct thread *td; 1283 register struct ocreat_args /* { 1284 syscallarg(char *) path; 1285 syscallarg(int) mode; 1286 } */ *uap; 1287 { 1288 struct open_args /* { 1289 syscallarg(char *) path; 1290 syscallarg(int) flags; 1291 syscallarg(int) mode; 1292 } */ nuap; 1293 1294 SCARG(&nuap, path) = SCARG(uap, path); 1295 SCARG(&nuap, mode) = SCARG(uap, mode); 1296 SCARG(&nuap, flags) = O_WRONLY | O_CREAT | O_TRUNC; 1297 return (open(td, &nuap)); 1298 } 1299 #endif /* COMPAT_43 */ 1300 1301 /* 1302 * Create a special file. 1303 */ 1304 #ifndef _SYS_SYSPROTO_H_ 1305 struct mknod_args { 1306 char *path; 1307 int mode; 1308 int dev; 1309 }; 1310 #endif 1311 /* ARGSUSED */ 1312 int 1313 mknod(td, uap) 1314 struct thread *td; 1315 register struct mknod_args /* { 1316 syscallarg(char *) path; 1317 syscallarg(int) mode; 1318 syscallarg(int) dev; 1319 } */ *uap; 1320 { 1321 struct vnode *vp; 1322 struct mount *mp; 1323 struct vattr vattr; 1324 int error; 1325 int whiteout = 0; 1326 struct nameidata nd; 1327 1328 switch (SCARG(uap, mode) & S_IFMT) { 1329 case S_IFCHR: 1330 case S_IFBLK: 1331 error = suser_td(td); 1332 break; 1333 default: 1334 error = suser_xxx(0, td->td_proc, PRISON_ROOT); 1335 break; 1336 } 1337 if (error) 1338 return (error); 1339 restart: 1340 bwillwrite(); 1341 NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, SCARG(uap, path), td); 1342 if ((error = namei(&nd)) != 0) 1343 return (error); 1344 vp = nd.ni_vp; 1345 if (vp != NULL) { 1346 vrele(vp); 1347 error = EEXIST; 1348 } else { 1349 VATTR_NULL(&vattr); 1350 FILEDESC_LOCK(td->td_proc->p_fd); 1351 vattr.va_mode = (SCARG(uap, mode) & ALLPERMS) &~ td->td_proc->p_fd->fd_cmask; 1352 FILEDESC_UNLOCK(td->td_proc->p_fd); 1353 vattr.va_rdev = SCARG(uap, dev); 1354 whiteout = 0; 1355 1356 switch (SCARG(uap, mode) & S_IFMT) { 1357 case S_IFMT: /* used by badsect to flag bad sectors */ 1358 vattr.va_type = VBAD; 1359 break; 1360 case S_IFCHR: 1361 vattr.va_type = VCHR; 1362 break; 1363 case S_IFBLK: 1364 vattr.va_type = VBLK; 1365 break; 1366 case S_IFWHT: 1367 whiteout = 1; 1368 break; 1369 default: 1370 error = EINVAL; 1371 break; 1372 } 1373 } 1374 if (vn_start_write(nd.ni_dvp, &mp, V_NOWAIT) != 0) { 1375 NDFREE(&nd, NDF_ONLY_PNBUF); 1376 vput(nd.ni_dvp); 1377 if ((error = vn_start_write(NULL, &mp, V_XSLEEP | PCATCH)) != 0) 1378 return (error); 1379 goto restart; 1380 } 1381 if (!error) { 1382 VOP_LEASE(nd.ni_dvp, td, td->td_proc->p_ucred, LEASE_WRITE); 1383 if (whiteout) 1384 error = VOP_WHITEOUT(nd.ni_dvp, &nd.ni_cnd, CREATE); 1385 else { 1386 error = VOP_MKNOD(nd.ni_dvp, &nd.ni_vp, 1387 &nd.ni_cnd, &vattr); 1388 if (error == 0) 1389 vput(nd.ni_vp); 1390 } 1391 } 1392 NDFREE(&nd, NDF_ONLY_PNBUF); 1393 vput(nd.ni_dvp); 1394 vn_finished_write(mp); 1395 ASSERT_VOP_UNLOCKED(nd.ni_dvp, "mknod"); 1396 ASSERT_VOP_UNLOCKED(nd.ni_vp, "mknod"); 1397 return (error); 1398 } 1399 1400 /* 1401 * Create a named pipe. 1402 */ 1403 #ifndef _SYS_SYSPROTO_H_ 1404 struct mkfifo_args { 1405 char *path; 1406 int mode; 1407 }; 1408 #endif 1409 /* ARGSUSED */ 1410 int 1411 mkfifo(td, uap) 1412 struct thread *td; 1413 register struct mkfifo_args /* { 1414 syscallarg(char *) path; 1415 syscallarg(int) mode; 1416 } */ *uap; 1417 { 1418 struct mount *mp; 1419 struct vattr vattr; 1420 int error; 1421 struct nameidata nd; 1422 1423 restart: 1424 bwillwrite(); 1425 NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, SCARG(uap, path), td); 1426 if ((error = namei(&nd)) != 0) 1427 return (error); 1428 if (nd.ni_vp != NULL) { 1429 NDFREE(&nd, NDF_ONLY_PNBUF); 1430 vrele(nd.ni_vp); 1431 vput(nd.ni_dvp); 1432 return (EEXIST); 1433 } 1434 if (vn_start_write(nd.ni_dvp, &mp, V_NOWAIT) != 0) { 1435 NDFREE(&nd, NDF_ONLY_PNBUF); 1436 vput(nd.ni_dvp); 1437 if ((error = vn_start_write(NULL, &mp, V_XSLEEP | PCATCH)) != 0) 1438 return (error); 1439 goto restart; 1440 } 1441 VATTR_NULL(&vattr); 1442 vattr.va_type = VFIFO; 1443 FILEDESC_LOCK(td->td_proc->p_fd); 1444 vattr.va_mode = (SCARG(uap, mode) & ALLPERMS) &~ td->td_proc->p_fd->fd_cmask; 1445 FILEDESC_UNLOCK(td->td_proc->p_fd); 1446 VOP_LEASE(nd.ni_dvp, td, td->td_proc->p_ucred, LEASE_WRITE); 1447 error = VOP_MKNOD(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr); 1448 if (error == 0) 1449 vput(nd.ni_vp); 1450 NDFREE(&nd, NDF_ONLY_PNBUF); 1451 vput(nd.ni_dvp); 1452 vn_finished_write(mp); 1453 return (error); 1454 } 1455 1456 /* 1457 * Make a hard file link. 1458 */ 1459 #ifndef _SYS_SYSPROTO_H_ 1460 struct link_args { 1461 char *path; 1462 char *link; 1463 }; 1464 #endif 1465 /* ARGSUSED */ 1466 int 1467 link(td, uap) 1468 struct thread *td; 1469 register struct link_args /* { 1470 syscallarg(char *) path; 1471 syscallarg(char *) link; 1472 } */ *uap; 1473 { 1474 struct vnode *vp; 1475 struct mount *mp; 1476 struct nameidata nd; 1477 int error; 1478 1479 bwillwrite(); 1480 NDINIT(&nd, LOOKUP, FOLLOW|NOOBJ, UIO_USERSPACE, SCARG(uap, path), td); 1481 if ((error = namei(&nd)) != 0) 1482 return (error); 1483 NDFREE(&nd, NDF_ONLY_PNBUF); 1484 vp = nd.ni_vp; 1485 if (vp->v_type == VDIR) { 1486 vrele(vp); 1487 return (EPERM); /* POSIX */ 1488 } 1489 if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0) { 1490 vrele(vp); 1491 return (error); 1492 } 1493 NDINIT(&nd, CREATE, LOCKPARENT|NOOBJ, UIO_USERSPACE, SCARG(uap, link), td); 1494 if ((error = namei(&nd)) == 0) { 1495 if (nd.ni_vp != NULL) { 1496 vrele(nd.ni_vp); 1497 error = EEXIST; 1498 } else { 1499 VOP_LEASE(nd.ni_dvp, td, td->td_proc->p_ucred, LEASE_WRITE); 1500 VOP_LEASE(vp, td, td->td_proc->p_ucred, LEASE_WRITE); 1501 error = VOP_LINK(nd.ni_dvp, vp, &nd.ni_cnd); 1502 } 1503 NDFREE(&nd, NDF_ONLY_PNBUF); 1504 vput(nd.ni_dvp); 1505 } 1506 vrele(vp); 1507 vn_finished_write(mp); 1508 ASSERT_VOP_UNLOCKED(nd.ni_dvp, "link"); 1509 ASSERT_VOP_UNLOCKED(nd.ni_vp, "link"); 1510 return (error); 1511 } 1512 1513 /* 1514 * Make a symbolic link. 1515 */ 1516 #ifndef _SYS_SYSPROTO_H_ 1517 struct symlink_args { 1518 char *path; 1519 char *link; 1520 }; 1521 #endif 1522 /* ARGSUSED */ 1523 int 1524 symlink(td, uap) 1525 struct thread *td; 1526 register struct symlink_args /* { 1527 syscallarg(char *) path; 1528 syscallarg(char *) link; 1529 } */ *uap; 1530 { 1531 struct mount *mp; 1532 struct vattr vattr; 1533 char *path; 1534 int error; 1535 struct nameidata nd; 1536 1537 path = zalloc(namei_zone); 1538 if ((error = copyinstr(SCARG(uap, path), path, MAXPATHLEN, NULL)) != 0) 1539 goto out; 1540 restart: 1541 bwillwrite(); 1542 NDINIT(&nd, CREATE, LOCKPARENT|NOOBJ, UIO_USERSPACE, SCARG(uap, link), td); 1543 if ((error = namei(&nd)) != 0) 1544 goto out; 1545 if (nd.ni_vp) { 1546 NDFREE(&nd, NDF_ONLY_PNBUF); 1547 vrele(nd.ni_vp); 1548 vput(nd.ni_dvp); 1549 error = EEXIST; 1550 goto out; 1551 } 1552 if (vn_start_write(nd.ni_dvp, &mp, V_NOWAIT) != 0) { 1553 NDFREE(&nd, NDF_ONLY_PNBUF); 1554 vput(nd.ni_dvp); 1555 if ((error = vn_start_write(NULL, &mp, V_XSLEEP | PCATCH)) != 0) 1556 return (error); 1557 goto restart; 1558 } 1559 VATTR_NULL(&vattr); 1560 FILEDESC_LOCK(td->td_proc->p_fd); 1561 vattr.va_mode = ACCESSPERMS &~ td->td_proc->p_fd->fd_cmask; 1562 FILEDESC_UNLOCK(td->td_proc->p_fd); 1563 VOP_LEASE(nd.ni_dvp, td, td->td_proc->p_ucred, LEASE_WRITE); 1564 error = VOP_SYMLINK(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr, path); 1565 NDFREE(&nd, NDF_ONLY_PNBUF); 1566 if (error == 0) 1567 vput(nd.ni_vp); 1568 vput(nd.ni_dvp); 1569 vn_finished_write(mp); 1570 ASSERT_VOP_UNLOCKED(nd.ni_dvp, "symlink"); 1571 ASSERT_VOP_UNLOCKED(nd.ni_vp, "symlink"); 1572 out: 1573 zfree(namei_zone, path); 1574 return (error); 1575 } 1576 1577 /* 1578 * Delete a whiteout from the filesystem. 1579 */ 1580 /* ARGSUSED */ 1581 int 1582 undelete(td, uap) 1583 struct thread *td; 1584 register struct undelete_args /* { 1585 syscallarg(char *) path; 1586 } */ *uap; 1587 { 1588 int error; 1589 struct mount *mp; 1590 struct nameidata nd; 1591 1592 restart: 1593 bwillwrite(); 1594 NDINIT(&nd, DELETE, LOCKPARENT|DOWHITEOUT, UIO_USERSPACE, 1595 SCARG(uap, path), td); 1596 error = namei(&nd); 1597 if (error) 1598 return (error); 1599 1600 if (nd.ni_vp != NULLVP || !(nd.ni_cnd.cn_flags & ISWHITEOUT)) { 1601 NDFREE(&nd, NDF_ONLY_PNBUF); 1602 if (nd.ni_vp) 1603 vrele(nd.ni_vp); 1604 vput(nd.ni_dvp); 1605 return (EEXIST); 1606 } 1607 if (vn_start_write(nd.ni_dvp, &mp, V_NOWAIT) != 0) { 1608 NDFREE(&nd, NDF_ONLY_PNBUF); 1609 vput(nd.ni_dvp); 1610 if ((error = vn_start_write(NULL, &mp, V_XSLEEP | PCATCH)) != 0) 1611 return (error); 1612 goto restart; 1613 } 1614 VOP_LEASE(nd.ni_dvp, td, td->td_proc->p_ucred, LEASE_WRITE); 1615 error = VOP_WHITEOUT(nd.ni_dvp, &nd.ni_cnd, DELETE); 1616 NDFREE(&nd, NDF_ONLY_PNBUF); 1617 vput(nd.ni_dvp); 1618 vn_finished_write(mp); 1619 ASSERT_VOP_UNLOCKED(nd.ni_dvp, "undelete"); 1620 ASSERT_VOP_UNLOCKED(nd.ni_vp, "undelete"); 1621 return (error); 1622 } 1623 1624 /* 1625 * Delete a name from the filesystem. 1626 */ 1627 #ifndef _SYS_SYSPROTO_H_ 1628 struct unlink_args { 1629 char *path; 1630 }; 1631 #endif 1632 /* ARGSUSED */ 1633 int 1634 unlink(td, uap) 1635 struct thread *td; 1636 struct unlink_args /* { 1637 syscallarg(char *) path; 1638 } */ *uap; 1639 { 1640 struct mount *mp; 1641 struct vnode *vp; 1642 int error; 1643 struct nameidata nd; 1644 1645 restart: 1646 bwillwrite(); 1647 NDINIT(&nd, DELETE, LOCKPARENT, UIO_USERSPACE, SCARG(uap, path), td); 1648 if ((error = namei(&nd)) != 0) 1649 return (error); 1650 vp = nd.ni_vp; 1651 if (vp->v_type == VDIR) 1652 error = EPERM; /* POSIX */ 1653 else { 1654 /* 1655 * The root of a mounted filesystem cannot be deleted. 1656 * 1657 * XXX: can this only be a VDIR case? 1658 */ 1659 if (vp->v_flag & VROOT) 1660 error = EBUSY; 1661 } 1662 if (vn_start_write(nd.ni_dvp, &mp, V_NOWAIT) != 0) { 1663 NDFREE(&nd, NDF_ONLY_PNBUF); 1664 vrele(vp); 1665 vput(nd.ni_dvp); 1666 if ((error = vn_start_write(NULL, &mp, V_XSLEEP | PCATCH)) != 0) 1667 return (error); 1668 goto restart; 1669 } 1670 VOP_LEASE(vp, td, td->td_proc->p_ucred, LEASE_WRITE); 1671 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 1672 if (!error) { 1673 VOP_LEASE(nd.ni_dvp, td, td->td_proc->p_ucred, LEASE_WRITE); 1674 error = VOP_REMOVE(nd.ni_dvp, vp, &nd.ni_cnd); 1675 } 1676 NDFREE(&nd, NDF_ONLY_PNBUF); 1677 vput(nd.ni_dvp); 1678 vput(vp); 1679 vn_finished_write(mp); 1680 ASSERT_VOP_UNLOCKED(nd.ni_dvp, "unlink"); 1681 ASSERT_VOP_UNLOCKED(nd.ni_vp, "unlink"); 1682 return (error); 1683 } 1684 1685 /* 1686 * Reposition read/write file offset. 1687 */ 1688 #ifndef _SYS_SYSPROTO_H_ 1689 struct lseek_args { 1690 int fd; 1691 int pad; 1692 off_t offset; 1693 int whence; 1694 }; 1695 #endif 1696 int 1697 lseek(td, uap) 1698 struct thread *td; 1699 register struct lseek_args /* { 1700 syscallarg(int) fd; 1701 syscallarg(int) pad; 1702 syscallarg(off_t) offset; 1703 syscallarg(int) whence; 1704 } */ *uap; 1705 { 1706 struct ucred *cred = td->td_proc->p_ucred; 1707 struct file *fp; 1708 struct vnode *vp; 1709 struct vattr vattr; 1710 off_t offset; 1711 int error, noneg; 1712 1713 if ((error = fget(td, uap->fd, &fp)) != 0) 1714 return (error); 1715 if (fp->f_type != DTYPE_VNODE) { 1716 fdrop(fp, td); 1717 return (ESPIPE); 1718 } 1719 vp = (struct vnode *)fp->f_data; 1720 noneg = (vp->v_type != VCHR); 1721 offset = SCARG(uap, offset); 1722 switch (SCARG(uap, whence)) { 1723 case L_INCR: 1724 if (noneg && 1725 (fp->f_offset < 0 || 1726 (offset > 0 && fp->f_offset > OFF_MAX - offset))) 1727 return (EOVERFLOW); 1728 offset += fp->f_offset; 1729 break; 1730 case L_XTND: 1731 error = VOP_GETATTR(vp, &vattr, cred, td); 1732 if (error) 1733 return (error); 1734 if (noneg && 1735 (vattr.va_size > OFF_MAX || 1736 (offset > 0 && vattr.va_size > OFF_MAX - offset))) 1737 return (EOVERFLOW); 1738 offset += vattr.va_size; 1739 break; 1740 case L_SET: 1741 break; 1742 default: 1743 fdrop(fp, td); 1744 return (EINVAL); 1745 } 1746 if (noneg && offset < 0) 1747 return (EINVAL); 1748 fp->f_offset = offset; 1749 *(off_t *)(td->td_retval) = fp->f_offset; 1750 fdrop(fp, td); 1751 return (0); 1752 } 1753 1754 #if defined(COMPAT_43) || defined(COMPAT_SUNOS) 1755 /* 1756 * Reposition read/write file offset. 1757 */ 1758 #ifndef _SYS_SYSPROTO_H_ 1759 struct olseek_args { 1760 int fd; 1761 long offset; 1762 int whence; 1763 }; 1764 #endif 1765 int 1766 olseek(td, uap) 1767 struct thread *td; 1768 register struct olseek_args /* { 1769 syscallarg(int) fd; 1770 syscallarg(long) offset; 1771 syscallarg(int) whence; 1772 } */ *uap; 1773 { 1774 struct lseek_args /* { 1775 syscallarg(int) fd; 1776 syscallarg(int) pad; 1777 syscallarg(off_t) offset; 1778 syscallarg(int) whence; 1779 } */ nuap; 1780 int error; 1781 1782 SCARG(&nuap, fd) = SCARG(uap, fd); 1783 SCARG(&nuap, offset) = SCARG(uap, offset); 1784 SCARG(&nuap, whence) = SCARG(uap, whence); 1785 error = lseek(td, &nuap); 1786 return (error); 1787 } 1788 #endif /* COMPAT_43 */ 1789 1790 /* 1791 * Check access permissions using passed credentials. 1792 */ 1793 static int 1794 vn_access(vp, user_flags, cred, td) 1795 struct vnode *vp; 1796 int user_flags; 1797 struct ucred *cred; 1798 struct thread *td; 1799 { 1800 int error, flags; 1801 1802 /* Flags == 0 means only check for existence. */ 1803 error = 0; 1804 if (user_flags) { 1805 flags = 0; 1806 if (user_flags & R_OK) 1807 flags |= VREAD; 1808 if (user_flags & W_OK) 1809 flags |= VWRITE; 1810 if (user_flags & X_OK) 1811 flags |= VEXEC; 1812 if ((flags & VWRITE) == 0 || (error = vn_writechk(vp)) == 0) 1813 error = VOP_ACCESS(vp, flags, cred, td); 1814 } 1815 return (error); 1816 } 1817 1818 /* 1819 * Check access permissions using "real" credentials. 1820 */ 1821 #ifndef _SYS_SYSPROTO_H_ 1822 struct access_args { 1823 char *path; 1824 int flags; 1825 }; 1826 #endif 1827 int 1828 access(td, uap) 1829 struct thread *td; 1830 register struct access_args /* { 1831 syscallarg(char *) path; 1832 syscallarg(int) flags; 1833 } */ *uap; 1834 { 1835 struct ucred *cred, *tmpcred; 1836 register struct vnode *vp; 1837 int error; 1838 struct nameidata nd; 1839 1840 cred = td->td_proc->p_ucred; 1841 /* 1842 * Create and modify a temporary credential instead of one that 1843 * is potentially shared. This could also mess up socket 1844 * buffer accounting which can run in an interrupt context. 1845 * 1846 * XXX - Depending on how "threads" are finally implemented, it 1847 * may be better to explicitly pass the credential to namei() 1848 * rather than to modify the potentially shared process structure. 1849 */ 1850 tmpcred = crdup(cred); 1851 tmpcred->cr_uid = cred->cr_ruid; 1852 tmpcred->cr_groups[0] = cred->cr_rgid; 1853 td->td_proc->p_ucred = tmpcred; 1854 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE, 1855 SCARG(uap, path), td); 1856 if ((error = namei(&nd)) != 0) 1857 goto out1; 1858 vp = nd.ni_vp; 1859 1860 error = vn_access(vp, SCARG(uap, flags), tmpcred, td); 1861 NDFREE(&nd, NDF_ONLY_PNBUF); 1862 vput(vp); 1863 out1: 1864 td->td_proc->p_ucred = cred; 1865 crfree(tmpcred); 1866 return (error); 1867 } 1868 1869 /* 1870 * Check access permissions using "effective" credentials. 1871 */ 1872 #ifndef _SYS_SYSPROTO_H_ 1873 struct eaccess_args { 1874 char *path; 1875 int flags; 1876 }; 1877 #endif 1878 int 1879 eaccess(td, uap) 1880 struct thread *td; 1881 register struct eaccess_args /* { 1882 syscallarg(char *) path; 1883 syscallarg(int) flags; 1884 } */ *uap; 1885 { 1886 struct nameidata nd; 1887 struct vnode *vp; 1888 int error; 1889 1890 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE, 1891 SCARG(uap, path), td); 1892 if ((error = namei(&nd)) != 0) 1893 return (error); 1894 vp = nd.ni_vp; 1895 1896 error = vn_access(vp, SCARG(uap, flags), td->td_proc->p_ucred, td); 1897 NDFREE(&nd, NDF_ONLY_PNBUF); 1898 vput(vp); 1899 return (error); 1900 } 1901 1902 #if defined(COMPAT_43) || defined(COMPAT_SUNOS) 1903 /* 1904 * Get file status; this version follows links. 1905 */ 1906 #ifndef _SYS_SYSPROTO_H_ 1907 struct ostat_args { 1908 char *path; 1909 struct ostat *ub; 1910 }; 1911 #endif 1912 /* ARGSUSED */ 1913 int 1914 ostat(td, uap) 1915 struct thread *td; 1916 register struct ostat_args /* { 1917 syscallarg(char *) path; 1918 syscallarg(struct ostat *) ub; 1919 } */ *uap; 1920 { 1921 struct stat sb; 1922 struct ostat osb; 1923 int error; 1924 struct nameidata nd; 1925 1926 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE, 1927 SCARG(uap, path), td); 1928 if ((error = namei(&nd)) != 0) 1929 return (error); 1930 NDFREE(&nd, NDF_ONLY_PNBUF); 1931 error = vn_stat(nd.ni_vp, &sb, td); 1932 vput(nd.ni_vp); 1933 if (error) 1934 return (error); 1935 cvtstat(&sb, &osb); 1936 error = copyout((caddr_t)&osb, (caddr_t)SCARG(uap, ub), sizeof (osb)); 1937 return (error); 1938 } 1939 1940 /* 1941 * Get file status; this version does not follow links. 1942 */ 1943 #ifndef _SYS_SYSPROTO_H_ 1944 struct olstat_args { 1945 char *path; 1946 struct ostat *ub; 1947 }; 1948 #endif 1949 /* ARGSUSED */ 1950 int 1951 olstat(td, uap) 1952 struct thread *td; 1953 register struct olstat_args /* { 1954 syscallarg(char *) path; 1955 syscallarg(struct ostat *) ub; 1956 } */ *uap; 1957 { 1958 struct vnode *vp; 1959 struct stat sb; 1960 struct ostat osb; 1961 int error; 1962 struct nameidata nd; 1963 1964 NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE, 1965 SCARG(uap, path), td); 1966 if ((error = namei(&nd)) != 0) 1967 return (error); 1968 vp = nd.ni_vp; 1969 error = vn_stat(vp, &sb, td); 1970 NDFREE(&nd, NDF_ONLY_PNBUF); 1971 vput(vp); 1972 if (error) 1973 return (error); 1974 cvtstat(&sb, &osb); 1975 error = copyout((caddr_t)&osb, (caddr_t)SCARG(uap, ub), sizeof (osb)); 1976 return (error); 1977 } 1978 1979 /* 1980 * Convert from an old to a new stat structure. 1981 */ 1982 void 1983 cvtstat(st, ost) 1984 struct stat *st; 1985 struct ostat *ost; 1986 { 1987 1988 ost->st_dev = st->st_dev; 1989 ost->st_ino = st->st_ino; 1990 ost->st_mode = st->st_mode; 1991 ost->st_nlink = st->st_nlink; 1992 ost->st_uid = st->st_uid; 1993 ost->st_gid = st->st_gid; 1994 ost->st_rdev = st->st_rdev; 1995 if (st->st_size < (quad_t)1 << 32) 1996 ost->st_size = st->st_size; 1997 else 1998 ost->st_size = -2; 1999 ost->st_atime = st->st_atime; 2000 ost->st_mtime = st->st_mtime; 2001 ost->st_ctime = st->st_ctime; 2002 ost->st_blksize = st->st_blksize; 2003 ost->st_blocks = st->st_blocks; 2004 ost->st_flags = st->st_flags; 2005 ost->st_gen = st->st_gen; 2006 } 2007 #endif /* COMPAT_43 || COMPAT_SUNOS */ 2008 2009 /* 2010 * Get file status; this version follows links. 2011 */ 2012 #ifndef _SYS_SYSPROTO_H_ 2013 struct stat_args { 2014 char *path; 2015 struct stat *ub; 2016 }; 2017 #endif 2018 /* ARGSUSED */ 2019 int 2020 stat(td, uap) 2021 struct thread *td; 2022 register struct stat_args /* { 2023 syscallarg(char *) path; 2024 syscallarg(struct stat *) ub; 2025 } */ *uap; 2026 { 2027 struct stat sb; 2028 int error; 2029 struct nameidata nd; 2030 2031 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE, 2032 SCARG(uap, path), td); 2033 if ((error = namei(&nd)) != 0) 2034 return (error); 2035 error = vn_stat(nd.ni_vp, &sb, td); 2036 NDFREE(&nd, NDF_ONLY_PNBUF); 2037 vput(nd.ni_vp); 2038 if (error) 2039 return (error); 2040 error = copyout((caddr_t)&sb, (caddr_t)SCARG(uap, ub), sizeof (sb)); 2041 return (error); 2042 } 2043 2044 /* 2045 * Get file status; this version does not follow links. 2046 */ 2047 #ifndef _SYS_SYSPROTO_H_ 2048 struct lstat_args { 2049 char *path; 2050 struct stat *ub; 2051 }; 2052 #endif 2053 /* ARGSUSED */ 2054 int 2055 lstat(td, uap) 2056 struct thread *td; 2057 register struct lstat_args /* { 2058 syscallarg(char *) path; 2059 syscallarg(struct stat *) ub; 2060 } */ *uap; 2061 { 2062 int error; 2063 struct vnode *vp; 2064 struct stat sb; 2065 struct nameidata nd; 2066 2067 NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE, 2068 SCARG(uap, path), td); 2069 if ((error = namei(&nd)) != 0) 2070 return (error); 2071 vp = nd.ni_vp; 2072 error = vn_stat(vp, &sb, td); 2073 NDFREE(&nd, NDF_ONLY_PNBUF); 2074 vput(vp); 2075 if (error) 2076 return (error); 2077 error = copyout((caddr_t)&sb, (caddr_t)SCARG(uap, ub), sizeof (sb)); 2078 return (error); 2079 } 2080 2081 /* 2082 * Implementation of the NetBSD stat() function. 2083 * XXX This should probably be collapsed with the FreeBSD version, 2084 * as the differences are only due to vn_stat() clearing spares at 2085 * the end of the structures. vn_stat could be split to avoid this, 2086 * and thus collapse the following to close to zero code. 2087 */ 2088 void 2089 cvtnstat(sb, nsb) 2090 struct stat *sb; 2091 struct nstat *nsb; 2092 { 2093 nsb->st_dev = sb->st_dev; 2094 nsb->st_ino = sb->st_ino; 2095 nsb->st_mode = sb->st_mode; 2096 nsb->st_nlink = sb->st_nlink; 2097 nsb->st_uid = sb->st_uid; 2098 nsb->st_gid = sb->st_gid; 2099 nsb->st_rdev = sb->st_rdev; 2100 nsb->st_atimespec = sb->st_atimespec; 2101 nsb->st_mtimespec = sb->st_mtimespec; 2102 nsb->st_ctimespec = sb->st_ctimespec; 2103 nsb->st_size = sb->st_size; 2104 nsb->st_blocks = sb->st_blocks; 2105 nsb->st_blksize = sb->st_blksize; 2106 nsb->st_flags = sb->st_flags; 2107 nsb->st_gen = sb->st_gen; 2108 nsb->st_qspare[0] = sb->st_qspare[0]; 2109 nsb->st_qspare[1] = sb->st_qspare[1]; 2110 } 2111 2112 #ifndef _SYS_SYSPROTO_H_ 2113 struct nstat_args { 2114 char *path; 2115 struct nstat *ub; 2116 }; 2117 #endif 2118 /* ARGSUSED */ 2119 int 2120 nstat(td, uap) 2121 struct thread *td; 2122 register struct nstat_args /* { 2123 syscallarg(char *) path; 2124 syscallarg(struct nstat *) ub; 2125 } */ *uap; 2126 { 2127 struct stat sb; 2128 struct nstat nsb; 2129 int error; 2130 struct nameidata nd; 2131 2132 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE, 2133 SCARG(uap, path), td); 2134 if ((error = namei(&nd)) != 0) 2135 return (error); 2136 NDFREE(&nd, NDF_ONLY_PNBUF); 2137 error = vn_stat(nd.ni_vp, &sb, td); 2138 vput(nd.ni_vp); 2139 if (error) 2140 return (error); 2141 cvtnstat(&sb, &nsb); 2142 error = copyout((caddr_t)&nsb, (caddr_t)SCARG(uap, ub), sizeof (nsb)); 2143 return (error); 2144 } 2145 2146 /* 2147 * NetBSD lstat. Get file status; this version does not follow links. 2148 */ 2149 #ifndef _SYS_SYSPROTO_H_ 2150 struct lstat_args { 2151 char *path; 2152 struct stat *ub; 2153 }; 2154 #endif 2155 /* ARGSUSED */ 2156 int 2157 nlstat(td, uap) 2158 struct thread *td; 2159 register struct nlstat_args /* { 2160 syscallarg(char *) path; 2161 syscallarg(struct nstat *) ub; 2162 } */ *uap; 2163 { 2164 int error; 2165 struct vnode *vp; 2166 struct stat sb; 2167 struct nstat nsb; 2168 struct nameidata nd; 2169 2170 NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE, 2171 SCARG(uap, path), td); 2172 if ((error = namei(&nd)) != 0) 2173 return (error); 2174 vp = nd.ni_vp; 2175 NDFREE(&nd, NDF_ONLY_PNBUF); 2176 error = vn_stat(vp, &sb, td); 2177 vput(vp); 2178 if (error) 2179 return (error); 2180 cvtnstat(&sb, &nsb); 2181 error = copyout((caddr_t)&nsb, (caddr_t)SCARG(uap, ub), sizeof (nsb)); 2182 return (error); 2183 } 2184 2185 /* 2186 * Get configurable pathname variables. 2187 */ 2188 #ifndef _SYS_SYSPROTO_H_ 2189 struct pathconf_args { 2190 char *path; 2191 int name; 2192 }; 2193 #endif 2194 /* ARGSUSED */ 2195 int 2196 pathconf(td, uap) 2197 struct thread *td; 2198 register struct pathconf_args /* { 2199 syscallarg(char *) path; 2200 syscallarg(int) name; 2201 } */ *uap; 2202 { 2203 int error; 2204 struct nameidata nd; 2205 2206 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE, 2207 SCARG(uap, path), td); 2208 if ((error = namei(&nd)) != 0) 2209 return (error); 2210 NDFREE(&nd, NDF_ONLY_PNBUF); 2211 error = VOP_PATHCONF(nd.ni_vp, SCARG(uap, name), td->td_retval); 2212 vput(nd.ni_vp); 2213 return (error); 2214 } 2215 2216 /* 2217 * Return target name of a symbolic link. 2218 */ 2219 #ifndef _SYS_SYSPROTO_H_ 2220 struct readlink_args { 2221 char *path; 2222 char *buf; 2223 int count; 2224 }; 2225 #endif 2226 /* ARGSUSED */ 2227 int 2228 readlink(td, uap) 2229 struct thread *td; 2230 register struct readlink_args /* { 2231 syscallarg(char *) path; 2232 syscallarg(char *) buf; 2233 syscallarg(int) count; 2234 } */ *uap; 2235 { 2236 register struct vnode *vp; 2237 struct iovec aiov; 2238 struct uio auio; 2239 int error; 2240 struct nameidata nd; 2241 2242 NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF | NOOBJ, UIO_USERSPACE, 2243 SCARG(uap, path), td); 2244 if ((error = namei(&nd)) != 0) 2245 return (error); 2246 NDFREE(&nd, NDF_ONLY_PNBUF); 2247 vp = nd.ni_vp; 2248 if (vp->v_type != VLNK) 2249 error = EINVAL; 2250 else { 2251 aiov.iov_base = SCARG(uap, buf); 2252 aiov.iov_len = SCARG(uap, count); 2253 auio.uio_iov = &aiov; 2254 auio.uio_iovcnt = 1; 2255 auio.uio_offset = 0; 2256 auio.uio_rw = UIO_READ; 2257 auio.uio_segflg = UIO_USERSPACE; 2258 auio.uio_td = td; 2259 auio.uio_resid = SCARG(uap, count); 2260 error = VOP_READLINK(vp, &auio, td->td_proc->p_ucred); 2261 } 2262 vput(vp); 2263 td->td_retval[0] = SCARG(uap, count) - auio.uio_resid; 2264 return (error); 2265 } 2266 2267 /* 2268 * Common implementation code for chflags() and fchflags(). 2269 */ 2270 static int 2271 setfflags(td, vp, flags) 2272 struct thread *td; 2273 struct vnode *vp; 2274 int flags; 2275 { 2276 int error; 2277 struct mount *mp; 2278 struct vattr vattr; 2279 2280 /* 2281 * Prevent non-root users from setting flags on devices. When 2282 * a device is reused, users can retain ownership of the device 2283 * if they are allowed to set flags and programs assume that 2284 * chown can't fail when done as root. 2285 */ 2286 if (vp->v_type == VCHR || vp->v_type == VBLK) { 2287 error = suser_xxx(td->td_proc->p_ucred, td->td_proc, 2288 PRISON_ROOT); 2289 if (error) 2290 return (error); 2291 } 2292 2293 if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0) 2294 return (error); 2295 VOP_LEASE(vp, td, td->td_proc->p_ucred, LEASE_WRITE); 2296 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 2297 VATTR_NULL(&vattr); 2298 vattr.va_flags = flags; 2299 error = VOP_SETATTR(vp, &vattr, td->td_proc->p_ucred, td); 2300 VOP_UNLOCK(vp, 0, td); 2301 vn_finished_write(mp); 2302 return (error); 2303 } 2304 2305 /* 2306 * Change flags of a file given a path name. 2307 */ 2308 #ifndef _SYS_SYSPROTO_H_ 2309 struct chflags_args { 2310 char *path; 2311 int flags; 2312 }; 2313 #endif 2314 /* ARGSUSED */ 2315 int 2316 chflags(td, uap) 2317 struct thread *td; 2318 register struct chflags_args /* { 2319 syscallarg(char *) path; 2320 syscallarg(int) flags; 2321 } */ *uap; 2322 { 2323 int error; 2324 struct nameidata nd; 2325 2326 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), td); 2327 if ((error = namei(&nd)) != 0) 2328 return (error); 2329 NDFREE(&nd, NDF_ONLY_PNBUF); 2330 error = setfflags(td, nd.ni_vp, SCARG(uap, flags)); 2331 vrele(nd.ni_vp); 2332 return error; 2333 } 2334 2335 /* 2336 * Change flags of a file given a file descriptor. 2337 */ 2338 #ifndef _SYS_SYSPROTO_H_ 2339 struct fchflags_args { 2340 int fd; 2341 int flags; 2342 }; 2343 #endif 2344 /* ARGSUSED */ 2345 int 2346 fchflags(td, uap) 2347 struct thread *td; 2348 register struct fchflags_args /* { 2349 syscallarg(int) fd; 2350 syscallarg(int) flags; 2351 } */ *uap; 2352 { 2353 struct file *fp; 2354 int error; 2355 2356 if ((error = getvnode(td->td_proc->p_fd, SCARG(uap, fd), &fp)) != 0) 2357 return (error); 2358 error = setfflags(td, (struct vnode *) fp->f_data, SCARG(uap, flags)); 2359 fdrop(fp, td); 2360 return (error); 2361 } 2362 2363 /* 2364 * Common implementation code for chmod(), lchmod() and fchmod(). 2365 */ 2366 static int 2367 setfmode(td, vp, mode) 2368 struct thread *td; 2369 struct vnode *vp; 2370 int mode; 2371 { 2372 int error; 2373 struct mount *mp; 2374 struct vattr vattr; 2375 2376 if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0) 2377 return (error); 2378 VOP_LEASE(vp, td, td->td_proc->p_ucred, LEASE_WRITE); 2379 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 2380 VATTR_NULL(&vattr); 2381 vattr.va_mode = mode & ALLPERMS; 2382 error = VOP_SETATTR(vp, &vattr, td->td_proc->p_ucred, td); 2383 VOP_UNLOCK(vp, 0, td); 2384 vn_finished_write(mp); 2385 return error; 2386 } 2387 2388 /* 2389 * Change mode of a file given path name. 2390 */ 2391 #ifndef _SYS_SYSPROTO_H_ 2392 struct chmod_args { 2393 char *path; 2394 int mode; 2395 }; 2396 #endif 2397 /* ARGSUSED */ 2398 int 2399 chmod(td, uap) 2400 struct thread *td; 2401 register struct chmod_args /* { 2402 syscallarg(char *) path; 2403 syscallarg(int) mode; 2404 } */ *uap; 2405 { 2406 int error; 2407 struct nameidata nd; 2408 2409 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), td); 2410 if ((error = namei(&nd)) != 0) 2411 return (error); 2412 NDFREE(&nd, NDF_ONLY_PNBUF); 2413 error = setfmode(td, nd.ni_vp, SCARG(uap, mode)); 2414 vrele(nd.ni_vp); 2415 return error; 2416 } 2417 2418 /* 2419 * Change mode of a file given path name (don't follow links.) 2420 */ 2421 #ifndef _SYS_SYSPROTO_H_ 2422 struct lchmod_args { 2423 char *path; 2424 int mode; 2425 }; 2426 #endif 2427 /* ARGSUSED */ 2428 int 2429 lchmod(td, uap) 2430 struct thread *td; 2431 register struct lchmod_args /* { 2432 syscallarg(char *) path; 2433 syscallarg(int) mode; 2434 } */ *uap; 2435 { 2436 int error; 2437 struct nameidata nd; 2438 2439 NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_USERSPACE, SCARG(uap, path), td); 2440 if ((error = namei(&nd)) != 0) 2441 return (error); 2442 NDFREE(&nd, NDF_ONLY_PNBUF); 2443 error = setfmode(td, nd.ni_vp, SCARG(uap, mode)); 2444 vrele(nd.ni_vp); 2445 return error; 2446 } 2447 2448 /* 2449 * Change mode of a file given a file descriptor. 2450 */ 2451 #ifndef _SYS_SYSPROTO_H_ 2452 struct fchmod_args { 2453 int fd; 2454 int mode; 2455 }; 2456 #endif 2457 /* ARGSUSED */ 2458 int 2459 fchmod(td, uap) 2460 struct thread *td; 2461 register struct fchmod_args /* { 2462 syscallarg(int) fd; 2463 syscallarg(int) mode; 2464 } */ *uap; 2465 { 2466 struct file *fp; 2467 struct vnode *vp; 2468 int error; 2469 2470 if ((error = getvnode(td->td_proc->p_fd, SCARG(uap, fd), &fp)) != 0) 2471 return (error); 2472 vp = (struct vnode *)fp->f_data; 2473 error = setfmode(td, (struct vnode *)fp->f_data, SCARG(uap, mode)); 2474 fdrop(fp, td); 2475 return (error); 2476 } 2477 2478 /* 2479 * Common implementation for chown(), lchown(), and fchown() 2480 */ 2481 static int 2482 setfown(td, vp, uid, gid) 2483 struct thread *td; 2484 struct vnode *vp; 2485 uid_t uid; 2486 gid_t gid; 2487 { 2488 int error; 2489 struct mount *mp; 2490 struct vattr vattr; 2491 2492 if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0) 2493 return (error); 2494 VOP_LEASE(vp, td, td->td_proc->p_ucred, LEASE_WRITE); 2495 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 2496 VATTR_NULL(&vattr); 2497 vattr.va_uid = uid; 2498 vattr.va_gid = gid; 2499 error = VOP_SETATTR(vp, &vattr, td->td_proc->p_ucred, td); 2500 VOP_UNLOCK(vp, 0, td); 2501 vn_finished_write(mp); 2502 return error; 2503 } 2504 2505 /* 2506 * Set ownership given a path name. 2507 */ 2508 #ifndef _SYS_SYSPROTO_H_ 2509 struct chown_args { 2510 char *path; 2511 int uid; 2512 int gid; 2513 }; 2514 #endif 2515 /* ARGSUSED */ 2516 int 2517 chown(td, uap) 2518 struct thread *td; 2519 register struct chown_args /* { 2520 syscallarg(char *) path; 2521 syscallarg(int) uid; 2522 syscallarg(int) gid; 2523 } */ *uap; 2524 { 2525 int error; 2526 struct nameidata nd; 2527 2528 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), td); 2529 if ((error = namei(&nd)) != 0) 2530 return (error); 2531 NDFREE(&nd, NDF_ONLY_PNBUF); 2532 error = setfown(td, nd.ni_vp, SCARG(uap, uid), SCARG(uap, gid)); 2533 vrele(nd.ni_vp); 2534 return (error); 2535 } 2536 2537 /* 2538 * Set ownership given a path name, do not cross symlinks. 2539 */ 2540 #ifndef _SYS_SYSPROTO_H_ 2541 struct lchown_args { 2542 char *path; 2543 int uid; 2544 int gid; 2545 }; 2546 #endif 2547 /* ARGSUSED */ 2548 int 2549 lchown(td, uap) 2550 struct thread *td; 2551 register struct lchown_args /* { 2552 syscallarg(char *) path; 2553 syscallarg(int) uid; 2554 syscallarg(int) gid; 2555 } */ *uap; 2556 { 2557 int error; 2558 struct nameidata nd; 2559 2560 NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_USERSPACE, SCARG(uap, path), td); 2561 if ((error = namei(&nd)) != 0) 2562 return (error); 2563 NDFREE(&nd, NDF_ONLY_PNBUF); 2564 error = setfown(td, nd.ni_vp, SCARG(uap, uid), SCARG(uap, gid)); 2565 vrele(nd.ni_vp); 2566 return (error); 2567 } 2568 2569 /* 2570 * Set ownership given a file descriptor. 2571 */ 2572 #ifndef _SYS_SYSPROTO_H_ 2573 struct fchown_args { 2574 int fd; 2575 int uid; 2576 int gid; 2577 }; 2578 #endif 2579 /* ARGSUSED */ 2580 int 2581 fchown(td, uap) 2582 struct thread *td; 2583 register struct fchown_args /* { 2584 syscallarg(int) fd; 2585 syscallarg(int) uid; 2586 syscallarg(int) gid; 2587 } */ *uap; 2588 { 2589 struct file *fp; 2590 struct vnode *vp; 2591 int error; 2592 2593 if ((error = getvnode(td->td_proc->p_fd, SCARG(uap, fd), &fp)) != 0) 2594 return (error); 2595 vp = (struct vnode *)fp->f_data; 2596 error = setfown(td, (struct vnode *)fp->f_data, 2597 SCARG(uap, uid), SCARG(uap, gid)); 2598 fdrop(fp, td); 2599 return (error); 2600 } 2601 2602 /* 2603 * Common implementation code for utimes(), lutimes(), and futimes(). 2604 */ 2605 static int 2606 getutimes(usrtvp, tsp) 2607 const struct timeval *usrtvp; 2608 struct timespec *tsp; 2609 { 2610 struct timeval tv[2]; 2611 int error; 2612 2613 if (usrtvp == NULL) { 2614 microtime(&tv[0]); 2615 TIMEVAL_TO_TIMESPEC(&tv[0], &tsp[0]); 2616 tsp[1] = tsp[0]; 2617 } else { 2618 if ((error = copyin(usrtvp, tv, sizeof (tv))) != 0) 2619 return (error); 2620 TIMEVAL_TO_TIMESPEC(&tv[0], &tsp[0]); 2621 TIMEVAL_TO_TIMESPEC(&tv[1], &tsp[1]); 2622 } 2623 return 0; 2624 } 2625 2626 /* 2627 * Common implementation code for utimes(), lutimes(), and futimes(). 2628 */ 2629 static int 2630 setutimes(td, vp, ts, nullflag) 2631 struct thread *td; 2632 struct vnode *vp; 2633 const struct timespec *ts; 2634 int nullflag; 2635 { 2636 int error; 2637 struct mount *mp; 2638 struct vattr vattr; 2639 2640 if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0) 2641 return (error); 2642 VOP_LEASE(vp, td, td->td_proc->p_ucred, LEASE_WRITE); 2643 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 2644 VATTR_NULL(&vattr); 2645 vattr.va_atime = ts[0]; 2646 vattr.va_mtime = ts[1]; 2647 if (nullflag) 2648 vattr.va_vaflags |= VA_UTIMES_NULL; 2649 error = VOP_SETATTR(vp, &vattr, td->td_proc->p_ucred, td); 2650 VOP_UNLOCK(vp, 0, td); 2651 vn_finished_write(mp); 2652 return error; 2653 } 2654 2655 /* 2656 * Set the access and modification times of a file. 2657 */ 2658 #ifndef _SYS_SYSPROTO_H_ 2659 struct utimes_args { 2660 char *path; 2661 struct timeval *tptr; 2662 }; 2663 #endif 2664 /* ARGSUSED */ 2665 int 2666 utimes(td, uap) 2667 struct thread *td; 2668 register struct utimes_args /* { 2669 syscallarg(char *) path; 2670 syscallarg(struct timeval *) tptr; 2671 } */ *uap; 2672 { 2673 struct timespec ts[2]; 2674 struct timeval *usrtvp; 2675 int error; 2676 struct nameidata nd; 2677 2678 usrtvp = SCARG(uap, tptr); 2679 if ((error = getutimes(usrtvp, ts)) != 0) 2680 return (error); 2681 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), td); 2682 if ((error = namei(&nd)) != 0) 2683 return (error); 2684 NDFREE(&nd, NDF_ONLY_PNBUF); 2685 error = setutimes(td, nd.ni_vp, ts, usrtvp == NULL); 2686 vrele(nd.ni_vp); 2687 return (error); 2688 } 2689 2690 /* 2691 * Set the access and modification times of a file. 2692 */ 2693 #ifndef _SYS_SYSPROTO_H_ 2694 struct lutimes_args { 2695 char *path; 2696 struct timeval *tptr; 2697 }; 2698 #endif 2699 /* ARGSUSED */ 2700 int 2701 lutimes(td, uap) 2702 struct thread *td; 2703 register struct lutimes_args /* { 2704 syscallarg(char *) path; 2705 syscallarg(struct timeval *) tptr; 2706 } */ *uap; 2707 { 2708 struct timespec ts[2]; 2709 struct timeval *usrtvp; 2710 int error; 2711 struct nameidata nd; 2712 2713 usrtvp = SCARG(uap, tptr); 2714 if ((error = getutimes(usrtvp, ts)) != 0) 2715 return (error); 2716 NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_USERSPACE, SCARG(uap, path), td); 2717 if ((error = namei(&nd)) != 0) 2718 return (error); 2719 NDFREE(&nd, NDF_ONLY_PNBUF); 2720 error = setutimes(td, nd.ni_vp, ts, usrtvp == NULL); 2721 vrele(nd.ni_vp); 2722 return (error); 2723 } 2724 2725 /* 2726 * Set the access and modification times of a file. 2727 */ 2728 #ifndef _SYS_SYSPROTO_H_ 2729 struct futimes_args { 2730 int fd; 2731 struct timeval *tptr; 2732 }; 2733 #endif 2734 /* ARGSUSED */ 2735 int 2736 futimes(td, uap) 2737 struct thread *td; 2738 register struct futimes_args /* { 2739 syscallarg(int ) fd; 2740 syscallarg(struct timeval *) tptr; 2741 } */ *uap; 2742 { 2743 struct timespec ts[2]; 2744 struct file *fp; 2745 struct timeval *usrtvp; 2746 int error; 2747 2748 usrtvp = SCARG(uap, tptr); 2749 if ((error = getutimes(usrtvp, ts)) != 0) 2750 return (error); 2751 if ((error = getvnode(td->td_proc->p_fd, SCARG(uap, fd), &fp)) != 0) 2752 return (error); 2753 error = setutimes(td, (struct vnode *)fp->f_data, ts, usrtvp == NULL); 2754 fdrop(fp, td); 2755 return (error); 2756 } 2757 2758 /* 2759 * Truncate a file given its path name. 2760 */ 2761 #ifndef _SYS_SYSPROTO_H_ 2762 struct truncate_args { 2763 char *path; 2764 int pad; 2765 off_t length; 2766 }; 2767 #endif 2768 /* ARGSUSED */ 2769 int 2770 truncate(td, uap) 2771 struct thread *td; 2772 register struct truncate_args /* { 2773 syscallarg(char *) path; 2774 syscallarg(int) pad; 2775 syscallarg(off_t) length; 2776 } */ *uap; 2777 { 2778 struct mount *mp; 2779 struct vnode *vp; 2780 struct vattr vattr; 2781 int error; 2782 struct nameidata nd; 2783 2784 if (uap->length < 0) 2785 return(EINVAL); 2786 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), td); 2787 if ((error = namei(&nd)) != 0) 2788 return (error); 2789 vp = nd.ni_vp; 2790 if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0) { 2791 vrele(vp); 2792 return (error); 2793 } 2794 NDFREE(&nd, NDF_ONLY_PNBUF); 2795 VOP_LEASE(vp, td, td->td_proc->p_ucred, LEASE_WRITE); 2796 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 2797 if (vp->v_type == VDIR) 2798 error = EISDIR; 2799 else if ((error = vn_writechk(vp)) == 0 && 2800 (error = VOP_ACCESS(vp, VWRITE, td->td_proc->p_ucred, td)) == 0) { 2801 VATTR_NULL(&vattr); 2802 vattr.va_size = SCARG(uap, length); 2803 error = VOP_SETATTR(vp, &vattr, td->td_proc->p_ucred, td); 2804 } 2805 vput(vp); 2806 vn_finished_write(mp); 2807 return (error); 2808 } 2809 2810 /* 2811 * Truncate a file given a file descriptor. 2812 */ 2813 #ifndef _SYS_SYSPROTO_H_ 2814 struct ftruncate_args { 2815 int fd; 2816 int pad; 2817 off_t length; 2818 }; 2819 #endif 2820 /* ARGSUSED */ 2821 int 2822 ftruncate(td, uap) 2823 struct thread *td; 2824 register struct ftruncate_args /* { 2825 syscallarg(int) fd; 2826 syscallarg(int) pad; 2827 syscallarg(off_t) length; 2828 } */ *uap; 2829 { 2830 struct mount *mp; 2831 struct vattr vattr; 2832 struct vnode *vp; 2833 struct file *fp; 2834 int error; 2835 2836 if (uap->length < 0) 2837 return(EINVAL); 2838 if ((error = getvnode(td->td_proc->p_fd, SCARG(uap, fd), &fp)) != 0) 2839 return (error); 2840 if ((fp->f_flag & FWRITE) == 0) { 2841 fdrop(fp, td); 2842 return (EINVAL); 2843 } 2844 vp = (struct vnode *)fp->f_data; 2845 if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0) { 2846 fdrop(fp, td); 2847 return (error); 2848 } 2849 VOP_LEASE(vp, td, td->td_proc->p_ucred, LEASE_WRITE); 2850 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 2851 if (vp->v_type == VDIR) 2852 error = EISDIR; 2853 else if ((error = vn_writechk(vp)) == 0) { 2854 VATTR_NULL(&vattr); 2855 vattr.va_size = SCARG(uap, length); 2856 error = VOP_SETATTR(vp, &vattr, fp->f_cred, td); 2857 } 2858 VOP_UNLOCK(vp, 0, td); 2859 vn_finished_write(mp); 2860 fdrop(fp, td); 2861 return (error); 2862 } 2863 2864 #if defined(COMPAT_43) || defined(COMPAT_SUNOS) 2865 /* 2866 * Truncate a file given its path name. 2867 */ 2868 #ifndef _SYS_SYSPROTO_H_ 2869 struct otruncate_args { 2870 char *path; 2871 long length; 2872 }; 2873 #endif 2874 /* ARGSUSED */ 2875 int 2876 otruncate(td, uap) 2877 struct thread *td; 2878 register struct otruncate_args /* { 2879 syscallarg(char *) path; 2880 syscallarg(long) length; 2881 } */ *uap; 2882 { 2883 struct truncate_args /* { 2884 syscallarg(char *) path; 2885 syscallarg(int) pad; 2886 syscallarg(off_t) length; 2887 } */ nuap; 2888 2889 SCARG(&nuap, path) = SCARG(uap, path); 2890 SCARG(&nuap, length) = SCARG(uap, length); 2891 return (truncate(td, &nuap)); 2892 } 2893 2894 /* 2895 * Truncate a file given a file descriptor. 2896 */ 2897 #ifndef _SYS_SYSPROTO_H_ 2898 struct oftruncate_args { 2899 int fd; 2900 long length; 2901 }; 2902 #endif 2903 /* ARGSUSED */ 2904 int 2905 oftruncate(td, uap) 2906 struct thread *td; 2907 register struct oftruncate_args /* { 2908 syscallarg(int) fd; 2909 syscallarg(long) length; 2910 } */ *uap; 2911 { 2912 struct ftruncate_args /* { 2913 syscallarg(int) fd; 2914 syscallarg(int) pad; 2915 syscallarg(off_t) length; 2916 } */ nuap; 2917 2918 SCARG(&nuap, fd) = SCARG(uap, fd); 2919 SCARG(&nuap, length) = SCARG(uap, length); 2920 return (ftruncate(td, &nuap)); 2921 } 2922 #endif /* COMPAT_43 || COMPAT_SUNOS */ 2923 2924 /* 2925 * Sync an open file. 2926 */ 2927 #ifndef _SYS_SYSPROTO_H_ 2928 struct fsync_args { 2929 int fd; 2930 }; 2931 #endif 2932 /* ARGSUSED */ 2933 int 2934 fsync(td, uap) 2935 struct thread *td; 2936 struct fsync_args /* { 2937 syscallarg(int) fd; 2938 } */ *uap; 2939 { 2940 struct vnode *vp; 2941 struct mount *mp; 2942 struct file *fp; 2943 vm_object_t obj; 2944 int error; 2945 2946 GIANT_REQUIRED; 2947 2948 if ((error = getvnode(td->td_proc->p_fd, SCARG(uap, fd), &fp)) != 0) 2949 return (error); 2950 vp = (struct vnode *)fp->f_data; 2951 if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0) { 2952 fdrop(fp, td); 2953 return (error); 2954 } 2955 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 2956 if (VOP_GETVOBJECT(vp, &obj) == 0) { 2957 vm_object_page_clean(obj, 0, 0, 0); 2958 } 2959 error = VOP_FSYNC(vp, fp->f_cred, MNT_WAIT, td); 2960 #ifdef SOFTUPDATES 2961 if (error == 0 && vp->v_mount && (vp->v_mount->mnt_flag & MNT_SOFTDEP)) 2962 error = softdep_fsync(vp); 2963 #endif 2964 2965 VOP_UNLOCK(vp, 0, td); 2966 vn_finished_write(mp); 2967 fdrop(fp, td); 2968 return (error); 2969 } 2970 2971 /* 2972 * Rename files. Source and destination must either both be directories, 2973 * or both not be directories. If target is a directory, it must be empty. 2974 */ 2975 #ifndef _SYS_SYSPROTO_H_ 2976 struct rename_args { 2977 char *from; 2978 char *to; 2979 }; 2980 #endif 2981 /* ARGSUSED */ 2982 int 2983 rename(td, uap) 2984 struct thread *td; 2985 register struct rename_args /* { 2986 syscallarg(char *) from; 2987 syscallarg(char *) to; 2988 } */ *uap; 2989 { 2990 struct mount *mp; 2991 struct vnode *tvp, *fvp, *tdvp; 2992 struct nameidata fromnd, tond; 2993 int error; 2994 2995 bwillwrite(); 2996 NDINIT(&fromnd, DELETE, WANTPARENT | SAVESTART, UIO_USERSPACE, 2997 SCARG(uap, from), td); 2998 if ((error = namei(&fromnd)) != 0) 2999 return (error); 3000 fvp = fromnd.ni_vp; 3001 if ((error = vn_start_write(fvp, &mp, V_WAIT | PCATCH)) != 0) { 3002 NDFREE(&fromnd, NDF_ONLY_PNBUF); 3003 vrele(fromnd.ni_dvp); 3004 vrele(fvp); 3005 goto out1; 3006 } 3007 NDINIT(&tond, RENAME, LOCKPARENT | LOCKLEAF | NOCACHE | SAVESTART | NOOBJ, 3008 UIO_USERSPACE, SCARG(uap, to), td); 3009 if (fromnd.ni_vp->v_type == VDIR) 3010 tond.ni_cnd.cn_flags |= WILLBEDIR; 3011 if ((error = namei(&tond)) != 0) { 3012 /* Translate error code for rename("dir1", "dir2/."). */ 3013 if (error == EISDIR && fvp->v_type == VDIR) 3014 error = EINVAL; 3015 NDFREE(&fromnd, NDF_ONLY_PNBUF); 3016 vrele(fromnd.ni_dvp); 3017 vrele(fvp); 3018 goto out1; 3019 } 3020 tdvp = tond.ni_dvp; 3021 tvp = tond.ni_vp; 3022 if (tvp != NULL) { 3023 if (fvp->v_type == VDIR && tvp->v_type != VDIR) { 3024 error = ENOTDIR; 3025 goto out; 3026 } else if (fvp->v_type != VDIR && tvp->v_type == VDIR) { 3027 error = EISDIR; 3028 goto out; 3029 } 3030 } 3031 if (fvp == tdvp) 3032 error = EINVAL; 3033 /* 3034 * If source is the same as the destination (that is the 3035 * same inode number with the same name in the same directory), 3036 * then there is nothing to do. 3037 */ 3038 if (fvp == tvp && fromnd.ni_dvp == tdvp && 3039 fromnd.ni_cnd.cn_namelen == tond.ni_cnd.cn_namelen && 3040 !bcmp(fromnd.ni_cnd.cn_nameptr, tond.ni_cnd.cn_nameptr, 3041 fromnd.ni_cnd.cn_namelen)) 3042 error = -1; 3043 out: 3044 if (!error) { 3045 VOP_LEASE(tdvp, td, td->td_proc->p_ucred, LEASE_WRITE); 3046 if (fromnd.ni_dvp != tdvp) { 3047 VOP_LEASE(fromnd.ni_dvp, td, td->td_proc->p_ucred, LEASE_WRITE); 3048 } 3049 if (tvp) { 3050 VOP_LEASE(tvp, td, td->td_proc->p_ucred, LEASE_WRITE); 3051 } 3052 error = VOP_RENAME(fromnd.ni_dvp, fromnd.ni_vp, &fromnd.ni_cnd, 3053 tond.ni_dvp, tond.ni_vp, &tond.ni_cnd); 3054 NDFREE(&fromnd, NDF_ONLY_PNBUF); 3055 NDFREE(&tond, NDF_ONLY_PNBUF); 3056 } else { 3057 NDFREE(&fromnd, NDF_ONLY_PNBUF); 3058 NDFREE(&tond, NDF_ONLY_PNBUF); 3059 if (tdvp == tvp) 3060 vrele(tdvp); 3061 else 3062 vput(tdvp); 3063 if (tvp) 3064 vput(tvp); 3065 vrele(fromnd.ni_dvp); 3066 vrele(fvp); 3067 } 3068 vrele(tond.ni_startdir); 3069 vn_finished_write(mp); 3070 ASSERT_VOP_UNLOCKED(fromnd.ni_dvp, "rename"); 3071 ASSERT_VOP_UNLOCKED(fromnd.ni_vp, "rename"); 3072 ASSERT_VOP_UNLOCKED(tond.ni_dvp, "rename"); 3073 ASSERT_VOP_UNLOCKED(tond.ni_vp, "rename"); 3074 out1: 3075 if (fromnd.ni_startdir) 3076 vrele(fromnd.ni_startdir); 3077 if (error == -1) 3078 return (0); 3079 return (error); 3080 } 3081 3082 /* 3083 * Make a directory file. 3084 */ 3085 #ifndef _SYS_SYSPROTO_H_ 3086 struct mkdir_args { 3087 char *path; 3088 int mode; 3089 }; 3090 #endif 3091 /* ARGSUSED */ 3092 int 3093 mkdir(td, uap) 3094 struct thread *td; 3095 register struct mkdir_args /* { 3096 syscallarg(char *) path; 3097 syscallarg(int) mode; 3098 } */ *uap; 3099 { 3100 3101 return vn_mkdir(uap->path, uap->mode, UIO_USERSPACE, td); 3102 } 3103 3104 int 3105 vn_mkdir(path, mode, segflg, td) 3106 char *path; 3107 int mode; 3108 enum uio_seg segflg; 3109 struct thread *td; 3110 { 3111 struct mount *mp; 3112 struct vnode *vp; 3113 struct vattr vattr; 3114 int error; 3115 struct nameidata nd; 3116 3117 restart: 3118 bwillwrite(); 3119 NDINIT(&nd, CREATE, LOCKPARENT, segflg, path, td); 3120 nd.ni_cnd.cn_flags |= WILLBEDIR; 3121 if ((error = namei(&nd)) != 0) 3122 return (error); 3123 vp = nd.ni_vp; 3124 if (vp != NULL) { 3125 NDFREE(&nd, NDF_ONLY_PNBUF); 3126 vrele(vp); 3127 vput(nd.ni_dvp); 3128 return (EEXIST); 3129 } 3130 if (vn_start_write(nd.ni_dvp, &mp, V_NOWAIT) != 0) { 3131 NDFREE(&nd, NDF_ONLY_PNBUF); 3132 vput(nd.ni_dvp); 3133 if ((error = vn_start_write(NULL, &mp, V_XSLEEP | PCATCH)) != 0) 3134 return (error); 3135 goto restart; 3136 } 3137 VATTR_NULL(&vattr); 3138 vattr.va_type = VDIR; 3139 FILEDESC_LOCK(td->td_proc->p_fd); 3140 vattr.va_mode = (mode & ACCESSPERMS) &~ td->td_proc->p_fd->fd_cmask; 3141 FILEDESC_UNLOCK(td->td_proc->p_fd); 3142 VOP_LEASE(nd.ni_dvp, td, td->td_proc->p_ucred, LEASE_WRITE); 3143 error = VOP_MKDIR(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr); 3144 NDFREE(&nd, NDF_ONLY_PNBUF); 3145 vput(nd.ni_dvp); 3146 if (!error) 3147 vput(nd.ni_vp); 3148 vn_finished_write(mp); 3149 ASSERT_VOP_UNLOCKED(nd.ni_dvp, "mkdir"); 3150 ASSERT_VOP_UNLOCKED(nd.ni_vp, "mkdir"); 3151 return (error); 3152 } 3153 3154 /* 3155 * Remove a directory file. 3156 */ 3157 #ifndef _SYS_SYSPROTO_H_ 3158 struct rmdir_args { 3159 char *path; 3160 }; 3161 #endif 3162 /* ARGSUSED */ 3163 int 3164 rmdir(td, uap) 3165 struct thread *td; 3166 struct rmdir_args /* { 3167 syscallarg(char *) path; 3168 } */ *uap; 3169 { 3170 struct mount *mp; 3171 struct vnode *vp; 3172 int error; 3173 struct nameidata nd; 3174 3175 restart: 3176 bwillwrite(); 3177 NDINIT(&nd, DELETE, LOCKPARENT | LOCKLEAF, UIO_USERSPACE, 3178 SCARG(uap, path), td); 3179 if ((error = namei(&nd)) != 0) 3180 return (error); 3181 vp = nd.ni_vp; 3182 if (vp->v_type != VDIR) { 3183 error = ENOTDIR; 3184 goto out; 3185 } 3186 /* 3187 * No rmdir "." please. 3188 */ 3189 if (nd.ni_dvp == vp) { 3190 error = EINVAL; 3191 goto out; 3192 } 3193 /* 3194 * The root of a mounted filesystem cannot be deleted. 3195 */ 3196 if (vp->v_flag & VROOT) { 3197 error = EBUSY; 3198 goto out; 3199 } 3200 if (vn_start_write(nd.ni_dvp, &mp, V_NOWAIT) != 0) { 3201 NDFREE(&nd, NDF_ONLY_PNBUF); 3202 if (nd.ni_dvp == vp) 3203 vrele(nd.ni_dvp); 3204 else 3205 vput(nd.ni_dvp); 3206 vput(vp); 3207 if ((error = vn_start_write(NULL, &mp, V_XSLEEP | PCATCH)) != 0) 3208 return (error); 3209 goto restart; 3210 } 3211 VOP_LEASE(nd.ni_dvp, td, td->td_proc->p_ucred, LEASE_WRITE); 3212 VOP_LEASE(vp, td, td->td_proc->p_ucred, LEASE_WRITE); 3213 error = VOP_RMDIR(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd); 3214 vn_finished_write(mp); 3215 out: 3216 NDFREE(&nd, NDF_ONLY_PNBUF); 3217 if (nd.ni_dvp == vp) 3218 vrele(nd.ni_dvp); 3219 else 3220 vput(nd.ni_dvp); 3221 vput(vp); 3222 ASSERT_VOP_UNLOCKED(nd.ni_dvp, "rmdir"); 3223 ASSERT_VOP_UNLOCKED(nd.ni_vp, "rmdir"); 3224 return (error); 3225 } 3226 3227 #ifdef COMPAT_43 3228 /* 3229 * Read a block of directory entries in a file system independent format. 3230 */ 3231 #ifndef _SYS_SYSPROTO_H_ 3232 struct ogetdirentries_args { 3233 int fd; 3234 char *buf; 3235 u_int count; 3236 long *basep; 3237 }; 3238 #endif 3239 int 3240 ogetdirentries(td, uap) 3241 struct thread *td; 3242 register struct ogetdirentries_args /* { 3243 syscallarg(int) fd; 3244 syscallarg(char *) buf; 3245 syscallarg(u_int) count; 3246 syscallarg(long *) basep; 3247 } */ *uap; 3248 { 3249 struct vnode *vp; 3250 struct file *fp; 3251 struct uio auio, kuio; 3252 struct iovec aiov, kiov; 3253 struct dirent *dp, *edp; 3254 caddr_t dirbuf; 3255 int error, eofflag, readcnt; 3256 long loff; 3257 3258 /* XXX arbitrary sanity limit on `count'. */ 3259 if (SCARG(uap, count) > 64 * 1024) 3260 return (EINVAL); 3261 if ((error = getvnode(td->td_proc->p_fd, SCARG(uap, fd), &fp)) != 0) 3262 return (error); 3263 if ((fp->f_flag & FREAD) == 0) { 3264 fdrop(fp, td); 3265 return (EBADF); 3266 } 3267 vp = (struct vnode *)fp->f_data; 3268 unionread: 3269 if (vp->v_type != VDIR) { 3270 fdrop(fp, td); 3271 return (EINVAL); 3272 } 3273 aiov.iov_base = SCARG(uap, buf); 3274 aiov.iov_len = SCARG(uap, count); 3275 auio.uio_iov = &aiov; 3276 auio.uio_iovcnt = 1; 3277 auio.uio_rw = UIO_READ; 3278 auio.uio_segflg = UIO_USERSPACE; 3279 auio.uio_td = td; 3280 auio.uio_resid = SCARG(uap, count); 3281 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 3282 loff = auio.uio_offset = fp->f_offset; 3283 # if (BYTE_ORDER != LITTLE_ENDIAN) 3284 if (vp->v_mount->mnt_maxsymlinklen <= 0) { 3285 error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, 3286 NULL, NULL); 3287 fp->f_offset = auio.uio_offset; 3288 } else 3289 # endif 3290 { 3291 kuio = auio; 3292 kuio.uio_iov = &kiov; 3293 kuio.uio_segflg = UIO_SYSSPACE; 3294 kiov.iov_len = SCARG(uap, count); 3295 MALLOC(dirbuf, caddr_t, SCARG(uap, count), M_TEMP, M_WAITOK); 3296 kiov.iov_base = dirbuf; 3297 error = VOP_READDIR(vp, &kuio, fp->f_cred, &eofflag, 3298 NULL, NULL); 3299 fp->f_offset = kuio.uio_offset; 3300 if (error == 0) { 3301 readcnt = SCARG(uap, count) - kuio.uio_resid; 3302 edp = (struct dirent *)&dirbuf[readcnt]; 3303 for (dp = (struct dirent *)dirbuf; dp < edp; ) { 3304 # if (BYTE_ORDER == LITTLE_ENDIAN) 3305 /* 3306 * The expected low byte of 3307 * dp->d_namlen is our dp->d_type. 3308 * The high MBZ byte of dp->d_namlen 3309 * is our dp->d_namlen. 3310 */ 3311 dp->d_type = dp->d_namlen; 3312 dp->d_namlen = 0; 3313 # else 3314 /* 3315 * The dp->d_type is the high byte 3316 * of the expected dp->d_namlen, 3317 * so must be zero'ed. 3318 */ 3319 dp->d_type = 0; 3320 # endif 3321 if (dp->d_reclen > 0) { 3322 dp = (struct dirent *) 3323 ((char *)dp + dp->d_reclen); 3324 } else { 3325 error = EIO; 3326 break; 3327 } 3328 } 3329 if (dp >= edp) 3330 error = uiomove(dirbuf, readcnt, &auio); 3331 } 3332 FREE(dirbuf, M_TEMP); 3333 } 3334 VOP_UNLOCK(vp, 0, td); 3335 if (error) { 3336 fdrop(fp, td); 3337 return (error); 3338 } 3339 if (SCARG(uap, count) == auio.uio_resid) { 3340 if (union_dircheckp) { 3341 error = union_dircheckp(td, &vp, fp); 3342 if (error == -1) 3343 goto unionread; 3344 if (error) { 3345 fdrop(fp, td); 3346 return (error); 3347 } 3348 } 3349 if ((vp->v_flag & VROOT) && 3350 (vp->v_mount->mnt_flag & MNT_UNION)) { 3351 struct vnode *tvp = vp; 3352 vp = vp->v_mount->mnt_vnodecovered; 3353 VREF(vp); 3354 fp->f_data = (caddr_t) vp; 3355 fp->f_offset = 0; 3356 vrele(tvp); 3357 goto unionread; 3358 } 3359 } 3360 error = copyout((caddr_t)&loff, (caddr_t)SCARG(uap, basep), 3361 sizeof(long)); 3362 fdrop(fp, td); 3363 td->td_retval[0] = SCARG(uap, count) - auio.uio_resid; 3364 return (error); 3365 } 3366 #endif /* COMPAT_43 */ 3367 3368 /* 3369 * Read a block of directory entries in a file system independent format. 3370 */ 3371 #ifndef _SYS_SYSPROTO_H_ 3372 struct getdirentries_args { 3373 int fd; 3374 char *buf; 3375 u_int count; 3376 long *basep; 3377 }; 3378 #endif 3379 int 3380 getdirentries(td, uap) 3381 struct thread *td; 3382 register struct getdirentries_args /* { 3383 syscallarg(int) fd; 3384 syscallarg(char *) buf; 3385 syscallarg(u_int) count; 3386 syscallarg(long *) basep; 3387 } */ *uap; 3388 { 3389 struct vnode *vp; 3390 struct file *fp; 3391 struct uio auio; 3392 struct iovec aiov; 3393 long loff; 3394 int error, eofflag; 3395 3396 if ((error = getvnode(td->td_proc->p_fd, SCARG(uap, fd), &fp)) != 0) 3397 return (error); 3398 if ((fp->f_flag & FREAD) == 0) { 3399 fdrop(fp, td); 3400 return (EBADF); 3401 } 3402 vp = (struct vnode *)fp->f_data; 3403 unionread: 3404 if (vp->v_type != VDIR) { 3405 fdrop(fp, td); 3406 return (EINVAL); 3407 } 3408 aiov.iov_base = SCARG(uap, buf); 3409 aiov.iov_len = SCARG(uap, count); 3410 auio.uio_iov = &aiov; 3411 auio.uio_iovcnt = 1; 3412 auio.uio_rw = UIO_READ; 3413 auio.uio_segflg = UIO_USERSPACE; 3414 auio.uio_td = td; 3415 auio.uio_resid = SCARG(uap, count); 3416 /* vn_lock(vp, LK_SHARED | LK_RETRY, td); */ 3417 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 3418 loff = auio.uio_offset = fp->f_offset; 3419 error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, NULL, NULL); 3420 fp->f_offset = auio.uio_offset; 3421 VOP_UNLOCK(vp, 0, td); 3422 if (error) { 3423 fdrop(fp, td); 3424 return (error); 3425 } 3426 if (SCARG(uap, count) == auio.uio_resid) { 3427 if (union_dircheckp) { 3428 error = union_dircheckp(td, &vp, fp); 3429 if (error == -1) 3430 goto unionread; 3431 if (error) { 3432 fdrop(fp, td); 3433 return (error); 3434 } 3435 } 3436 if ((vp->v_flag & VROOT) && 3437 (vp->v_mount->mnt_flag & MNT_UNION)) { 3438 struct vnode *tvp = vp; 3439 vp = vp->v_mount->mnt_vnodecovered; 3440 VREF(vp); 3441 fp->f_data = (caddr_t) vp; 3442 fp->f_offset = 0; 3443 vrele(tvp); 3444 goto unionread; 3445 } 3446 } 3447 if (SCARG(uap, basep) != NULL) { 3448 error = copyout((caddr_t)&loff, (caddr_t)SCARG(uap, basep), 3449 sizeof(long)); 3450 } 3451 td->td_retval[0] = SCARG(uap, count) - auio.uio_resid; 3452 fdrop(fp, td); 3453 return (error); 3454 } 3455 #ifndef _SYS_SYSPROTO_H_ 3456 struct getdents_args { 3457 int fd; 3458 char *buf; 3459 size_t count; 3460 }; 3461 #endif 3462 int 3463 getdents(td, uap) 3464 struct thread *td; 3465 register struct getdents_args /* { 3466 syscallarg(int) fd; 3467 syscallarg(char *) buf; 3468 syscallarg(u_int) count; 3469 } */ *uap; 3470 { 3471 struct getdirentries_args ap; 3472 ap.fd = uap->fd; 3473 ap.buf = uap->buf; 3474 ap.count = uap->count; 3475 ap.basep = NULL; 3476 return getdirentries(td, &ap); 3477 } 3478 3479 /* 3480 * Set the mode mask for creation of filesystem nodes. 3481 * 3482 * MP SAFE 3483 */ 3484 #ifndef _SYS_SYSPROTO_H_ 3485 struct umask_args { 3486 int newmask; 3487 }; 3488 #endif 3489 int 3490 umask(td, uap) 3491 struct thread *td; 3492 struct umask_args /* { 3493 syscallarg(int) newmask; 3494 } */ *uap; 3495 { 3496 register struct filedesc *fdp; 3497 3498 FILEDESC_LOCK(td->td_proc->p_fd); 3499 fdp = td->td_proc->p_fd; 3500 td->td_retval[0] = fdp->fd_cmask; 3501 fdp->fd_cmask = SCARG(uap, newmask) & ALLPERMS; 3502 FILEDESC_UNLOCK(td->td_proc->p_fd); 3503 return (0); 3504 } 3505 3506 /* 3507 * Void all references to file by ripping underlying filesystem 3508 * away from vnode. 3509 */ 3510 #ifndef _SYS_SYSPROTO_H_ 3511 struct revoke_args { 3512 char *path; 3513 }; 3514 #endif 3515 /* ARGSUSED */ 3516 int 3517 revoke(td, uap) 3518 struct thread *td; 3519 register struct revoke_args /* { 3520 syscallarg(char *) path; 3521 } */ *uap; 3522 { 3523 struct mount *mp; 3524 struct vnode *vp; 3525 struct vattr vattr; 3526 int error; 3527 struct nameidata nd; 3528 3529 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), td); 3530 if ((error = namei(&nd)) != 0) 3531 return (error); 3532 vp = nd.ni_vp; 3533 NDFREE(&nd, NDF_ONLY_PNBUF); 3534 if (vp->v_type != VCHR) { 3535 error = EINVAL; 3536 goto out; 3537 } 3538 error = VOP_GETATTR(vp, &vattr, td->td_proc->p_ucred, td); 3539 if (error) 3540 goto out; 3541 if (td->td_proc->p_ucred->cr_uid != vattr.va_uid) { 3542 error = suser_xxx(0, td->td_proc, PRISON_ROOT); 3543 if (error) 3544 goto out; 3545 } 3546 if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0) 3547 goto out; 3548 if (vcount(vp) > 1) 3549 VOP_REVOKE(vp, REVOKEALL); 3550 vn_finished_write(mp); 3551 out: 3552 vrele(vp); 3553 return (error); 3554 } 3555 3556 /* 3557 * Convert a user file descriptor to a kernel file entry. 3558 * The file entry is locked upon returning. 3559 */ 3560 int 3561 getvnode(fdp, fd, fpp) 3562 struct filedesc *fdp; 3563 int fd; 3564 struct file **fpp; 3565 { 3566 int error; 3567 struct file *fp; 3568 3569 fp = NULL; 3570 if (fdp == NULL) 3571 error = EBADF; 3572 else { 3573 FILEDESC_LOCK(fdp); 3574 if ((u_int)fd >= fdp->fd_nfiles || 3575 (fp = fdp->fd_ofiles[fd]) == NULL) 3576 error = EBADF; 3577 else if (fp->f_type != DTYPE_VNODE && fp->f_type != DTYPE_FIFO) { 3578 fp = NULL; 3579 error = EINVAL; 3580 } else { 3581 fhold(fp); 3582 error = 0; 3583 } 3584 FILEDESC_UNLOCK(fdp); 3585 } 3586 *fpp = fp; 3587 return (error); 3588 } 3589 /* 3590 * Get (NFS) file handle 3591 */ 3592 #ifndef _SYS_SYSPROTO_H_ 3593 struct getfh_args { 3594 char *fname; 3595 fhandle_t *fhp; 3596 }; 3597 #endif 3598 int 3599 getfh(td, uap) 3600 struct thread *td; 3601 register struct getfh_args *uap; 3602 { 3603 struct nameidata nd; 3604 fhandle_t fh; 3605 register struct vnode *vp; 3606 int error; 3607 3608 /* 3609 * Must be super user 3610 */ 3611 error = suser_td(td); 3612 if (error) 3613 return (error); 3614 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->fname, td); 3615 error = namei(&nd); 3616 if (error) 3617 return (error); 3618 NDFREE(&nd, NDF_ONLY_PNBUF); 3619 vp = nd.ni_vp; 3620 bzero(&fh, sizeof(fh)); 3621 fh.fh_fsid = vp->v_mount->mnt_stat.f_fsid; 3622 error = VFS_VPTOFH(vp, &fh.fh_fid); 3623 vput(vp); 3624 if (error) 3625 return (error); 3626 error = copyout(&fh, uap->fhp, sizeof (fh)); 3627 return (error); 3628 } 3629 3630 /* 3631 * syscall for the rpc.lockd to use to translate a NFS file handle into 3632 * an open descriptor. 3633 * 3634 * warning: do not remove the suser() call or this becomes one giant 3635 * security hole. 3636 */ 3637 #ifndef _SYS_SYSPROTO_H_ 3638 struct fhopen_args { 3639 const struct fhandle *u_fhp; 3640 int flags; 3641 }; 3642 #endif 3643 int 3644 fhopen(td, uap) 3645 struct thread *td; 3646 struct fhopen_args /* { 3647 syscallarg(const struct fhandle *) u_fhp; 3648 syscallarg(int) flags; 3649 } */ *uap; 3650 { 3651 struct proc *p = td->td_proc; 3652 struct mount *mp; 3653 struct vnode *vp; 3654 struct fhandle fhp; 3655 struct vattr vat; 3656 struct vattr *vap = &vat; 3657 struct flock lf; 3658 struct file *fp; 3659 register struct filedesc *fdp = p->p_fd; 3660 int fmode, mode, error, type; 3661 struct file *nfp; 3662 int indx; 3663 3664 /* 3665 * Must be super user 3666 */ 3667 error = suser_td(td); 3668 if (error) 3669 return (error); 3670 3671 fmode = FFLAGS(SCARG(uap, flags)); 3672 /* why not allow a non-read/write open for our lockd? */ 3673 if (((fmode & (FREAD | FWRITE)) == 0) || (fmode & O_CREAT)) 3674 return (EINVAL); 3675 error = copyin(SCARG(uap,u_fhp), &fhp, sizeof(fhp)); 3676 if (error) 3677 return(error); 3678 /* find the mount point */ 3679 mp = vfs_getvfs(&fhp.fh_fsid); 3680 if (mp == NULL) 3681 return (ESTALE); 3682 /* now give me my vnode, it gets returned to me locked */ 3683 error = VFS_FHTOVP(mp, &fhp.fh_fid, &vp); 3684 if (error) 3685 return (error); 3686 /* 3687 * from now on we have to make sure not 3688 * to forget about the vnode 3689 * any error that causes an abort must vput(vp) 3690 * just set error = err and 'goto bad;'. 3691 */ 3692 3693 /* 3694 * from vn_open 3695 */ 3696 if (vp->v_type == VLNK) { 3697 error = EMLINK; 3698 goto bad; 3699 } 3700 if (vp->v_type == VSOCK) { 3701 error = EOPNOTSUPP; 3702 goto bad; 3703 } 3704 mode = 0; 3705 if (fmode & (FWRITE | O_TRUNC)) { 3706 if (vp->v_type == VDIR) { 3707 error = EISDIR; 3708 goto bad; 3709 } 3710 error = vn_writechk(vp); 3711 if (error) 3712 goto bad; 3713 mode |= VWRITE; 3714 } 3715 if (fmode & FREAD) 3716 mode |= VREAD; 3717 if (mode) { 3718 error = VOP_ACCESS(vp, mode, p->p_ucred, td); 3719 if (error) 3720 goto bad; 3721 } 3722 if (fmode & O_TRUNC) { 3723 VOP_UNLOCK(vp, 0, td); /* XXX */ 3724 if ((error = vn_start_write(NULL, &mp, V_WAIT | PCATCH)) != 0) { 3725 vrele(vp); 3726 return (error); 3727 } 3728 VOP_LEASE(vp, td, p->p_ucred, LEASE_WRITE); 3729 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); /* XXX */ 3730 VATTR_NULL(vap); 3731 vap->va_size = 0; 3732 error = VOP_SETATTR(vp, vap, p->p_ucred, td); 3733 vn_finished_write(mp); 3734 if (error) 3735 goto bad; 3736 } 3737 error = VOP_OPEN(vp, fmode, p->p_ucred, td); 3738 if (error) 3739 goto bad; 3740 /* 3741 * Make sure that a VM object is created for VMIO support. 3742 */ 3743 if (vn_canvmio(vp) == TRUE) { 3744 if ((error = vfs_object_create(vp, td, p->p_ucred)) != 0) 3745 goto bad; 3746 } 3747 if (fmode & FWRITE) 3748 vp->v_writecount++; 3749 3750 /* 3751 * end of vn_open code 3752 */ 3753 3754 if ((error = falloc(td, &nfp, &indx)) != 0) { 3755 if (fmode & FWRITE) 3756 vp->v_writecount--; 3757 goto bad; 3758 } 3759 fp = nfp; 3760 3761 /* 3762 * Hold an extra reference to avoid having fp ripped out 3763 * from under us while we block in the lock op 3764 */ 3765 fhold(fp); 3766 nfp->f_data = (caddr_t)vp; 3767 nfp->f_flag = fmode & FMASK; 3768 nfp->f_ops = &vnops; 3769 nfp->f_type = DTYPE_VNODE; 3770 if (fmode & (O_EXLOCK | O_SHLOCK)) { 3771 lf.l_whence = SEEK_SET; 3772 lf.l_start = 0; 3773 lf.l_len = 0; 3774 if (fmode & O_EXLOCK) 3775 lf.l_type = F_WRLCK; 3776 else 3777 lf.l_type = F_RDLCK; 3778 type = F_FLOCK; 3779 if ((fmode & FNONBLOCK) == 0) 3780 type |= F_WAIT; 3781 VOP_UNLOCK(vp, 0, td); 3782 if ((error = VOP_ADVLOCK(vp, (caddr_t)fp, F_SETLK, &lf, type)) != 0) { 3783 /* 3784 * The lock request failed. Normally close the 3785 * descriptor but handle the case where someone might 3786 * have dup()d or close()d it when we weren't looking. 3787 */ 3788 FILEDESC_LOCK(fdp); 3789 if (fdp->fd_ofiles[indx] == fp) { 3790 fdp->fd_ofiles[indx] = NULL; 3791 FILEDESC_UNLOCK(fdp); 3792 fdrop(fp, td); 3793 } else 3794 FILEDESC_UNLOCK(fdp); 3795 /* 3796 * release our private reference 3797 */ 3798 fdrop(fp, td); 3799 return(error); 3800 } 3801 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 3802 fp->f_flag |= FHASLOCK; 3803 } 3804 if ((vp->v_type == VREG) && (VOP_GETVOBJECT(vp, NULL) != 0)) 3805 vfs_object_create(vp, td, p->p_ucred); 3806 3807 VOP_UNLOCK(vp, 0, td); 3808 fdrop(fp, td); 3809 td->td_retval[0] = indx; 3810 return (0); 3811 3812 bad: 3813 vput(vp); 3814 return (error); 3815 } 3816 3817 /* 3818 * Stat an (NFS) file handle. 3819 */ 3820 #ifndef _SYS_SYSPROTO_H_ 3821 struct fhstat_args { 3822 struct fhandle *u_fhp; 3823 struct stat *sb; 3824 }; 3825 #endif 3826 int 3827 fhstat(td, uap) 3828 struct thread *td; 3829 register struct fhstat_args /* { 3830 syscallarg(struct fhandle *) u_fhp; 3831 syscallarg(struct stat *) sb; 3832 } */ *uap; 3833 { 3834 struct stat sb; 3835 fhandle_t fh; 3836 struct mount *mp; 3837 struct vnode *vp; 3838 int error; 3839 3840 /* 3841 * Must be super user 3842 */ 3843 error = suser_td(td); 3844 if (error) 3845 return (error); 3846 3847 error = copyin(SCARG(uap, u_fhp), &fh, sizeof(fhandle_t)); 3848 if (error) 3849 return (error); 3850 3851 if ((mp = vfs_getvfs(&fh.fh_fsid)) == NULL) 3852 return (ESTALE); 3853 if ((error = VFS_FHTOVP(mp, &fh.fh_fid, &vp))) 3854 return (error); 3855 error = vn_stat(vp, &sb, td); 3856 vput(vp); 3857 if (error) 3858 return (error); 3859 error = copyout(&sb, SCARG(uap, sb), sizeof(sb)); 3860 return (error); 3861 } 3862 3863 /* 3864 * Implement fstatfs() for (NFS) file handles. 3865 */ 3866 #ifndef _SYS_SYSPROTO_H_ 3867 struct fhstatfs_args { 3868 struct fhandle *u_fhp; 3869 struct statfs *buf; 3870 }; 3871 #endif 3872 int 3873 fhstatfs(td, uap) 3874 struct thread *td; 3875 struct fhstatfs_args /* { 3876 syscallarg(struct fhandle) *u_fhp; 3877 syscallarg(struct statfs) *buf; 3878 } */ *uap; 3879 { 3880 struct statfs *sp; 3881 struct mount *mp; 3882 struct vnode *vp; 3883 struct statfs sb; 3884 fhandle_t fh; 3885 int error; 3886 3887 /* 3888 * Must be super user 3889 */ 3890 error = suser_td(td); 3891 if (error) 3892 return (error); 3893 3894 if ((error = copyin(SCARG(uap, u_fhp), &fh, sizeof(fhandle_t))) != 0) 3895 return (error); 3896 3897 if ((mp = vfs_getvfs(&fh.fh_fsid)) == NULL) 3898 return (ESTALE); 3899 if ((error = VFS_FHTOVP(mp, &fh.fh_fid, &vp))) 3900 return (error); 3901 mp = vp->v_mount; 3902 sp = &mp->mnt_stat; 3903 vput(vp); 3904 if ((error = VFS_STATFS(mp, sp, td)) != 0) 3905 return (error); 3906 sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK; 3907 if (suser_xxx(td->td_proc->p_ucred, 0, 0)) { 3908 bcopy((caddr_t)sp, (caddr_t)&sb, sizeof(sb)); 3909 sb.f_fsid.val[0] = sb.f_fsid.val[1] = 0; 3910 sp = &sb; 3911 } 3912 return (copyout(sp, SCARG(uap, buf), sizeof(*sp))); 3913 } 3914 3915 /* 3916 * Syscall to push extended attribute configuration information into the 3917 * VFS. Accepts a path, which it converts to a mountpoint, as well as 3918 * a command (int cmd), and attribute name and misc data. For now, the 3919 * attribute name is left in userspace for consumption by the VFS_op. 3920 * It will probably be changed to be copied into sysspace by the 3921 * syscall in the future, once issues with various consumers of the 3922 * attribute code have raised their hands. 3923 * 3924 * Currently this is used only by UFS Extended Attributes. 3925 */ 3926 int 3927 extattrctl(td, uap) 3928 struct thread *td; 3929 struct extattrctl_args *uap; 3930 { 3931 struct vnode *filename_vp; 3932 struct nameidata nd; 3933 struct mount *mp; 3934 char attrname[EXTATTR_MAXNAMELEN]; 3935 int error; 3936 3937 /* 3938 * SCARG(uap, attrname) not always defined. We check again later 3939 * when we invoke the VFS call so as to pass in NULL there if needed. 3940 */ 3941 if (SCARG(uap, attrname) != NULL) { 3942 error = copyinstr(SCARG(uap, attrname), attrname, 3943 EXTATTR_MAXNAMELEN, NULL); 3944 if (error) 3945 return (error); 3946 } 3947 3948 /* 3949 * SCARG(uap, filename) not always defined. If it is, grab 3950 * a vnode lock, which VFS_EXTATTRCTL() will later release. 3951 */ 3952 filename_vp = NULL; 3953 if (SCARG(uap, filename) != NULL) { 3954 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, 3955 SCARG(uap, filename), td); 3956 if ((error = namei(&nd)) != 0) 3957 return (error); 3958 filename_vp = nd.ni_vp; 3959 NDFREE(&nd, NDF_NO_VP_RELE | NDF_NO_VP_UNLOCK); 3960 } 3961 3962 /* SCARG(uap, path) always defined. */ 3963 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), td); 3964 if ((error = namei(&nd)) != 0) 3965 return (error); 3966 error = vn_start_write(nd.ni_vp, &mp, V_WAIT | PCATCH); 3967 NDFREE(&nd, 0); 3968 if (error) { 3969 if (filename_vp) 3970 vrele(filename_vp); 3971 return (error); 3972 } 3973 3974 if (SCARG(uap, attrname) != NULL) { 3975 error = VFS_EXTATTRCTL(mp, SCARG(uap, cmd), filename_vp, 3976 SCARG(uap, attrnamespace), attrname, td); 3977 } else { 3978 error = VFS_EXTATTRCTL(mp, SCARG(uap, cmd), filename_vp, 3979 SCARG(uap, attrnamespace), NULL, td); 3980 } 3981 3982 vn_finished_write(mp); 3983 /* 3984 * VFS_EXTATTRCTL will have unlocked, but not de-ref'd, 3985 * filename_vp, so vrele it if it is defined. 3986 */ 3987 if (filename_vp != NULL) 3988 vrele(filename_vp); 3989 3990 return (error); 3991 } 3992 3993 /* 3994 * extattr_set_vp(): Set a named extended attribute on a file or directory 3995 * 3996 * Arguments: unlocked vnode "vp", attribute namespace "attrnamespace", 3997 * kernelspace string pointer "attrname", 3998 * userspace iovec array pointer "iovp", unsigned int iovcnt 3999 * proc "p" 4000 * Returns: 0 on success, an error number otherwise 4001 * Locks: none 4002 * References: vp must be a valid reference for the duration of the call 4003 */ 4004 static int 4005 extattr_set_vp(struct vnode *vp, int attrnamespace, const char *attrname, 4006 struct iovec *iovp, unsigned iovcnt, struct thread *td) 4007 { 4008 struct mount *mp; 4009 struct uio auio; 4010 struct iovec *iov, *needfree = NULL, aiov[UIO_SMALLIOV]; 4011 u_int iovlen, cnt; 4012 int error, i; 4013 4014 if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0) 4015 return (error); 4016 VOP_LEASE(vp, td, td->td_proc->p_ucred, LEASE_WRITE); 4017 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 4018 4019 iovlen = iovcnt * sizeof(struct iovec); 4020 if (iovcnt > UIO_SMALLIOV) { 4021 if (iovcnt > UIO_MAXIOV) { 4022 error = EINVAL; 4023 goto done; 4024 } 4025 MALLOC(iov, struct iovec *, iovlen, M_IOV, M_WAITOK); 4026 needfree = iov; 4027 } else 4028 iov = aiov; 4029 auio.uio_iov = iov; 4030 auio.uio_iovcnt = iovcnt; 4031 auio.uio_rw = UIO_WRITE; 4032 auio.uio_segflg = UIO_USERSPACE; 4033 auio.uio_td = td; 4034 auio.uio_offset = 0; 4035 if ((error = copyin((caddr_t)iovp, (caddr_t)iov, iovlen))) 4036 goto done; 4037 auio.uio_resid = 0; 4038 for (i = 0; i < iovcnt; i++) { 4039 if (iov->iov_len > INT_MAX - auio.uio_resid) { 4040 error = EINVAL; 4041 goto done; 4042 } 4043 auio.uio_resid += iov->iov_len; 4044 iov++; 4045 } 4046 cnt = auio.uio_resid; 4047 error = VOP_SETEXTATTR(vp, attrnamespace, attrname, &auio, 4048 td->td_proc->p_ucred, td); 4049 cnt -= auio.uio_resid; 4050 td->td_retval[0] = cnt; 4051 done: 4052 if (needfree) 4053 FREE(needfree, M_IOV); 4054 VOP_UNLOCK(vp, 0, td); 4055 vn_finished_write(mp); 4056 return (error); 4057 } 4058 4059 int 4060 extattr_set_file(td, uap) 4061 struct thread *td; 4062 struct extattr_set_file_args *uap; 4063 { 4064 struct nameidata nd; 4065 char attrname[EXTATTR_MAXNAMELEN]; 4066 int error; 4067 4068 error = copyinstr(SCARG(uap, attrname), attrname, EXTATTR_MAXNAMELEN, 4069 NULL); 4070 if (error) 4071 return (error); 4072 4073 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), td); 4074 if ((error = namei(&nd)) != 0) 4075 return (error); 4076 NDFREE(&nd, NDF_ONLY_PNBUF); 4077 4078 error = extattr_set_vp(nd.ni_vp, SCARG(uap, attrnamespace), attrname, 4079 SCARG(uap, iovp), SCARG(uap, iovcnt), td); 4080 4081 vrele(nd.ni_vp); 4082 return (error); 4083 } 4084 4085 int 4086 extattr_set_fd(td, uap) 4087 struct thread *td; 4088 struct extattr_set_fd_args *uap; 4089 { 4090 struct file *fp; 4091 char attrname[EXTATTR_MAXNAMELEN]; 4092 int error; 4093 4094 error = copyinstr(SCARG(uap, attrname), attrname, EXTATTR_MAXNAMELEN, 4095 NULL); 4096 if (error) 4097 return (error); 4098 4099 if ((error = getvnode(td->td_proc->p_fd, SCARG(uap, fd), &fp)) != 0) 4100 return (error); 4101 4102 error = extattr_set_vp((struct vnode *)fp->f_data, 4103 SCARG(uap, attrnamespace), attrname, SCARG(uap, iovp), 4104 SCARG(uap, iovcnt), td); 4105 fdrop(fp, td); 4106 4107 return (error); 4108 } 4109 4110 /* 4111 * extattr_get_vp(): Get a named extended attribute on a file or directory 4112 * 4113 * Arguments: unlocked vnode "vp", attribute namespace "attrnamespace", 4114 * kernelspace string pointer "attrname", 4115 * userspace iovec array pointer "iovp", unsigned int iovcnt, 4116 * proc "p" 4117 * Returns: 0 on success, an error number otherwise 4118 * Locks: none 4119 * References: vp must be a valid reference for the duration of the call 4120 */ 4121 static int 4122 extattr_get_vp(struct vnode *vp, int attrnamespace, const char *attrname, 4123 struct iovec *iovp, unsigned iovcnt, struct thread *td) 4124 { 4125 struct uio auio; 4126 struct iovec *iov, *needfree = NULL, aiov[UIO_SMALLIOV]; 4127 u_int iovlen, cnt; 4128 int error, i; 4129 4130 VOP_LEASE(vp, td, td->td_proc->p_ucred, LEASE_READ); 4131 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 4132 4133 iovlen = iovcnt * sizeof (struct iovec); 4134 if (iovcnt > UIO_SMALLIOV) { 4135 if (iovcnt > UIO_MAXIOV) { 4136 error = EINVAL; 4137 goto done; 4138 } 4139 MALLOC(iov, struct iovec *, iovlen, M_IOV, M_WAITOK); 4140 needfree = iov; 4141 } else 4142 iov = aiov; 4143 auio.uio_iov = iov; 4144 auio.uio_iovcnt = iovcnt; 4145 auio.uio_rw = UIO_READ; 4146 auio.uio_segflg = UIO_USERSPACE; 4147 auio.uio_td = td; 4148 auio.uio_offset = 0; 4149 if ((error = copyin((caddr_t)iovp, (caddr_t)iov, iovlen))) 4150 goto done; 4151 auio.uio_resid = 0; 4152 for (i = 0; i < iovcnt; i++) { 4153 if (iov->iov_len > INT_MAX - auio.uio_resid) { 4154 error = EINVAL; 4155 goto done; 4156 } 4157 auio.uio_resid += iov->iov_len; 4158 iov++; 4159 } 4160 cnt = auio.uio_resid; 4161 error = VOP_GETEXTATTR(vp, attrnamespace, attrname, &auio, 4162 td->td_proc->p_ucred, td); 4163 cnt -= auio.uio_resid; 4164 td->td_retval[0] = cnt; 4165 done: 4166 if (needfree) 4167 FREE(needfree, M_IOV); 4168 VOP_UNLOCK(vp, 0, td); 4169 return (error); 4170 } 4171 4172 int 4173 extattr_get_file(td, uap) 4174 struct thread *td; 4175 struct extattr_get_file_args *uap; 4176 { 4177 struct nameidata nd; 4178 char attrname[EXTATTR_MAXNAMELEN]; 4179 int error; 4180 4181 error = copyinstr(SCARG(uap, attrname), attrname, EXTATTR_MAXNAMELEN, 4182 NULL); 4183 if (error) 4184 return (error); 4185 4186 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), td); 4187 if ((error = namei(&nd)) != 0) 4188 return (error); 4189 NDFREE(&nd, NDF_ONLY_PNBUF); 4190 4191 error = extattr_get_vp(nd.ni_vp, SCARG(uap, attrnamespace), attrname, 4192 SCARG(uap, iovp), SCARG(uap, iovcnt), td); 4193 4194 vrele(nd.ni_vp); 4195 return (error); 4196 } 4197 4198 int 4199 extattr_get_fd(td, uap) 4200 struct thread *td; 4201 struct extattr_get_fd_args *uap; 4202 { 4203 struct file *fp; 4204 char attrname[EXTATTR_MAXNAMELEN]; 4205 int error; 4206 4207 error = copyinstr(SCARG(uap, attrname), attrname, EXTATTR_MAXNAMELEN, 4208 NULL); 4209 if (error) 4210 return (error); 4211 4212 if ((error = getvnode(td->td_proc->p_fd, SCARG(uap, fd), &fp)) != 0) 4213 return (error); 4214 4215 error = extattr_get_vp((struct vnode *)fp->f_data, 4216 SCARG(uap, attrnamespace), attrname, SCARG(uap, iovp), 4217 SCARG(uap, iovcnt), td); 4218 4219 fdrop(fp, td); 4220 return (error); 4221 } 4222 4223 /* 4224 * extattr_delete_vp(): Delete a named extended attribute on a file or 4225 * directory 4226 * 4227 * Arguments: unlocked vnode "vp", attribute namespace "attrnamespace", 4228 * kernelspace string pointer "attrname", proc "p" 4229 * Returns: 0 on success, an error number otherwise 4230 * Locks: none 4231 * References: vp must be a valid reference for the duration of the call 4232 */ 4233 static int 4234 extattr_delete_vp(struct vnode *vp, int attrnamespace, const char *attrname, 4235 struct thread *td) 4236 { 4237 struct mount *mp; 4238 int error; 4239 4240 if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0) 4241 return (error); 4242 VOP_LEASE(vp, td, td->td_proc->p_ucred, LEASE_WRITE); 4243 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); 4244 4245 error = VOP_SETEXTATTR(vp, attrnamespace, attrname, NULL, 4246 td->td_proc->p_ucred, td); 4247 4248 VOP_UNLOCK(vp, 0, td); 4249 vn_finished_write(mp); 4250 return (error); 4251 } 4252 4253 int 4254 extattr_delete_file(td, uap) 4255 struct thread *td; 4256 struct extattr_delete_file_args *uap; 4257 { 4258 struct nameidata nd; 4259 char attrname[EXTATTR_MAXNAMELEN]; 4260 int error; 4261 4262 error = copyinstr(SCARG(uap, attrname), attrname, EXTATTR_MAXNAMELEN, 4263 NULL); 4264 if (error) 4265 return(error); 4266 4267 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), td); 4268 if ((error = namei(&nd)) != 0) 4269 return(error); 4270 NDFREE(&nd, NDF_ONLY_PNBUF); 4271 4272 error = extattr_delete_vp(nd.ni_vp, SCARG(uap, attrnamespace), 4273 attrname, td); 4274 4275 vrele(nd.ni_vp); 4276 return(error); 4277 } 4278 4279 int 4280 extattr_delete_fd(td, uap) 4281 struct thread *td; 4282 struct extattr_delete_fd_args *uap; 4283 { 4284 struct file *fp; 4285 struct vnode *vp; 4286 char attrname[EXTATTR_MAXNAMELEN]; 4287 int error; 4288 4289 error = copyinstr(SCARG(uap, attrname), attrname, EXTATTR_MAXNAMELEN, 4290 NULL); 4291 if (error) 4292 return (error); 4293 4294 if ((error = getvnode(td->td_proc->p_fd, SCARG(uap, fd), &fp)) != 0) 4295 return (error); 4296 vp = (struct vnode *)fp->f_data; 4297 4298 error = extattr_delete_vp((struct vnode *)fp->f_data, 4299 SCARG(uap, attrnamespace), attrname, td); 4300 4301 fdrop(fp, td); 4302 return (error); 4303 } 4304