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