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