1 /* $NetBSD: vfs_syscalls.c,v 1.212 2004/10/01 16:30:56 yamt Exp $ */ 2 3 /* 4 * Copyright (c) 1989, 1993 5 * The Regents of the University of California. All rights reserved. 6 * (c) UNIX System Laboratories, Inc. 7 * All or some portions of this file are derived from material licensed 8 * to the University of California by American Telephone and Telegraph 9 * Co. or Unix System Laboratories, Inc. and are reproduced herein with 10 * the permission of UNIX System Laboratories, Inc. 11 * 12 * Redistribution and use in source and binary forms, with or without 13 * modification, are permitted provided that the following conditions 14 * are met: 15 * 1. Redistributions of source code must retain the above copyright 16 * notice, this list of conditions and the following disclaimer. 17 * 2. Redistributions in binary form must reproduce the above copyright 18 * notice, this list of conditions and the following disclaimer in the 19 * documentation and/or other materials provided with the distribution. 20 * 3. Neither the name of the University nor the names of its contributors 21 * may be used to endorse or promote products derived from this software 22 * without specific prior written permission. 23 * 24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 34 * SUCH DAMAGE. 35 * 36 * @(#)vfs_syscalls.c 8.42 (Berkeley) 7/31/95 37 */ 38 39 #include <sys/cdefs.h> 40 __KERNEL_RCSID(0, "$NetBSD: vfs_syscalls.c,v 1.212 2004/10/01 16:30:56 yamt Exp $"); 41 42 #include "opt_compat_netbsd.h" 43 #include "opt_compat_43.h" 44 #include "opt_ktrace.h" 45 #include "fss.h" 46 47 #include <sys/param.h> 48 #include <sys/systm.h> 49 #include <sys/namei.h> 50 #include <sys/filedesc.h> 51 #include <sys/kernel.h> 52 #include <sys/file.h> 53 #include <sys/stat.h> 54 #include <sys/vnode.h> 55 #include <sys/mount.h> 56 #include <sys/proc.h> 57 #include <sys/uio.h> 58 #include <sys/malloc.h> 59 #include <sys/dirent.h> 60 #include <sys/sysctl.h> 61 #include <sys/sa.h> 62 #include <sys/syscallargs.h> 63 #ifdef KTRACE 64 #include <sys/ktrace.h> 65 #endif 66 67 #include <miscfs/genfs/genfs.h> 68 #include <miscfs/syncfs/syncfs.h> 69 70 #if NFSS > 0 71 #include <dev/fssvar.h> 72 #endif 73 74 MALLOC_DEFINE(M_MOUNT, "mount", "vfs mount struct"); 75 76 static int change_dir(struct nameidata *, struct proc *); 77 static int change_flags(struct vnode *, u_long, struct proc *); 78 static int change_mode(struct vnode *, int, struct proc *p); 79 static int change_owner(struct vnode *, uid_t, gid_t, struct proc *, int); 80 static int change_utimes(struct vnode *vp, const struct timeval *, 81 struct proc *p); 82 static int rename_files(const char *, const char *, struct proc *, int); 83 84 void checkdirs(struct vnode *); 85 86 int dovfsusermount = 0; 87 88 /* 89 * Virtual File System System Calls 90 */ 91 92 /* 93 * Mount a file system. 94 */ 95 96 #if defined(COMPAT_09) || defined(COMPAT_43) 97 /* 98 * This table is used to maintain compatibility with 4.3BSD 99 * and NetBSD 0.9 mount syscalls. Note, the order is important! 100 * 101 * Do not modify this table. It should only contain filesystems 102 * supported by NetBSD 0.9 and 4.3BSD. 103 */ 104 const char * const mountcompatnames[] = { 105 NULL, /* 0 = MOUNT_NONE */ 106 MOUNT_FFS, /* 1 = MOUNT_UFS */ 107 MOUNT_NFS, /* 2 */ 108 MOUNT_MFS, /* 3 */ 109 MOUNT_MSDOS, /* 4 */ 110 MOUNT_CD9660, /* 5 = MOUNT_ISOFS */ 111 MOUNT_FDESC, /* 6 */ 112 MOUNT_KERNFS, /* 7 */ 113 NULL, /* 8 = MOUNT_DEVFS */ 114 MOUNT_AFS, /* 9 */ 115 }; 116 const int nmountcompatnames = sizeof(mountcompatnames) / 117 sizeof(mountcompatnames[0]); 118 #endif /* COMPAT_09 || COMPAT_43 */ 119 120 /* ARGSUSED */ 121 int 122 sys_mount(l, v, retval) 123 struct lwp *l; 124 void *v; 125 register_t *retval; 126 { 127 struct sys_mount_args /* { 128 syscallarg(const char *) type; 129 syscallarg(const char *) path; 130 syscallarg(int) flags; 131 syscallarg(void *) data; 132 } */ *uap = v; 133 struct proc *p = l->l_proc; 134 struct vnode *vp; 135 struct mount *mp; 136 int error, flag = 0; 137 char fstypename[MFSNAMELEN]; 138 struct vattr va; 139 struct nameidata nd; 140 struct vfsops *vfs; 141 142 if (dovfsusermount == 0 && (SCARG(uap, flags) & MNT_GETARGS) == 0 && 143 (error = suser(p->p_ucred, &p->p_acflag))) 144 return (error); 145 /* 146 * Get vnode to be covered 147 */ 148 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, 149 SCARG(uap, path), p); 150 if ((error = namei(&nd)) != 0) 151 return (error); 152 vp = nd.ni_vp; 153 /* 154 * A lookup in VFS_MOUNT might result in an attempt to 155 * lock this vnode again, so make the lock recursive. 156 */ 157 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY | LK_SETRECURSE); 158 if (SCARG(uap, flags) & (MNT_UPDATE | MNT_GETARGS)) { 159 if ((vp->v_flag & VROOT) == 0) { 160 vput(vp); 161 return (EINVAL); 162 } 163 mp = vp->v_mount; 164 flag = mp->mnt_flag; 165 vfs = mp->mnt_op; 166 /* 167 * We only allow the filesystem to be reloaded if it 168 * is currently mounted read-only. 169 */ 170 if ((SCARG(uap, flags) & MNT_RELOAD) && 171 ((mp->mnt_flag & MNT_RDONLY) == 0)) { 172 vput(vp); 173 return (EOPNOTSUPP); /* Needs translation */ 174 } 175 /* 176 * In "highly secure" mode, don't let the caller do anything 177 * but downgrade a filesystem from read-write to read-only. 178 * (see also below; MNT_UPDATE or MNT_GETARGS is required.) 179 */ 180 if (securelevel >= 2 && 181 SCARG(uap, flags) != MNT_GETARGS && 182 SCARG(uap, flags) != 183 (mp->mnt_flag | MNT_RDONLY | 184 MNT_RELOAD | MNT_FORCE | MNT_UPDATE)) { 185 vput(vp); 186 return (EPERM); 187 } 188 mp->mnt_flag |= SCARG(uap, flags) & 189 (MNT_RELOAD | MNT_FORCE | MNT_UPDATE | MNT_GETARGS); 190 /* 191 * Only root, or the user that did the original mount is 192 * permitted to update it. 193 */ 194 if ((mp->mnt_flag & MNT_GETARGS) == 0 && 195 mp->mnt_stat.f_owner != p->p_ucred->cr_uid && 196 (error = suser(p->p_ucred, &p->p_acflag)) != 0) { 197 vput(vp); 198 return (error); 199 } 200 /* 201 * Do not allow NFS export by non-root users. For non-root 202 * users, silently enforce MNT_NOSUID and MNT_NODEV, and 203 * MNT_NOEXEC if mount point is already MNT_NOEXEC. 204 */ 205 if (p->p_ucred->cr_uid != 0) { 206 if (SCARG(uap, flags) & MNT_EXPORTED) { 207 vput(vp); 208 return (EPERM); 209 } 210 SCARG(uap, flags) |= MNT_NOSUID | MNT_NODEV; 211 if (flag & MNT_NOEXEC) 212 SCARG(uap, flags) |= MNT_NOEXEC; 213 } 214 if (vfs_busy(mp, LK_NOWAIT, 0)) { 215 vput(vp); 216 return (EPERM); 217 } 218 goto update; 219 } else { 220 if (securelevel >= 2) { 221 vput(vp); 222 return (EPERM); 223 } 224 } 225 /* 226 * If the user is not root, ensure that they own the directory 227 * onto which we are attempting to mount. 228 */ 229 if ((error = VOP_GETATTR(vp, &va, p->p_ucred, p)) != 0 || 230 (va.va_uid != p->p_ucred->cr_uid && 231 (error = suser(p->p_ucred, &p->p_acflag)) != 0)) { 232 vput(vp); 233 return (error); 234 } 235 /* 236 * Do not allow NFS export by non-root users. For non-root users, 237 * silently enforce MNT_NOSUID and MNT_NODEV, and MNT_NOEXEC if the 238 * mount point is already MNT_NOEXEC. 239 */ 240 if (p->p_ucred->cr_uid != 0) { 241 if (SCARG(uap, flags) & MNT_EXPORTED) { 242 vput(vp); 243 return (EPERM); 244 } 245 SCARG(uap, flags) |= MNT_NOSUID | MNT_NODEV; 246 if (vp->v_mount->mnt_flag & MNT_NOEXEC) 247 SCARG(uap, flags) |= MNT_NOEXEC; 248 } 249 if ((error = vinvalbuf(vp, V_SAVE, p->p_ucred, p, 0, 0)) != 0) { 250 vput(vp); 251 return (error); 252 } 253 if (vp->v_type != VDIR) { 254 vput(vp); 255 return (ENOTDIR); 256 } 257 error = copyinstr(SCARG(uap, type), fstypename, MFSNAMELEN, NULL); 258 if (error) { 259 #if defined(COMPAT_09) || defined(COMPAT_43) 260 /* 261 * Historically filesystem types were identified by number. 262 * If we get an integer for the filesystem type instead of a 263 * string, we check to see if it matches one of the historic 264 * filesystem types. 265 */ 266 u_long fsindex = (u_long)SCARG(uap, type); 267 if (fsindex >= nmountcompatnames || 268 mountcompatnames[fsindex] == NULL) { 269 vput(vp); 270 return (ENODEV); 271 } 272 strncpy(fstypename, mountcompatnames[fsindex], MFSNAMELEN); 273 #else 274 vput(vp); 275 return (error); 276 #endif 277 } 278 #ifdef COMPAT_10 279 /* Accept `ufs' as an alias for `ffs'. */ 280 if (!strncmp(fstypename, "ufs", MFSNAMELEN)) 281 strncpy(fstypename, "ffs", MFSNAMELEN); 282 #endif 283 if ((vfs = vfs_getopsbyname(fstypename)) == NULL) { 284 vput(vp); 285 return (ENODEV); 286 } 287 if (vp->v_mountedhere != NULL) { 288 vput(vp); 289 return (EBUSY); 290 } 291 292 /* 293 * Allocate and initialize the file system. 294 */ 295 mp = (struct mount *)malloc((u_long)sizeof(struct mount), 296 M_MOUNT, M_WAITOK); 297 memset((char *)mp, 0, (u_long)sizeof(struct mount)); 298 lockinit(&mp->mnt_lock, PVFS, "vfslock", 0, 0); 299 simple_lock_init(&mp->mnt_slock); 300 (void)vfs_busy(mp, LK_NOWAIT, 0); 301 mp->mnt_op = vfs; 302 vfs->vfs_refcount++; 303 mp->mnt_vnodecovered = vp; 304 mp->mnt_stat.f_owner = p->p_ucred->cr_uid; 305 mp->mnt_unmounter = NULL; 306 mp->mnt_leaf = mp; 307 308 /* 309 * The underlying file system may refuse the mount for 310 * various reasons. Allow the user to force it to happen. 311 */ 312 mp->mnt_flag |= SCARG(uap, flags) & MNT_FORCE; 313 update: 314 /* 315 * Set the mount level flags. 316 */ 317 if (SCARG(uap, flags) & MNT_RDONLY) 318 mp->mnt_flag |= MNT_RDONLY; 319 else if (mp->mnt_flag & MNT_RDONLY) 320 mp->mnt_iflag |= IMNT_WANTRDWR; 321 mp->mnt_flag &= 322 ~(MNT_NOSUID | MNT_NOEXEC | MNT_NODEV | 323 MNT_SYNCHRONOUS | MNT_UNION | MNT_ASYNC | MNT_NOCOREDUMP | 324 MNT_NOATIME | MNT_NODEVMTIME | MNT_SYMPERM | MNT_SOFTDEP); 325 mp->mnt_flag |= SCARG(uap, flags) & 326 (MNT_NOSUID | MNT_NOEXEC | MNT_NODEV | 327 MNT_SYNCHRONOUS | MNT_UNION | MNT_ASYNC | MNT_NOCOREDUMP | 328 MNT_NOATIME | MNT_NODEVMTIME | MNT_SYMPERM | MNT_SOFTDEP | 329 MNT_IGNORE); 330 /* 331 * Mount the filesystem. 332 */ 333 error = VFS_MOUNT(mp, SCARG(uap, path), SCARG(uap, data), &nd, p); 334 if (mp->mnt_flag & (MNT_UPDATE | MNT_GETARGS)) { 335 if (mp->mnt_iflag & IMNT_WANTRDWR) 336 mp->mnt_flag &= ~MNT_RDONLY; 337 if (error || (mp->mnt_flag & MNT_GETARGS)) 338 mp->mnt_flag = flag; 339 mp->mnt_flag &=~ 340 (MNT_RELOAD | MNT_FORCE | MNT_UPDATE | MNT_GETARGS); 341 mp->mnt_iflag &=~ IMNT_WANTRDWR; 342 if ((mp->mnt_flag & (MNT_RDONLY | MNT_ASYNC)) == 0) { 343 if (mp->mnt_syncer == NULL) 344 error = vfs_allocate_syncvnode(mp); 345 } else { 346 if (mp->mnt_syncer != NULL) 347 vfs_deallocate_syncvnode(mp); 348 } 349 vfs_unbusy(mp); 350 VOP_UNLOCK(vp, 0); 351 vrele(vp); 352 return (error); 353 } 354 /* 355 * Put the new filesystem on the mount list after root. 356 */ 357 cache_purge(vp); 358 if (!error) { 359 mp->mnt_flag &=~ 360 (MNT_RELOAD | MNT_FORCE | MNT_UPDATE | MNT_GETARGS); 361 mp->mnt_iflag &=~ IMNT_WANTRDWR; 362 vp->v_mountedhere = mp; 363 simple_lock(&mountlist_slock); 364 CIRCLEQ_INSERT_TAIL(&mountlist, mp, mnt_list); 365 simple_unlock(&mountlist_slock); 366 checkdirs(vp); 367 VOP_UNLOCK(vp, 0); 368 if ((mp->mnt_flag & (MNT_RDONLY | MNT_ASYNC)) == 0) 369 error = vfs_allocate_syncvnode(mp); 370 vfs_unbusy(mp); 371 (void) VFS_STATVFS(mp, &mp->mnt_stat, p); 372 if ((error = VFS_START(mp, 0, p))) 373 vrele(vp); 374 } else { 375 vp->v_mountedhere = (struct mount *)0; 376 vfs->vfs_refcount--; 377 vfs_unbusy(mp); 378 free(mp, M_MOUNT); 379 vput(vp); 380 } 381 return (error); 382 } 383 384 /* 385 * Scan all active processes to see if any of them have a current 386 * or root directory onto which the new filesystem has just been 387 * mounted. If so, replace them with the new mount point. 388 */ 389 void 390 checkdirs(olddp) 391 struct vnode *olddp; 392 { 393 struct cwdinfo *cwdi; 394 struct vnode *newdp; 395 struct proc *p; 396 397 if (olddp->v_usecount == 1) 398 return; 399 if (VFS_ROOT(olddp->v_mountedhere, &newdp)) 400 panic("mount: lost mount"); 401 proclist_lock_read(); 402 PROCLIST_FOREACH(p, &allproc) { 403 cwdi = p->p_cwdi; 404 if (cwdi->cwdi_cdir == olddp) { 405 vrele(cwdi->cwdi_cdir); 406 VREF(newdp); 407 cwdi->cwdi_cdir = newdp; 408 } 409 if (cwdi->cwdi_rdir == olddp) { 410 vrele(cwdi->cwdi_rdir); 411 VREF(newdp); 412 cwdi->cwdi_rdir = newdp; 413 } 414 } 415 proclist_unlock_read(); 416 if (rootvnode == olddp) { 417 vrele(rootvnode); 418 VREF(newdp); 419 rootvnode = newdp; 420 } 421 vput(newdp); 422 } 423 424 /* 425 * Unmount a file system. 426 * 427 * Note: unmount takes a path to the vnode mounted on as argument, 428 * not special file (as before). 429 */ 430 /* ARGSUSED */ 431 int 432 sys_unmount(l, v, retval) 433 struct lwp *l; 434 void *v; 435 register_t *retval; 436 { 437 struct sys_unmount_args /* { 438 syscallarg(const char *) path; 439 syscallarg(int) flags; 440 } */ *uap = v; 441 struct proc *p = l->l_proc; 442 struct vnode *vp; 443 struct mount *mp; 444 int error; 445 struct nameidata nd; 446 447 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, 448 SCARG(uap, path), p); 449 if ((error = namei(&nd)) != 0) 450 return (error); 451 vp = nd.ni_vp; 452 mp = vp->v_mount; 453 454 /* 455 * Only root, or the user that did the original mount is 456 * permitted to unmount this filesystem. 457 */ 458 if ((mp->mnt_stat.f_owner != p->p_ucred->cr_uid) && 459 (error = suser(p->p_ucred, &p->p_acflag)) != 0) { 460 vput(vp); 461 return (error); 462 } 463 464 /* 465 * Don't allow unmounting the root file system. 466 */ 467 if (mp->mnt_flag & MNT_ROOTFS) { 468 vput(vp); 469 return (EINVAL); 470 } 471 472 /* 473 * Must be the root of the filesystem 474 */ 475 if ((vp->v_flag & VROOT) == 0) { 476 vput(vp); 477 return (EINVAL); 478 } 479 vput(vp); 480 481 /* 482 * XXX Freeze syncer. Must do this before locking the 483 * mount point. See dounmount() for details. 484 */ 485 lockmgr(&syncer_lock, LK_EXCLUSIVE, NULL); 486 487 if (vfs_busy(mp, 0, 0)) { 488 lockmgr(&syncer_lock, LK_RELEASE, NULL); 489 return (EBUSY); 490 } 491 492 return (dounmount(mp, SCARG(uap, flags), p)); 493 } 494 495 /* 496 * Do the actual file system unmount. File system is assumed to have been 497 * marked busy by the caller. 498 */ 499 int 500 dounmount(mp, flags, p) 501 struct mount *mp; 502 int flags; 503 struct proc *p; 504 { 505 struct vnode *coveredvp; 506 int error; 507 int async; 508 int used_syncer; 509 510 simple_lock(&mountlist_slock); 511 vfs_unbusy(mp); 512 used_syncer = (mp->mnt_syncer != NULL); 513 514 /* 515 * XXX Syncer must be frozen when we get here. This should really 516 * be done on a per-mountpoint basis, but especially the softdep 517 * code possibly called from the syncer doens't exactly work on a 518 * per-mountpoint basis, so the softdep code would become a maze 519 * of vfs_busy() calls. 520 * 521 * The caller of dounmount() must acquire syncer_lock because 522 * the syncer itself acquires locks in syncer_lock -> vfs_busy 523 * order, and we must preserve that order to avoid deadlock. 524 * 525 * So, if the file system did not use the syncer, now is 526 * the time to release the syncer_lock. 527 */ 528 if (used_syncer == 0) 529 lockmgr(&syncer_lock, LK_RELEASE, NULL); 530 531 mp->mnt_iflag |= IMNT_UNMOUNT; 532 mp->mnt_unmounter = p; 533 lockmgr(&mp->mnt_lock, LK_DRAIN | LK_INTERLOCK, &mountlist_slock); 534 vn_start_write(NULL, &mp, V_WAIT); 535 536 if (mp->mnt_flag & MNT_EXPUBLIC) 537 vfs_setpublicfs(NULL, NULL, NULL); 538 async = mp->mnt_flag & MNT_ASYNC; 539 mp->mnt_flag &= ~MNT_ASYNC; 540 cache_purgevfs(mp); /* remove cache entries for this file sys */ 541 if (mp->mnt_syncer != NULL) 542 vfs_deallocate_syncvnode(mp); 543 error = 0; 544 if ((mp->mnt_flag & MNT_RDONLY) == 0) { 545 #if NFSS > 0 546 error = fss_umount_hook(mp, (flags & MNT_FORCE)); 547 #endif 548 if (error == 0) 549 error = VFS_SYNC(mp, MNT_WAIT, p->p_ucred, p); 550 } 551 if (error == 0 || (flags & MNT_FORCE)) 552 error = VFS_UNMOUNT(mp, flags, p); 553 vn_finished_write(mp, 0); 554 simple_lock(&mountlist_slock); 555 if (error) { 556 if ((mp->mnt_flag & (MNT_RDONLY | MNT_ASYNC)) == 0) 557 (void) vfs_allocate_syncvnode(mp); 558 mp->mnt_iflag &= ~IMNT_UNMOUNT; 559 mp->mnt_unmounter = NULL; 560 mp->mnt_flag |= async; 561 lockmgr(&mp->mnt_lock, LK_RELEASE | LK_INTERLOCK | LK_REENABLE, 562 &mountlist_slock); 563 if (used_syncer) 564 lockmgr(&syncer_lock, LK_RELEASE, NULL); 565 simple_lock(&mp->mnt_slock); 566 while (mp->mnt_wcnt > 0) { 567 wakeup(mp); 568 ltsleep(&mp->mnt_wcnt, PVFS, "mntwcnt1", 569 0, &mp->mnt_slock); 570 } 571 simple_unlock(&mp->mnt_slock); 572 return (error); 573 } 574 CIRCLEQ_REMOVE(&mountlist, mp, mnt_list); 575 if ((coveredvp = mp->mnt_vnodecovered) != NULLVP) { 576 coveredvp->v_mountedhere = NULL; 577 vrele(coveredvp); 578 } 579 mp->mnt_op->vfs_refcount--; 580 if (LIST_FIRST(&mp->mnt_vnodelist) != NULL) 581 panic("unmount: dangling vnode"); 582 mp->mnt_iflag |= IMNT_GONE; 583 lockmgr(&mp->mnt_lock, LK_RELEASE | LK_INTERLOCK, &mountlist_slock); 584 if (used_syncer) 585 lockmgr(&syncer_lock, LK_RELEASE, NULL); 586 simple_lock(&mp->mnt_slock); 587 while (mp->mnt_wcnt > 0) { 588 wakeup(mp); 589 ltsleep(&mp->mnt_wcnt, PVFS, "mntwcnt2", 0, &mp->mnt_slock); 590 } 591 simple_unlock(&mp->mnt_slock); 592 free(mp, M_MOUNT); 593 return (0); 594 } 595 596 /* 597 * Sync each mounted filesystem. 598 */ 599 #ifdef DEBUG 600 int syncprt = 0; 601 struct ctldebug debug0 = { "syncprt", &syncprt }; 602 #endif 603 604 /* ARGSUSED */ 605 int 606 sys_sync(l, v, retval) 607 struct lwp *l; 608 void *v; 609 register_t *retval; 610 { 611 struct mount *mp, *nmp; 612 int asyncflag; 613 struct proc *p = l == NULL ? &proc0 : l->l_proc; 614 615 simple_lock(&mountlist_slock); 616 for (mp = mountlist.cqh_last; mp != (void *)&mountlist; mp = nmp) { 617 if (vfs_busy(mp, LK_NOWAIT, &mountlist_slock)) { 618 nmp = mp->mnt_list.cqe_prev; 619 continue; 620 } 621 if ((mp->mnt_flag & MNT_RDONLY) == 0 && 622 vn_start_write(NULL, &mp, V_NOWAIT) == 0) { 623 asyncflag = mp->mnt_flag & MNT_ASYNC; 624 mp->mnt_flag &= ~MNT_ASYNC; 625 VFS_SYNC(mp, MNT_NOWAIT, p->p_ucred, p); 626 if (asyncflag) 627 mp->mnt_flag |= MNT_ASYNC; 628 vn_finished_write(mp, 0); 629 } 630 simple_lock(&mountlist_slock); 631 nmp = mp->mnt_list.cqe_prev; 632 vfs_unbusy(mp); 633 634 } 635 simple_unlock(&mountlist_slock); 636 #ifdef DEBUG 637 if (syncprt) 638 vfs_bufstats(); 639 #endif /* DEBUG */ 640 return (0); 641 } 642 643 /* 644 * Change filesystem quotas. 645 */ 646 /* ARGSUSED */ 647 int 648 sys_quotactl(l, v, retval) 649 struct lwp *l; 650 void *v; 651 register_t *retval; 652 { 653 struct sys_quotactl_args /* { 654 syscallarg(const char *) path; 655 syscallarg(int) cmd; 656 syscallarg(int) uid; 657 syscallarg(caddr_t) arg; 658 } */ *uap = v; 659 struct proc *p = l->l_proc; 660 struct mount *mp; 661 int error; 662 struct nameidata nd; 663 664 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p); 665 if ((error = namei(&nd)) != 0) 666 return (error); 667 error = vn_start_write(nd.ni_vp, &mp, V_WAIT | V_PCATCH); 668 vrele(nd.ni_vp); 669 if (error) 670 return (error); 671 error = VFS_QUOTACTL(mp, SCARG(uap, cmd), SCARG(uap, uid), 672 SCARG(uap, arg), p); 673 vn_finished_write(mp, 0); 674 return (error); 675 } 676 677 int 678 dostatvfs(struct mount *mp, struct statvfs *sp, struct proc *p, int flags, 679 int root) 680 { 681 struct cwdinfo *cwdi = p->p_cwdi; 682 int error = 0; 683 684 /* 685 * If MNT_NOWAIT or MNT_LAZY is specified, do not 686 * refresh the fsstat cache. MNT_WAIT or MNT_LAZY 687 * overrides MNT_NOWAIT. 688 */ 689 if (flags == MNT_NOWAIT || flags == MNT_LAZY || 690 (flags != MNT_WAIT && flags != 0)) { 691 memcpy(sp, &mp->mnt_stat, sizeof(*sp)); 692 goto done; 693 } 694 695 /* Get the filesystem stats now */ 696 memset(sp, 0, sizeof(*sp)); 697 if ((error = VFS_STATVFS(mp, sp, p)) != 0) { 698 return error; 699 } 700 701 if (cwdi->cwdi_rdir == NULL) 702 (void)memcpy(&mp->mnt_stat, sp, sizeof(mp->mnt_stat)); 703 done: 704 if (cwdi->cwdi_rdir != NULL) { 705 size_t len; 706 char *bp; 707 char *path = malloc(MAXPATHLEN, M_TEMP, M_WAITOK); 708 if (!path) 709 return ENOMEM; 710 711 bp = path + MAXPATHLEN; 712 *--bp = '\0'; 713 error = getcwd_common(cwdi->cwdi_rdir, rootvnode, &bp, path, 714 MAXPATHLEN / 2, 0, p); 715 if (error) { 716 free(path, M_TEMP); 717 return error; 718 } 719 len = strlen(bp); 720 /* 721 * for mount points that are below our root, we can see 722 * them, so we fix up the pathname and return them. The 723 * rest we cannot see, so we don't allow viewing the 724 * data. 725 */ 726 if (strncmp(bp, sp->f_mntonname, len) == 0) { 727 strlcpy(sp->f_mntonname, &sp->f_mntonname[len], 728 sizeof(sp->f_mntonname)); 729 if (sp->f_mntonname[0] == '\0') 730 (void)strlcpy(sp->f_mntonname, "/", 731 sizeof(sp->f_mntonname)); 732 } else { 733 if (root) 734 (void)strlcpy(sp->f_mntonname, "/", 735 sizeof(sp->f_mntonname)); 736 else 737 error = EPERM; 738 } 739 free(path, M_TEMP); 740 } 741 sp->f_flag = mp->mnt_flag & MNT_VISFLAGMASK; 742 return error; 743 } 744 745 /* 746 * Get filesystem statistics. 747 */ 748 /* ARGSUSED */ 749 int 750 sys_statvfs1(l, v, retval) 751 struct lwp *l; 752 void *v; 753 register_t *retval; 754 { 755 struct sys_statvfs1_args /* { 756 syscallarg(const char *) path; 757 syscallarg(struct statvfs *) buf; 758 syscallarg(int) flags; 759 } */ *uap = v; 760 struct proc *p = l->l_proc; 761 struct mount *mp; 762 struct statvfs sbuf; 763 int error; 764 struct nameidata nd; 765 766 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p); 767 if ((error = namei(&nd)) != 0) 768 return error; 769 mp = nd.ni_vp->v_mount; 770 vrele(nd.ni_vp); 771 if ((error = dostatvfs(mp, &sbuf, p, SCARG(uap, flags), 1)) != 0) 772 return error; 773 return copyout(&sbuf, SCARG(uap, buf), sizeof(sbuf)); 774 } 775 776 /* 777 * Get filesystem statistics. 778 */ 779 /* ARGSUSED */ 780 int 781 sys_fstatvfs1(l, v, retval) 782 struct lwp *l; 783 void *v; 784 register_t *retval; 785 { 786 struct sys_fstatvfs1_args /* { 787 syscallarg(int) fd; 788 syscallarg(struct statvfs *) buf; 789 syscallarg(int) flags; 790 } */ *uap = v; 791 struct proc *p = l->l_proc; 792 struct file *fp; 793 struct mount *mp; 794 struct statvfs sbuf; 795 int error; 796 797 /* getvnode() will use the descriptor for us */ 798 if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0) 799 return (error); 800 mp = ((struct vnode *)fp->f_data)->v_mount; 801 if ((error = dostatvfs(mp, &sbuf, p, SCARG(uap, flags), 1)) != 0) 802 goto out; 803 error = copyout(&sbuf, SCARG(uap, buf), sizeof(sbuf)); 804 out: 805 FILE_UNUSE(fp, p); 806 return error; 807 } 808 809 810 /* 811 * Get statistics on all filesystems. 812 */ 813 int 814 sys_getvfsstat(l, v, retval) 815 struct lwp *l; 816 void *v; 817 register_t *retval; 818 { 819 struct sys_getvfsstat_args /* { 820 syscallarg(struct statvfs *) buf; 821 syscallarg(size_t) bufsize; 822 syscallarg(int) flags; 823 } */ *uap = v; 824 int root = 0; 825 struct proc *p = l->l_proc; 826 struct mount *mp, *nmp; 827 struct statvfs sbuf; 828 struct statvfs *sfsp; 829 size_t count, maxcount; 830 int error = 0; 831 832 maxcount = SCARG(uap, bufsize) / sizeof(struct statvfs); 833 sfsp = SCARG(uap, buf); 834 simple_lock(&mountlist_slock); 835 count = 0; 836 for (mp = CIRCLEQ_FIRST(&mountlist); mp != (void *)&mountlist; 837 mp = nmp) { 838 if (vfs_busy(mp, LK_NOWAIT, &mountlist_slock)) { 839 nmp = CIRCLEQ_NEXT(mp, mnt_list); 840 continue; 841 } 842 if (sfsp && count < maxcount) { 843 error = dostatvfs(mp, &sbuf, p, SCARG(uap, flags), 0); 844 if (error) { 845 simple_lock(&mountlist_slock); 846 nmp = CIRCLEQ_NEXT(mp, mnt_list); 847 vfs_unbusy(mp); 848 continue; 849 } 850 error = copyout(&sbuf, sfsp, sizeof(*sfsp)); 851 if (error) { 852 vfs_unbusy(mp); 853 return (error); 854 } 855 sfsp++; 856 root |= strcmp(sbuf.f_mntonname, "/") == 0; 857 } 858 count++; 859 simple_lock(&mountlist_slock); 860 nmp = CIRCLEQ_NEXT(mp, mnt_list); 861 vfs_unbusy(mp); 862 } 863 simple_unlock(&mountlist_slock); 864 if (root == 0 && p->p_cwdi->cwdi_rdir) { 865 /* 866 * fake a root entry 867 */ 868 if ((error = dostatvfs(p->p_cwdi->cwdi_rdir->v_mount, &sbuf, p, 869 SCARG(uap, flags), 1)) != 0) 870 return error; 871 if (sfsp) 872 error = copyout(&sbuf, sfsp, sizeof(*sfsp)); 873 count++; 874 } 875 if (sfsp && count > maxcount) 876 *retval = maxcount; 877 else 878 *retval = count; 879 return error; 880 } 881 882 /* 883 * Change current working directory to a given file descriptor. 884 */ 885 /* ARGSUSED */ 886 int 887 sys_fchdir(l, v, retval) 888 struct lwp *l; 889 void *v; 890 register_t *retval; 891 { 892 struct sys_fchdir_args /* { 893 syscallarg(int) fd; 894 } */ *uap = v; 895 struct proc *p = l->l_proc; 896 struct filedesc *fdp = p->p_fd; 897 struct cwdinfo *cwdi = p->p_cwdi; 898 struct vnode *vp, *tdp; 899 struct mount *mp; 900 struct file *fp; 901 int error; 902 903 /* getvnode() will use the descriptor for us */ 904 if ((error = getvnode(fdp, SCARG(uap, fd), &fp)) != 0) 905 return (error); 906 vp = (struct vnode *)fp->f_data; 907 908 VREF(vp); 909 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); 910 if (vp->v_type != VDIR) 911 error = ENOTDIR; 912 else 913 error = VOP_ACCESS(vp, VEXEC, p->p_ucred, p); 914 while (!error && (mp = vp->v_mountedhere) != NULL) { 915 if (vfs_busy(mp, 0, 0)) 916 continue; 917 error = VFS_ROOT(mp, &tdp); 918 vfs_unbusy(mp); 919 if (error) 920 break; 921 vput(vp); 922 vp = tdp; 923 } 924 if (error) { 925 vput(vp); 926 goto out; 927 } 928 VOP_UNLOCK(vp, 0); 929 930 /* 931 * Disallow changing to a directory not under the process's 932 * current root directory (if there is one). 933 */ 934 if (cwdi->cwdi_rdir && !vn_isunder(vp, NULL, p)) { 935 vrele(vp); 936 error = EPERM; /* operation not permitted */ 937 goto out; 938 } 939 940 vrele(cwdi->cwdi_cdir); 941 cwdi->cwdi_cdir = vp; 942 out: 943 FILE_UNUSE(fp, p); 944 return (error); 945 } 946 947 /* 948 * Change this process's notion of the root directory to a given file descriptor. 949 */ 950 951 int 952 sys_fchroot(l, v, retval) 953 struct lwp *l; 954 void *v; 955 register_t *retval; 956 { 957 struct sys_fchroot_args *uap = v; 958 struct proc *p = l->l_proc; 959 struct filedesc *fdp = p->p_fd; 960 struct cwdinfo *cwdi = p->p_cwdi; 961 struct vnode *vp; 962 struct file *fp; 963 int error; 964 965 if ((error = suser(p->p_ucred, &p->p_acflag)) != 0) 966 return error; 967 /* getvnode() will use the descriptor for us */ 968 if ((error = getvnode(fdp, SCARG(uap, fd), &fp)) != 0) 969 return error; 970 vp = (struct vnode *) fp->f_data; 971 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); 972 if (vp->v_type != VDIR) 973 error = ENOTDIR; 974 else 975 error = VOP_ACCESS(vp, VEXEC, p->p_ucred, p); 976 VOP_UNLOCK(vp, 0); 977 if (error) 978 goto out; 979 VREF(vp); 980 981 /* 982 * Prevent escaping from chroot by putting the root under 983 * the working directory. Silently chdir to / if we aren't 984 * already there. 985 */ 986 if (!vn_isunder(cwdi->cwdi_cdir, vp, p)) { 987 /* 988 * XXX would be more failsafe to change directory to a 989 * deadfs node here instead 990 */ 991 vrele(cwdi->cwdi_cdir); 992 VREF(vp); 993 cwdi->cwdi_cdir = vp; 994 } 995 996 if (cwdi->cwdi_rdir != NULL) 997 vrele(cwdi->cwdi_rdir); 998 cwdi->cwdi_rdir = vp; 999 out: 1000 FILE_UNUSE(fp, p); 1001 return (error); 1002 } 1003 1004 1005 1006 /* 1007 * Change current working directory (``.''). 1008 */ 1009 /* ARGSUSED */ 1010 int 1011 sys_chdir(l, v, retval) 1012 struct lwp *l; 1013 void *v; 1014 register_t *retval; 1015 { 1016 struct sys_chdir_args /* { 1017 syscallarg(const char *) path; 1018 } */ *uap = v; 1019 struct proc *p = l->l_proc; 1020 struct cwdinfo *cwdi = p->p_cwdi; 1021 int error; 1022 struct nameidata nd; 1023 1024 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, 1025 SCARG(uap, path), p); 1026 if ((error = change_dir(&nd, p)) != 0) 1027 return (error); 1028 vrele(cwdi->cwdi_cdir); 1029 cwdi->cwdi_cdir = nd.ni_vp; 1030 return (0); 1031 } 1032 1033 /* 1034 * Change notion of root (``/'') directory. 1035 */ 1036 /* ARGSUSED */ 1037 int 1038 sys_chroot(l, v, retval) 1039 struct lwp *l; 1040 void *v; 1041 register_t *retval; 1042 { 1043 struct sys_chroot_args /* { 1044 syscallarg(const char *) path; 1045 } */ *uap = v; 1046 struct proc *p = l->l_proc; 1047 struct cwdinfo *cwdi = p->p_cwdi; 1048 struct vnode *vp; 1049 int error; 1050 struct nameidata nd; 1051 1052 if ((error = suser(p->p_ucred, &p->p_acflag)) != 0) 1053 return (error); 1054 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, 1055 SCARG(uap, path), p); 1056 if ((error = change_dir(&nd, p)) != 0) 1057 return (error); 1058 if (cwdi->cwdi_rdir != NULL) 1059 vrele(cwdi->cwdi_rdir); 1060 vp = nd.ni_vp; 1061 cwdi->cwdi_rdir = vp; 1062 1063 /* 1064 * Prevent escaping from chroot by putting the root under 1065 * the working directory. Silently chdir to / if we aren't 1066 * already there. 1067 */ 1068 if (!vn_isunder(cwdi->cwdi_cdir, vp, p)) { 1069 /* 1070 * XXX would be more failsafe to change directory to a 1071 * deadfs node here instead 1072 */ 1073 vrele(cwdi->cwdi_cdir); 1074 VREF(vp); 1075 cwdi->cwdi_cdir = vp; 1076 } 1077 1078 return (0); 1079 } 1080 1081 /* 1082 * Common routine for chroot and chdir. 1083 */ 1084 static int 1085 change_dir(ndp, p) 1086 struct nameidata *ndp; 1087 struct proc *p; 1088 { 1089 struct vnode *vp; 1090 int error; 1091 1092 if ((error = namei(ndp)) != 0) 1093 return (error); 1094 vp = ndp->ni_vp; 1095 if (vp->v_type != VDIR) 1096 error = ENOTDIR; 1097 else 1098 error = VOP_ACCESS(vp, VEXEC, p->p_ucred, p); 1099 1100 if (error) 1101 vput(vp); 1102 else 1103 VOP_UNLOCK(vp, 0); 1104 return (error); 1105 } 1106 1107 /* 1108 * Check permissions, allocate an open file structure, 1109 * and call the device open routine if any. 1110 */ 1111 int 1112 sys_open(l, v, retval) 1113 struct lwp *l; 1114 void *v; 1115 register_t *retval; 1116 { 1117 struct sys_open_args /* { 1118 syscallarg(const char *) path; 1119 syscallarg(int) flags; 1120 syscallarg(int) mode; 1121 } */ *uap = v; 1122 struct proc *p = l->l_proc; 1123 struct cwdinfo *cwdi = p->p_cwdi; 1124 struct filedesc *fdp = p->p_fd; 1125 struct file *fp; 1126 struct vnode *vp; 1127 int flags, cmode; 1128 int type, indx, error; 1129 struct flock lf; 1130 struct nameidata nd; 1131 1132 flags = FFLAGS(SCARG(uap, flags)); 1133 if ((flags & (FREAD | FWRITE)) == 0) 1134 return (EINVAL); 1135 /* falloc() will use the file descriptor for us */ 1136 if ((error = falloc(p, &fp, &indx)) != 0) 1137 return (error); 1138 cmode = ((SCARG(uap, mode) &~ cwdi->cwdi_cmask) & ALLPERMS) &~ S_ISTXT; 1139 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p); 1140 l->l_dupfd = -indx - 1; /* XXX check for fdopen */ 1141 if ((error = vn_open(&nd, flags, cmode)) != 0) { 1142 FILE_UNUSE(fp, p); 1143 fdp->fd_ofiles[indx] = NULL; 1144 ffree(fp); 1145 if ((error == ENODEV || error == ENXIO) && 1146 l->l_dupfd >= 0 && /* XXX from fdopen */ 1147 (error = 1148 dupfdopen(p, indx, l->l_dupfd, flags, error)) == 0) { 1149 *retval = indx; 1150 return (0); 1151 } 1152 if (error == ERESTART) 1153 error = EINTR; 1154 fdremove(fdp, indx); 1155 return (error); 1156 } 1157 l->l_dupfd = 0; 1158 vp = nd.ni_vp; 1159 fp->f_flag = flags & FMASK; 1160 fp->f_type = DTYPE_VNODE; 1161 fp->f_ops = &vnops; 1162 fp->f_data = vp; 1163 if (flags & (O_EXLOCK | O_SHLOCK)) { 1164 lf.l_whence = SEEK_SET; 1165 lf.l_start = 0; 1166 lf.l_len = 0; 1167 if (flags & O_EXLOCK) 1168 lf.l_type = F_WRLCK; 1169 else 1170 lf.l_type = F_RDLCK; 1171 type = F_FLOCK; 1172 if ((flags & FNONBLOCK) == 0) 1173 type |= F_WAIT; 1174 VOP_UNLOCK(vp, 0); 1175 error = VOP_ADVLOCK(vp, fp, F_SETLK, &lf, type); 1176 if (error) { 1177 (void) vn_close(vp, fp->f_flag, fp->f_cred, p); 1178 FILE_UNUSE(fp, p); 1179 ffree(fp); 1180 fdremove(fdp, indx); 1181 return (error); 1182 } 1183 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); 1184 fp->f_flag |= FHASLOCK; 1185 } 1186 VOP_UNLOCK(vp, 0); 1187 *retval = indx; 1188 FILE_SET_MATURE(fp); 1189 FILE_UNUSE(fp, p); 1190 return (0); 1191 } 1192 1193 /* 1194 * Get file handle system call 1195 */ 1196 int 1197 sys_getfh(l, v, retval) 1198 struct lwp *l; 1199 void *v; 1200 register_t *retval; 1201 { 1202 struct sys_getfh_args /* { 1203 syscallarg(char *) fname; 1204 syscallarg(fhandle_t *) fhp; 1205 } */ *uap = v; 1206 struct proc *p = l->l_proc; 1207 struct vnode *vp; 1208 fhandle_t fh; 1209 int error; 1210 struct nameidata nd; 1211 1212 /* 1213 * Must be super user 1214 */ 1215 error = suser(p->p_ucred, &p->p_acflag); 1216 if (error) 1217 return (error); 1218 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, 1219 SCARG(uap, fname), p); 1220 error = namei(&nd); 1221 if (error) 1222 return (error); 1223 vp = nd.ni_vp; 1224 memset(&fh, 0, sizeof(fh)); 1225 fh.fh_fsid = vp->v_mount->mnt_stat.f_fsidx; 1226 error = VFS_VPTOFH(vp, &fh.fh_fid); 1227 vput(vp); 1228 if (error) 1229 return (error); 1230 error = copyout(&fh, (caddr_t)SCARG(uap, fhp), sizeof (fh)); 1231 return (error); 1232 } 1233 1234 /* 1235 * Open a file given a file handle. 1236 * 1237 * Check permissions, allocate an open file structure, 1238 * and call the device open routine if any. 1239 */ 1240 int 1241 sys_fhopen(l, v, retval) 1242 struct lwp *l; 1243 void *v; 1244 register_t *retval; 1245 { 1246 struct sys_fhopen_args /* { 1247 syscallarg(const fhandle_t *) fhp; 1248 syscallarg(int) flags; 1249 } */ *uap = v; 1250 struct proc *p = l->l_proc; 1251 struct filedesc *fdp = p->p_fd; 1252 struct file *fp; 1253 struct vnode *vp = NULL; 1254 struct mount *mp; 1255 struct ucred *cred = p->p_ucred; 1256 int flags; 1257 struct file *nfp; 1258 int type, indx, error=0; 1259 struct flock lf; 1260 struct vattr va; 1261 fhandle_t fh; 1262 1263 /* 1264 * Must be super user 1265 */ 1266 if ((error = suser(p->p_ucred, &p->p_acflag))) 1267 return (error); 1268 1269 flags = FFLAGS(SCARG(uap, flags)); 1270 if ((flags & (FREAD | FWRITE)) == 0) 1271 return (EINVAL); 1272 if ((flags & O_CREAT)) 1273 return (EINVAL); 1274 /* falloc() will use the file descriptor for us */ 1275 if ((error = falloc(p, &nfp, &indx)) != 0) 1276 return (error); 1277 fp = nfp; 1278 if ((error = copyin(SCARG(uap, fhp), &fh, sizeof(fhandle_t))) != 0) 1279 goto bad; 1280 1281 if ((mp = vfs_getvfs(&fh.fh_fsid)) == NULL) { 1282 error = ESTALE; 1283 goto bad; 1284 } 1285 1286 if ((error = VFS_FHTOVP(mp, &fh.fh_fid, &vp)) != 0) { 1287 vp = NULL; /* most likely unnecessary sanity for bad: */ 1288 goto bad; 1289 } 1290 1291 /* Now do an effective vn_open */ 1292 1293 if (vp->v_type == VSOCK) { 1294 error = EOPNOTSUPP; 1295 goto bad; 1296 } 1297 if (flags & FREAD) { 1298 if ((error = VOP_ACCESS(vp, VREAD, cred, p)) != 0) 1299 goto bad; 1300 } 1301 if (flags & (FWRITE | O_TRUNC)) { 1302 if (vp->v_type == VDIR) { 1303 error = EISDIR; 1304 goto bad; 1305 } 1306 if ((error = vn_writechk(vp)) != 0 || 1307 (error = VOP_ACCESS(vp, VWRITE, cred, p)) != 0) 1308 goto bad; 1309 } 1310 if (flags & O_TRUNC) { 1311 if ((error = vn_start_write(vp, &mp, V_WAIT | V_PCATCH)) != 0) 1312 goto bad; 1313 VOP_UNLOCK(vp, 0); /* XXX */ 1314 VOP_LEASE(vp, p, cred, LEASE_WRITE); 1315 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); /* XXX */ 1316 VATTR_NULL(&va); 1317 va.va_size = 0; 1318 error = VOP_SETATTR(vp, &va, cred, p); 1319 vn_finished_write(mp, 0); 1320 if (error) 1321 goto bad; 1322 } 1323 if ((error = VOP_OPEN(vp, flags, cred, p)) != 0) 1324 goto bad; 1325 if (vp->v_type == VREG && 1326 uvn_attach(vp, flags & FWRITE ? VM_PROT_WRITE : 0) == NULL) { 1327 error = EIO; 1328 goto bad; 1329 } 1330 if (flags & FWRITE) 1331 vp->v_writecount++; 1332 1333 /* done with modified vn_open, now finish what sys_open does. */ 1334 1335 fp->f_flag = flags & FMASK; 1336 fp->f_type = DTYPE_VNODE; 1337 fp->f_ops = &vnops; 1338 fp->f_data = vp; 1339 if (flags & (O_EXLOCK | O_SHLOCK)) { 1340 lf.l_whence = SEEK_SET; 1341 lf.l_start = 0; 1342 lf.l_len = 0; 1343 if (flags & O_EXLOCK) 1344 lf.l_type = F_WRLCK; 1345 else 1346 lf.l_type = F_RDLCK; 1347 type = F_FLOCK; 1348 if ((flags & FNONBLOCK) == 0) 1349 type |= F_WAIT; 1350 VOP_UNLOCK(vp, 0); 1351 error = VOP_ADVLOCK(vp, fp, F_SETLK, &lf, type); 1352 if (error) { 1353 (void) vn_close(vp, fp->f_flag, fp->f_cred, p); 1354 FILE_UNUSE(fp, p); 1355 ffree(fp); 1356 fdremove(fdp, indx); 1357 return (error); 1358 } 1359 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); 1360 fp->f_flag |= FHASLOCK; 1361 } 1362 VOP_UNLOCK(vp, 0); 1363 *retval = indx; 1364 FILE_SET_MATURE(fp); 1365 FILE_UNUSE(fp, p); 1366 return (0); 1367 1368 bad: 1369 FILE_UNUSE(fp, p); 1370 ffree(fp); 1371 fdremove(fdp, indx); 1372 if (vp != NULL) 1373 vput(vp); 1374 return (error); 1375 } 1376 1377 /* ARGSUSED */ 1378 int 1379 sys_fhstat(l, v, retval) 1380 struct lwp *l; 1381 void *v; 1382 register_t *retval; 1383 { 1384 struct sys_fhstat_args /* { 1385 syscallarg(const fhandle_t *) fhp; 1386 syscallarg(struct stat *) sb; 1387 } */ *uap = v; 1388 struct proc *p = l->l_proc; 1389 struct stat sb; 1390 int error; 1391 fhandle_t fh; 1392 struct mount *mp; 1393 struct vnode *vp; 1394 1395 /* 1396 * Must be super user 1397 */ 1398 if ((error = suser(p->p_ucred, &p->p_acflag))) 1399 return (error); 1400 1401 if ((error = copyin(SCARG(uap, fhp), &fh, sizeof(fhandle_t))) != 0) 1402 return (error); 1403 1404 if ((mp = vfs_getvfs(&fh.fh_fsid)) == NULL) 1405 return (ESTALE); 1406 if ((error = VFS_FHTOVP(mp, &fh.fh_fid, &vp))) 1407 return (error); 1408 error = vn_stat(vp, &sb, p); 1409 vput(vp); 1410 if (error) 1411 return (error); 1412 error = copyout(&sb, SCARG(uap, sb), sizeof(sb)); 1413 return (error); 1414 } 1415 1416 /* ARGSUSED */ 1417 int 1418 sys_fhstatvfs1(l, v, retval) 1419 struct lwp *l; 1420 void *v; 1421 register_t *retval; 1422 { 1423 struct sys_fhstatvfs1_args /* 1424 syscallarg(const fhandle_t *) fhp; 1425 syscallarg(struct statvfs *) buf; 1426 syscallarg(int) flags; 1427 } */ *uap = v; 1428 struct proc *p = l->l_proc; 1429 struct statvfs sbuf; 1430 fhandle_t fh; 1431 struct mount *mp; 1432 struct vnode *vp; 1433 int error; 1434 1435 /* 1436 * Must be super user 1437 */ 1438 if ((error = suser(p->p_ucred, &p->p_acflag)) != 0) 1439 return error; 1440 1441 if ((error = copyin(SCARG(uap, fhp), &fh, sizeof(fhandle_t))) != 0) 1442 return error; 1443 1444 if ((mp = vfs_getvfs(&fh.fh_fsid)) == NULL) 1445 return ESTALE; 1446 if ((error = VFS_FHTOVP(mp, &fh.fh_fid, &vp))) 1447 return error; 1448 1449 mp = vp->v_mount; 1450 if ((error = dostatvfs(mp, &sbuf, p, SCARG(uap, flags), 1)) != 0) { 1451 vput(vp); 1452 return error; 1453 } 1454 vput(vp); 1455 return copyout(&sbuf, SCARG(uap, buf), sizeof(sbuf)); 1456 } 1457 1458 /* 1459 * Create a special file. 1460 */ 1461 /* ARGSUSED */ 1462 int 1463 sys_mknod(l, v, retval) 1464 struct lwp *l; 1465 void *v; 1466 register_t *retval; 1467 { 1468 struct sys_mknod_args /* { 1469 syscallarg(const char *) path; 1470 syscallarg(int) mode; 1471 syscallarg(int) dev; 1472 } */ *uap = v; 1473 struct proc *p = l->l_proc; 1474 struct vnode *vp; 1475 struct mount *mp; 1476 struct vattr vattr; 1477 int error; 1478 int whiteout = 0; 1479 struct nameidata nd; 1480 1481 if ((error = suser(p->p_ucred, &p->p_acflag)) != 0) 1482 return (error); 1483 restart: 1484 NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, SCARG(uap, path), p); 1485 if ((error = namei(&nd)) != 0) 1486 return (error); 1487 vp = nd.ni_vp; 1488 if (vp != NULL) 1489 error = EEXIST; 1490 else { 1491 VATTR_NULL(&vattr); 1492 vattr.va_mode = 1493 (SCARG(uap, mode) & ALLPERMS) &~ p->p_cwdi->cwdi_cmask; 1494 vattr.va_rdev = SCARG(uap, dev); 1495 whiteout = 0; 1496 1497 switch (SCARG(uap, mode) & S_IFMT) { 1498 case S_IFMT: /* used by badsect to flag bad sectors */ 1499 vattr.va_type = VBAD; 1500 break; 1501 case S_IFCHR: 1502 vattr.va_type = VCHR; 1503 break; 1504 case S_IFBLK: 1505 vattr.va_type = VBLK; 1506 break; 1507 case S_IFWHT: 1508 whiteout = 1; 1509 break; 1510 default: 1511 error = EINVAL; 1512 break; 1513 } 1514 } 1515 if (vn_start_write(nd.ni_dvp, &mp, V_NOWAIT) != 0) { 1516 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); 1517 if (nd.ni_dvp == vp) 1518 vrele(nd.ni_dvp); 1519 else 1520 vput(nd.ni_dvp); 1521 if (vp) 1522 vrele(vp); 1523 if ((error = vn_start_write(NULL, &mp, 1524 V_WAIT | V_SLEEPONLY | V_PCATCH)) != 0) 1525 return (error); 1526 goto restart; 1527 } 1528 if (!error) { 1529 VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE); 1530 if (whiteout) { 1531 error = VOP_WHITEOUT(nd.ni_dvp, &nd.ni_cnd, CREATE); 1532 if (error) 1533 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); 1534 vput(nd.ni_dvp); 1535 } else { 1536 error = VOP_MKNOD(nd.ni_dvp, &nd.ni_vp, 1537 &nd.ni_cnd, &vattr); 1538 if (error == 0) 1539 vput(nd.ni_vp); 1540 } 1541 } else { 1542 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); 1543 if (nd.ni_dvp == vp) 1544 vrele(nd.ni_dvp); 1545 else 1546 vput(nd.ni_dvp); 1547 if (vp) 1548 vrele(vp); 1549 } 1550 vn_finished_write(mp, 0); 1551 return (error); 1552 } 1553 1554 /* 1555 * Create a named pipe. 1556 */ 1557 /* ARGSUSED */ 1558 int 1559 sys_mkfifo(l, v, retval) 1560 struct lwp *l; 1561 void *v; 1562 register_t *retval; 1563 { 1564 struct sys_mkfifo_args /* { 1565 syscallarg(const char *) path; 1566 syscallarg(int) mode; 1567 } */ *uap = v; 1568 struct proc *p = l->l_proc; 1569 struct mount *mp; 1570 struct vattr vattr; 1571 int error; 1572 struct nameidata nd; 1573 1574 restart: 1575 NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, SCARG(uap, path), p); 1576 if ((error = namei(&nd)) != 0) 1577 return (error); 1578 if (nd.ni_vp != NULL) { 1579 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); 1580 if (nd.ni_dvp == nd.ni_vp) 1581 vrele(nd.ni_dvp); 1582 else 1583 vput(nd.ni_dvp); 1584 vrele(nd.ni_vp); 1585 return (EEXIST); 1586 } 1587 if (vn_start_write(nd.ni_dvp, &mp, V_NOWAIT) != 0) { 1588 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); 1589 if (nd.ni_dvp == nd.ni_vp) 1590 vrele(nd.ni_dvp); 1591 else 1592 vput(nd.ni_dvp); 1593 if (nd.ni_vp) 1594 vrele(nd.ni_vp); 1595 if ((error = vn_start_write(NULL, &mp, 1596 V_WAIT | V_SLEEPONLY | V_PCATCH)) != 0) 1597 return (error); 1598 goto restart; 1599 } 1600 VATTR_NULL(&vattr); 1601 vattr.va_type = VFIFO; 1602 vattr.va_mode = (SCARG(uap, mode) & ALLPERMS) &~ p->p_cwdi->cwdi_cmask; 1603 VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE); 1604 error = VOP_MKNOD(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr); 1605 if (error == 0) 1606 vput(nd.ni_vp); 1607 vn_finished_write(mp, 0); 1608 return (error); 1609 } 1610 1611 /* 1612 * Make a hard file link. 1613 */ 1614 /* ARGSUSED */ 1615 int 1616 sys_link(l, v, retval) 1617 struct lwp *l; 1618 void *v; 1619 register_t *retval; 1620 { 1621 struct sys_link_args /* { 1622 syscallarg(const char *) path; 1623 syscallarg(const char *) link; 1624 } */ *uap = v; 1625 struct proc *p = l->l_proc; 1626 struct vnode *vp; 1627 struct mount *mp; 1628 struct nameidata nd; 1629 int error; 1630 1631 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p); 1632 if ((error = namei(&nd)) != 0) 1633 return (error); 1634 vp = nd.ni_vp; 1635 if ((error = vn_start_write(vp, &mp, V_WAIT | V_PCATCH)) != 0) { 1636 vrele(vp); 1637 return (error); 1638 } 1639 NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, SCARG(uap, link), p); 1640 if ((error = namei(&nd)) != 0) 1641 goto out; 1642 if (nd.ni_vp) { 1643 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); 1644 if (nd.ni_dvp == nd.ni_vp) 1645 vrele(nd.ni_dvp); 1646 else 1647 vput(nd.ni_dvp); 1648 vrele(nd.ni_vp); 1649 error = EEXIST; 1650 goto out; 1651 } 1652 VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE); 1653 VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE); 1654 error = VOP_LINK(nd.ni_dvp, vp, &nd.ni_cnd); 1655 out: 1656 vrele(vp); 1657 vn_finished_write(mp, 0); 1658 return (error); 1659 } 1660 1661 /* 1662 * Make a symbolic link. 1663 */ 1664 /* ARGSUSED */ 1665 int 1666 sys_symlink(l, v, retval) 1667 struct lwp *l; 1668 void *v; 1669 register_t *retval; 1670 { 1671 struct sys_symlink_args /* { 1672 syscallarg(const char *) path; 1673 syscallarg(const char *) link; 1674 } */ *uap = v; 1675 struct proc *p = l->l_proc; 1676 struct mount *mp; 1677 struct vattr vattr; 1678 char *path; 1679 int error; 1680 struct nameidata nd; 1681 1682 path = PNBUF_GET(); 1683 error = copyinstr(SCARG(uap, path), path, MAXPATHLEN, NULL); 1684 if (error) 1685 goto out; 1686 restart: 1687 NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, SCARG(uap, link), p); 1688 if ((error = namei(&nd)) != 0) 1689 goto out; 1690 if (nd.ni_vp) { 1691 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); 1692 if (nd.ni_dvp == nd.ni_vp) 1693 vrele(nd.ni_dvp); 1694 else 1695 vput(nd.ni_dvp); 1696 vrele(nd.ni_vp); 1697 error = EEXIST; 1698 goto out; 1699 } 1700 if (vn_start_write(nd.ni_dvp, &mp, V_NOWAIT) != 0) { 1701 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); 1702 if (nd.ni_dvp == nd.ni_vp) 1703 vrele(nd.ni_dvp); 1704 else 1705 vput(nd.ni_dvp); 1706 if ((error = vn_start_write(NULL, &mp, 1707 V_WAIT | V_SLEEPONLY | V_PCATCH)) != 0) 1708 return (error); 1709 goto restart; 1710 } 1711 VATTR_NULL(&vattr); 1712 vattr.va_mode = ACCESSPERMS &~ p->p_cwdi->cwdi_cmask; 1713 VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE); 1714 error = VOP_SYMLINK(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr, path); 1715 if (error == 0) 1716 vput(nd.ni_vp); 1717 vn_finished_write(mp, 0); 1718 out: 1719 PNBUF_PUT(path); 1720 return (error); 1721 } 1722 1723 /* 1724 * Delete a whiteout from the filesystem. 1725 */ 1726 /* ARGSUSED */ 1727 int 1728 sys_undelete(l, v, retval) 1729 struct lwp *l; 1730 void *v; 1731 register_t *retval; 1732 { 1733 struct sys_undelete_args /* { 1734 syscallarg(const char *) path; 1735 } */ *uap = v; 1736 struct proc *p = l->l_proc; 1737 int error; 1738 struct mount *mp; 1739 struct nameidata nd; 1740 1741 restart: 1742 NDINIT(&nd, DELETE, LOCKPARENT|DOWHITEOUT, UIO_USERSPACE, 1743 SCARG(uap, path), p); 1744 error = namei(&nd); 1745 if (error) 1746 return (error); 1747 1748 if (nd.ni_vp != NULLVP || !(nd.ni_cnd.cn_flags & ISWHITEOUT)) { 1749 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); 1750 if (nd.ni_dvp == nd.ni_vp) 1751 vrele(nd.ni_dvp); 1752 else 1753 vput(nd.ni_dvp); 1754 if (nd.ni_vp) 1755 vrele(nd.ni_vp); 1756 return (EEXIST); 1757 } 1758 if (vn_start_write(nd.ni_dvp, &mp, V_NOWAIT) != 0) { 1759 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); 1760 if (nd.ni_dvp == nd.ni_vp) 1761 vrele(nd.ni_dvp); 1762 else 1763 vput(nd.ni_dvp); 1764 if ((error = vn_start_write(NULL, &mp, 1765 V_WAIT | V_SLEEPONLY | V_PCATCH)) != 0) 1766 return (error); 1767 goto restart; 1768 } 1769 VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE); 1770 if ((error = VOP_WHITEOUT(nd.ni_dvp, &nd.ni_cnd, DELETE)) != 0) 1771 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); 1772 vput(nd.ni_dvp); 1773 vn_finished_write(mp, 0); 1774 return (error); 1775 } 1776 1777 /* 1778 * Delete a name from the filesystem. 1779 */ 1780 /* ARGSUSED */ 1781 int 1782 sys_unlink(l, v, retval) 1783 struct lwp *l; 1784 void *v; 1785 register_t *retval; 1786 { 1787 struct sys_unlink_args /* { 1788 syscallarg(const char *) path; 1789 } */ *uap = v; 1790 struct proc *p = l->l_proc; 1791 struct mount *mp; 1792 struct vnode *vp; 1793 int error; 1794 struct nameidata nd; 1795 1796 restart: 1797 NDINIT(&nd, DELETE, LOCKPARENT | LOCKLEAF, UIO_USERSPACE, 1798 SCARG(uap, path), p); 1799 if ((error = namei(&nd)) != 0) 1800 return (error); 1801 vp = nd.ni_vp; 1802 1803 /* 1804 * The root of a mounted filesystem cannot be deleted. 1805 */ 1806 if (vp->v_flag & VROOT) { 1807 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); 1808 if (nd.ni_dvp == vp) 1809 vrele(nd.ni_dvp); 1810 else 1811 vput(nd.ni_dvp); 1812 vput(vp); 1813 error = EBUSY; 1814 goto out; 1815 } 1816 if (vn_start_write(nd.ni_dvp, &mp, V_NOWAIT) != 0) { 1817 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); 1818 if (nd.ni_dvp == vp) 1819 vrele(nd.ni_dvp); 1820 else 1821 vput(nd.ni_dvp); 1822 vput(vp); 1823 if ((error = vn_start_write(NULL, &mp, 1824 V_WAIT | V_SLEEPONLY | V_PCATCH)) != 0) 1825 return (error); 1826 goto restart; 1827 } 1828 VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE); 1829 VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE); 1830 error = VOP_REMOVE(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd); 1831 vn_finished_write(mp, 0); 1832 out: 1833 return (error); 1834 } 1835 1836 /* 1837 * Reposition read/write file offset. 1838 */ 1839 int 1840 sys_lseek(l, v, retval) 1841 struct lwp *l; 1842 void *v; 1843 register_t *retval; 1844 { 1845 struct sys_lseek_args /* { 1846 syscallarg(int) fd; 1847 syscallarg(int) pad; 1848 syscallarg(off_t) offset; 1849 syscallarg(int) whence; 1850 } */ *uap = v; 1851 struct proc *p = l->l_proc; 1852 struct ucred *cred = p->p_ucred; 1853 struct filedesc *fdp = p->p_fd; 1854 struct file *fp; 1855 struct vnode *vp; 1856 struct vattr vattr; 1857 off_t newoff; 1858 int error; 1859 1860 if ((fp = fd_getfile(fdp, SCARG(uap, fd))) == NULL) 1861 return (EBADF); 1862 1863 FILE_USE(fp); 1864 1865 vp = (struct vnode *)fp->f_data; 1866 if (fp->f_type != DTYPE_VNODE || vp->v_type == VFIFO) { 1867 error = ESPIPE; 1868 goto out; 1869 } 1870 1871 switch (SCARG(uap, whence)) { 1872 case SEEK_CUR: 1873 newoff = fp->f_offset + SCARG(uap, offset); 1874 break; 1875 case SEEK_END: 1876 error = VOP_GETATTR(vp, &vattr, cred, p); 1877 if (error) 1878 goto out; 1879 newoff = SCARG(uap, offset) + vattr.va_size; 1880 break; 1881 case SEEK_SET: 1882 newoff = SCARG(uap, offset); 1883 break; 1884 default: 1885 error = EINVAL; 1886 goto out; 1887 } 1888 if ((error = VOP_SEEK(vp, fp->f_offset, newoff, cred)) != 0) 1889 goto out; 1890 1891 *(off_t *)retval = fp->f_offset = newoff; 1892 out: 1893 FILE_UNUSE(fp, p); 1894 return (error); 1895 } 1896 1897 /* 1898 * Positional read system call. 1899 */ 1900 int 1901 sys_pread(l, v, retval) 1902 struct lwp *l; 1903 void *v; 1904 register_t *retval; 1905 { 1906 struct sys_pread_args /* { 1907 syscallarg(int) fd; 1908 syscallarg(void *) buf; 1909 syscallarg(size_t) nbyte; 1910 syscallarg(off_t) offset; 1911 } */ *uap = v; 1912 struct proc *p = l->l_proc; 1913 struct filedesc *fdp = p->p_fd; 1914 struct file *fp; 1915 struct vnode *vp; 1916 off_t offset; 1917 int error, fd = SCARG(uap, fd); 1918 1919 if ((fp = fd_getfile(fdp, fd)) == NULL) 1920 return (EBADF); 1921 1922 if ((fp->f_flag & FREAD) == 0) { 1923 simple_unlock(&fp->f_slock); 1924 return (EBADF); 1925 } 1926 1927 FILE_USE(fp); 1928 1929 vp = (struct vnode *)fp->f_data; 1930 if (fp->f_type != DTYPE_VNODE || vp->v_type == VFIFO) { 1931 error = ESPIPE; 1932 goto out; 1933 } 1934 1935 offset = SCARG(uap, offset); 1936 1937 /* 1938 * XXX This works because no file systems actually 1939 * XXX take any action on the seek operation. 1940 */ 1941 if ((error = VOP_SEEK(vp, fp->f_offset, offset, fp->f_cred)) != 0) 1942 goto out; 1943 1944 /* dofileread() will unuse the descriptor for us */ 1945 return (dofileread(p, fd, fp, SCARG(uap, buf), SCARG(uap, nbyte), 1946 &offset, 0, retval)); 1947 1948 out: 1949 FILE_UNUSE(fp, p); 1950 return (error); 1951 } 1952 1953 /* 1954 * Positional scatter read system call. 1955 */ 1956 int 1957 sys_preadv(l, v, retval) 1958 struct lwp *l; 1959 void *v; 1960 register_t *retval; 1961 { 1962 struct sys_preadv_args /* { 1963 syscallarg(int) fd; 1964 syscallarg(const struct iovec *) iovp; 1965 syscallarg(int) iovcnt; 1966 syscallarg(off_t) offset; 1967 } */ *uap = v; 1968 struct proc *p = l->l_proc; 1969 struct filedesc *fdp = p->p_fd; 1970 struct file *fp; 1971 struct vnode *vp; 1972 off_t offset; 1973 int error, fd = SCARG(uap, fd); 1974 1975 if ((fp = fd_getfile(fdp, fd)) == NULL) 1976 return (EBADF); 1977 1978 if ((fp->f_flag & FREAD) == 0) { 1979 simple_unlock(&fp->f_slock); 1980 return (EBADF); 1981 } 1982 1983 FILE_USE(fp); 1984 1985 vp = (struct vnode *)fp->f_data; 1986 if (fp->f_type != DTYPE_VNODE || vp->v_type == VFIFO) { 1987 error = ESPIPE; 1988 goto out; 1989 } 1990 1991 offset = SCARG(uap, offset); 1992 1993 /* 1994 * XXX This works because no file systems actually 1995 * XXX take any action on the seek operation. 1996 */ 1997 if ((error = VOP_SEEK(vp, fp->f_offset, offset, fp->f_cred)) != 0) 1998 goto out; 1999 2000 /* dofilereadv() will unuse the descriptor for us */ 2001 return (dofilereadv(p, fd, fp, SCARG(uap, iovp), SCARG(uap, iovcnt), 2002 &offset, 0, retval)); 2003 2004 out: 2005 FILE_UNUSE(fp, p); 2006 return (error); 2007 } 2008 2009 /* 2010 * Positional write system call. 2011 */ 2012 int 2013 sys_pwrite(l, v, retval) 2014 struct lwp *l; 2015 void *v; 2016 register_t *retval; 2017 { 2018 struct sys_pwrite_args /* { 2019 syscallarg(int) fd; 2020 syscallarg(const void *) buf; 2021 syscallarg(size_t) nbyte; 2022 syscallarg(off_t) offset; 2023 } */ *uap = v; 2024 struct proc *p = l->l_proc; 2025 struct filedesc *fdp = p->p_fd; 2026 struct file *fp; 2027 struct vnode *vp; 2028 off_t offset; 2029 int error, fd = SCARG(uap, fd); 2030 2031 if ((fp = fd_getfile(fdp, fd)) == NULL) 2032 return (EBADF); 2033 2034 if ((fp->f_flag & FWRITE) == 0) { 2035 simple_unlock(&fp->f_slock); 2036 return (EBADF); 2037 } 2038 2039 FILE_USE(fp); 2040 2041 vp = (struct vnode *)fp->f_data; 2042 if (fp->f_type != DTYPE_VNODE || vp->v_type == VFIFO) { 2043 error = ESPIPE; 2044 goto out; 2045 } 2046 2047 offset = SCARG(uap, offset); 2048 2049 /* 2050 * XXX This works because no file systems actually 2051 * XXX take any action on the seek operation. 2052 */ 2053 if ((error = VOP_SEEK(vp, fp->f_offset, offset, fp->f_cred)) != 0) 2054 goto out; 2055 2056 /* dofilewrite() will unuse the descriptor for us */ 2057 return (dofilewrite(p, fd, fp, SCARG(uap, buf), SCARG(uap, nbyte), 2058 &offset, 0, retval)); 2059 2060 out: 2061 FILE_UNUSE(fp, p); 2062 return (error); 2063 } 2064 2065 /* 2066 * Positional gather write system call. 2067 */ 2068 int 2069 sys_pwritev(l, v, retval) 2070 struct lwp *l; 2071 void *v; 2072 register_t *retval; 2073 { 2074 struct sys_pwritev_args /* { 2075 syscallarg(int) fd; 2076 syscallarg(const struct iovec *) iovp; 2077 syscallarg(int) iovcnt; 2078 syscallarg(off_t) offset; 2079 } */ *uap = v; 2080 struct proc *p = l->l_proc; 2081 struct filedesc *fdp = p->p_fd; 2082 struct file *fp; 2083 struct vnode *vp; 2084 off_t offset; 2085 int error, fd = SCARG(uap, fd); 2086 2087 if ((fp = fd_getfile(fdp, fd)) == NULL) 2088 return (EBADF); 2089 2090 if ((fp->f_flag & FWRITE) == 0) { 2091 simple_unlock(&fp->f_slock); 2092 return (EBADF); 2093 } 2094 2095 FILE_USE(fp); 2096 2097 vp = (struct vnode *)fp->f_data; 2098 if (fp->f_type != DTYPE_VNODE || vp->v_type == VFIFO) { 2099 error = ESPIPE; 2100 goto out; 2101 } 2102 2103 offset = SCARG(uap, offset); 2104 2105 /* 2106 * XXX This works because no file systems actually 2107 * XXX take any action on the seek operation. 2108 */ 2109 if ((error = VOP_SEEK(vp, fp->f_offset, offset, fp->f_cred)) != 0) 2110 goto out; 2111 2112 /* dofilewritev() will unuse the descriptor for us */ 2113 return (dofilewritev(p, fd, fp, SCARG(uap, iovp), SCARG(uap, iovcnt), 2114 &offset, 0, retval)); 2115 2116 out: 2117 FILE_UNUSE(fp, p); 2118 return (error); 2119 } 2120 2121 /* 2122 * Check access permissions. 2123 */ 2124 int 2125 sys_access(l, v, retval) 2126 struct lwp *l; 2127 void *v; 2128 register_t *retval; 2129 { 2130 struct sys_access_args /* { 2131 syscallarg(const char *) path; 2132 syscallarg(int) flags; 2133 } */ *uap = v; 2134 struct proc *p = l->l_proc; 2135 struct ucred *cred; 2136 struct vnode *vp; 2137 int error, flags; 2138 struct nameidata nd; 2139 2140 cred = crdup(p->p_ucred); 2141 cred->cr_uid = p->p_cred->p_ruid; 2142 cred->cr_gid = p->p_cred->p_rgid; 2143 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, 2144 SCARG(uap, path), p); 2145 /* Override default credentials */ 2146 nd.ni_cnd.cn_cred = cred; 2147 if ((error = namei(&nd)) != 0) 2148 goto out; 2149 vp = nd.ni_vp; 2150 2151 /* Flags == 0 means only check for existence. */ 2152 if (SCARG(uap, flags)) { 2153 flags = 0; 2154 if (SCARG(uap, flags) & R_OK) 2155 flags |= VREAD; 2156 if (SCARG(uap, flags) & W_OK) 2157 flags |= VWRITE; 2158 if (SCARG(uap, flags) & X_OK) 2159 flags |= VEXEC; 2160 2161 error = VOP_ACCESS(vp, flags, cred, p); 2162 if (!error && (flags & VWRITE)) 2163 error = vn_writechk(vp); 2164 } 2165 vput(vp); 2166 out: 2167 crfree(cred); 2168 return (error); 2169 } 2170 2171 /* 2172 * Get file status; this version follows links. 2173 */ 2174 /* ARGSUSED */ 2175 int 2176 sys___stat13(l, v, retval) 2177 struct lwp *l; 2178 void *v; 2179 register_t *retval; 2180 { 2181 struct sys___stat13_args /* { 2182 syscallarg(const char *) path; 2183 syscallarg(struct stat *) ub; 2184 } */ *uap = v; 2185 struct proc *p = l->l_proc; 2186 struct stat sb; 2187 int error; 2188 struct nameidata nd; 2189 2190 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, 2191 SCARG(uap, path), p); 2192 if ((error = namei(&nd)) != 0) 2193 return (error); 2194 error = vn_stat(nd.ni_vp, &sb, p); 2195 vput(nd.ni_vp); 2196 if (error) 2197 return (error); 2198 error = copyout(&sb, SCARG(uap, ub), sizeof(sb)); 2199 return (error); 2200 } 2201 2202 /* 2203 * Get file status; this version does not follow links. 2204 */ 2205 /* ARGSUSED */ 2206 int 2207 sys___lstat13(l, v, retval) 2208 struct lwp *l; 2209 void *v; 2210 register_t *retval; 2211 { 2212 struct sys___lstat13_args /* { 2213 syscallarg(const char *) path; 2214 syscallarg(struct stat *) ub; 2215 } */ *uap = v; 2216 struct proc *p = l->l_proc; 2217 struct stat sb; 2218 int error; 2219 struct nameidata nd; 2220 2221 NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF, UIO_USERSPACE, 2222 SCARG(uap, path), p); 2223 if ((error = namei(&nd)) != 0) 2224 return (error); 2225 error = vn_stat(nd.ni_vp, &sb, p); 2226 vput(nd.ni_vp); 2227 if (error) 2228 return (error); 2229 error = copyout(&sb, SCARG(uap, ub), sizeof(sb)); 2230 return (error); 2231 } 2232 2233 /* 2234 * Get configurable pathname variables. 2235 */ 2236 /* ARGSUSED */ 2237 int 2238 sys_pathconf(l, v, retval) 2239 struct lwp *l; 2240 void *v; 2241 register_t *retval; 2242 { 2243 struct sys_pathconf_args /* { 2244 syscallarg(const char *) path; 2245 syscallarg(int) name; 2246 } */ *uap = v; 2247 struct proc *p = l->l_proc; 2248 int error; 2249 struct nameidata nd; 2250 2251 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, 2252 SCARG(uap, path), p); 2253 if ((error = namei(&nd)) != 0) 2254 return (error); 2255 error = VOP_PATHCONF(nd.ni_vp, SCARG(uap, name), retval); 2256 vput(nd.ni_vp); 2257 return (error); 2258 } 2259 2260 /* 2261 * Return target name of a symbolic link. 2262 */ 2263 /* ARGSUSED */ 2264 int 2265 sys_readlink(l, v, retval) 2266 struct lwp *l; 2267 void *v; 2268 register_t *retval; 2269 { 2270 struct sys_readlink_args /* { 2271 syscallarg(const char *) path; 2272 syscallarg(char *) buf; 2273 syscallarg(size_t) count; 2274 } */ *uap = v; 2275 struct proc *p = l->l_proc; 2276 struct vnode *vp; 2277 struct iovec aiov; 2278 struct uio auio; 2279 int error; 2280 struct nameidata nd; 2281 2282 NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF, UIO_USERSPACE, 2283 SCARG(uap, path), p); 2284 if ((error = namei(&nd)) != 0) 2285 return (error); 2286 vp = nd.ni_vp; 2287 if (vp->v_type != VLNK) 2288 error = EINVAL; 2289 else if (!(vp->v_mount->mnt_flag & MNT_SYMPERM) || 2290 (error = VOP_ACCESS(vp, VREAD, p->p_ucred, p)) == 0) { 2291 aiov.iov_base = SCARG(uap, buf); 2292 aiov.iov_len = SCARG(uap, count); 2293 auio.uio_iov = &aiov; 2294 auio.uio_iovcnt = 1; 2295 auio.uio_offset = 0; 2296 auio.uio_rw = UIO_READ; 2297 auio.uio_segflg = UIO_USERSPACE; 2298 auio.uio_procp = p; 2299 auio.uio_resid = SCARG(uap, count); 2300 error = VOP_READLINK(vp, &auio, p->p_ucred); 2301 } 2302 vput(vp); 2303 *retval = SCARG(uap, count) - auio.uio_resid; 2304 return (error); 2305 } 2306 2307 /* 2308 * Change flags of a file given a path name. 2309 */ 2310 /* ARGSUSED */ 2311 int 2312 sys_chflags(l, v, retval) 2313 struct lwp *l; 2314 void *v; 2315 register_t *retval; 2316 { 2317 struct sys_chflags_args /* { 2318 syscallarg(const char *) path; 2319 syscallarg(u_long) flags; 2320 } */ *uap = v; 2321 struct proc *p = l->l_proc; 2322 struct vnode *vp; 2323 int error; 2324 struct nameidata nd; 2325 2326 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p); 2327 if ((error = namei(&nd)) != 0) 2328 return (error); 2329 vp = nd.ni_vp; 2330 error = change_flags(vp, SCARG(uap, flags), p); 2331 vput(vp); 2332 return (error); 2333 } 2334 2335 /* 2336 * Change flags of a file given a file descriptor. 2337 */ 2338 /* ARGSUSED */ 2339 int 2340 sys_fchflags(l, v, retval) 2341 struct lwp *l; 2342 void *v; 2343 register_t *retval; 2344 { 2345 struct sys_fchflags_args /* { 2346 syscallarg(int) fd; 2347 syscallarg(u_long) flags; 2348 } */ *uap = v; 2349 struct proc *p = l->l_proc; 2350 struct vnode *vp; 2351 struct file *fp; 2352 int error; 2353 2354 /* getvnode() will use the descriptor for us */ 2355 if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0) 2356 return (error); 2357 vp = (struct vnode *)fp->f_data; 2358 error = change_flags(vp, SCARG(uap, flags), p); 2359 VOP_UNLOCK(vp, 0); 2360 FILE_UNUSE(fp, p); 2361 return (error); 2362 } 2363 2364 /* 2365 * Change flags of a file given a path name; this version does 2366 * not follow links. 2367 */ 2368 int 2369 sys_lchflags(l, v, retval) 2370 struct lwp *l; 2371 void *v; 2372 register_t *retval; 2373 { 2374 struct sys_lchflags_args /* { 2375 syscallarg(const char *) path; 2376 syscallarg(u_long) flags; 2377 } */ *uap = v; 2378 struct proc *p = l->l_proc; 2379 struct vnode *vp; 2380 int error; 2381 struct nameidata nd; 2382 2383 NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_USERSPACE, SCARG(uap, path), p); 2384 if ((error = namei(&nd)) != 0) 2385 return (error); 2386 vp = nd.ni_vp; 2387 error = change_flags(vp, SCARG(uap, flags), p); 2388 vput(vp); 2389 return (error); 2390 } 2391 2392 /* 2393 * Common routine to change flags of a file. 2394 */ 2395 int 2396 change_flags(vp, flags, p) 2397 struct vnode *vp; 2398 u_long flags; 2399 struct proc *p; 2400 { 2401 struct mount *mp; 2402 struct vattr vattr; 2403 int error; 2404 2405 if ((error = vn_start_write(vp, &mp, V_WAIT | V_PCATCH)) != 0) 2406 return (error); 2407 VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE); 2408 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); 2409 /* 2410 * Non-superusers cannot change the flags on devices, even if they 2411 * own them. 2412 */ 2413 if (suser(p->p_ucred, &p->p_acflag) != 0) { 2414 if ((error = VOP_GETATTR(vp, &vattr, p->p_ucred, p)) != 0) 2415 goto out; 2416 if (vattr.va_type == VCHR || vattr.va_type == VBLK) { 2417 error = EINVAL; 2418 goto out; 2419 } 2420 } 2421 VATTR_NULL(&vattr); 2422 vattr.va_flags = flags; 2423 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); 2424 out: 2425 vn_finished_write(mp, 0); 2426 return (error); 2427 } 2428 2429 /* 2430 * Change mode of a file given path name; this version follows links. 2431 */ 2432 /* ARGSUSED */ 2433 int 2434 sys_chmod(l, v, retval) 2435 struct lwp *l; 2436 void *v; 2437 register_t *retval; 2438 { 2439 struct sys_chmod_args /* { 2440 syscallarg(const char *) path; 2441 syscallarg(int) mode; 2442 } */ *uap = v; 2443 struct proc *p = l->l_proc; 2444 int error; 2445 struct nameidata nd; 2446 2447 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p); 2448 if ((error = namei(&nd)) != 0) 2449 return (error); 2450 2451 error = change_mode(nd.ni_vp, SCARG(uap, mode), p); 2452 2453 vrele(nd.ni_vp); 2454 return (error); 2455 } 2456 2457 /* 2458 * Change mode of a file given a file descriptor. 2459 */ 2460 /* ARGSUSED */ 2461 int 2462 sys_fchmod(l, v, retval) 2463 struct lwp *l; 2464 void *v; 2465 register_t *retval; 2466 { 2467 struct sys_fchmod_args /* { 2468 syscallarg(int) fd; 2469 syscallarg(int) mode; 2470 } */ *uap = v; 2471 struct proc *p = l->l_proc; 2472 struct file *fp; 2473 int error; 2474 2475 /* getvnode() will use the descriptor for us */ 2476 if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0) 2477 return (error); 2478 2479 error = change_mode((struct vnode *)fp->f_data, SCARG(uap, mode), p); 2480 FILE_UNUSE(fp, p); 2481 return (error); 2482 } 2483 2484 /* 2485 * Change mode of a file given path name; this version does not follow links. 2486 */ 2487 /* ARGSUSED */ 2488 int 2489 sys_lchmod(l, v, retval) 2490 struct lwp *l; 2491 void *v; 2492 register_t *retval; 2493 { 2494 struct sys_lchmod_args /* { 2495 syscallarg(const char *) path; 2496 syscallarg(int) mode; 2497 } */ *uap = v; 2498 struct proc *p = l->l_proc; 2499 int error; 2500 struct nameidata nd; 2501 2502 NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_USERSPACE, SCARG(uap, path), p); 2503 if ((error = namei(&nd)) != 0) 2504 return (error); 2505 2506 error = change_mode(nd.ni_vp, SCARG(uap, mode), p); 2507 2508 vrele(nd.ni_vp); 2509 return (error); 2510 } 2511 2512 /* 2513 * Common routine to set mode given a vnode. 2514 */ 2515 static int 2516 change_mode(vp, mode, p) 2517 struct vnode *vp; 2518 int mode; 2519 struct proc *p; 2520 { 2521 struct mount *mp; 2522 struct vattr vattr; 2523 int error; 2524 2525 if ((error = vn_start_write(vp, &mp, V_WAIT | V_PCATCH)) != 0) 2526 return (error); 2527 VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE); 2528 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); 2529 VATTR_NULL(&vattr); 2530 vattr.va_mode = mode & ALLPERMS; 2531 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); 2532 VOP_UNLOCK(vp, 0); 2533 vn_finished_write(mp, 0); 2534 return (error); 2535 } 2536 2537 /* 2538 * Set ownership given a path name; this version follows links. 2539 */ 2540 /* ARGSUSED */ 2541 int 2542 sys_chown(l, v, retval) 2543 struct lwp *l; 2544 void *v; 2545 register_t *retval; 2546 { 2547 struct sys_chown_args /* { 2548 syscallarg(const char *) path; 2549 syscallarg(uid_t) uid; 2550 syscallarg(gid_t) gid; 2551 } */ *uap = v; 2552 struct proc *p = l->l_proc; 2553 int error; 2554 struct nameidata nd; 2555 2556 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p); 2557 if ((error = namei(&nd)) != 0) 2558 return (error); 2559 2560 error = change_owner(nd.ni_vp, SCARG(uap, uid), SCARG(uap, gid), p, 0); 2561 2562 vrele(nd.ni_vp); 2563 return (error); 2564 } 2565 2566 /* 2567 * Set ownership given a path name; this version follows links. 2568 * Provides POSIX semantics. 2569 */ 2570 /* ARGSUSED */ 2571 int 2572 sys___posix_chown(l, v, retval) 2573 struct lwp *l; 2574 void *v; 2575 register_t *retval; 2576 { 2577 struct sys_chown_args /* { 2578 syscallarg(const char *) path; 2579 syscallarg(uid_t) uid; 2580 syscallarg(gid_t) gid; 2581 } */ *uap = v; 2582 struct proc *p = l->l_proc; 2583 int error; 2584 struct nameidata nd; 2585 2586 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p); 2587 if ((error = namei(&nd)) != 0) 2588 return (error); 2589 2590 error = change_owner(nd.ni_vp, SCARG(uap, uid), SCARG(uap, gid), p, 1); 2591 2592 vrele(nd.ni_vp); 2593 return (error); 2594 } 2595 2596 /* 2597 * Set ownership given a file descriptor. 2598 */ 2599 /* ARGSUSED */ 2600 int 2601 sys_fchown(l, v, retval) 2602 struct lwp *l; 2603 void *v; 2604 register_t *retval; 2605 { 2606 struct sys_fchown_args /* { 2607 syscallarg(int) fd; 2608 syscallarg(uid_t) uid; 2609 syscallarg(gid_t) gid; 2610 } */ *uap = v; 2611 struct proc *p = l->l_proc; 2612 int error; 2613 struct file *fp; 2614 2615 /* getvnode() will use the descriptor for us */ 2616 if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0) 2617 return (error); 2618 2619 error = change_owner((struct vnode *)fp->f_data, SCARG(uap, uid), 2620 SCARG(uap, gid), p, 0); 2621 FILE_UNUSE(fp, p); 2622 return (error); 2623 } 2624 2625 /* 2626 * Set ownership given a file descriptor, providing POSIX/XPG semantics. 2627 */ 2628 /* ARGSUSED */ 2629 int 2630 sys___posix_fchown(l, v, retval) 2631 struct lwp *l; 2632 void *v; 2633 register_t *retval; 2634 { 2635 struct sys_fchown_args /* { 2636 syscallarg(int) fd; 2637 syscallarg(uid_t) uid; 2638 syscallarg(gid_t) gid; 2639 } */ *uap = v; 2640 struct proc *p = l->l_proc; 2641 int error; 2642 struct file *fp; 2643 2644 /* getvnode() will use the descriptor for us */ 2645 if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0) 2646 return (error); 2647 2648 error = change_owner((struct vnode *)fp->f_data, SCARG(uap, uid), 2649 SCARG(uap, gid), p, 1); 2650 FILE_UNUSE(fp, p); 2651 return (error); 2652 } 2653 2654 /* 2655 * Set ownership given a path name; this version does not follow links. 2656 */ 2657 /* ARGSUSED */ 2658 int 2659 sys_lchown(l, v, retval) 2660 struct lwp *l; 2661 void *v; 2662 register_t *retval; 2663 { 2664 struct sys_lchown_args /* { 2665 syscallarg(const char *) path; 2666 syscallarg(uid_t) uid; 2667 syscallarg(gid_t) gid; 2668 } */ *uap = v; 2669 struct proc *p = l->l_proc; 2670 int error; 2671 struct nameidata nd; 2672 2673 NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_USERSPACE, SCARG(uap, path), p); 2674 if ((error = namei(&nd)) != 0) 2675 return (error); 2676 2677 error = change_owner(nd.ni_vp, SCARG(uap, uid), SCARG(uap, gid), p, 0); 2678 2679 vrele(nd.ni_vp); 2680 return (error); 2681 } 2682 2683 /* 2684 * Set ownership given a path name; this version does not follow links. 2685 * Provides POSIX/XPG semantics. 2686 */ 2687 /* ARGSUSED */ 2688 int 2689 sys___posix_lchown(l, v, retval) 2690 struct lwp *l; 2691 void *v; 2692 register_t *retval; 2693 { 2694 struct sys_lchown_args /* { 2695 syscallarg(const char *) path; 2696 syscallarg(uid_t) uid; 2697 syscallarg(gid_t) gid; 2698 } */ *uap = v; 2699 struct proc *p = l->l_proc; 2700 int error; 2701 struct nameidata nd; 2702 2703 NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_USERSPACE, SCARG(uap, path), p); 2704 if ((error = namei(&nd)) != 0) 2705 return (error); 2706 2707 error = change_owner(nd.ni_vp, SCARG(uap, uid), SCARG(uap, gid), p, 1); 2708 2709 vrele(nd.ni_vp); 2710 return (error); 2711 } 2712 2713 /* 2714 * Common routine to set ownership given a vnode. 2715 */ 2716 static int 2717 change_owner(vp, uid, gid, p, posix_semantics) 2718 struct vnode *vp; 2719 uid_t uid; 2720 gid_t gid; 2721 struct proc *p; 2722 int posix_semantics; 2723 { 2724 struct mount *mp; 2725 struct vattr vattr; 2726 mode_t newmode; 2727 int error; 2728 2729 if ((error = vn_start_write(vp, &mp, V_WAIT | V_PCATCH)) != 0) 2730 return (error); 2731 VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE); 2732 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); 2733 if ((error = VOP_GETATTR(vp, &vattr, p->p_ucred, p)) != 0) 2734 goto out; 2735 2736 #define CHANGED(x) ((int)(x) != -1) 2737 newmode = vattr.va_mode; 2738 if (posix_semantics) { 2739 /* 2740 * POSIX/XPG semantics: if the caller is not the super-user, 2741 * clear set-user-id and set-group-id bits. Both POSIX and 2742 * the XPG consider the behaviour for calls by the super-user 2743 * implementation-defined; we leave the set-user-id and set- 2744 * group-id settings intact in that case. 2745 */ 2746 if (suser(p->p_ucred, NULL) != 0) 2747 newmode &= ~(S_ISUID | S_ISGID); 2748 } else { 2749 /* 2750 * NetBSD semantics: when changing owner and/or group, 2751 * clear the respective bit(s). 2752 */ 2753 if (CHANGED(uid)) 2754 newmode &= ~S_ISUID; 2755 if (CHANGED(gid)) 2756 newmode &= ~S_ISGID; 2757 } 2758 /* Update va_mode iff altered. */ 2759 if (vattr.va_mode == newmode) 2760 newmode = VNOVAL; 2761 2762 VATTR_NULL(&vattr); 2763 vattr.va_uid = CHANGED(uid) ? uid : (uid_t)VNOVAL; 2764 vattr.va_gid = CHANGED(gid) ? gid : (gid_t)VNOVAL; 2765 vattr.va_mode = newmode; 2766 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); 2767 #undef CHANGED 2768 2769 out: 2770 VOP_UNLOCK(vp, 0); 2771 vn_finished_write(mp, 0); 2772 return (error); 2773 } 2774 2775 /* 2776 * Set the access and modification times given a path name; this 2777 * version follows links. 2778 */ 2779 /* ARGSUSED */ 2780 int 2781 sys_utimes(l, v, retval) 2782 struct lwp *l; 2783 void *v; 2784 register_t *retval; 2785 { 2786 struct sys_utimes_args /* { 2787 syscallarg(const char *) path; 2788 syscallarg(const struct timeval *) tptr; 2789 } */ *uap = v; 2790 struct proc *p = l->l_proc; 2791 int error; 2792 struct nameidata nd; 2793 2794 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p); 2795 if ((error = namei(&nd)) != 0) 2796 return (error); 2797 2798 error = change_utimes(nd.ni_vp, SCARG(uap, tptr), p); 2799 2800 vrele(nd.ni_vp); 2801 return (error); 2802 } 2803 2804 /* 2805 * Set the access and modification times given a file descriptor. 2806 */ 2807 /* ARGSUSED */ 2808 int 2809 sys_futimes(l, v, retval) 2810 struct lwp *l; 2811 void *v; 2812 register_t *retval; 2813 { 2814 struct sys_futimes_args /* { 2815 syscallarg(int) fd; 2816 syscallarg(const struct timeval *) tptr; 2817 } */ *uap = v; 2818 struct proc *p = l->l_proc; 2819 int error; 2820 struct file *fp; 2821 2822 /* getvnode() will use the descriptor for us */ 2823 if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0) 2824 return (error); 2825 2826 error = change_utimes((struct vnode *)fp->f_data, SCARG(uap, tptr), p); 2827 FILE_UNUSE(fp, p); 2828 return (error); 2829 } 2830 2831 /* 2832 * Set the access and modification times given a path name; this 2833 * version does not follow links. 2834 */ 2835 /* ARGSUSED */ 2836 int 2837 sys_lutimes(l, v, retval) 2838 struct lwp *l; 2839 void *v; 2840 register_t *retval; 2841 { 2842 struct sys_lutimes_args /* { 2843 syscallarg(const char *) path; 2844 syscallarg(const struct timeval *) tptr; 2845 } */ *uap = v; 2846 struct proc *p = l->l_proc; 2847 int error; 2848 struct nameidata nd; 2849 2850 NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_USERSPACE, SCARG(uap, path), p); 2851 if ((error = namei(&nd)) != 0) 2852 return (error); 2853 2854 error = change_utimes(nd.ni_vp, SCARG(uap, tptr), p); 2855 2856 vrele(nd.ni_vp); 2857 return (error); 2858 } 2859 2860 /* 2861 * Common routine to set access and modification times given a vnode. 2862 */ 2863 static int 2864 change_utimes(vp, tptr, p) 2865 struct vnode *vp; 2866 const struct timeval *tptr; 2867 struct proc *p; 2868 { 2869 struct timeval tv[2]; 2870 struct mount *mp; 2871 struct vattr vattr; 2872 int error; 2873 2874 if ((error = vn_start_write(vp, &mp, V_WAIT | V_PCATCH)) != 0) 2875 return (error); 2876 VATTR_NULL(&vattr); 2877 if (tptr == NULL) { 2878 microtime(&tv[0]); 2879 tv[1] = tv[0]; 2880 vattr.va_vaflags |= VA_UTIMES_NULL; 2881 } else { 2882 error = copyin(tptr, tv, sizeof(tv)); 2883 if (error) 2884 goto out; 2885 } 2886 VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE); 2887 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); 2888 vattr.va_atime.tv_sec = tv[0].tv_sec; 2889 vattr.va_atime.tv_nsec = tv[0].tv_usec * 1000; 2890 vattr.va_mtime.tv_sec = tv[1].tv_sec; 2891 vattr.va_mtime.tv_nsec = tv[1].tv_usec * 1000; 2892 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); 2893 VOP_UNLOCK(vp, 0); 2894 out: 2895 vn_finished_write(mp, 0); 2896 return (error); 2897 } 2898 2899 /* 2900 * Truncate a file given its path name. 2901 */ 2902 /* ARGSUSED */ 2903 int 2904 sys_truncate(l, v, retval) 2905 struct lwp *l; 2906 void *v; 2907 register_t *retval; 2908 { 2909 struct sys_truncate_args /* { 2910 syscallarg(const char *) path; 2911 syscallarg(int) pad; 2912 syscallarg(off_t) length; 2913 } */ *uap = v; 2914 struct proc *p = l->l_proc; 2915 struct vnode *vp; 2916 struct mount *mp; 2917 struct vattr vattr; 2918 int error; 2919 struct nameidata nd; 2920 2921 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p); 2922 if ((error = namei(&nd)) != 0) 2923 return (error); 2924 vp = nd.ni_vp; 2925 if ((error = vn_start_write(vp, &mp, V_WAIT | V_PCATCH)) != 0) { 2926 vrele(vp); 2927 return (error); 2928 } 2929 VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE); 2930 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); 2931 if (vp->v_type == VDIR) 2932 error = EISDIR; 2933 else if ((error = vn_writechk(vp)) == 0 && 2934 (error = VOP_ACCESS(vp, VWRITE, p->p_ucred, p)) == 0) { 2935 VATTR_NULL(&vattr); 2936 vattr.va_size = SCARG(uap, length); 2937 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); 2938 } 2939 vput(vp); 2940 vn_finished_write(mp, 0); 2941 return (error); 2942 } 2943 2944 /* 2945 * Truncate a file given a file descriptor. 2946 */ 2947 /* ARGSUSED */ 2948 int 2949 sys_ftruncate(l, v, retval) 2950 struct lwp *l; 2951 void *v; 2952 register_t *retval; 2953 { 2954 struct sys_ftruncate_args /* { 2955 syscallarg(int) fd; 2956 syscallarg(int) pad; 2957 syscallarg(off_t) length; 2958 } */ *uap = v; 2959 struct proc *p = l->l_proc; 2960 struct mount *mp; 2961 struct vattr vattr; 2962 struct vnode *vp; 2963 struct file *fp; 2964 int error; 2965 2966 /* getvnode() will use the descriptor for us */ 2967 if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0) 2968 return (error); 2969 if ((fp->f_flag & FWRITE) == 0) { 2970 error = EINVAL; 2971 goto out; 2972 } 2973 vp = (struct vnode *)fp->f_data; 2974 if ((error = vn_start_write(vp, &mp, V_WAIT | V_PCATCH)) != 0) { 2975 FILE_UNUSE(fp, p); 2976 return (error); 2977 } 2978 VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE); 2979 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); 2980 if (vp->v_type == VDIR) 2981 error = EISDIR; 2982 else if ((error = vn_writechk(vp)) == 0) { 2983 VATTR_NULL(&vattr); 2984 vattr.va_size = SCARG(uap, length); 2985 error = VOP_SETATTR(vp, &vattr, fp->f_cred, p); 2986 } 2987 VOP_UNLOCK(vp, 0); 2988 vn_finished_write(mp, 0); 2989 out: 2990 FILE_UNUSE(fp, p); 2991 return (error); 2992 } 2993 2994 /* 2995 * Sync an open file. 2996 */ 2997 /* ARGSUSED */ 2998 int 2999 sys_fsync(l, v, retval) 3000 struct lwp *l; 3001 void *v; 3002 register_t *retval; 3003 { 3004 struct sys_fsync_args /* { 3005 syscallarg(int) fd; 3006 } */ *uap = v; 3007 struct proc *p = l->l_proc; 3008 struct vnode *vp; 3009 struct mount *mp; 3010 struct file *fp; 3011 int error; 3012 3013 /* getvnode() will use the descriptor for us */ 3014 if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0) 3015 return (error); 3016 vp = (struct vnode *)fp->f_data; 3017 if ((error = vn_start_write(vp, &mp, V_WAIT | V_PCATCH)) != 0) { 3018 FILE_UNUSE(fp, p); 3019 return (error); 3020 } 3021 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); 3022 error = VOP_FSYNC(vp, fp->f_cred, FSYNC_WAIT, 0, 0, p); 3023 if (error == 0 && bioops.io_fsync != NULL && 3024 vp->v_mount && (vp->v_mount->mnt_flag & MNT_SOFTDEP)) 3025 (*bioops.io_fsync)(vp); 3026 VOP_UNLOCK(vp, 0); 3027 vn_finished_write(mp, 0); 3028 FILE_UNUSE(fp, p); 3029 return (error); 3030 } 3031 3032 /* 3033 * Sync a range of file data. API modeled after that found in AIX. 3034 * 3035 * FDATASYNC indicates that we need only save enough metadata to be able 3036 * to re-read the written data. Note we duplicate AIX's requirement that 3037 * the file be open for writing. 3038 */ 3039 /* ARGSUSED */ 3040 int 3041 sys_fsync_range(l, v, retval) 3042 struct lwp *l; 3043 void *v; 3044 register_t *retval; 3045 { 3046 struct sys_fsync_range_args /* { 3047 syscallarg(int) fd; 3048 syscallarg(int) flags; 3049 syscallarg(off_t) start; 3050 syscallarg(int) length; 3051 } */ *uap = v; 3052 struct proc *p = l->l_proc; 3053 struct vnode *vp; 3054 struct file *fp; 3055 int flags, nflags; 3056 off_t s, e, len; 3057 int error; 3058 3059 /* getvnode() will use the descriptor for us */ 3060 if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0) 3061 return (error); 3062 3063 if ((fp->f_flag & FWRITE) == 0) { 3064 FILE_UNUSE(fp, p); 3065 return (EBADF); 3066 } 3067 3068 flags = SCARG(uap, flags); 3069 if (((flags & (FDATASYNC | FFILESYNC)) == 0) || 3070 ((~flags & (FDATASYNC | FFILESYNC)) == 0)) { 3071 return (EINVAL); 3072 } 3073 /* Now set up the flags for value(s) to pass to VOP_FSYNC() */ 3074 if (flags & FDATASYNC) 3075 nflags = FSYNC_DATAONLY | FSYNC_WAIT; 3076 else 3077 nflags = FSYNC_WAIT; 3078 3079 len = SCARG(uap, length); 3080 /* If length == 0, we do the whole file, and s = l = 0 will do that */ 3081 if (len) { 3082 s = SCARG(uap, start); 3083 e = s + len; 3084 if (e < s) { 3085 FILE_UNUSE(fp, p); 3086 return (EINVAL); 3087 } 3088 } else { 3089 e = 0; 3090 s = 0; 3091 } 3092 3093 vp = (struct vnode *)fp->f_data; 3094 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); 3095 error = VOP_FSYNC(vp, fp->f_cred, nflags, s, e, p); 3096 3097 if (error == 0 && bioops.io_fsync != NULL && 3098 vp->v_mount && (vp->v_mount->mnt_flag & MNT_SOFTDEP)) 3099 (*bioops.io_fsync)(vp); 3100 3101 VOP_UNLOCK(vp, 0); 3102 FILE_UNUSE(fp, p); 3103 return (error); 3104 } 3105 3106 /* 3107 * Sync the data of an open file. 3108 */ 3109 /* ARGSUSED */ 3110 int 3111 sys_fdatasync(l, v, retval) 3112 struct lwp *l; 3113 void *v; 3114 register_t *retval; 3115 { 3116 struct sys_fdatasync_args /* { 3117 syscallarg(int) fd; 3118 } */ *uap = v; 3119 struct proc *p = l->l_proc; 3120 struct vnode *vp; 3121 struct file *fp; 3122 int error; 3123 3124 /* getvnode() will use the descriptor for us */ 3125 if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0) 3126 return (error); 3127 if ((fp->f_flag & FWRITE) == 0) { 3128 FILE_UNUSE(fp, p); 3129 return (EBADF); 3130 } 3131 vp = (struct vnode *)fp->f_data; 3132 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); 3133 error = VOP_FSYNC(vp, fp->f_cred, FSYNC_WAIT|FSYNC_DATAONLY, 0, 0, p); 3134 VOP_UNLOCK(vp, 0); 3135 FILE_UNUSE(fp, p); 3136 return (error); 3137 } 3138 3139 /* 3140 * Rename files, (standard) BSD semantics frontend. 3141 */ 3142 /* ARGSUSED */ 3143 int 3144 sys_rename(l, v, retval) 3145 struct lwp *l; 3146 void *v; 3147 register_t *retval; 3148 { 3149 struct sys_rename_args /* { 3150 syscallarg(const char *) from; 3151 syscallarg(const char *) to; 3152 } */ *uap = v; 3153 struct proc *p = l->l_proc; 3154 3155 return (rename_files(SCARG(uap, from), SCARG(uap, to), p, 0)); 3156 } 3157 3158 /* 3159 * Rename files, POSIX semantics frontend. 3160 */ 3161 /* ARGSUSED */ 3162 int 3163 sys___posix_rename(l, v, retval) 3164 struct lwp *l; 3165 void *v; 3166 register_t *retval; 3167 { 3168 struct sys___posix_rename_args /* { 3169 syscallarg(const char *) from; 3170 syscallarg(const char *) to; 3171 } */ *uap = v; 3172 struct proc *p = l->l_proc; 3173 3174 return (rename_files(SCARG(uap, from), SCARG(uap, to), p, 1)); 3175 } 3176 3177 /* 3178 * Rename files. Source and destination must either both be directories, 3179 * or both not be directories. If target is a directory, it must be empty. 3180 * If `from' and `to' refer to the same object, the value of the `retain' 3181 * argument is used to determine whether `from' will be 3182 * 3183 * (retain == 0) deleted unless `from' and `to' refer to the same 3184 * object in the file system's name space (BSD). 3185 * (retain == 1) always retained (POSIX). 3186 */ 3187 static int 3188 rename_files(from, to, p, retain) 3189 const char *from, *to; 3190 struct proc *p; 3191 int retain; 3192 { 3193 struct mount *mp = NULL; 3194 struct vnode *tvp, *fvp, *tdvp; 3195 struct nameidata fromnd, tond; 3196 int error; 3197 3198 NDINIT(&fromnd, DELETE, WANTPARENT | SAVESTART, UIO_USERSPACE, 3199 from, p); 3200 if ((error = namei(&fromnd)) != 0) 3201 return (error); 3202 fvp = fromnd.ni_vp; 3203 error = vn_start_write(fvp, &mp, V_WAIT | V_PCATCH); 3204 if (error != 0) { 3205 VOP_ABORTOP(fromnd.ni_dvp, &fromnd.ni_cnd); 3206 vrele(fromnd.ni_dvp); 3207 vrele(fvp); 3208 if (fromnd.ni_startdir) 3209 vrele(fromnd.ni_startdir); 3210 PNBUF_PUT(fromnd.ni_cnd.cn_pnbuf); 3211 return (error); 3212 } 3213 NDINIT(&tond, RENAME, LOCKPARENT | LOCKLEAF | NOCACHE | SAVESTART | 3214 (fvp->v_type == VDIR ? CREATEDIR : 0), UIO_USERSPACE, to, p); 3215 if ((error = namei(&tond)) != 0) { 3216 VOP_ABORTOP(fromnd.ni_dvp, &fromnd.ni_cnd); 3217 vrele(fromnd.ni_dvp); 3218 vrele(fvp); 3219 goto out1; 3220 } 3221 tdvp = tond.ni_dvp; 3222 tvp = tond.ni_vp; 3223 3224 if (tvp != NULL) { 3225 if (fvp->v_type == VDIR && tvp->v_type != VDIR) { 3226 error = ENOTDIR; 3227 goto out; 3228 } else if (fvp->v_type != VDIR && tvp->v_type == VDIR) { 3229 error = EISDIR; 3230 goto out; 3231 } 3232 } 3233 3234 if (fvp == tdvp) 3235 error = EINVAL; 3236 3237 /* 3238 * Source and destination refer to the same object. 3239 */ 3240 if (fvp == tvp) { 3241 if (retain) 3242 error = -1; 3243 else if (fromnd.ni_dvp == tdvp && 3244 fromnd.ni_cnd.cn_namelen == tond.ni_cnd.cn_namelen && 3245 !memcmp(fromnd.ni_cnd.cn_nameptr, 3246 tond.ni_cnd.cn_nameptr, 3247 fromnd.ni_cnd.cn_namelen)) 3248 error = -1; 3249 } 3250 3251 out: 3252 if (!error) { 3253 VOP_LEASE(tdvp, p, p->p_ucred, LEASE_WRITE); 3254 if (fromnd.ni_dvp != tdvp) 3255 VOP_LEASE(fromnd.ni_dvp, p, p->p_ucred, LEASE_WRITE); 3256 if (tvp) { 3257 VOP_LEASE(tvp, p, p->p_ucred, LEASE_WRITE); 3258 } 3259 error = VOP_RENAME(fromnd.ni_dvp, fromnd.ni_vp, &fromnd.ni_cnd, 3260 tond.ni_dvp, tond.ni_vp, &tond.ni_cnd); 3261 } else { 3262 VOP_ABORTOP(tond.ni_dvp, &tond.ni_cnd); 3263 if (tdvp == tvp) 3264 vrele(tdvp); 3265 else 3266 vput(tdvp); 3267 if (tvp) 3268 vput(tvp); 3269 VOP_ABORTOP(fromnd.ni_dvp, &fromnd.ni_cnd); 3270 vrele(fromnd.ni_dvp); 3271 vrele(fvp); 3272 } 3273 vrele(tond.ni_startdir); 3274 PNBUF_PUT(tond.ni_cnd.cn_pnbuf); 3275 out1: 3276 vn_finished_write(mp, 0); 3277 if (fromnd.ni_startdir) 3278 vrele(fromnd.ni_startdir); 3279 PNBUF_PUT(fromnd.ni_cnd.cn_pnbuf); 3280 return (error == -1 ? 0 : error); 3281 } 3282 3283 /* 3284 * Make a directory file. 3285 */ 3286 /* ARGSUSED */ 3287 int 3288 sys_mkdir(l, v, retval) 3289 struct lwp *l; 3290 void *v; 3291 register_t *retval; 3292 { 3293 struct sys_mkdir_args /* { 3294 syscallarg(const char *) path; 3295 syscallarg(int) mode; 3296 } */ *uap = v; 3297 struct proc *p = l->l_proc; 3298 struct mount *mp; 3299 struct vnode *vp; 3300 struct vattr vattr; 3301 int error; 3302 struct nameidata nd; 3303 3304 restart: 3305 NDINIT(&nd, CREATE, LOCKPARENT | CREATEDIR, UIO_USERSPACE, 3306 SCARG(uap, path), p); 3307 if ((error = namei(&nd)) != 0) 3308 return (error); 3309 vp = nd.ni_vp; 3310 if (vp != NULL) { 3311 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); 3312 if (nd.ni_dvp == vp) 3313 vrele(nd.ni_dvp); 3314 else 3315 vput(nd.ni_dvp); 3316 vrele(vp); 3317 return (EEXIST); 3318 } 3319 if (vn_start_write(nd.ni_dvp, &mp, V_NOWAIT) != 0) { 3320 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); 3321 if (nd.ni_dvp == vp) 3322 vrele(nd.ni_dvp); 3323 else 3324 vput(nd.ni_dvp); 3325 if ((error = vn_start_write(NULL, &mp, 3326 V_WAIT | V_SLEEPONLY | V_PCATCH)) != 0) 3327 return (error); 3328 goto restart; 3329 } 3330 VATTR_NULL(&vattr); 3331 vattr.va_type = VDIR; 3332 vattr.va_mode = 3333 (SCARG(uap, mode) & ACCESSPERMS) &~ p->p_cwdi->cwdi_cmask; 3334 VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE); 3335 error = VOP_MKDIR(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr); 3336 if (!error) 3337 vput(nd.ni_vp); 3338 vn_finished_write(mp, 0); 3339 return (error); 3340 } 3341 3342 /* 3343 * Remove a directory file. 3344 */ 3345 /* ARGSUSED */ 3346 int 3347 sys_rmdir(l, v, retval) 3348 struct lwp *l; 3349 void *v; 3350 register_t *retval; 3351 { 3352 struct sys_rmdir_args /* { 3353 syscallarg(const char *) path; 3354 } */ *uap = v; 3355 struct proc *p = l->l_proc; 3356 struct mount *mp; 3357 struct vnode *vp; 3358 int error; 3359 struct nameidata nd; 3360 3361 restart: 3362 NDINIT(&nd, DELETE, LOCKPARENT | LOCKLEAF, UIO_USERSPACE, 3363 SCARG(uap, path), p); 3364 if ((error = namei(&nd)) != 0) 3365 return (error); 3366 vp = nd.ni_vp; 3367 if (vp->v_type != VDIR) { 3368 error = ENOTDIR; 3369 goto out; 3370 } 3371 /* 3372 * No rmdir "." please. 3373 */ 3374 if (nd.ni_dvp == vp) { 3375 error = EINVAL; 3376 goto out; 3377 } 3378 /* 3379 * The root of a mounted filesystem cannot be deleted. 3380 */ 3381 if (vp->v_flag & VROOT) { 3382 error = EBUSY; 3383 goto out; 3384 } 3385 if (vn_start_write(nd.ni_dvp, &mp, V_NOWAIT) != 0) { 3386 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); 3387 if (nd.ni_dvp == vp) 3388 vrele(nd.ni_dvp); 3389 else 3390 vput(nd.ni_dvp); 3391 vput(vp); 3392 if ((error = vn_start_write(NULL, &mp, 3393 V_WAIT | V_SLEEPONLY | V_PCATCH)) != 0) 3394 return (error); 3395 goto restart; 3396 } 3397 VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE); 3398 VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE); 3399 error = VOP_RMDIR(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd); 3400 vn_finished_write(mp, 0); 3401 return (error); 3402 3403 out: 3404 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); 3405 if (nd.ni_dvp == vp) 3406 vrele(nd.ni_dvp); 3407 else 3408 vput(nd.ni_dvp); 3409 vput(vp); 3410 return (error); 3411 } 3412 3413 /* 3414 * Read a block of directory entries in a file system independent format. 3415 */ 3416 int 3417 sys_getdents(l, v, retval) 3418 struct lwp *l; 3419 void *v; 3420 register_t *retval; 3421 { 3422 struct sys_getdents_args /* { 3423 syscallarg(int) fd; 3424 syscallarg(char *) buf; 3425 syscallarg(size_t) count; 3426 } */ *uap = v; 3427 struct proc *p = l->l_proc; 3428 struct file *fp; 3429 int error, done; 3430 3431 /* getvnode() will use the descriptor for us */ 3432 if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0) 3433 return (error); 3434 if ((fp->f_flag & FREAD) == 0) { 3435 error = EBADF; 3436 goto out; 3437 } 3438 error = vn_readdir(fp, SCARG(uap, buf), UIO_USERSPACE, 3439 SCARG(uap, count), &done, p, 0, 0); 3440 #ifdef KTRACE 3441 if (!error && KTRPOINT(p, KTR_GENIO)) { 3442 struct iovec iov; 3443 iov.iov_base = SCARG(uap, buf); 3444 iov.iov_len = done; 3445 ktrgenio(p, SCARG(uap, fd), UIO_READ, &iov, done, 0); 3446 } 3447 #endif 3448 *retval = done; 3449 out: 3450 FILE_UNUSE(fp, p); 3451 return (error); 3452 } 3453 3454 /* 3455 * Set the mode mask for creation of filesystem nodes. 3456 */ 3457 int 3458 sys_umask(l, v, retval) 3459 struct lwp *l; 3460 void *v; 3461 register_t *retval; 3462 { 3463 struct sys_umask_args /* { 3464 syscallarg(mode_t) newmask; 3465 } */ *uap = v; 3466 struct proc *p = l->l_proc; 3467 struct cwdinfo *cwdi; 3468 3469 cwdi = p->p_cwdi; 3470 *retval = cwdi->cwdi_cmask; 3471 cwdi->cwdi_cmask = SCARG(uap, newmask) & ALLPERMS; 3472 return (0); 3473 } 3474 3475 /* 3476 * Void all references to file by ripping underlying filesystem 3477 * away from vnode. 3478 */ 3479 /* ARGSUSED */ 3480 int 3481 sys_revoke(l, v, retval) 3482 struct lwp *l; 3483 void *v; 3484 register_t *retval; 3485 { 3486 struct sys_revoke_args /* { 3487 syscallarg(const char *) path; 3488 } */ *uap = v; 3489 struct proc *p = l->l_proc; 3490 struct mount *mp; 3491 struct vnode *vp; 3492 struct vattr vattr; 3493 int error; 3494 struct nameidata nd; 3495 3496 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p); 3497 if ((error = namei(&nd)) != 0) 3498 return (error); 3499 vp = nd.ni_vp; 3500 if ((error = VOP_GETATTR(vp, &vattr, p->p_ucred, p)) != 0) 3501 goto out; 3502 if (p->p_ucred->cr_uid != vattr.va_uid && 3503 (error = suser(p->p_ucred, &p->p_acflag)) != 0) 3504 goto out; 3505 if ((error = vn_start_write(vp, &mp, V_WAIT | V_PCATCH)) != 0) 3506 goto out; 3507 if (vp->v_usecount > 1 || (vp->v_flag & (VALIASED | VLAYER))) 3508 VOP_REVOKE(vp, REVOKEALL); 3509 vn_finished_write(mp, 0); 3510 out: 3511 vrele(vp); 3512 return (error); 3513 } 3514 3515 /* 3516 * Convert a user file descriptor to a kernel file entry. 3517 */ 3518 int 3519 getvnode(fdp, fd, fpp) 3520 struct filedesc *fdp; 3521 int fd; 3522 struct file **fpp; 3523 { 3524 struct vnode *vp; 3525 struct file *fp; 3526 3527 if ((fp = fd_getfile(fdp, fd)) == NULL) 3528 return (EBADF); 3529 3530 FILE_USE(fp); 3531 3532 if (fp->f_type != DTYPE_VNODE) { 3533 FILE_UNUSE(fp, NULL); 3534 return (EINVAL); 3535 } 3536 3537 vp = (struct vnode *)fp->f_data; 3538 if (vp->v_type == VBAD) { 3539 FILE_UNUSE(fp, NULL); 3540 return (EBADF); 3541 } 3542 3543 *fpp = fp; 3544 return (0); 3545 } 3546