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