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