home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / bsd_srcs / sys / kern / vfs_syscalls.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-06-29  |  35.1 KB  |  1,795 lines

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