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