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