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