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