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