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