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