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