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