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