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