1 /* 2 * Copyright (c) 1989 The Regents of the University of California. 3 * All rights reserved. 4 * 5 * %sccs.include.redist.c% 6 * 7 * @(#)vfs_syscalls.c 7.90 (Berkeley) 07/03/92 8 */ 9 10 #include "param.h" 11 #include "systm.h" 12 #include "namei.h" 13 #include "filedesc.h" 14 #include "kernel.h" 15 #include "file.h" 16 #include "stat.h" 17 #include "vnode.h" 18 #include "mount.h" 19 #include "proc.h" 20 #include "uio.h" 21 #include "malloc.h" 22 #include "dirent.h" 23 #include <vm/vm.h> 24 25 /* 26 * Virtual File System System Calls 27 */ 28 29 /* 30 * Mount system call. 31 */ 32 /* ARGSUSED */ 33 mount(p, uap, retval) 34 struct proc *p; 35 register struct args { 36 int type; 37 char *dir; 38 int flags; 39 caddr_t data; 40 } *uap; 41 int *retval; 42 { 43 register struct vnode *vp; 44 register struct mount *mp; 45 int error, flag; 46 struct nameidata nd; 47 48 /* 49 * Must be super user 50 */ 51 if (error = suser(p->p_ucred, &p->p_acflag)) 52 return (error); 53 /* 54 * Get vnode to be covered 55 */ 56 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->dir, p); 57 if (error = namei(&nd)) 58 return (error); 59 vp = nd.ni_vp; 60 if (uap->flags & MNT_UPDATE) { 61 if ((vp->v_flag & VROOT) == 0) { 62 vput(vp); 63 return (EINVAL); 64 } 65 mp = vp->v_mount; 66 /* 67 * We allow going from read-only to read-write, 68 * but not from read-write to read-only. 69 */ 70 if ((mp->mnt_flag & MNT_RDONLY) == 0 && 71 (uap->flags & MNT_RDONLY) != 0) { 72 vput(vp); 73 return (EOPNOTSUPP); /* Needs translation */ 74 } 75 flag = mp->mnt_flag; 76 mp->mnt_flag |= MNT_UPDATE; 77 VOP_UNLOCK(vp); 78 goto update; 79 } 80 if (vp->v_usecount != 1) { 81 vput(vp); 82 return (EBUSY); 83 } 84 if (error = vinvalbuf(vp, 1, p->p_ucred, p)) 85 return (error); 86 if (vp->v_type != VDIR) { 87 vput(vp); 88 return (ENOTDIR); 89 } 90 if ((unsigned long)uap->type > MOUNT_MAXTYPE || 91 vfssw[uap->type] == (struct vfsops *)0) { 92 vput(vp); 93 return (ENODEV); 94 } 95 96 /* 97 * Allocate and initialize the file system. 98 */ 99 mp = (struct mount *)malloc((u_long)sizeof(struct mount), 100 M_MOUNT, M_WAITOK); 101 bzero((char *)mp, (u_long)sizeof(struct mount)); 102 mp->mnt_op = vfssw[uap->type]; 103 if (error = vfs_lock(mp)) { 104 free((caddr_t)mp, M_MOUNT); 105 vput(vp); 106 return (error); 107 } 108 if (vp->v_mountedhere != (struct mount *)0) { 109 vfs_unlock(mp); 110 free((caddr_t)mp, M_MOUNT); 111 vput(vp); 112 return (EBUSY); 113 } 114 vp->v_mountedhere = mp; 115 mp->mnt_vnodecovered = vp; 116 update: 117 /* 118 * Set the mount level flags. 119 */ 120 if (uap->flags & MNT_RDONLY) 121 mp->mnt_flag |= MNT_RDONLY; 122 else 123 mp->mnt_flag &= ~MNT_RDONLY; 124 if (uap->flags & MNT_NOSUID) 125 mp->mnt_flag |= MNT_NOSUID; 126 else 127 mp->mnt_flag &= ~MNT_NOSUID; 128 if (uap->flags & MNT_NOEXEC) 129 mp->mnt_flag |= MNT_NOEXEC; 130 else 131 mp->mnt_flag &= ~MNT_NOEXEC; 132 if (uap->flags & MNT_NODEV) 133 mp->mnt_flag |= MNT_NODEV; 134 else 135 mp->mnt_flag &= ~MNT_NODEV; 136 if (uap->flags & MNT_SYNCHRONOUS) 137 mp->mnt_flag |= MNT_SYNCHRONOUS; 138 else 139 mp->mnt_flag &= ~MNT_SYNCHRONOUS; 140 /* 141 * Mount the filesystem. 142 */ 143 error = VFS_MOUNT(mp, uap->dir, uap->data, &nd, p); 144 if (mp->mnt_flag & MNT_UPDATE) { 145 mp->mnt_flag &= ~MNT_UPDATE; 146 vrele(vp); 147 if (error) 148 mp->mnt_flag = flag; 149 return (error); 150 } 151 /* 152 * Put the new filesystem on the mount list after root. 153 */ 154 mp->mnt_next = rootfs->mnt_next; 155 mp->mnt_prev = rootfs; 156 rootfs->mnt_next = mp; 157 mp->mnt_next->mnt_prev = mp; 158 cache_purge(vp); 159 if (!error) { 160 VOP_UNLOCK(vp); 161 vfs_unlock(mp); 162 error = VFS_START(mp, 0, p); 163 } else { 164 vfs_remove(mp); 165 free((caddr_t)mp, M_MOUNT); 166 vput(vp); 167 } 168 return (error); 169 } 170 171 /* 172 * Unmount system call. 173 * 174 * Note: unmount takes a path to the vnode mounted on as argument, 175 * not special file (as before). 176 */ 177 /* ARGSUSED */ 178 unmount(p, uap, retval) 179 struct proc *p; 180 register struct args { 181 char *pathp; 182 int flags; 183 } *uap; 184 int *retval; 185 { 186 register struct vnode *vp; 187 struct mount *mp; 188 int error; 189 struct nameidata nd; 190 191 /* 192 * Must be super user 193 */ 194 if (error = suser(p->p_ucred, &p->p_acflag)) 195 return (error); 196 197 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->pathp, p); 198 if (error = namei(&nd)) 199 return (error); 200 vp = nd.ni_vp; 201 /* 202 * Must be the root of the filesystem 203 */ 204 if ((vp->v_flag & VROOT) == 0) { 205 vput(vp); 206 return (EINVAL); 207 } 208 mp = vp->v_mount; 209 vput(vp); 210 return (dounmount(mp, uap->flags, p)); 211 } 212 213 /* 214 * Do an unmount. 215 */ 216 dounmount(mp, flags, p) 217 register struct mount *mp; 218 int flags; 219 struct proc *p; 220 { 221 struct vnode *coveredvp; 222 int error; 223 224 coveredvp = mp->mnt_vnodecovered; 225 if (vfs_busy(mp)) 226 return (EBUSY); 227 mp->mnt_flag |= MNT_UNMOUNT; 228 if (error = vfs_lock(mp)) 229 return (error); 230 231 vnode_pager_umount(mp); /* release cached vnodes */ 232 cache_purgevfs(mp); /* remove cache entries for this file sys */ 233 if ((error = VFS_SYNC(mp, MNT_WAIT, p->p_ucred, p)) == 0 || 234 (flags & MNT_FORCE)) 235 error = VFS_UNMOUNT(mp, flags, p); 236 mp->mnt_flag &= ~MNT_UNMOUNT; 237 vfs_unbusy(mp); 238 if (error) { 239 vfs_unlock(mp); 240 } else { 241 vrele(coveredvp); 242 vfs_remove(mp); 243 if (mp->mnt_mounth != NULL) 244 panic("unmount: dangling vnode"); 245 free((caddr_t)mp, M_MOUNT); 246 } 247 return (error); 248 } 249 250 /* 251 * Sync system call. 252 * Sync each mounted filesystem. 253 */ 254 /* ARGSUSED */ 255 sync(p, uap, retval) 256 struct proc *p; 257 void *uap; 258 int *retval; 259 { 260 register struct mount *mp; 261 struct mount *omp; 262 263 mp = rootfs; 264 do { 265 /* 266 * The lock check below is to avoid races with mount 267 * and unmount. 268 */ 269 if ((mp->mnt_flag & (MNT_MLOCK|MNT_RDONLY|MNT_MPBUSY)) == 0 && 270 !vfs_busy(mp)) { 271 VFS_SYNC(mp, MNT_NOWAIT, p->p_ucred, p); 272 omp = mp; 273 mp = mp->mnt_next; 274 vfs_unbusy(omp); 275 } else 276 mp = mp->mnt_next; 277 } while (mp != rootfs); 278 return (0); 279 } 280 281 /* 282 * Operate on filesystem quotas. 283 */ 284 /* ARGSUSED */ 285 quotactl(p, uap, retval) 286 struct proc *p; 287 register struct args { 288 char *path; 289 int cmd; 290 int uid; 291 caddr_t arg; 292 } *uap; 293 int *retval; 294 { 295 register struct mount *mp; 296 int error; 297 struct nameidata nd; 298 299 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, p); 300 if (error = namei(&nd)) 301 return (error); 302 mp = nd.ni_vp->v_mount; 303 vrele(nd.ni_vp); 304 return (VFS_QUOTACTL(mp, uap->cmd, uap->uid, uap->arg, p)); 305 } 306 307 /* 308 * Get filesystem statistics. 309 */ 310 /* ARGSUSED */ 311 statfs(p, uap, retval) 312 struct proc *p; 313 register struct args { 314 char *path; 315 struct statfs *buf; 316 } *uap; 317 int *retval; 318 { 319 register struct mount *mp; 320 register struct statfs *sp; 321 int error; 322 struct nameidata nd; 323 324 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, p); 325 if (error = namei(&nd)) 326 return (error); 327 mp = nd.ni_vp->v_mount; 328 sp = &mp->mnt_stat; 329 vrele(nd.ni_vp); 330 if (error = VFS_STATFS(mp, sp, p)) 331 return (error); 332 sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK; 333 return (copyout((caddr_t)sp, (caddr_t)uap->buf, sizeof(*sp))); 334 } 335 336 /* 337 * Get filesystem statistics. 338 */ 339 /* ARGSUSED */ 340 fstatfs(p, uap, retval) 341 struct proc *p; 342 register struct args { 343 int fd; 344 struct statfs *buf; 345 } *uap; 346 int *retval; 347 { 348 struct file *fp; 349 struct mount *mp; 350 register struct statfs *sp; 351 int error; 352 353 if (error = getvnode(p->p_fd, uap->fd, &fp)) 354 return (error); 355 mp = ((struct vnode *)fp->f_data)->v_mount; 356 sp = &mp->mnt_stat; 357 if (error = VFS_STATFS(mp, sp, p)) 358 return (error); 359 sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK; 360 return (copyout((caddr_t)sp, (caddr_t)uap->buf, sizeof(*sp))); 361 } 362 363 /* 364 * Get statistics on all filesystems. 365 */ 366 getfsstat(p, uap, retval) 367 struct proc *p; 368 register struct args { 369 struct statfs *buf; 370 long bufsize; 371 int flags; 372 } *uap; 373 int *retval; 374 { 375 register struct mount *mp; 376 register struct statfs *sp; 377 caddr_t sfsp; 378 long count, maxcount, error; 379 380 maxcount = uap->bufsize / sizeof(struct statfs); 381 sfsp = (caddr_t)uap->buf; 382 mp = rootfs; 383 count = 0; 384 do { 385 if (sfsp && count < maxcount && 386 ((mp->mnt_flag & MNT_MLOCK) == 0)) { 387 sp = &mp->mnt_stat; 388 /* 389 * If MNT_NOWAIT is specified, do not refresh the 390 * fsstat cache. MNT_WAIT overrides MNT_NOWAIT. 391 */ 392 if (((uap->flags & MNT_NOWAIT) == 0 || 393 (uap->flags & MNT_WAIT)) && 394 (error = VFS_STATFS(mp, sp, p))) { 395 mp = mp->mnt_prev; 396 continue; 397 } 398 sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK; 399 if (error = copyout((caddr_t)sp, sfsp, sizeof(*sp))) 400 return (error); 401 sfsp += sizeof(*sp); 402 } 403 count++; 404 mp = mp->mnt_prev; 405 } while (mp != rootfs); 406 if (sfsp && count > maxcount) 407 *retval = maxcount; 408 else 409 *retval = count; 410 return (0); 411 } 412 413 /* 414 * Change current working directory to a given file descriptor. 415 */ 416 /* ARGSUSED */ 417 fchdir(p, uap, retval) 418 struct proc *p; 419 struct args { 420 int fd; 421 } *uap; 422 int *retval; 423 { 424 register struct filedesc *fdp = p->p_fd; 425 register struct vnode *vp; 426 struct file *fp; 427 int error; 428 429 if (error = getvnode(fdp, uap->fd, &fp)) 430 return (error); 431 vp = (struct vnode *)fp->f_data; 432 VOP_LOCK(vp); 433 if (vp->v_type != VDIR) 434 error = ENOTDIR; 435 else 436 error = VOP_ACCESS(vp, VEXEC, p->p_ucred, p); 437 VOP_UNLOCK(vp); 438 if (error) 439 return (error); 440 VREF(vp); 441 vrele(fdp->fd_cdir); 442 fdp->fd_cdir = vp; 443 return (0); 444 } 445 446 /* 447 * Change current working directory (``.''). 448 */ 449 /* ARGSUSED */ 450 chdir(p, uap, retval) 451 struct proc *p; 452 struct args { 453 char *fname; 454 } *uap; 455 int *retval; 456 { 457 register struct filedesc *fdp = p->p_fd; 458 int error; 459 struct nameidata nd; 460 461 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->fname, p); 462 if (error = chdirec(&nd, p)) 463 return (error); 464 vrele(fdp->fd_cdir); 465 fdp->fd_cdir = nd.ni_vp; 466 return (0); 467 } 468 469 /* 470 * Change notion of root (``/'') directory. 471 */ 472 /* ARGSUSED */ 473 chroot(p, uap, retval) 474 struct proc *p; 475 struct args { 476 char *fname; 477 } *uap; 478 int *retval; 479 { 480 register struct filedesc *fdp = p->p_fd; 481 int error; 482 struct nameidata nd; 483 484 if (error = suser(p->p_ucred, &p->p_acflag)) 485 return (error); 486 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->fname, p); 487 if (error = chdirec(&nd, p)) 488 return (error); 489 if (fdp->fd_rdir != NULL) 490 vrele(fdp->fd_rdir); 491 fdp->fd_rdir = nd.ni_vp; 492 return (0); 493 } 494 495 /* 496 * Common routine for chroot and chdir. 497 */ 498 chdirec(ndp, p) 499 register struct nameidata *ndp; 500 struct proc *p; 501 { 502 struct vnode *vp; 503 int error; 504 505 if (error = namei(ndp)) 506 return (error); 507 vp = ndp->ni_vp; 508 if (vp->v_type != VDIR) 509 error = ENOTDIR; 510 else 511 error = VOP_ACCESS(vp, VEXEC, p->p_ucred, p); 512 VOP_UNLOCK(vp); 513 if (error) 514 vrele(vp); 515 return (error); 516 } 517 518 /* 519 * Open system call. 520 * Check permissions, allocate an open file structure, 521 * and call the device open routine if any. 522 */ 523 open(p, uap, retval) 524 struct proc *p; 525 register struct args { 526 char *fname; 527 int mode; 528 int crtmode; 529 } *uap; 530 int *retval; 531 { 532 register struct filedesc *fdp = p->p_fd; 533 register struct file *fp; 534 register struct vnode *vp; 535 int fmode, cmode; 536 struct file *nfp; 537 int type, indx, error; 538 struct flock lf; 539 struct nameidata nd; 540 extern struct fileops vnops; 541 542 if (error = falloc(p, &nfp, &indx)) 543 return (error); 544 fp = nfp; 545 fmode = FFLAGS(uap->mode); 546 cmode = ((uap->crtmode &~ fdp->fd_cmask) & 07777) &~ S_ISVTX; 547 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->fname, p); 548 p->p_dupfd = -indx - 1; /* XXX check for fdopen */ 549 if (error = vn_open(&nd, fmode, cmode)) { 550 int dfd = p->p_dupfd; 551 p->p_dupfd = 0; 552 ffree(fp); 553 if ((error == ENODEV || error == ENXIO) && /* XXX from fdopen */ 554 dfd >= 0 && 555 (error = dupfdopen(fdp, indx, p->p_dupfd, 556 fmode, error)) == 0) { 557 *retval = indx; 558 return (0); 559 } 560 if (error == ERESTART) 561 error = EINTR; 562 fdp->fd_ofiles[indx] = NULL; 563 return (error); 564 } 565 p->p_dupfd = 0; 566 vp = nd.ni_vp; 567 fp->f_flag = fmode & FMASK; 568 fp->f_type = DTYPE_VNODE; 569 fp->f_ops = &vnops; 570 fp->f_data = (caddr_t)vp; 571 if (fmode & (O_EXLOCK | O_SHLOCK)) { 572 lf.l_whence = SEEK_SET; 573 lf.l_start = 0; 574 lf.l_len = 0; 575 if (fmode & O_EXLOCK) 576 lf.l_type = F_WRLCK; 577 else 578 lf.l_type = F_RDLCK; 579 type = F_FLOCK; 580 if ((fmode & FNONBLOCK) == 0) 581 type |= F_WAIT; 582 if (error = VOP_ADVLOCK(vp, (caddr_t)fp, F_SETLK, &lf, type)) { 583 VOP_UNLOCK(vp); 584 (void) vn_close(vp, fp->f_flag, fp->f_cred, p); 585 ffree(fp); 586 fdp->fd_ofiles[indx] = NULL; 587 return (error); 588 } 589 fp->f_flag |= FHASLOCK; 590 } 591 VOP_UNLOCK(vp); 592 *retval = indx; 593 return (0); 594 } 595 596 #ifdef COMPAT_43 597 /* 598 * Creat system call. 599 */ 600 ocreat(p, uap, retval) 601 struct proc *p; 602 register struct args { 603 char *fname; 604 int fmode; 605 } *uap; 606 int *retval; 607 { 608 struct nargs { 609 char *fname; 610 int mode; 611 int crtmode; 612 } openuap; 613 614 openuap.fname = uap->fname; 615 openuap.crtmode = uap->fmode; 616 openuap.mode = O_WRONLY | O_CREAT | O_TRUNC; 617 return (open(p, &openuap, retval)); 618 } 619 #endif /* COMPAT_43 */ 620 621 /* 622 * Mknod system call. 623 */ 624 /* ARGSUSED */ 625 mknod(p, uap, retval) 626 struct proc *p; 627 register struct args { 628 char *fname; 629 int fmode; 630 int dev; 631 } *uap; 632 int *retval; 633 { 634 register struct vnode *vp; 635 struct vattr vattr; 636 int error; 637 struct nameidata nd; 638 639 if (error = suser(p->p_ucred, &p->p_acflag)) 640 return (error); 641 NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, uap->fname, p); 642 if (error = namei(&nd)) 643 return (error); 644 vp = nd.ni_vp; 645 if (vp != NULL) { 646 error = EEXIST; 647 goto out; 648 } 649 VATTR_NULL(&vattr); 650 switch (uap->fmode & S_IFMT) { 651 652 case S_IFMT: /* used by badsect to flag bad sectors */ 653 vattr.va_type = VBAD; 654 break; 655 case S_IFCHR: 656 vattr.va_type = VCHR; 657 break; 658 case S_IFBLK: 659 vattr.va_type = VBLK; 660 break; 661 default: 662 error = EINVAL; 663 goto out; 664 } 665 vattr.va_mode = (uap->fmode & 07777) &~ p->p_fd->fd_cmask; 666 vattr.va_rdev = uap->dev; 667 out: 668 if (!error) { 669 LEASE_CHECK(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE); 670 error = VOP_MKNOD(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr); 671 } else { 672 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); 673 if (nd.ni_dvp == vp) 674 vrele(nd.ni_dvp); 675 else 676 vput(nd.ni_dvp); 677 if (vp) 678 vrele(vp); 679 } 680 return (error); 681 } 682 683 /* 684 * Mkfifo system call. 685 */ 686 /* ARGSUSED */ 687 mkfifo(p, uap, retval) 688 struct proc *p; 689 register struct args { 690 char *fname; 691 int fmode; 692 } *uap; 693 int *retval; 694 { 695 struct vattr vattr; 696 int error; 697 struct nameidata nd; 698 699 #ifndef FIFO 700 return (EOPNOTSUPP); 701 #else 702 NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, uap->fname, p); 703 if (error = namei(&nd)) 704 return (error); 705 if (nd.ni_vp != NULL) { 706 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); 707 if (nd.ni_dvp == nd.ni_vp) 708 vrele(nd.ni_dvp); 709 else 710 vput(nd.ni_dvp); 711 vrele(nd.ni_vp); 712 return (EEXIST); 713 } 714 VATTR_NULL(&vattr); 715 vattr.va_type = VFIFO; 716 vattr.va_mode = (uap->fmode & 07777) &~ p->p_fd->fd_cmask; 717 LEASE_CHECK(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE); 718 return (VOP_MKNOD(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr)); 719 #endif /* FIFO */ 720 } 721 722 /* 723 * Link system call. 724 */ 725 /* ARGSUSED */ 726 link(p, uap, retval) 727 struct proc *p; 728 register struct args { 729 char *target; 730 char *linkname; 731 } *uap; 732 int *retval; 733 { 734 register struct vnode *vp, *xp; 735 int error; 736 struct nameidata nd; 737 738 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->target, p); 739 if (error = namei(&nd)) 740 return (error); 741 vp = nd.ni_vp; 742 if (vp->v_type == VDIR && 743 (error = suser(p->p_ucred, &p->p_acflag))) 744 goto out1; 745 nd.ni_cnd.cn_nameiop = CREATE; 746 nd.ni_cnd.cn_flags = LOCKPARENT; 747 nd.ni_dirp = (caddr_t)uap->linkname; 748 if (error = namei(&nd)) 749 goto out1; 750 xp = nd.ni_vp; 751 if (xp != NULL) { 752 error = EEXIST; 753 goto out; 754 } 755 xp = nd.ni_dvp; 756 out: 757 if (!error) { 758 LEASE_CHECK(xp, p, p->p_ucred, LEASE_WRITE); 759 LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE); 760 error = VOP_LINK(nd.ni_dvp, vp, &nd.ni_cnd); 761 } else { 762 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); 763 if (nd.ni_dvp == nd.ni_vp) 764 vrele(nd.ni_dvp); 765 else 766 vput(nd.ni_dvp); 767 if (nd.ni_vp) 768 vrele(nd.ni_vp); 769 } 770 out1: 771 vrele(vp); 772 return (error); 773 } 774 775 /* 776 * Make a symbolic link. 777 */ 778 /* ARGSUSED */ 779 symlink(p, uap, retval) 780 struct proc *p; 781 register struct args { 782 char *target; 783 char *linkname; 784 } *uap; 785 int *retval; 786 { 787 struct vattr vattr; 788 char *target; 789 int error; 790 struct nameidata nd; 791 792 MALLOC(target, char *, MAXPATHLEN, M_NAMEI, M_WAITOK); 793 if (error = copyinstr(uap->target, target, MAXPATHLEN, (u_int *)0)) 794 goto out; 795 NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, uap->linkname, p); 796 if (error = namei(&nd)) 797 goto out; 798 if (nd.ni_vp) { 799 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); 800 if (nd.ni_dvp == nd.ni_vp) 801 vrele(nd.ni_dvp); 802 else 803 vput(nd.ni_dvp); 804 vrele(nd.ni_vp); 805 error = EEXIST; 806 goto out; 807 } 808 VATTR_NULL(&vattr); 809 vattr.va_mode = 0777 &~ p->p_fd->fd_cmask; 810 LEASE_CHECK(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE); 811 error = VOP_SYMLINK(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr, target); 812 out: 813 FREE(target, M_NAMEI); 814 return (error); 815 } 816 817 /* 818 * Delete a name from the filesystem. 819 */ 820 /* ARGSUSED */ 821 unlink(p, uap, retval) 822 struct proc *p; 823 struct args { 824 char *name; 825 } *uap; 826 int *retval; 827 { 828 register struct vnode *vp; 829 int error; 830 struct nameidata nd; 831 832 NDINIT(&nd, DELETE, LOCKPARENT | LOCKLEAF, UIO_USERSPACE, uap->name, p); 833 if (error = namei(&nd)) 834 return (error); 835 vp = nd.ni_vp; 836 if (vp->v_type == VDIR && 837 (error = suser(p->p_ucred, &p->p_acflag))) 838 goto out; 839 /* 840 * The root of a mounted filesystem cannot be deleted. 841 */ 842 if (vp->v_flag & VROOT) { 843 error = EBUSY; 844 goto out; 845 } 846 (void) vnode_pager_uncache(vp); 847 out: 848 if (!error) { 849 LEASE_CHECK(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE); 850 LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE); 851 error = VOP_REMOVE(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd); 852 } else { 853 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); 854 if (nd.ni_dvp == vp) 855 vrele(nd.ni_dvp); 856 else 857 vput(nd.ni_dvp); 858 vput(vp); 859 } 860 return (error); 861 } 862 863 #if defined(COMPAT_43) || defined(COMPAT_SUNOS) 864 /* 865 * Seek system call. 866 */ 867 lseek(p, uap, retval) 868 struct proc *p; 869 register struct args { 870 int fdes; 871 long off; 872 int sbase; 873 } *uap; 874 long *retval; 875 { 876 struct nargs { 877 int fdes; 878 off_t off; 879 int sbase; 880 } nuap; 881 quad_t qret; 882 int error; 883 884 nuap.fdes = uap->fdes; 885 nuap.off = uap->off; 886 nuap.sbase = uap->sbase; 887 error = __lseek(p, &nuap, &qret); 888 *retval = qret; 889 return (error); 890 } 891 #endif /* COMPAT_43 || COMPAT_SUNOS */ 892 893 /* 894 * Seek system call. 895 */ 896 __lseek(p, uap, retval) 897 struct proc *p; 898 register struct args { 899 int fdes; 900 off_t off; 901 int sbase; 902 } *uap; 903 off_t *retval; 904 { 905 struct ucred *cred = p->p_ucred; 906 register struct filedesc *fdp = p->p_fd; 907 register struct file *fp; 908 struct vattr vattr; 909 int error; 910 911 if ((unsigned)uap->fdes >= fdp->fd_nfiles || 912 (fp = fdp->fd_ofiles[uap->fdes]) == NULL) 913 return (EBADF); 914 if (fp->f_type != DTYPE_VNODE) 915 return (ESPIPE); 916 switch (uap->sbase) { 917 918 case L_INCR: 919 fp->f_offset += uap->off; 920 break; 921 922 case L_XTND: 923 if (error = VOP_GETATTR((struct vnode *)fp->f_data, 924 &vattr, cred, p)) 925 return (error); 926 fp->f_offset = uap->off + vattr.va_size; 927 break; 928 929 case L_SET: 930 fp->f_offset = uap->off; 931 break; 932 933 default: 934 return (EINVAL); 935 } 936 *retval = fp->f_offset; 937 return (0); 938 } 939 940 /* 941 * Check access permissions. 942 */ 943 /* ARGSUSED */ 944 saccess(p, uap, retval) 945 struct proc *p; 946 register struct args { 947 char *fname; 948 int fmode; 949 } *uap; 950 int *retval; 951 { 952 register struct ucred *cred = p->p_ucred; 953 register struct vnode *vp; 954 int error, mode, svuid, svgid; 955 struct nameidata nd; 956 957 svuid = cred->cr_uid; 958 svgid = cred->cr_groups[0]; 959 cred->cr_uid = p->p_cred->p_ruid; 960 cred->cr_groups[0] = p->p_cred->p_rgid; 961 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->fname, p); 962 if (error = namei(&nd)) 963 goto out1; 964 vp = nd.ni_vp; 965 /* 966 * fmode == 0 means only check for exist 967 */ 968 if (uap->fmode) { 969 mode = 0; 970 if (uap->fmode & R_OK) 971 mode |= VREAD; 972 if (uap->fmode & W_OK) 973 mode |= VWRITE; 974 if (uap->fmode & X_OK) 975 mode |= VEXEC; 976 if ((mode & VWRITE) == 0 || (error = vn_writechk(vp)) == 0) 977 error = VOP_ACCESS(vp, mode, cred, p); 978 } 979 vput(vp); 980 out1: 981 cred->cr_uid = svuid; 982 cred->cr_groups[0] = svgid; 983 return (error); 984 } 985 986 #if defined(COMPAT_43) || defined(COMPAT_SUNOS) 987 /* 988 * Stat system call. 989 * This version follows links. 990 */ 991 /* ARGSUSED */ 992 ostat(p, uap, retval) 993 struct proc *p; 994 register struct args { 995 char *fname; 996 struct ostat *ub; 997 } *uap; 998 int *retval; 999 { 1000 struct stat sb; 1001 struct ostat osb; 1002 int error; 1003 struct nameidata nd; 1004 1005 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->fname, p); 1006 if (error = namei(&nd)) 1007 return (error); 1008 error = vn_stat(nd.ni_vp, &sb, p); 1009 vput(nd.ni_vp); 1010 if (error) 1011 return (error); 1012 cvtstat(&sb, &osb); 1013 error = copyout((caddr_t)&osb, (caddr_t)uap->ub, sizeof (osb)); 1014 return (error); 1015 } 1016 1017 /* 1018 * Lstat system call. 1019 * This version does not follow links. 1020 */ 1021 /* ARGSUSED */ 1022 olstat(p, uap, retval) 1023 struct proc *p; 1024 register struct args { 1025 char *fname; 1026 struct ostat *ub; 1027 } *uap; 1028 int *retval; 1029 { 1030 struct stat sb; 1031 struct ostat osb; 1032 int error; 1033 struct nameidata nd; 1034 1035 NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF, UIO_USERSPACE, uap->fname, p); 1036 if (error = namei(&nd)) 1037 return (error); 1038 error = vn_stat(nd.ni_vp, &sb, p); 1039 vput(nd.ni_vp); 1040 if (error) 1041 return (error); 1042 cvtstat(&sb, &osb); 1043 error = copyout((caddr_t)&osb, (caddr_t)uap->ub, sizeof (osb)); 1044 return (error); 1045 } 1046 1047 /* 1048 * convert from an old to a new stat structure. 1049 */ 1050 cvtstat(st, ost) 1051 struct stat *st; 1052 struct ostat *ost; 1053 { 1054 1055 ost->st_dev = st->st_dev; 1056 ost->st_ino = st->st_ino; 1057 ost->st_mode = st->st_mode; 1058 ost->st_nlink = st->st_nlink; 1059 ost->st_uid = st->st_uid; 1060 ost->st_gid = st->st_gid; 1061 ost->st_rdev = st->st_rdev; 1062 if (st->st_size < (quad_t)1 << 32) 1063 ost->st_size = st->st_size; 1064 else 1065 ost->st_size = -2; 1066 ost->st_atime = st->st_atime; 1067 ost->st_mtime = st->st_mtime; 1068 ost->st_ctime = st->st_ctime; 1069 ost->st_blksize = st->st_blksize; 1070 ost->st_blocks = st->st_blocks; 1071 ost->st_flags = st->st_flags; 1072 ost->st_gen = st->st_gen; 1073 } 1074 #endif /* COMPAT_43 || COMPAT_SUNOS */ 1075 1076 /* 1077 * Stat system call. 1078 * This version follows links. 1079 */ 1080 /* ARGSUSED */ 1081 stat(p, uap, retval) 1082 struct proc *p; 1083 register struct args { 1084 char *fname; 1085 struct stat *ub; 1086 } *uap; 1087 int *retval; 1088 { 1089 struct stat sb; 1090 int error; 1091 struct nameidata nd; 1092 1093 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->fname, p); 1094 if (error = namei(&nd)) 1095 return (error); 1096 error = vn_stat(nd.ni_vp, &sb, p); 1097 vput(nd.ni_vp); 1098 if (error) 1099 return (error); 1100 error = copyout((caddr_t)&sb, (caddr_t)uap->ub, sizeof (sb)); 1101 return (error); 1102 } 1103 1104 /* 1105 * Lstat system call. 1106 * This version does not follow links. 1107 */ 1108 /* ARGSUSED */ 1109 lstat(p, uap, retval) 1110 struct proc *p; 1111 register struct args { 1112 char *fname; 1113 struct stat *ub; 1114 } *uap; 1115 int *retval; 1116 { 1117 struct stat sb; 1118 int error; 1119 struct nameidata nd; 1120 1121 NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF, UIO_USERSPACE, uap->fname, p); 1122 if (error = namei(&nd)) 1123 return (error); 1124 error = vn_stat(nd.ni_vp, &sb, p); 1125 vput(nd.ni_vp); 1126 if (error) 1127 return (error); 1128 error = copyout((caddr_t)&sb, (caddr_t)uap->ub, sizeof (sb)); 1129 return (error); 1130 } 1131 1132 /* 1133 * Return target name of a symbolic link. 1134 */ 1135 /* ARGSUSED */ 1136 readlink(p, uap, retval) 1137 struct proc *p; 1138 register struct args { 1139 char *name; 1140 char *buf; 1141 int count; 1142 } *uap; 1143 int *retval; 1144 { 1145 register struct vnode *vp; 1146 struct iovec aiov; 1147 struct uio auio; 1148 int error; 1149 struct nameidata nd; 1150 1151 NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF, UIO_USERSPACE, uap->name, p); 1152 if (error = namei(&nd)) 1153 return (error); 1154 vp = nd.ni_vp; 1155 if (vp->v_type != VLNK) { 1156 error = EINVAL; 1157 goto out; 1158 } 1159 aiov.iov_base = uap->buf; 1160 aiov.iov_len = uap->count; 1161 auio.uio_iov = &aiov; 1162 auio.uio_iovcnt = 1; 1163 auio.uio_offset = 0; 1164 auio.uio_rw = UIO_READ; 1165 auio.uio_segflg = UIO_USERSPACE; 1166 auio.uio_procp = p; 1167 auio.uio_resid = uap->count; 1168 error = VOP_READLINK(vp, &auio, p->p_ucred); 1169 out: 1170 vput(vp); 1171 *retval = uap->count - auio.uio_resid; 1172 return (error); 1173 } 1174 1175 /* 1176 * Change flags of a file given path name. 1177 */ 1178 /* ARGSUSED */ 1179 chflags(p, uap, retval) 1180 struct proc *p; 1181 register struct args { 1182 char *fname; 1183 int flags; 1184 } *uap; 1185 int *retval; 1186 { 1187 register struct vnode *vp; 1188 struct vattr vattr; 1189 int error; 1190 struct nameidata nd; 1191 1192 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->fname, p); 1193 if (error = namei(&nd)) 1194 return (error); 1195 vp = nd.ni_vp; 1196 if (vp->v_mount->mnt_flag & MNT_RDONLY) { 1197 error = EROFS; 1198 goto out; 1199 } 1200 VATTR_NULL(&vattr); 1201 vattr.va_flags = uap->flags; 1202 LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE); 1203 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); 1204 out: 1205 vput(vp); 1206 return (error); 1207 } 1208 1209 /* 1210 * Change flags of a file given a file descriptor. 1211 */ 1212 /* ARGSUSED */ 1213 fchflags(p, uap, retval) 1214 struct proc *p; 1215 register struct args { 1216 int fd; 1217 int flags; 1218 } *uap; 1219 int *retval; 1220 { 1221 struct vattr vattr; 1222 struct vnode *vp; 1223 struct file *fp; 1224 int error; 1225 1226 if (error = getvnode(p->p_fd, uap->fd, &fp)) 1227 return (error); 1228 vp = (struct vnode *)fp->f_data; 1229 VOP_LOCK(vp); 1230 if (vp->v_mount->mnt_flag & MNT_RDONLY) { 1231 error = EROFS; 1232 goto out; 1233 } 1234 VATTR_NULL(&vattr); 1235 vattr.va_flags = uap->flags; 1236 LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE); 1237 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); 1238 out: 1239 VOP_UNLOCK(vp); 1240 return (error); 1241 } 1242 1243 /* 1244 * Change mode of a file given path name. 1245 */ 1246 /* ARGSUSED */ 1247 chmod(p, uap, retval) 1248 struct proc *p; 1249 register struct args { 1250 char *fname; 1251 int fmode; 1252 } *uap; 1253 int *retval; 1254 { 1255 register struct vnode *vp; 1256 struct vattr vattr; 1257 int error; 1258 struct nameidata nd; 1259 1260 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->fname, p); 1261 if (error = namei(&nd)) 1262 return (error); 1263 vp = nd.ni_vp; 1264 if (vp->v_mount->mnt_flag & MNT_RDONLY) { 1265 error = EROFS; 1266 goto out; 1267 } 1268 VATTR_NULL(&vattr); 1269 vattr.va_mode = uap->fmode & 07777; 1270 LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE); 1271 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); 1272 out: 1273 vput(vp); 1274 return (error); 1275 } 1276 1277 /* 1278 * Change mode of a file given a file descriptor. 1279 */ 1280 /* ARGSUSED */ 1281 fchmod(p, uap, retval) 1282 struct proc *p; 1283 register struct args { 1284 int fd; 1285 int fmode; 1286 } *uap; 1287 int *retval; 1288 { 1289 struct vattr vattr; 1290 struct vnode *vp; 1291 struct file *fp; 1292 int error; 1293 1294 if (error = getvnode(p->p_fd, uap->fd, &fp)) 1295 return (error); 1296 vp = (struct vnode *)fp->f_data; 1297 VOP_LOCK(vp); 1298 if (vp->v_mount->mnt_flag & MNT_RDONLY) { 1299 error = EROFS; 1300 goto out; 1301 } 1302 VATTR_NULL(&vattr); 1303 vattr.va_mode = uap->fmode & 07777; 1304 LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE); 1305 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); 1306 out: 1307 VOP_UNLOCK(vp); 1308 return (error); 1309 } 1310 1311 /* 1312 * Set ownership given a path name. 1313 */ 1314 /* ARGSUSED */ 1315 chown(p, uap, retval) 1316 struct proc *p; 1317 register struct args { 1318 char *fname; 1319 int uid; 1320 int gid; 1321 } *uap; 1322 int *retval; 1323 { 1324 register struct vnode *vp; 1325 struct vattr vattr; 1326 int error; 1327 struct nameidata nd; 1328 1329 NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF, UIO_USERSPACE, uap->fname, p); 1330 if (error = namei(&nd)) 1331 return (error); 1332 vp = nd.ni_vp; 1333 if (vp->v_mount->mnt_flag & MNT_RDONLY) { 1334 error = EROFS; 1335 goto out; 1336 } 1337 VATTR_NULL(&vattr); 1338 vattr.va_uid = uap->uid; 1339 vattr.va_gid = uap->gid; 1340 LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE); 1341 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); 1342 out: 1343 vput(vp); 1344 return (error); 1345 } 1346 1347 /* 1348 * Set ownership given a file descriptor. 1349 */ 1350 /* ARGSUSED */ 1351 fchown(p, uap, retval) 1352 struct proc *p; 1353 register struct args { 1354 int fd; 1355 int uid; 1356 int gid; 1357 } *uap; 1358 int *retval; 1359 { 1360 struct vattr vattr; 1361 struct vnode *vp; 1362 struct file *fp; 1363 int error; 1364 1365 if (error = getvnode(p->p_fd, uap->fd, &fp)) 1366 return (error); 1367 vp = (struct vnode *)fp->f_data; 1368 VOP_LOCK(vp); 1369 if (vp->v_mount->mnt_flag & MNT_RDONLY) { 1370 error = EROFS; 1371 goto out; 1372 } 1373 VATTR_NULL(&vattr); 1374 vattr.va_uid = uap->uid; 1375 vattr.va_gid = uap->gid; 1376 LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE); 1377 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); 1378 out: 1379 VOP_UNLOCK(vp); 1380 return (error); 1381 } 1382 1383 /* 1384 * Set the access and modification times of a file. 1385 */ 1386 /* ARGSUSED */ 1387 utimes(p, uap, retval) 1388 struct proc *p; 1389 register struct args { 1390 char *fname; 1391 struct timeval *tptr; 1392 } *uap; 1393 int *retval; 1394 { 1395 register struct vnode *vp; 1396 struct timeval tv[2]; 1397 struct vattr vattr; 1398 int error; 1399 struct nameidata nd; 1400 1401 if (error = copyin((caddr_t)uap->tptr, (caddr_t)tv, sizeof (tv))) 1402 return (error); 1403 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->fname, p); 1404 if (error = namei(&nd)) 1405 return (error); 1406 vp = nd.ni_vp; 1407 if (vp->v_mount->mnt_flag & MNT_RDONLY) { 1408 error = EROFS; 1409 goto out; 1410 } 1411 VATTR_NULL(&vattr); 1412 vattr.va_atime.ts_sec = tv[0].tv_sec; 1413 vattr.va_atime.ts_nsec = tv[0].tv_usec * 1000; 1414 vattr.va_mtime.ts_sec = tv[1].tv_sec; 1415 vattr.va_mtime.ts_nsec = tv[1].tv_usec * 1000; 1416 LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE); 1417 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); 1418 out: 1419 vput(vp); 1420 return (error); 1421 } 1422 1423 #if defined(COMPAT_43) || defined(COMPAT_SUNOS) 1424 /* 1425 * Truncate a file given its path name. 1426 */ 1427 /* ARGSUSED */ 1428 truncate(p, uap, retval) 1429 struct proc *p; 1430 register struct args { 1431 char *fname; 1432 long length; 1433 } *uap; 1434 int *retval; 1435 { 1436 struct nargs { 1437 char *fname; 1438 off_t length; 1439 } nuap; 1440 1441 nuap.fname = uap->fname; 1442 nuap.length = uap->length; 1443 return (__truncate(p, &nuap, retval)); 1444 } 1445 1446 /* 1447 * Truncate a file given a file descriptor. 1448 */ 1449 /* ARGSUSED */ 1450 ftruncate(p, uap, retval) 1451 struct proc *p; 1452 register struct args { 1453 int fd; 1454 long length; 1455 } *uap; 1456 int *retval; 1457 { 1458 struct nargs { 1459 int fd; 1460 off_t length; 1461 } nuap; 1462 1463 nuap.fd = uap->fd; 1464 nuap.length = uap->length; 1465 return (__ftruncate(p, &nuap, retval)); 1466 } 1467 #endif /* COMPAT_43 || COMPAT_SUNOS */ 1468 1469 /* 1470 * Truncate a file given its path name. 1471 */ 1472 /* ARGSUSED */ 1473 __truncate(p, uap, retval) 1474 struct proc *p; 1475 register struct args { 1476 char *fname; 1477 off_t length; 1478 } *uap; 1479 int *retval; 1480 { 1481 register struct vnode *vp; 1482 struct vattr vattr; 1483 int error; 1484 struct nameidata nd; 1485 1486 NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE, uap->fname, p); 1487 if (error = namei(&nd)) 1488 return (error); 1489 vp = nd.ni_vp; 1490 if (vp->v_type == VDIR) { 1491 error = EISDIR; 1492 goto out; 1493 } 1494 if ((error = vn_writechk(vp)) || 1495 (error = VOP_ACCESS(vp, VWRITE, p->p_ucred, p))) 1496 goto out; 1497 VATTR_NULL(&vattr); 1498 vattr.va_size = uap->length; 1499 LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE); 1500 error = VOP_SETATTR(vp, &vattr, p->p_ucred, p); 1501 out: 1502 vput(vp); 1503 return (error); 1504 } 1505 1506 /* 1507 * Truncate a file given a file descriptor. 1508 */ 1509 /* ARGSUSED */ 1510 __ftruncate(p, uap, retval) 1511 struct proc *p; 1512 register struct args { 1513 int fd; 1514 off_t length; 1515 } *uap; 1516 int *retval; 1517 { 1518 struct vattr vattr; 1519 struct vnode *vp; 1520 struct file *fp; 1521 int error; 1522 1523 if (error = getvnode(p->p_fd, uap->fd, &fp)) 1524 return (error); 1525 if ((fp->f_flag & FWRITE) == 0) 1526 return (EINVAL); 1527 vp = (struct vnode *)fp->f_data; 1528 VOP_LOCK(vp); 1529 if (vp->v_type == VDIR) { 1530 error = EISDIR; 1531 goto out; 1532 } 1533 if (error = vn_writechk(vp)) 1534 goto out; 1535 VATTR_NULL(&vattr); 1536 vattr.va_size = uap->length; 1537 LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE); 1538 error = VOP_SETATTR(vp, &vattr, fp->f_cred, p); 1539 out: 1540 VOP_UNLOCK(vp); 1541 return (error); 1542 } 1543 1544 /* 1545 * Synch an open file. 1546 */ 1547 /* ARGSUSED */ 1548 fsync(p, uap, retval) 1549 struct proc *p; 1550 struct args { 1551 int fd; 1552 } *uap; 1553 int *retval; 1554 { 1555 register struct vnode *vp; 1556 struct file *fp; 1557 int error; 1558 1559 if (error = getvnode(p->p_fd, uap->fd, &fp)) 1560 return (error); 1561 vp = (struct vnode *)fp->f_data; 1562 VOP_LOCK(vp); 1563 error = VOP_FSYNC(vp, fp->f_cred, MNT_WAIT, p); 1564 VOP_UNLOCK(vp); 1565 return (error); 1566 } 1567 1568 /* 1569 * Rename system call. 1570 * 1571 * Source and destination must either both be directories, or both 1572 * not be directories. If target is a directory, it must be empty. 1573 */ 1574 /* ARGSUSED */ 1575 rename(p, uap, retval) 1576 struct proc *p; 1577 register struct args { 1578 char *from; 1579 char *to; 1580 } *uap; 1581 int *retval; 1582 { 1583 register struct vnode *tvp, *fvp, *tdvp; 1584 struct nameidata fromnd, tond; 1585 int error; 1586 1587 NDINIT(&fromnd, DELETE, WANTPARENT | SAVESTART, UIO_USERSPACE, 1588 uap->from, p); 1589 if (error = namei(&fromnd)) 1590 return (error); 1591 fvp = fromnd.ni_vp; 1592 NDINIT(&tond, RENAME, LOCKPARENT | LOCKLEAF | NOCACHE | SAVESTART, 1593 UIO_USERSPACE, uap->to, p); 1594 if (error = namei(&tond)) { 1595 VOP_ABORTOP(fromnd.ni_dvp, &fromnd.ni_cnd); 1596 vrele(fromnd.ni_dvp); 1597 vrele(fvp); 1598 goto out1; 1599 } 1600 tdvp = tond.ni_dvp; 1601 tvp = tond.ni_vp; 1602 if (tvp != NULL) { 1603 if (fvp->v_type == VDIR && tvp->v_type != VDIR) { 1604 error = ENOTDIR; 1605 goto out; 1606 } else if (fvp->v_type != VDIR && tvp->v_type == VDIR) { 1607 error = EISDIR; 1608 goto out; 1609 } 1610 } 1611 if (fvp == tdvp) 1612 error = EINVAL; 1613 /* 1614 * If source is the same as the destination (that is the 1615 * same inode number with the same name in the same directory), 1616 * then there is nothing to do. 1617 */ 1618 if (fvp == tvp && fromnd.ni_dvp == tdvp && 1619 fromnd.ni_cnd.cn_namelen == tond.ni_cnd.cn_namelen && 1620 !bcmp(fromnd.ni_cnd.cn_nameptr, tond.ni_cnd.cn_nameptr, 1621 fromnd.ni_cnd.cn_namelen)) 1622 error = -1; 1623 out: 1624 if (!error) { 1625 LEASE_CHECK(tdvp, p, p->p_ucred, LEASE_WRITE); 1626 if (fromnd.ni_dvp != tdvp) 1627 LEASE_CHECK(fromnd.ni_dvp, p, p->p_ucred, LEASE_WRITE); 1628 if (tvp) 1629 LEASE_CHECK(tvp, p, p->p_ucred, LEASE_WRITE); 1630 error = VOP_RENAME(fromnd.ni_dvp, fromnd.ni_vp, &fromnd.ni_cnd, 1631 tond.ni_dvp, tond.ni_vp, &tond.ni_cnd); 1632 } else { 1633 VOP_ABORTOP(tond.ni_dvp, &tond.ni_cnd); 1634 if (tdvp == tvp) 1635 vrele(tdvp); 1636 else 1637 vput(tdvp); 1638 if (tvp) 1639 vput(tvp); 1640 VOP_ABORTOP(fromnd.ni_dvp, &fromnd.ni_cnd); 1641 vrele(fromnd.ni_dvp); 1642 vrele(fvp); 1643 } 1644 vrele(tond.ni_startdir); 1645 FREE(tond.ni_cnd.cn_pnbuf, M_NAMEI); 1646 out1: 1647 vrele(fromnd.ni_startdir); 1648 FREE(fromnd.ni_cnd.cn_pnbuf, M_NAMEI); 1649 if (error == -1) 1650 return (0); 1651 return (error); 1652 } 1653 1654 /* 1655 * Mkdir system call. 1656 */ 1657 /* ARGSUSED */ 1658 mkdir(p, uap, retval) 1659 struct proc *p; 1660 register struct args { 1661 char *name; 1662 int dmode; 1663 } *uap; 1664 int *retval; 1665 { 1666 register struct vnode *vp; 1667 struct vattr vattr; 1668 int error; 1669 struct nameidata nd; 1670 1671 NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, uap->name, p); 1672 if (error = namei(&nd)) 1673 return (error); 1674 vp = nd.ni_vp; 1675 if (vp != NULL) { 1676 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); 1677 if (nd.ni_dvp == vp) 1678 vrele(nd.ni_dvp); 1679 else 1680 vput(nd.ni_dvp); 1681 vrele(vp); 1682 return (EEXIST); 1683 } 1684 VATTR_NULL(&vattr); 1685 vattr.va_type = VDIR; 1686 vattr.va_mode = (uap->dmode & 0777) &~ p->p_fd->fd_cmask; 1687 LEASE_CHECK(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE); 1688 error = VOP_MKDIR(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr); 1689 if (!error) 1690 vput(nd.ni_vp); 1691 return (error); 1692 } 1693 1694 /* 1695 * Rmdir system call. 1696 */ 1697 /* ARGSUSED */ 1698 rmdir(p, uap, retval) 1699 struct proc *p; 1700 struct args { 1701 char *name; 1702 } *uap; 1703 int *retval; 1704 { 1705 register struct vnode *vp; 1706 int error; 1707 struct nameidata nd; 1708 1709 NDINIT(&nd, DELETE, LOCKPARENT | LOCKLEAF, UIO_USERSPACE, uap->name, p); 1710 if (error = namei(&nd)) 1711 return (error); 1712 vp = nd.ni_vp; 1713 if (vp->v_type != VDIR) { 1714 error = ENOTDIR; 1715 goto out; 1716 } 1717 /* 1718 * No rmdir "." please. 1719 */ 1720 if (nd.ni_dvp == vp) { 1721 error = EINVAL; 1722 goto out; 1723 } 1724 /* 1725 * The root of a mounted filesystem cannot be deleted. 1726 */ 1727 if (vp->v_flag & VROOT) 1728 error = EBUSY; 1729 out: 1730 if (!error) { 1731 LEASE_CHECK(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE); 1732 LEASE_CHECK(vp, p, p->p_ucred, LEASE_WRITE); 1733 error = VOP_RMDIR(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd); 1734 } else { 1735 VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd); 1736 if (nd.ni_dvp == vp) 1737 vrele(nd.ni_dvp); 1738 else 1739 vput(nd.ni_dvp); 1740 vput(vp); 1741 } 1742 return (error); 1743 } 1744 1745 #ifdef COMPAT_43 1746 /* 1747 * Read a block of directory entries in a file system independent format. 1748 */ 1749 ogetdirentries(p, uap, retval) 1750 struct proc *p; 1751 register struct args { 1752 int fd; 1753 char *buf; 1754 unsigned count; 1755 long *basep; 1756 } *uap; 1757 int *retval; 1758 { 1759 register struct vnode *vp; 1760 struct file *fp; 1761 struct uio auio, kuio; 1762 struct iovec aiov, kiov; 1763 struct dirent *dp, *edp; 1764 caddr_t dirbuf; 1765 int error, readcnt; 1766 off_t off; 1767 1768 if (error = getvnode(p->p_fd, uap->fd, &fp)) 1769 return (error); 1770 if ((fp->f_flag & FREAD) == 0) 1771 return (EBADF); 1772 vp = (struct vnode *)fp->f_data; 1773 if (vp->v_type != VDIR) 1774 return (EINVAL); 1775 aiov.iov_base = uap->buf; 1776 aiov.iov_len = uap->count; 1777 auio.uio_iov = &aiov; 1778 auio.uio_iovcnt = 1; 1779 auio.uio_rw = UIO_READ; 1780 auio.uio_segflg = UIO_USERSPACE; 1781 auio.uio_procp = p; 1782 auio.uio_resid = uap->count; 1783 VOP_LOCK(vp); 1784 auio.uio_offset = off = fp->f_offset; 1785 # if (BYTE_ORDER != LITTLE_ENDIAN) 1786 if (vp->v_mount->mnt_maxsymlinklen <= 0) 1787 error = VOP_READDIR(vp, &auio, fp->f_cred); 1788 else 1789 # endif 1790 { 1791 kuio = auio; 1792 kuio.uio_iov = &kiov; 1793 kuio.uio_segflg = UIO_SYSSPACE; 1794 kiov.iov_len = uap->count; 1795 MALLOC(dirbuf, caddr_t, uap->count, M_TEMP, M_WAITOK); 1796 kiov.iov_base = dirbuf; 1797 error = VOP_READDIR(vp, &kuio, fp->f_cred); 1798 if (error == 0) { 1799 readcnt = uap->count - kuio.uio_resid; 1800 edp = (struct dirent *)&dirbuf[readcnt]; 1801 for (dp = (struct dirent *)dirbuf; dp < edp; ) { 1802 dp->d_type = 0; 1803 # if (BYTE_ORDER == LITTLE_ENDIAN) 1804 { u_char tmp = dp->d_namlen; 1805 dp->d_namlen = dp->d_type; 1806 dp->d_type = tmp; } 1807 # endif 1808 if (dp->d_reclen > 0) { 1809 dp = (struct dirent *) 1810 ((char *)dp + dp->d_reclen); 1811 } else { 1812 error = EIO; 1813 break; 1814 } 1815 } 1816 if (dp >= edp) 1817 error = uiomove(dirbuf, readcnt, &auio); 1818 } 1819 FREE(dirbuf, M_TEMP); 1820 } 1821 fp->f_offset = auio.uio_offset; 1822 VOP_UNLOCK(vp); 1823 if (error) 1824 return (error); 1825 error = copyout((caddr_t)&off, (caddr_t)uap->basep, sizeof(long)); 1826 *retval = uap->count - auio.uio_resid; 1827 return (error); 1828 } 1829 #endif 1830 1831 /* 1832 * Read a block of directory entries in a file system independent format. 1833 */ 1834 getdirentries(p, uap, retval) 1835 struct proc *p; 1836 register struct args { 1837 int fd; 1838 char *buf; 1839 unsigned count; 1840 long *basep; 1841 } *uap; 1842 int *retval; 1843 { 1844 register struct vnode *vp; 1845 struct file *fp; 1846 struct uio auio; 1847 struct iovec aiov; 1848 off_t off; 1849 int error; 1850 1851 if (error = getvnode(p->p_fd, uap->fd, &fp)) 1852 return (error); 1853 if ((fp->f_flag & FREAD) == 0) 1854 return (EBADF); 1855 vp = (struct vnode *)fp->f_data; 1856 if (vp->v_type != VDIR) 1857 return (EINVAL); 1858 aiov.iov_base = uap->buf; 1859 aiov.iov_len = uap->count; 1860 auio.uio_iov = &aiov; 1861 auio.uio_iovcnt = 1; 1862 auio.uio_rw = UIO_READ; 1863 auio.uio_segflg = UIO_USERSPACE; 1864 auio.uio_procp = p; 1865 auio.uio_resid = uap->count; 1866 VOP_LOCK(vp); 1867 auio.uio_offset = off = fp->f_offset; 1868 error = VOP_READDIR(vp, &auio, fp->f_cred); 1869 fp->f_offset = auio.uio_offset; 1870 VOP_UNLOCK(vp); 1871 if (error) 1872 return (error); 1873 error = copyout((caddr_t)&off, (caddr_t)uap->basep, sizeof(long)); 1874 *retval = uap->count - auio.uio_resid; 1875 return (error); 1876 } 1877 1878 /* 1879 * Set the mode mask for creation of filesystem nodes. 1880 */ 1881 mode_t 1882 umask(p, uap, retval) 1883 struct proc *p; 1884 struct args { 1885 int mask; 1886 } *uap; 1887 int *retval; 1888 { 1889 register struct filedesc *fdp = p->p_fd; 1890 1891 *retval = fdp->fd_cmask; 1892 fdp->fd_cmask = uap->mask & 07777; 1893 return (0); 1894 } 1895 1896 /* 1897 * Void all references to file by ripping underlying filesystem 1898 * away from vnode. 1899 */ 1900 /* ARGSUSED */ 1901 revoke(p, uap, retval) 1902 struct proc *p; 1903 register struct args { 1904 char *fname; 1905 } *uap; 1906 int *retval; 1907 { 1908 register struct vnode *vp; 1909 struct vattr vattr; 1910 int error; 1911 struct nameidata nd; 1912 1913 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->fname, p); 1914 if (error = namei(&nd)) 1915 return (error); 1916 vp = nd.ni_vp; 1917 if (vp->v_type != VCHR && vp->v_type != VBLK) { 1918 error = EINVAL; 1919 goto out; 1920 } 1921 if (error = VOP_GETATTR(vp, &vattr, p->p_ucred, p)) 1922 goto out; 1923 if (p->p_ucred->cr_uid != vattr.va_uid && 1924 (error = suser(p->p_ucred, &p->p_acflag))) 1925 goto out; 1926 if (vp->v_usecount > 1 || (vp->v_flag & VALIASED)) 1927 vgoneall(vp); 1928 out: 1929 vrele(vp); 1930 return (error); 1931 } 1932 1933 /* 1934 * Convert a user file descriptor to a kernel file entry. 1935 */ 1936 getvnode(fdp, fdes, fpp) 1937 struct filedesc *fdp; 1938 struct file **fpp; 1939 int fdes; 1940 { 1941 struct file *fp; 1942 1943 if ((unsigned)fdes >= fdp->fd_nfiles || 1944 (fp = fdp->fd_ofiles[fdes]) == NULL) 1945 return (EBADF); 1946 if (fp->f_type != DTYPE_VNODE) 1947 return (EINVAL); 1948 *fpp = fp; 1949 return (0); 1950 } 1951