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