Annotation of 43BSDReno/sys/kern/vfs_syscalls.c, revision 1.1.1.1

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.