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