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