[BACK]Return to vfs_syscalls.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / sys / kern

Annotation of src/sys/kern/vfs_syscalls.c, Revision 1.159

1.159   ! mrg         1: /*     $NetBSD: vfs_syscalls.c,v 1.158 2000/06/19 18:53:55 pooka Exp $ */
1.31      cgd         2:
                      3: /*
                      4:  * Copyright (c) 1989, 1993
                      5:  *     The Regents of the University of California.  All rights reserved.
                      6:  * (c) UNIX System Laboratories, Inc.
                      7:  * All or some portions of this file are derived from material licensed
                      8:  * to the University of California by American Telephone and Telegraph
                      9:  * Co. or Unix System Laboratories, Inc. and are reproduced herein with
                     10:  * the permission of UNIX System Laboratories, Inc.
                     11:  *
                     12:  * Redistribution and use in source and binary forms, with or without
                     13:  * modification, are permitted provided that the following conditions
                     14:  * are met:
                     15:  * 1. Redistributions of source code must retain the above copyright
                     16:  *    notice, this list of conditions and the following disclaimer.
                     17:  * 2. Redistributions in binary form must reproduce the above copyright
                     18:  *    notice, this list of conditions and the following disclaimer in the
                     19:  *    documentation and/or other materials provided with the distribution.
                     20:  * 3. All advertising materials mentioning features or use of this software
                     21:  *    must display the following acknowledgement:
                     22:  *     This product includes software developed by the University of
                     23:  *     California, Berkeley and its contributors.
                     24:  * 4. Neither the name of the University nor the names of its contributors
                     25:  *    may be used to endorse or promote products derived from this software
                     26:  *    without specific prior written permission.
                     27:  *
                     28:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
                     29:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     30:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     31:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                     32:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     33:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     34:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     35:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     36:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     37:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     38:  * SUCH DAMAGE.
                     39:  *
1.113     fvdl       40:  *     @(#)vfs_syscalls.c      8.42 (Berkeley) 7/31/95
1.31      cgd        41:  */
1.111     mrg        42:
1.121     jonathan   43: #include "opt_compat_netbsd.h"
1.127     christos   44: #include "opt_compat_43.h"
1.31      cgd        45:
                     46: #include <sys/param.h>
                     47: #include <sys/systm.h>
                     48: #include <sys/namei.h>
                     49: #include <sys/filedesc.h>
                     50: #include <sys/kernel.h>
                     51: #include <sys/file.h>
                     52: #include <sys/stat.h>
                     53: #include <sys/vnode.h>
                     54: #include <sys/mount.h>
                     55: #include <sys/proc.h>
                     56: #include <sys/uio.h>
                     57: #include <sys/malloc.h>
                     58: #include <sys/dirent.h>
1.35      cgd        59: #include <sys/syscallargs.h>
                     60:
1.148     fvdl       61: #include <miscfs/genfs/genfs.h>
                     62: #include <miscfs/syncfs/syncfs.h>
                     63:
1.110     mrg        64: #include <uvm/uvm_extern.h>
1.159   ! mrg        65:
        !            66: #include <sys/sysctl.h>
1.110     mrg        67:
1.63      christos   68: static int change_dir __P((struct nameidata *, struct proc *));
1.97      enami      69: static int change_mode __P((struct vnode *, int, struct proc *p));
1.112     kleink     70: static int change_owner __P((struct vnode *, uid_t, gid_t, struct proc *,
                     71:     int));
1.97      enami      72: static int change_utimes __P((struct vnode *vp, const struct timeval *,
                     73:               struct proc *p));
1.90      kleink     74: static int rename_files __P((const char *, const char *, struct proc *, int));
1.63      christos   75:
                     76: void checkdirs __P((struct vnode *));
1.31      cgd        77:
1.150     fvdl       78: int dovfsusermount = 0;
                     79:
1.31      cgd        80: /*
                     81:  * Virtual File System System Calls
                     82:  */
                     83:
                     84: /*
                     85:  * Mount a file system.
                     86:  */
1.99      thorpej    87:
                     88: /*
                     89:  * This table is used to maintain compatibility with 4.3BSD
                     90:  * and NetBSD 0.9 mount syscalls.  Note, the order is important!
1.124     thorpej    91:  *
                     92:  * Also note that not all of these had actual numbers in 4.3BSD
                     93:  * or NetBSD 0.9!
1.99      thorpej    94:  */
1.113     fvdl       95: const char *mountcompatnames[] = {
1.99      thorpej    96:        NULL,           /* 0 = MOUNT_NONE */
                     97:        MOUNT_FFS,      /* 1 */
                     98:        MOUNT_NFS,      /* 2 */
                     99:        MOUNT_MFS,      /* 3 */
                    100:        MOUNT_MSDOS,    /* 4 */
                    101:        MOUNT_LFS,      /* 5 */
                    102:        NULL,           /* 6 = MOUNT_LOFS */
                    103:        MOUNT_FDESC,    /* 7 */
                    104:        MOUNT_PORTAL,   /* 8 */
                    105:        MOUNT_NULL,     /* 9 */
                    106:        MOUNT_UMAP,     /* 10 */
                    107:        MOUNT_KERNFS,   /* 11 */
                    108:        MOUNT_PROCFS,   /* 12 */
                    109:        MOUNT_AFS,      /* 13 */
                    110:        MOUNT_CD9660,   /* 14 = MOUNT_ISOFS */
                    111:        MOUNT_UNION,    /* 15 */
                    112:        MOUNT_ADOSFS,   /* 16 */
                    113:        MOUNT_EXT2FS,   /* 17 */
1.124     thorpej   114:        MOUNT_CODA,     /* 18 */
                    115:        MOUNT_FILECORE, /* 19 */
1.136     christos  116:        MOUNT_NTFS,     /* 20 */
1.99      thorpej   117: };
1.113     fvdl      118: const int nmountcompatnames = sizeof(mountcompatnames) /
1.99      thorpej   119:     sizeof(mountcompatnames[0]);
                    120:
1.31      cgd       121: /* ARGSUSED */
1.63      christos  122: int
1.57      mycroft   123: sys_mount(p, v, retval)
1.31      cgd       124:        struct proc *p;
1.56      thorpej   125:        void *v;
                    126:        register_t *retval;
                    127: {
1.155     augustss  128:        struct sys_mount_args /* {
1.74      cgd       129:                syscallarg(const char *) type;
                    130:                syscallarg(const char *) path;
1.35      cgd       131:                syscallarg(int) flags;
1.74      cgd       132:                syscallarg(void *) data;
1.56      thorpej   133:        } */ *uap = v;
1.113     fvdl      134:        struct vnode *vp;
                    135:        struct mount *mp;
1.63      christos  136:        int error, flag = 0;
1.31      cgd       137:        char fstypename[MFSNAMELEN];
1.43      mycroft   138:        struct vattr va;
1.31      cgd       139:        struct nameidata nd;
1.109     thorpej   140:        struct vfsops *vfs;
1.31      cgd       141:
1.150     fvdl      142:        if (dovfsusermount == 0 && (error = suser(p->p_ucred, &p->p_acflag)))
                    143:                return (error);
1.31      cgd       144:        /*
                    145:         * Get vnode to be covered
                    146:         */
1.113     fvdl      147:        NDINIT(&nd, LOOKUP, FOLLOW , UIO_USERSPACE,
1.35      cgd       148:            SCARG(uap, path), p);
1.63      christos  149:        if ((error = namei(&nd)) != 0)
1.31      cgd       150:                return (error);
                    151:        vp = nd.ni_vp;
1.113     fvdl      152:        /*
                    153:         * A lookup in VFS_MOUNT might result in an attempt to
                    154:         * lock this vnode again, so make the lock resursive.
                    155:         */
1.128     fvdl      156:        vn_lock(vp, LK_EXCLUSIVE | LK_RETRY | LK_SETRECURSE);
1.35      cgd       157:        if (SCARG(uap, flags) & MNT_UPDATE) {
1.31      cgd       158:                if ((vp->v_flag & VROOT) == 0) {
                    159:                        vput(vp);
                    160:                        return (EINVAL);
                    161:                }
                    162:                mp = vp->v_mount;
                    163:                flag = mp->mnt_flag;
1.109     thorpej   164:                vfs = mp->mnt_op;
1.31      cgd       165:                /*
                    166:                 * We only allow the filesystem to be reloaded if it
                    167:                 * is currently mounted read-only.
                    168:                 */
1.35      cgd       169:                if ((SCARG(uap, flags) & MNT_RELOAD) &&
1.31      cgd       170:                    ((mp->mnt_flag & MNT_RDONLY) == 0)) {
                    171:                        vput(vp);
                    172:                        return (EOPNOTSUPP);    /* Needs translation */
                    173:                }
1.125     tls       174:                /*
                    175:                 * In "highly secure" mode, don't let the caller do anything
                    176:                 * but downgrade a filesystem from read-write to read-only.
                    177:                 * (see also below; MNT_UPDATE is required.)
                    178:                 */
                    179:                if (securelevel >= 2 &&
                    180:                    (SCARG(uap, flags) !=
                    181:                    (mp->mnt_flag | MNT_RDONLY |
                    182:                    MNT_RELOAD | MNT_FORCE | MNT_UPDATE))) {
                    183:                        vput(vp);
                    184:                        return (EPERM);
                    185:                }
1.31      cgd       186:                mp->mnt_flag |=
1.35      cgd       187:                    SCARG(uap, flags) & (MNT_RELOAD | MNT_FORCE | MNT_UPDATE);
1.43      mycroft   188:                /*
                    189:                 * Only root, or the user that did the original mount is
                    190:                 * permitted to update it.
                    191:                 */
                    192:                if (mp->mnt_stat.f_owner != p->p_ucred->cr_uid &&
1.93      enami     193:                    (error = suser(p->p_ucred, &p->p_acflag)) != 0) {
1.43      mycroft   194:                        vput(vp);
                    195:                        return (error);
                    196:                }
                    197:                /*
1.130     bouyer    198:                 * Do not allow NFS export by non-root users. For non-root
                    199:                 * users, silently enforce MNT_NOSUID and MNT_NODEV, and
                    200:                 * MNT_NOEXEC if mount point is already MNT_NOEXEC.
1.43      mycroft   201:                 */
                    202:                if (p->p_ucred->cr_uid != 0) {
                    203:                        if (SCARG(uap, flags) & MNT_EXPORTED) {
                    204:                                vput(vp);
                    205:                                return (EPERM);
                    206:                        }
                    207:                        SCARG(uap, flags) |= MNT_NOSUID | MNT_NODEV;
1.130     bouyer    208:                        if (flag & MNT_NOEXEC)
                    209:                                SCARG(uap, flags) |= MNT_NOEXEC;
1.43      mycroft   210:                }
1.113     fvdl      211:                if (vfs_busy(mp, LK_NOWAIT, 0)) {
                    212:                        vput(vp);
                    213:                        return (EPERM);
                    214:                }
                    215:                VOP_UNLOCK(vp, 0);
1.31      cgd       216:                goto update;
1.125     tls       217:        } else {
1.158     pooka     218:                if (securelevel >= 2) {
                    219:                        vput(vp);
1.125     tls       220:                        return (EPERM);
1.158     pooka     221:                }
1.31      cgd       222:        }
1.43      mycroft   223:        /*
                    224:         * If the user is not root, ensure that they own the directory
                    225:         * onto which we are attempting to mount.
                    226:         */
1.93      enami     227:        if ((error = VOP_GETATTR(vp, &va, p->p_ucred, p)) != 0 ||
1.43      mycroft   228:            (va.va_uid != p->p_ucred->cr_uid &&
1.93      enami     229:                (error = suser(p->p_ucred, &p->p_acflag)) != 0)) {
1.43      mycroft   230:                vput(vp);
                    231:                return (error);
                    232:        }
                    233:        /*
1.130     bouyer    234:         * Do not allow NFS export by non-root users. For non-root users,
                    235:         * silently enforce MNT_NOSUID and MNT_NODEV, and MNT_NOEXEC if the
                    236:         * mount point is already MNT_NOEXEC.
1.43      mycroft   237:         */
                    238:        if (p->p_ucred->cr_uid != 0) {
                    239:                if (SCARG(uap, flags) & MNT_EXPORTED) {
                    240:                        vput(vp);
                    241:                        return (EPERM);
                    242:                }
                    243:                SCARG(uap, flags) |= MNT_NOSUID | MNT_NODEV;
1.130     bouyer    244:                if (vp->v_mount->mnt_flag & MNT_NOEXEC)
                    245:                        SCARG(uap, flags) |= MNT_NOEXEC;
1.43      mycroft   246:        }
1.63      christos  247:        if ((error = vinvalbuf(vp, V_SAVE, p->p_ucred, p, 0, 0)) != 0)
1.31      cgd       248:                return (error);
                    249:        if (vp->v_type != VDIR) {
                    250:                vput(vp);
                    251:                return (ENOTDIR);
                    252:        }
1.63      christos  253:        error = copyinstr(SCARG(uap, type), fstypename, MFSNAMELEN, NULL);
                    254:        if (error) {
1.54      cgd       255: #if defined(COMPAT_09) || defined(COMPAT_43)
                    256:                /*
                    257:                 * Historically filesystem types were identified by number.
                    258:                 * If we get an integer for the filesystem type instead of a
                    259:                 * string, we check to see if it matches one of the historic
                    260:                 * filesystem types.
                    261:                 */
1.109     thorpej   262:                u_long fsindex = (u_long)SCARG(uap, type);
1.99      thorpej   263:                if (fsindex >= nmountcompatnames ||
                    264:                    mountcompatnames[fsindex] == NULL) {
1.54      cgd       265:                        vput(vp);
                    266:                        return (ENODEV);
                    267:                }
1.99      thorpej   268:                strncpy(fstypename, mountcompatnames[fsindex], MFSNAMELEN);
1.31      cgd       269: #else
                    270:                vput(vp);
                    271:                return (error);
                    272: #endif
                    273:        }
1.58      gwr       274: #ifdef COMPAT_10
1.59      mycroft   275:        /* Accept `ufs' as an alias for `ffs'. */
                    276:        if (!strncmp(fstypename, "ufs", MFSNAMELEN))
                    277:                strncpy(fstypename, "ffs", MFSNAMELEN);
1.58      gwr       278: #endif
1.109     thorpej   279:        if ((vfs = vfs_getopsbyname(fstypename)) == NULL) {
1.31      cgd       280:                vput(vp);
                    281:                return (ENODEV);
                    282:        }
1.43      mycroft   283:        if (vp->v_mountedhere != NULL) {
                    284:                vput(vp);
                    285:                return (EBUSY);
                    286:        }
1.31      cgd       287:
                    288:        /*
                    289:         * Allocate and initialize the file system.
                    290:         */
                    291:        mp = (struct mount *)malloc((u_long)sizeof(struct mount),
                    292:                M_MOUNT, M_WAITOK);
1.123     perry     293:        memset((char *)mp, 0, (u_long)sizeof(struct mount));
1.113     fvdl      294:        lockinit(&mp->mnt_lock, PVFS, "vfslock", 0, 0);
                    295:        (void)vfs_busy(mp, LK_NOWAIT, 0);
1.109     thorpej   296:        mp->mnt_op = vfs;
                    297:        vfs->vfs_refcount++;
1.129     fvdl      298:        mp->mnt_vnodecovered = vp;
1.43      mycroft   299:        mp->mnt_stat.f_owner = p->p_ucred->cr_uid;
1.148     fvdl      300:        mp->mnt_unmounter = NULL;
1.31      cgd       301: update:
                    302:        /*
                    303:         * Set the mount level flags.
                    304:         */
1.35      cgd       305:        if (SCARG(uap, flags) & MNT_RDONLY)
1.31      cgd       306:                mp->mnt_flag |= MNT_RDONLY;
                    307:        else if (mp->mnt_flag & MNT_RDONLY)
                    308:                mp->mnt_flag |= MNT_WANTRDWR;
                    309:        mp->mnt_flag &=~ (MNT_NOSUID | MNT_NOEXEC | MNT_NODEV |
1.79      fvdl      310:            MNT_SYNCHRONOUS | MNT_UNION | MNT_ASYNC | MNT_NOCOREDUMP |
1.157     fvdl      311:            MNT_NOATIME | MNT_NODEVMTIME | MNT_SYMPERM | MNT_SOFTDEP);
1.35      cgd       312:        mp->mnt_flag |= SCARG(uap, flags) & (MNT_NOSUID | MNT_NOEXEC |
1.73      cgd       313:            MNT_NODEV | MNT_SYNCHRONOUS | MNT_UNION | MNT_ASYNC |
1.157     fvdl      314:            MNT_NOCOREDUMP | MNT_NOATIME | MNT_NODEVMTIME | MNT_SYMPERM |
                    315:            MNT_SOFTDEP);
1.31      cgd       316:        /*
                    317:         * Mount the filesystem.
                    318:         */
1.35      cgd       319:        error = VFS_MOUNT(mp, SCARG(uap, path), SCARG(uap, data), &nd, p);
1.31      cgd       320:        if (mp->mnt_flag & MNT_UPDATE) {
                    321:                vrele(vp);
                    322:                if (mp->mnt_flag & MNT_WANTRDWR)
                    323:                        mp->mnt_flag &= ~MNT_RDONLY;
                    324:                mp->mnt_flag &=~
                    325:                    (MNT_UPDATE | MNT_RELOAD | MNT_FORCE | MNT_WANTRDWR);
                    326:                if (error)
                    327:                        mp->mnt_flag = flag;
1.151     mycroft   328:                if ((mp->mnt_flag & (MNT_RDONLY | MNT_ASYNC)) == 0) {
1.148     fvdl      329:                        if (mp->mnt_syncer == NULL)
                    330:                                error = vfs_allocate_syncvnode(mp);
                    331:                } else {
1.151     mycroft   332:                        if (mp->mnt_syncer != NULL) {
1.148     fvdl      333:                                vgone(mp->mnt_syncer);
1.151     mycroft   334:                                mp->mnt_syncer = NULL;
                    335:                        }
1.148     fvdl      336:                }
1.113     fvdl      337:                vfs_unbusy(mp);
1.31      cgd       338:                return (error);
                    339:        }
                    340:        /*
                    341:         * Put the new filesystem on the mount list after root.
                    342:         */
                    343:        cache_purge(vp);
                    344:        if (!error) {
1.128     fvdl      345:                vp->v_mountedhere = mp;
1.113     fvdl      346:                simple_lock(&mountlist_slock);
1.47      mycroft   347:                CIRCLEQ_INSERT_TAIL(&mountlist, mp, mnt_list);
1.113     fvdl      348:                simple_unlock(&mountlist_slock);
1.43      mycroft   349:                checkdirs(vp);
1.113     fvdl      350:                VOP_UNLOCK(vp, 0);
1.151     mycroft   351:                if ((mp->mnt_flag & (MNT_RDONLY | MNT_ASYNC)) == 0)
1.148     fvdl      352:                        error = vfs_allocate_syncvnode(mp);
1.113     fvdl      353:                vfs_unbusy(mp);
1.46      mycroft   354:                (void) VFS_STATFS(mp, &mp->mnt_stat, p);
1.113     fvdl      355:                if ((error = VFS_START(mp, 0, p)))
                    356:                        vrele(vp);
1.31      cgd       357:        } else {
1.128     fvdl      358:                vp->v_mountedhere = (struct mount *)0;
1.109     thorpej   359:                vfs->vfs_refcount--;
1.113     fvdl      360:                vfs_unbusy(mp);
1.31      cgd       361:                free((caddr_t)mp, M_MOUNT);
                    362:                vput(vp);
                    363:        }
                    364:        return (error);
                    365: }
                    366:
                    367: /*
1.43      mycroft   368:  * Scan all active processes to see if any of them have a current
                    369:  * or root directory onto which the new filesystem has just been
                    370:  * mounted. If so, replace them with the new mount point.
                    371:  */
1.63      christos  372: void
1.43      mycroft   373: checkdirs(olddp)
                    374:        struct vnode *olddp;
                    375: {
1.134     thorpej   376:        struct cwdinfo *cwdi;
1.43      mycroft   377:        struct vnode *newdp;
                    378:        struct proc *p;
                    379:
                    380:        if (olddp->v_usecount == 1)
                    381:                return;
                    382:        if (VFS_ROOT(olddp->v_mountedhere, &newdp))
                    383:                panic("mount: lost mount");
1.144     thorpej   384:        proclist_lock_read();
1.43      mycroft   385:        for (p = allproc.lh_first; p != 0; p = p->p_list.le_next) {
1.134     thorpej   386:                cwdi = p->p_cwdi;
                    387:                if (cwdi->cwdi_cdir == olddp) {
                    388:                        vrele(cwdi->cwdi_cdir);
1.43      mycroft   389:                        VREF(newdp);
1.134     thorpej   390:                        cwdi->cwdi_cdir = newdp;
1.43      mycroft   391:                }
1.134     thorpej   392:                if (cwdi->cwdi_rdir == olddp) {
                    393:                        vrele(cwdi->cwdi_rdir);
1.43      mycroft   394:                        VREF(newdp);
1.134     thorpej   395:                        cwdi->cwdi_rdir = newdp;
1.43      mycroft   396:                }
                    397:        }
1.143     thorpej   398:        proclist_unlock_read();
1.43      mycroft   399:        if (rootvnode == olddp) {
                    400:                vrele(rootvnode);
                    401:                VREF(newdp);
                    402:                rootvnode = newdp;
                    403:        }
                    404:        vput(newdp);
                    405: }
                    406:
                    407: /*
1.31      cgd       408:  * Unmount a file system.
                    409:  *
                    410:  * Note: unmount takes a path to the vnode mounted on as argument,
                    411:  * not special file (as before).
                    412:  */
                    413: /* ARGSUSED */
1.63      christos  414: int
1.57      mycroft   415: sys_unmount(p, v, retval)
1.31      cgd       416:        struct proc *p;
1.56      thorpej   417:        void *v;
                    418:        register_t *retval;
                    419: {
1.155     augustss  420:        struct sys_unmount_args /* {
1.74      cgd       421:                syscallarg(const char *) path;
1.35      cgd       422:                syscallarg(int) flags;
1.56      thorpej   423:        } */ *uap = v;
1.155     augustss  424:        struct vnode *vp;
1.31      cgd       425:        struct mount *mp;
                    426:        int error;
                    427:        struct nameidata nd;
                    428:
1.35      cgd       429:        NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
                    430:            SCARG(uap, path), p);
1.63      christos  431:        if ((error = namei(&nd)) != 0)
1.31      cgd       432:                return (error);
                    433:        vp = nd.ni_vp;
1.43      mycroft   434:        mp = vp->v_mount;
1.31      cgd       435:
                    436:        /*
1.43      mycroft   437:         * Only root, or the user that did the original mount is
                    438:         * permitted to unmount this filesystem.
1.31      cgd       439:         */
1.43      mycroft   440:        if ((mp->mnt_stat.f_owner != p->p_ucred->cr_uid) &&
1.93      enami     441:            (error = suser(p->p_ucred, &p->p_acflag)) != 0) {
1.31      cgd       442:                vput(vp);
                    443:                return (error);
                    444:        }
                    445:
                    446:        /*
1.47      mycroft   447:         * Don't allow unmounting the root file system.
                    448:         */
                    449:        if (mp->mnt_flag & MNT_ROOTFS) {
                    450:                vput(vp);
                    451:                return (EINVAL);
                    452:        }
                    453:
                    454:        /*
1.31      cgd       455:         * Must be the root of the filesystem
                    456:         */
                    457:        if ((vp->v_flag & VROOT) == 0) {
                    458:                vput(vp);
                    459:                return (EINVAL);
                    460:        }
                    461:        vput(vp);
1.78      fvdl      462:
1.113     fvdl      463:        if (vfs_busy(mp, 0, 0))
1.78      fvdl      464:                return (EBUSY);
                    465:
1.35      cgd       466:        return (dounmount(mp, SCARG(uap, flags), p));
1.31      cgd       467: }
                    468:
                    469: /*
1.78      fvdl      470:  * Do the actual file system unmount. File system is assumed to have been
                    471:  * marked busy by the caller.
1.31      cgd       472:  */
1.63      christos  473: int
1.31      cgd       474: dounmount(mp, flags, p)
1.155     augustss  475:        struct mount *mp;
1.31      cgd       476:        int flags;
                    477:        struct proc *p;
                    478: {
                    479:        struct vnode *coveredvp;
                    480:        int error;
1.140     sommerfe  481:        int async;
1.31      cgd       482:
1.113     fvdl      483:        simple_lock(&mountlist_slock);
1.148     fvdl      484:        vfs_unbusy(mp);
                    485:        /*
                    486:         * XXX Freeze syncer. This should really be done on a mountpoint
                    487:         * basis, but especially the softdep code possibly called from
                    488:         * the syncer doesn't exactly work on a per-mountpoint basis,
                    489:         * so the softdep code would become a maze of vfs_busy calls.
                    490:         */
                    491:        lockmgr(&syncer_lock, LK_EXCLUSIVE, NULL);
                    492:
1.31      cgd       493:        mp->mnt_flag |= MNT_UNMOUNT;
1.148     fvdl      494:        mp->mnt_unmounter = p;
1.113     fvdl      495:        lockmgr(&mp->mnt_lock, LK_DRAIN | LK_INTERLOCK, &mountlist_slock);
1.91      fvdl      496:        if (mp->mnt_flag & MNT_EXPUBLIC)
                    497:                vfs_setpublicfs(NULL, NULL, NULL);
1.141     sommerfe  498:        async = mp->mnt_flag & MNT_ASYNC;
1.151     mycroft   499:        mp->mnt_flag &= ~MNT_ASYNC;
1.31      cgd       500:        cache_purgevfs(mp);     /* remove cache entries for this file sys */
1.151     mycroft   501:        if (mp->mnt_syncer != NULL) {
1.148     fvdl      502:                vgone(mp->mnt_syncer);
1.151     mycroft   503:                mp->mnt_syncer = NULL;
                    504:        }
1.113     fvdl      505:        if (((mp->mnt_flag & MNT_RDONLY) ||
                    506:            (error = VFS_SYNC(mp, MNT_WAIT, p->p_ucred, p)) == 0) ||
1.31      cgd       507:            (flags & MNT_FORCE))
                    508:                error = VFS_UNMOUNT(mp, flags, p);
1.113     fvdl      509:        simple_lock(&mountlist_slock);
1.31      cgd       510:        if (error) {
1.151     mycroft   511:                if ((mp->mnt_flag & (MNT_RDONLY | MNT_ASYNC)) == 0)
1.148     fvdl      512:                        (void) vfs_allocate_syncvnode(mp);
1.113     fvdl      513:                mp->mnt_flag &= ~MNT_UNMOUNT;
1.148     fvdl      514:                mp->mnt_unmounter = NULL;
1.140     sommerfe  515:                mp->mnt_flag |= async;
1.113     fvdl      516:                lockmgr(&mp->mnt_lock, LK_RELEASE | LK_INTERLOCK | LK_REENABLE,
                    517:                    &mountlist_slock);
1.148     fvdl      518:                lockmgr(&syncer_lock, LK_RELEASE, NULL);
1.151     mycroft   519:                while (mp->mnt_wcnt > 0) {
1.113     fvdl      520:                        wakeup((caddr_t)mp);
1.148     fvdl      521:                        tsleep(&mp->mnt_wcnt, PVFS, "mntwcnt1", 0);
1.142     sommerfe  522:                }
                    523:                return (error);
1.113     fvdl      524:        }
                    525:        CIRCLEQ_REMOVE(&mountlist, mp, mnt_list);
                    526:        if ((coveredvp = mp->mnt_vnodecovered) != NULLVP) {
                    527:                coveredvp->v_mountedhere = NULL;
                    528:                vrele(coveredvp);
                    529:        }
                    530:        mp->mnt_op->vfs_refcount--;
                    531:        if (mp->mnt_vnodelist.lh_first != NULL)
                    532:                panic("unmount: dangling vnode");
1.142     sommerfe  533:        mp->mnt_flag |= MNT_GONE;
1.113     fvdl      534:        lockmgr(&mp->mnt_lock, LK_RELEASE | LK_INTERLOCK, &mountlist_slock);
1.148     fvdl      535:        lockmgr(&syncer_lock, LK_RELEASE, NULL);
1.142     sommerfe  536:        while(mp->mnt_wcnt > 0) {
1.113     fvdl      537:                wakeup((caddr_t)mp);
1.148     fvdl      538:                tsleep(&mp->mnt_wcnt, PVFS, "mntwcnt2", 0);
1.142     sommerfe  539:        }
1.113     fvdl      540:        free((caddr_t)mp, M_MOUNT);
                    541:        return (0);
1.31      cgd       542: }
                    543:
                    544: /*
                    545:  * Sync each mounted filesystem.
                    546:  */
                    547: #ifdef DEBUG
                    548: int syncprt = 0;
                    549: struct ctldebug debug0 = { "syncprt", &syncprt };
                    550: #endif
                    551:
                    552: /* ARGSUSED */
1.63      christos  553: int
1.57      mycroft   554: sys_sync(p, v, retval)
1.31      cgd       555:        struct proc *p;
1.57      mycroft   556:        void *v;
1.35      cgd       557:        register_t *retval;
1.31      cgd       558: {
1.155     augustss  559:        struct mount *mp, *nmp;
1.31      cgd       560:        int asyncflag;
                    561:
1.113     fvdl      562:        simple_lock(&mountlist_slock);
1.77      mikel     563:        for (mp = mountlist.cqh_last; mp != (void *)&mountlist; mp = nmp) {
1.113     fvdl      564:                if (vfs_busy(mp, LK_NOWAIT, &mountlist_slock)) {
                    565:                        nmp = mp->mnt_list.cqe_prev;
                    566:                        continue;
                    567:                }
                    568:                if ((mp->mnt_flag & MNT_RDONLY) == 0) {
1.31      cgd       569:                        asyncflag = mp->mnt_flag & MNT_ASYNC;
                    570:                        mp->mnt_flag &= ~MNT_ASYNC;
1.110     mrg       571:                        uvm_vnp_sync(mp);
1.31      cgd       572:                        VFS_SYNC(mp, MNT_NOWAIT, p->p_ucred, p);
                    573:                        if (asyncflag)
1.113     fvdl      574:                                 mp->mnt_flag |= MNT_ASYNC;
1.31      cgd       575:                }
1.113     fvdl      576:                simple_lock(&mountlist_slock);
                    577:                nmp = mp->mnt_list.cqe_prev;
                    578:                vfs_unbusy(mp);
                    579:
1.31      cgd       580:        }
1.113     fvdl      581:        simple_unlock(&mountlist_slock);
1.31      cgd       582: #ifdef DEBUG
                    583:        if (syncprt)
                    584:                vfs_bufstats();
                    585: #endif /* DEBUG */
                    586:        return (0);
                    587: }
                    588:
                    589: /*
                    590:  * Change filesystem quotas.
                    591:  */
                    592: /* ARGSUSED */
1.63      christos  593: int
1.57      mycroft   594: sys_quotactl(p, v, retval)
1.31      cgd       595:        struct proc *p;
1.56      thorpej   596:        void *v;
                    597:        register_t *retval;
                    598: {
1.155     augustss  599:        struct sys_quotactl_args /* {
1.74      cgd       600:                syscallarg(const char *) path;
1.35      cgd       601:                syscallarg(int) cmd;
                    602:                syscallarg(int) uid;
                    603:                syscallarg(caddr_t) arg;
1.56      thorpej   604:        } */ *uap = v;
1.155     augustss  605:        struct mount *mp;
1.31      cgd       606:        int error;
                    607:        struct nameidata nd;
                    608:
1.35      cgd       609:        NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
1.63      christos  610:        if ((error = namei(&nd)) != 0)
1.31      cgd       611:                return (error);
                    612:        mp = nd.ni_vp->v_mount;
                    613:        vrele(nd.ni_vp);
1.35      cgd       614:        return (VFS_QUOTACTL(mp, SCARG(uap, cmd), SCARG(uap, uid),
                    615:            SCARG(uap, arg), p));
1.31      cgd       616: }
                    617:
                    618: /*
                    619:  * Get filesystem statistics.
                    620:  */
                    621: /* ARGSUSED */
1.63      christos  622: int
1.57      mycroft   623: sys_statfs(p, v, retval)
1.31      cgd       624:        struct proc *p;
1.56      thorpej   625:        void *v;
                    626:        register_t *retval;
                    627: {
1.155     augustss  628:        struct sys_statfs_args /* {
1.74      cgd       629:                syscallarg(const char *) path;
1.35      cgd       630:                syscallarg(struct statfs *) buf;
1.56      thorpej   631:        } */ *uap = v;
1.155     augustss  632:        struct mount *mp;
                    633:        struct statfs *sp;
1.31      cgd       634:        int error;
                    635:        struct nameidata nd;
                    636:
1.35      cgd       637:        NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
1.63      christos  638:        if ((error = namei(&nd)) != 0)
1.31      cgd       639:                return (error);
                    640:        mp = nd.ni_vp->v_mount;
                    641:        sp = &mp->mnt_stat;
                    642:        vrele(nd.ni_vp);
1.63      christos  643:        if ((error = VFS_STATFS(mp, sp, p)) != 0)
1.31      cgd       644:                return (error);
                    645:        sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
1.148     fvdl      646:        sp->f_oflags = sp->f_flags & 0xffff;
1.74      cgd       647:        return (copyout(sp, SCARG(uap, buf), sizeof(*sp)));
1.31      cgd       648: }
                    649:
                    650: /*
                    651:  * Get filesystem statistics.
                    652:  */
                    653: /* ARGSUSED */
1.63      christos  654: int
1.57      mycroft   655: sys_fstatfs(p, v, retval)
1.31      cgd       656:        struct proc *p;
1.56      thorpej   657:        void *v;
                    658:        register_t *retval;
                    659: {
1.155     augustss  660:        struct sys_fstatfs_args /* {
1.35      cgd       661:                syscallarg(int) fd;
                    662:                syscallarg(struct statfs *) buf;
1.56      thorpej   663:        } */ *uap = v;
1.31      cgd       664:        struct file *fp;
                    665:        struct mount *mp;
1.155     augustss  666:        struct statfs *sp;
1.31      cgd       667:        int error;
                    668:
1.135     thorpej   669:        /* getvnode() will use the descriptor for us */
1.63      christos  670:        if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0)
1.31      cgd       671:                return (error);
1.62      mycroft   672:        mp = ((struct vnode *)fp->f_data)->v_mount;
1.31      cgd       673:        sp = &mp->mnt_stat;
1.63      christos  674:        if ((error = VFS_STATFS(mp, sp, p)) != 0)
1.135     thorpej   675:                goto out;
1.31      cgd       676:        sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
1.148     fvdl      677:        sp->f_oflags = sp->f_flags & 0xffff;
1.135     thorpej   678:        error = copyout(sp, SCARG(uap, buf), sizeof(*sp));
                    679:  out:
                    680:        FILE_UNUSE(fp, p);
                    681:        return (error);
1.31      cgd       682: }
                    683:
                    684: /*
                    685:  * Get statistics on all filesystems.
                    686:  */
1.63      christos  687: int
1.57      mycroft   688: sys_getfsstat(p, v, retval)
1.31      cgd       689:        struct proc *p;
1.56      thorpej   690:        void *v;
                    691:        register_t *retval;
                    692: {
1.155     augustss  693:        struct sys_getfsstat_args /* {
1.35      cgd       694:                syscallarg(struct statfs *) buf;
                    695:                syscallarg(long) bufsize;
                    696:                syscallarg(int) flags;
1.56      thorpej   697:        } */ *uap = v;
1.155     augustss  698:        struct mount *mp, *nmp;
                    699:        struct statfs *sp;
1.31      cgd       700:        caddr_t sfsp;
                    701:        long count, maxcount, error;
                    702:
1.35      cgd       703:        maxcount = SCARG(uap, bufsize) / sizeof(struct statfs);
                    704:        sfsp = (caddr_t)SCARG(uap, buf);
1.113     fvdl      705:        simple_lock(&mountlist_slock);
                    706:        count = 0;
                    707:        for (mp = mountlist.cqh_first; mp != (void *)&mountlist; mp = nmp) {
                    708:                if (vfs_busy(mp, LK_NOWAIT, &mountlist_slock)) {
                    709:                        nmp = mp->mnt_list.cqe_next;
                    710:                        continue;
                    711:                }
                    712:                if (sfsp && count < maxcount) {
1.31      cgd       713:                        sp = &mp->mnt_stat;
                    714:                        /*
1.148     fvdl      715:                         * If MNT_NOWAIT or MNT_LAZY is specified, do not
                    716:                         * refresh the fsstat cache. MNT_WAIT or MNT_LAXY
                    717:                         * overrides MNT_NOWAIT.
1.31      cgd       718:                         */
1.148     fvdl      719:                        if (SCARG(uap, flags) != MNT_NOWAIT &&
                    720:                            SCARG(uap, flags) != MNT_LAZY &&
                    721:                            (SCARG(uap, flags) == MNT_WAIT ||
                    722:                             SCARG(uap, flags) == 0) &&
1.113     fvdl      723:                            (error = VFS_STATFS(mp, sp, p)) != 0) {
                    724:                                simple_lock(&mountlist_slock);
                    725:                                nmp = mp->mnt_list.cqe_next;
                    726:                                vfs_unbusy(mp);
1.31      cgd       727:                                continue;
1.113     fvdl      728:                        }
1.31      cgd       729:                        sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
1.148     fvdl      730:                        sp->f_oflags = sp->f_flags & 0xffff;
1.74      cgd       731:                        error = copyout(sp, sfsp, sizeof(*sp));
1.133     mycroft   732:                        if (error) {
                    733:                                vfs_unbusy(mp);
1.31      cgd       734:                                return (error);
1.133     mycroft   735:                        }
1.31      cgd       736:                        sfsp += sizeof(*sp);
                    737:                }
                    738:                count++;
1.113     fvdl      739:                simple_lock(&mountlist_slock);
                    740:                nmp = mp->mnt_list.cqe_next;
                    741:                vfs_unbusy(mp);
1.31      cgd       742:        }
1.113     fvdl      743:        simple_unlock(&mountlist_slock);
1.31      cgd       744:        if (sfsp && count > maxcount)
                    745:                *retval = maxcount;
                    746:        else
                    747:                *retval = count;
                    748:        return (0);
                    749: }
                    750:
                    751: /*
                    752:  * Change current working directory to a given file descriptor.
                    753:  */
                    754: /* ARGSUSED */
1.63      christos  755: int
1.57      mycroft   756: sys_fchdir(p, v, retval)
1.31      cgd       757:        struct proc *p;
1.56      thorpej   758:        void *v;
                    759:        register_t *retval;
                    760: {
1.57      mycroft   761:        struct sys_fchdir_args /* {
1.35      cgd       762:                syscallarg(int) fd;
1.56      thorpej   763:        } */ *uap = v;
1.134     thorpej   764:        struct filedesc *fdp = p->p_fd;
                    765:        struct cwdinfo *cwdi = p->p_cwdi;
1.43      mycroft   766:        struct vnode *vp, *tdp;
                    767:        struct mount *mp;
1.31      cgd       768:        struct file *fp;
                    769:        int error;
                    770:
1.135     thorpej   771:        /* getvnode() will use the descriptor for us */
1.63      christos  772:        if ((error = getvnode(fdp, SCARG(uap, fd), &fp)) != 0)
1.31      cgd       773:                return (error);
1.62      mycroft   774:        vp = (struct vnode *)fp->f_data;
1.131     sommerfe  775:
1.43      mycroft   776:        VREF(vp);
1.113     fvdl      777:        vn_lock(vp,  LK_EXCLUSIVE | LK_RETRY);
1.31      cgd       778:        if (vp->v_type != VDIR)
                    779:                error = ENOTDIR;
                    780:        else
1.89      mycroft   781:                error = VOP_ACCESS(vp, VEXEC, p->p_ucred, p);
1.43      mycroft   782:        while (!error && (mp = vp->v_mountedhere) != NULL) {
1.113     fvdl      783:                if (vfs_busy(mp, 0, 0))
1.43      mycroft   784:                        continue;
1.113     fvdl      785:                error = VFS_ROOT(mp, &tdp);
                    786:                vfs_unbusy(mp);
                    787:                if (error)
1.43      mycroft   788:                        break;
                    789:                vput(vp);
                    790:                vp = tdp;
                    791:        }
                    792:        if (error) {
1.113     fvdl      793:                vput(vp);
1.135     thorpej   794:                goto out;
1.43      mycroft   795:        }
1.113     fvdl      796:        VOP_UNLOCK(vp, 0);
1.131     sommerfe  797:
                    798:        /*
                    799:         * Disallow changing to a directory not under the process's
                    800:         * current root directory (if there is one).
                    801:         */
1.135     thorpej   802:        if (cwdi->cwdi_rdir && !vn_isunder(vp, NULL, p)) {
1.131     sommerfe  803:                vrele(vp);
1.135     thorpej   804:                error = EPERM;  /* operation not permitted */
                    805:                goto out;
1.131     sommerfe  806:        }
                    807:
1.134     thorpej   808:        vrele(cwdi->cwdi_cdir);
                    809:        cwdi->cwdi_cdir = vp;
1.135     thorpej   810:  out:
                    811:        FILE_UNUSE(fp, p);
                    812:        return (error);
1.31      cgd       813: }
                    814:
                    815: /*
1.131     sommerfe  816:  * Change this process's notion of the root directory to a given file descriptor.
                    817:  */
                    818:
                    819: int
                    820: sys_fchroot(p, v, retval)
                    821:        struct proc *p;
                    822:        void *v;
                    823:        register_t *retval;
                    824: {
                    825:        struct sys_fchroot_args *uap = v;
1.134     thorpej   826:        struct filedesc *fdp = p->p_fd;
                    827:        struct cwdinfo *cwdi = p->p_cwdi;
1.131     sommerfe  828:        struct vnode    *vp;
                    829:        struct file     *fp;
                    830:        int              error;
                    831:
                    832:        if ((error = suser(p->p_ucred, &p->p_acflag)) != 0)
                    833:                return error;
1.135     thorpej   834:        /* getvnode() will use the descriptor for us */
1.131     sommerfe  835:        if ((error = getvnode(fdp, SCARG(uap, fd), &fp)) != 0)
                    836:                return error;
                    837:        vp = (struct vnode *) fp->f_data;
                    838:        vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
                    839:        if (vp->v_type != VDIR)
                    840:                error = ENOTDIR;
                    841:        else
                    842:                error = VOP_ACCESS(vp, VEXEC, p->p_ucred, p);
                    843:        VOP_UNLOCK(vp, 0);
                    844:        if (error)
1.135     thorpej   845:                goto out;
1.131     sommerfe  846:        VREF(vp);
                    847:
                    848:        /*
                    849:         * Prevent escaping from chroot by putting the root under
                    850:         * the working directory.  Silently chdir to / if we aren't
                    851:         * already there.
                    852:         */
1.134     thorpej   853:        if (!vn_isunder(cwdi->cwdi_cdir, vp, p)) {
1.131     sommerfe  854:                /*
                    855:                 * XXX would be more failsafe to change directory to a
                    856:                 * deadfs node here instead
                    857:                 */
1.134     thorpej   858:                vrele(cwdi->cwdi_cdir);
1.131     sommerfe  859:                VREF(vp);
1.134     thorpej   860:                cwdi->cwdi_cdir = vp;
1.131     sommerfe  861:        }
                    862:
1.134     thorpej   863:        if (cwdi->cwdi_rdir != NULL)
                    864:                vrele(cwdi->cwdi_rdir);
                    865:        cwdi->cwdi_rdir = vp;
1.135     thorpej   866:  out:
                    867:        FILE_UNUSE(fp, p);
                    868:        return (error);
1.131     sommerfe  869: }
                    870:
                    871:
                    872:
                    873: /*
1.31      cgd       874:  * Change current working directory (``.'').
                    875:  */
                    876: /* ARGSUSED */
1.63      christos  877: int
1.57      mycroft   878: sys_chdir(p, v, retval)
1.31      cgd       879:        struct proc *p;
1.56      thorpej   880:        void *v;
                    881:        register_t *retval;
                    882: {
1.57      mycroft   883:        struct sys_chdir_args /* {
1.74      cgd       884:                syscallarg(const char *) path;
1.56      thorpej   885:        } */ *uap = v;
1.134     thorpej   886:        struct cwdinfo *cwdi = p->p_cwdi;
1.31      cgd       887:        int error;
                    888:        struct nameidata nd;
                    889:
1.35      cgd       890:        NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
                    891:            SCARG(uap, path), p);
1.63      christos  892:        if ((error = change_dir(&nd, p)) != 0)
1.31      cgd       893:                return (error);
1.134     thorpej   894:        vrele(cwdi->cwdi_cdir);
                    895:        cwdi->cwdi_cdir = nd.ni_vp;
1.31      cgd       896:        return (0);
                    897: }
                    898:
                    899: /*
                    900:  * Change notion of root (``/'') directory.
                    901:  */
                    902: /* ARGSUSED */
1.63      christos  903: int
1.57      mycroft   904: sys_chroot(p, v, retval)
1.31      cgd       905:        struct proc *p;
1.56      thorpej   906:        void *v;
                    907:        register_t *retval;
                    908: {
1.57      mycroft   909:        struct sys_chroot_args /* {
1.74      cgd       910:                syscallarg(const char *) path;
1.56      thorpej   911:        } */ *uap = v;
1.134     thorpej   912:        struct cwdinfo *cwdi = p->p_cwdi;
1.131     sommerfe  913:        struct vnode *vp;
1.31      cgd       914:        int error;
                    915:        struct nameidata nd;
                    916:
1.63      christos  917:        if ((error = suser(p->p_ucred, &p->p_acflag)) != 0)
1.31      cgd       918:                return (error);
1.35      cgd       919:        NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
                    920:            SCARG(uap, path), p);
1.63      christos  921:        if ((error = change_dir(&nd, p)) != 0)
1.31      cgd       922:                return (error);
1.134     thorpej   923:        if (cwdi->cwdi_rdir != NULL)
                    924:                vrele(cwdi->cwdi_rdir);
1.131     sommerfe  925:        vp = nd.ni_vp;
1.134     thorpej   926:        cwdi->cwdi_rdir = vp;
1.131     sommerfe  927:
                    928:        /*
                    929:         * Prevent escaping from chroot by putting the root under
                    930:         * the working directory.  Silently chdir to / if we aren't
                    931:         * already there.
                    932:         */
1.134     thorpej   933:        if (!vn_isunder(cwdi->cwdi_cdir, vp, p)) {
1.131     sommerfe  934:                /*
                    935:                 * XXX would be more failsafe to change directory to a
                    936:                 * deadfs node here instead
                    937:                 */
1.134     thorpej   938:                vrele(cwdi->cwdi_cdir);
1.131     sommerfe  939:                VREF(vp);
1.134     thorpej   940:                cwdi->cwdi_cdir = vp;
1.131     sommerfe  941:        }
                    942:
1.31      cgd       943:        return (0);
                    944: }
                    945:
                    946: /*
                    947:  * Common routine for chroot and chdir.
                    948:  */
                    949: static int
                    950: change_dir(ndp, p)
1.155     augustss  951:        struct nameidata *ndp;
1.31      cgd       952:        struct proc *p;
                    953: {
                    954:        struct vnode *vp;
                    955:        int error;
                    956:
1.63      christos  957:        if ((error = namei(ndp)) != 0)
1.31      cgd       958:                return (error);
                    959:        vp = ndp->ni_vp;
                    960:        if (vp->v_type != VDIR)
                    961:                error = ENOTDIR;
                    962:        else
1.89      mycroft   963:                error = VOP_ACCESS(vp, VEXEC, p->p_ucred, p);
1.113     fvdl      964:
1.31      cgd       965:        if (error)
1.113     fvdl      966:                vput(vp);
                    967:        else
                    968:                VOP_UNLOCK(vp, 0);
1.31      cgd       969:        return (error);
                    970: }
                    971:
                    972: /*
                    973:  * Check permissions, allocate an open file structure,
                    974:  * and call the device open routine if any.
                    975:  */
1.63      christos  976: int
1.57      mycroft   977: sys_open(p, v, retval)
1.31      cgd       978:        struct proc *p;
1.56      thorpej   979:        void *v;
                    980:        register_t *retval;
                    981: {
1.155     augustss  982:        struct sys_open_args /* {
1.74      cgd       983:                syscallarg(const char *) path;
1.35      cgd       984:                syscallarg(int) flags;
                    985:                syscallarg(int) mode;
1.56      thorpej   986:        } */ *uap = v;
1.134     thorpej   987:        struct cwdinfo *cwdi = p->p_cwdi;
1.135     thorpej   988:        struct filedesc *fdp = p->p_fd;
                    989:        struct file *fp;
                    990:        struct vnode *vp;
1.31      cgd       991:        int flags, cmode;
                    992:        int type, indx, error;
                    993:        struct flock lf;
                    994:        struct nameidata nd;
                    995:
1.104     mycroft   996:        flags = FFLAGS(SCARG(uap, flags));
                    997:        if ((flags & (FREAD | FWRITE)) == 0)
                    998:                return (EINVAL);
1.135     thorpej   999:        /* falloc() will use the file descriptor for us */
                   1000:        if ((error = falloc(p, &fp, &indx)) != 0)
1.31      cgd      1001:                return (error);
1.134     thorpej  1002:        cmode = ((SCARG(uap, mode) &~ cwdi->cwdi_cmask) & ALLPERMS) &~ S_ISTXT;
1.35      cgd      1003:        NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
1.31      cgd      1004:        p->p_dupfd = -indx - 1;                 /* XXX check for fdopen */
1.63      christos 1005:        if ((error = vn_open(&nd, flags, cmode)) != 0) {
1.135     thorpej  1006:                FILE_UNUSE(fp, p);
1.31      cgd      1007:                ffree(fp);
1.45      mycroft  1008:                if ((error == ENODEV || error == ENXIO) &&
                   1009:                    p->p_dupfd >= 0 &&                  /* XXX from fdopen */
                   1010:                    (error =
1.135     thorpej  1011:                        dupfdopen(p, indx, p->p_dupfd, flags, error)) == 0) {
1.45      mycroft  1012:                        *retval = indx;
                   1013:                        return (0);
                   1014:                }
                   1015:                if (error == ERESTART)
1.44      mycroft  1016:                        error = EINTR;
1.153     thorpej  1017:                fdremove(fdp, indx);
1.31      cgd      1018:                return (error);
                   1019:        }
                   1020:        p->p_dupfd = 0;
                   1021:        vp = nd.ni_vp;
                   1022:        fp->f_flag = flags & FMASK;
                   1023:        fp->f_type = DTYPE_VNODE;
                   1024:        fp->f_ops = &vnops;
                   1025:        fp->f_data = (caddr_t)vp;
                   1026:        if (flags & (O_EXLOCK | O_SHLOCK)) {
                   1027:                lf.l_whence = SEEK_SET;
                   1028:                lf.l_start = 0;
                   1029:                lf.l_len = 0;
                   1030:                if (flags & O_EXLOCK)
                   1031:                        lf.l_type = F_WRLCK;
                   1032:                else
                   1033:                        lf.l_type = F_RDLCK;
                   1034:                type = F_FLOCK;
                   1035:                if ((flags & FNONBLOCK) == 0)
                   1036:                        type |= F_WAIT;
1.113     fvdl     1037:                VOP_UNLOCK(vp, 0);
1.63      christos 1038:                error = VOP_ADVLOCK(vp, (caddr_t)fp, F_SETLK, &lf, type);
                   1039:                if (error) {
1.31      cgd      1040:                        (void) vn_close(vp, fp->f_flag, fp->f_cred, p);
1.135     thorpej  1041:                        FILE_UNUSE(fp, p);
1.31      cgd      1042:                        ffree(fp);
1.153     thorpej  1043:                        fdremove(fdp, indx);
1.31      cgd      1044:                        return (error);
                   1045:                }
1.113     fvdl     1046:                vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
1.31      cgd      1047:                fp->f_flag |= FHASLOCK;
                   1048:        }
1.113     fvdl     1049:        VOP_UNLOCK(vp, 0);
1.31      cgd      1050:        *retval = indx;
1.135     thorpej  1051:        FILE_UNUSE(fp, p);
1.31      cgd      1052:        return (0);
1.137     wrstuden 1053: }
                   1054:
                   1055: /*
                   1056:  * Get file handle system call
                   1057:  */
                   1058: int
                   1059: sys_getfh(p, v, retval)
                   1060:        struct proc *p;
1.155     augustss 1061:        void *v;
1.137     wrstuden 1062:        register_t *retval;
                   1063: {
1.155     augustss 1064:        struct sys_getfh_args /* {
1.137     wrstuden 1065:                syscallarg(char *) fname;
                   1066:                syscallarg(fhandle_t *) fhp;
                   1067:        } */ *uap = v;
1.155     augustss 1068:        struct vnode *vp;
1.137     wrstuden 1069:        fhandle_t fh;
                   1070:        int error;
                   1071:        struct nameidata nd;
                   1072:
                   1073:        /*
                   1074:         * Must be super user
                   1075:         */
                   1076:        error = suser(p->p_ucred, &p->p_acflag);
                   1077:        if (error)
                   1078:                return (error);
                   1079:        NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
                   1080:            SCARG(uap, fname), p);
                   1081:        error = namei(&nd);
                   1082:        if (error)
                   1083:                return (error);
                   1084:        vp = nd.ni_vp;
                   1085:        memset((caddr_t)&fh, 0, sizeof(fh));
                   1086:        fh.fh_fsid = vp->v_mount->mnt_stat.f_fsid;
                   1087:        error = VFS_VPTOFH(vp, &fh.fh_fid);
                   1088:        vput(vp);
                   1089:        if (error)
                   1090:                return (error);
                   1091:        error = copyout((caddr_t)&fh, (caddr_t)SCARG(uap, fhp), sizeof (fh));
                   1092:        return (error);
                   1093: }
                   1094:
                   1095: /*
                   1096:  * Open a file given a file handle.
                   1097:  *
                   1098:  * Check permissions, allocate an open file structure,
                   1099:  * and call the device open routine if any.
                   1100:  */
                   1101: int
                   1102: sys_fhopen(p, v, retval)
                   1103:        struct proc *p;
                   1104:        void *v;
                   1105:        register_t *retval;
                   1106: {
1.155     augustss 1107:        struct sys_fhopen_args /* {
1.137     wrstuden 1108:                syscallarg(const fhandle_t *) fhp;
                   1109:                syscallarg(int) flags;
                   1110:        } */ *uap = v;
                   1111:        struct filedesc *fdp = p->p_fd;
                   1112:        struct file *fp;
1.139     wrstuden 1113:        struct vnode *vp = NULL;
1.137     wrstuden 1114:        struct mount *mp;
                   1115:        struct ucred *cred = p->p_ucred;
                   1116:        int flags;
                   1117:        struct file *nfp;
                   1118:        int type, indx, error=0;
                   1119:        struct flock lf;
                   1120:        struct vattr va;
                   1121:        fhandle_t fh;
                   1122:
                   1123:        /*
                   1124:         * Must be super user
                   1125:         */
                   1126:        if ((error = suser(p->p_ucred, &p->p_acflag)))
                   1127:                return (error);
                   1128:
                   1129:        flags = FFLAGS(SCARG(uap, flags));
                   1130:        if ((flags & (FREAD | FWRITE)) == 0)
                   1131:                return (EINVAL);
                   1132:        if ((flags & O_CREAT))
                   1133:                return (EINVAL);
1.139     wrstuden 1134:        /* falloc() will use the file descriptor for us */
1.137     wrstuden 1135:        if ((error = falloc(p, &nfp, &indx)) != 0)
                   1136:                return (error);
                   1137:        fp = nfp;
                   1138:        if ((error = copyin(SCARG(uap, fhp), &fh, sizeof(fhandle_t))) != 0)
1.139     wrstuden 1139:                goto bad;
                   1140:
                   1141:        if ((mp = vfs_getvfs(&fh.fh_fsid)) == NULL) {
                   1142:                error = ESTALE;
                   1143:                goto bad;
                   1144:        }
1.137     wrstuden 1145:
1.139     wrstuden 1146:        if ((error = VFS_FHTOVP(mp, &fh.fh_fid, &vp)) != 0) {
                   1147:                vp = NULL;      /* most likely unnecessary sanity for bad: */
                   1148:                goto bad;
                   1149:        }
1.137     wrstuden 1150:
                   1151:        /* Now do an effective vn_open */
                   1152:
                   1153:        if (vp->v_type == VSOCK) {
                   1154:                error = EOPNOTSUPP;
                   1155:                goto bad;
                   1156:        }
                   1157:        if (flags & FREAD) {
                   1158:                if ((error = VOP_ACCESS(vp, VREAD, cred, p)) != 0)
                   1159:                        goto bad;
                   1160:        }
                   1161:        if (flags & (FWRITE | O_TRUNC)) {
                   1162:                if (vp->v_type == VDIR) {
                   1163:                        error = EISDIR;
                   1164:                        goto bad;
                   1165:                }
                   1166:                if ((error = vn_writechk(vp)) != 0 ||
                   1167:                    (error = VOP_ACCESS(vp, VWRITE, cred, p)) != 0)
                   1168:                        goto bad;
                   1169:        }
                   1170:        if (flags & O_TRUNC) {
                   1171:                VOP_UNLOCK(vp, 0);                      /* XXX */
                   1172:                VOP_LEASE(vp, p, cred, LEASE_WRITE);
                   1173:                vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);   /* XXX */
                   1174:                VATTR_NULL(&va);
                   1175:                va.va_size = 0;
                   1176:                if ((error = VOP_SETATTR(vp, &va, cred, p)) != 0)
                   1177:                        goto bad;
                   1178:        }
                   1179:        if ((error = VOP_OPEN(vp, flags, cred, p)) != 0)
                   1180:                goto bad;
                   1181:        if (flags & FWRITE)
                   1182:                vp->v_writecount++;
                   1183:
                   1184:        /* done with modified vn_open, now finish what sys_open does. */
                   1185:
                   1186:        fp->f_flag = flags & FMASK;
                   1187:        fp->f_type = DTYPE_VNODE;
                   1188:        fp->f_ops = &vnops;
                   1189:        fp->f_data = (caddr_t)vp;
                   1190:        if (flags & (O_EXLOCK | O_SHLOCK)) {
                   1191:                lf.l_whence = SEEK_SET;
                   1192:                lf.l_start = 0;
                   1193:                lf.l_len = 0;
                   1194:                if (flags & O_EXLOCK)
                   1195:                        lf.l_type = F_WRLCK;
                   1196:                else
                   1197:                        lf.l_type = F_RDLCK;
                   1198:                type = F_FLOCK;
                   1199:                if ((flags & FNONBLOCK) == 0)
                   1200:                        type |= F_WAIT;
                   1201:                VOP_UNLOCK(vp, 0);
                   1202:                error = VOP_ADVLOCK(vp, (caddr_t)fp, F_SETLK, &lf, type);
                   1203:                if (error) {
                   1204:                        (void) vn_close(vp, fp->f_flag, fp->f_cred, p);
1.139     wrstuden 1205:                        FILE_UNUSE(fp, p);
1.137     wrstuden 1206:                        ffree(fp);
1.153     thorpej  1207:                        fdremove(fdp, indx);
1.137     wrstuden 1208:                        return (error);
                   1209:                }
                   1210:                vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
                   1211:                fp->f_flag |= FHASLOCK;
                   1212:        }
                   1213:        VOP_UNLOCK(vp, 0);
                   1214:        *retval = indx;
1.139     wrstuden 1215:        FILE_UNUSE(fp, p);
1.137     wrstuden 1216:        return (0);
1.139     wrstuden 1217:
1.137     wrstuden 1218: bad:
1.139     wrstuden 1219:        FILE_UNUSE(fp, p);
                   1220:        ffree(fp);
1.153     thorpej  1221:        fdremove(fdp, indx);
1.139     wrstuden 1222:        if (vp != NULL)
                   1223:                vput(vp);
1.137     wrstuden 1224:        return (error);
                   1225: }
                   1226:
                   1227: /* ARGSUSED */
                   1228: int
                   1229: sys_fhstat(p, v, retval)
                   1230:        struct proc *p;
                   1231:        void *v;
                   1232:        register_t *retval;
                   1233: {
1.155     augustss 1234:        struct sys_fhstat_args /* {
1.137     wrstuden 1235:                syscallarg(const fhandle_t *) fhp;
                   1236:                syscallarg(struct stat *) sb;
                   1237:        } */ *uap = v;
                   1238:        struct stat sb;
                   1239:        int error;
                   1240:        fhandle_t fh;
                   1241:        struct mount *mp;
                   1242:        struct vnode *vp;
                   1243:
                   1244:        /*
                   1245:         * Must be super user
                   1246:         */
                   1247:        if ((error = suser(p->p_ucred, &p->p_acflag)))
                   1248:                return (error);
                   1249:
                   1250:        if ((error = copyin(SCARG(uap, fhp), &fh, sizeof(fhandle_t))) != 0)
                   1251:                return (error);
                   1252:
                   1253:        if ((mp = vfs_getvfs(&fh.fh_fsid)) == NULL)
                   1254:                return (ESTALE);
                   1255:        if ((error = VFS_FHTOVP(mp, &fh.fh_fid, &vp)))
                   1256:                return (error);
                   1257:        error = vn_stat(vp, &sb, p);
                   1258:        vput(vp);
                   1259:        if (error)
                   1260:                return (error);
                   1261:        error = copyout(&sb, SCARG(uap, sb), sizeof(sb));
                   1262:        return (error);
                   1263: }
                   1264:
                   1265: /* ARGSUSED */
                   1266: int
                   1267: sys_fhstatfs(p, v, retval)
                   1268:        struct proc *p;
                   1269:        void *v;
                   1270:        register_t *retval;
                   1271: {
1.155     augustss 1272:        struct sys_fhstatfs_args /*
1.137     wrstuden 1273:                syscallarg(const fhandle_t *) fhp;
                   1274:                syscallarg(struct statfs *) buf;
                   1275:        } */ *uap = v;
                   1276:        struct statfs sp;
                   1277:        fhandle_t fh;
                   1278:        struct mount *mp;
                   1279:        struct vnode *vp;
                   1280:        int error;
                   1281:
                   1282:        /*
                   1283:         * Must be super user
                   1284:         */
                   1285:        if ((error = suser(p->p_ucred, &p->p_acflag)))
                   1286:                return (error);
                   1287:
                   1288:        if ((error = copyin(SCARG(uap, fhp), &fh, sizeof(fhandle_t))) != 0)
                   1289:                return (error);
                   1290:
                   1291:        if ((mp = vfs_getvfs(&fh.fh_fsid)) == NULL)
                   1292:                return (ESTALE);
                   1293:        if ((error = VFS_FHTOVP(mp, &fh.fh_fid, &vp)))
                   1294:                return (error);
                   1295:        mp = vp->v_mount;
                   1296:        vput(vp);
                   1297:        if ((error = VFS_STATFS(mp, &sp, p)) != 0)
                   1298:                return (error);
                   1299:        sp.f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
1.148     fvdl     1300:        sp.f_oflags = sp.f_flags & 0xffff;
1.137     wrstuden 1301:        return (copyout(&sp, SCARG(uap, buf), sizeof(sp)));
1.31      cgd      1302: }
                   1303:
                   1304: /*
                   1305:  * Create a special file.
                   1306:  */
                   1307: /* ARGSUSED */
1.63      christos 1308: int
1.57      mycroft  1309: sys_mknod(p, v, retval)
1.31      cgd      1310:        struct proc *p;
1.56      thorpej  1311:        void *v;
                   1312:        register_t *retval;
                   1313: {
1.155     augustss 1314:        struct sys_mknod_args /* {
1.74      cgd      1315:                syscallarg(const char *) path;
1.35      cgd      1316:                syscallarg(int) mode;
                   1317:                syscallarg(int) dev;
1.56      thorpej  1318:        } */ *uap = v;
1.155     augustss 1319:        struct vnode *vp;
1.31      cgd      1320:        struct vattr vattr;
                   1321:        int error;
1.63      christos 1322:        int whiteout = 0;
1.31      cgd      1323:        struct nameidata nd;
                   1324:
1.63      christos 1325:        if ((error = suser(p->p_ucred, &p->p_acflag)) != 0)
1.31      cgd      1326:                return (error);
1.35      cgd      1327:        NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, SCARG(uap, path), p);
1.63      christos 1328:        if ((error = namei(&nd)) != 0)
1.31      cgd      1329:                return (error);
                   1330:        vp = nd.ni_vp;
1.43      mycroft  1331:        if (vp != NULL)
1.31      cgd      1332:                error = EEXIST;
1.43      mycroft  1333:        else {
                   1334:                VATTR_NULL(&vattr);
1.94      enami    1335:                vattr.va_mode =
1.134     thorpej  1336:                    (SCARG(uap, mode) & ALLPERMS) &~ p->p_cwdi->cwdi_cmask;
1.43      mycroft  1337:                vattr.va_rdev = SCARG(uap, dev);
                   1338:                whiteout = 0;
                   1339:
                   1340:                switch (SCARG(uap, mode) & S_IFMT) {
                   1341:                case S_IFMT:    /* used by badsect to flag bad sectors */
                   1342:                        vattr.va_type = VBAD;
                   1343:                        break;
                   1344:                case S_IFCHR:
                   1345:                        vattr.va_type = VCHR;
                   1346:                        break;
                   1347:                case S_IFBLK:
                   1348:                        vattr.va_type = VBLK;
                   1349:                        break;
                   1350:                case S_IFWHT:
                   1351:                        whiteout = 1;
                   1352:                        break;
                   1353:                default:
                   1354:                        error = EINVAL;
                   1355:                        break;
                   1356:                }
1.31      cgd      1357:        }
1.43      mycroft  1358:        if (!error) {
                   1359:                VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
                   1360:                if (whiteout) {
                   1361:                        error = VOP_WHITEOUT(nd.ni_dvp, &nd.ni_cnd, CREATE);
                   1362:                        if (error)
                   1363:                                VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
                   1364:                        vput(nd.ni_dvp);
                   1365:                } else {
                   1366:                        error = VOP_MKNOD(nd.ni_dvp, &nd.ni_vp,
                   1367:                                                &nd.ni_cnd, &vattr);
                   1368:                }
                   1369:        } else {
                   1370:                VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
                   1371:                if (nd.ni_dvp == vp)
                   1372:                        vrele(nd.ni_dvp);
                   1373:                else
                   1374:                        vput(nd.ni_dvp);
                   1375:                if (vp)
                   1376:                        vrele(vp);
1.31      cgd      1377:        }
                   1378:        return (error);
                   1379: }
                   1380:
                   1381: /*
                   1382:  * Create a named pipe.
                   1383:  */
                   1384: /* ARGSUSED */
1.63      christos 1385: int
1.57      mycroft  1386: sys_mkfifo(p, v, retval)
1.31      cgd      1387:        struct proc *p;
1.56      thorpej  1388:        void *v;
                   1389:        register_t *retval;
                   1390: {
1.155     augustss 1391:        struct sys_mkfifo_args /* {
1.74      cgd      1392:                syscallarg(const char *) path;
1.35      cgd      1393:                syscallarg(int) mode;
1.56      thorpej  1394:        } */ *uap = v;
1.31      cgd      1395:        struct vattr vattr;
                   1396:        int error;
                   1397:        struct nameidata nd;
                   1398:
1.35      cgd      1399:        NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, SCARG(uap, path), p);
1.63      christos 1400:        if ((error = namei(&nd)) != 0)
1.31      cgd      1401:                return (error);
                   1402:        if (nd.ni_vp != NULL) {
                   1403:                VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
                   1404:                if (nd.ni_dvp == nd.ni_vp)
                   1405:                        vrele(nd.ni_dvp);
                   1406:                else
                   1407:                        vput(nd.ni_dvp);
                   1408:                vrele(nd.ni_vp);
                   1409:                return (EEXIST);
                   1410:        }
                   1411:        VATTR_NULL(&vattr);
                   1412:        vattr.va_type = VFIFO;
1.134     thorpej  1413:        vattr.va_mode = (SCARG(uap, mode) & ALLPERMS) &~ p->p_cwdi->cwdi_cmask;
1.42      mycroft  1414:        VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
1.31      cgd      1415:        return (VOP_MKNOD(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr));
                   1416: }
                   1417:
                   1418: /*
                   1419:  * Make a hard file link.
                   1420:  */
                   1421: /* ARGSUSED */
1.63      christos 1422: int
1.57      mycroft  1423: sys_link(p, v, retval)
1.31      cgd      1424:        struct proc *p;
1.56      thorpej  1425:        void *v;
                   1426:        register_t *retval;
                   1427: {
1.155     augustss 1428:        struct sys_link_args /* {
1.74      cgd      1429:                syscallarg(const char *) path;
                   1430:                syscallarg(const char *) link;
1.56      thorpej  1431:        } */ *uap = v;
1.155     augustss 1432:        struct vnode *vp;
1.31      cgd      1433:        struct nameidata nd;
                   1434:        int error;
                   1435:
1.147     hubertf  1436:        NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
1.63      christos 1437:        if ((error = namei(&nd)) != 0)
1.31      cgd      1438:                return (error);
                   1439:        vp = nd.ni_vp;
1.66      mycroft  1440:        NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, SCARG(uap, link), p);
                   1441:        if ((error = namei(&nd)) != 0)
                   1442:                goto out;
                   1443:        if (nd.ni_vp) {
                   1444:                VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
                   1445:                if (nd.ni_dvp == nd.ni_vp)
                   1446:                        vrele(nd.ni_dvp);
                   1447:                else
                   1448:                        vput(nd.ni_dvp);
                   1449:                vrele(nd.ni_vp);
                   1450:                error = EEXIST;
                   1451:                goto out;
1.31      cgd      1452:        }
1.66      mycroft  1453:        VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
                   1454:        VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
                   1455:        error = VOP_LINK(nd.ni_dvp, vp, &nd.ni_cnd);
                   1456: out:
1.31      cgd      1457:        vrele(vp);
                   1458:        return (error);
                   1459: }
                   1460:
                   1461: /*
                   1462:  * Make a symbolic link.
                   1463:  */
                   1464: /* ARGSUSED */
1.63      christos 1465: int
1.57      mycroft  1466: sys_symlink(p, v, retval)
1.31      cgd      1467:        struct proc *p;
1.56      thorpej  1468:        void *v;
                   1469:        register_t *retval;
                   1470: {
1.155     augustss 1471:        struct sys_symlink_args /* {
1.74      cgd      1472:                syscallarg(const char *) path;
                   1473:                syscallarg(const char *) link;
1.56      thorpej  1474:        } */ *uap = v;
1.31      cgd      1475:        struct vattr vattr;
                   1476:        char *path;
                   1477:        int error;
                   1478:        struct nameidata nd;
                   1479:
                   1480:        MALLOC(path, char *, MAXPATHLEN, M_NAMEI, M_WAITOK);
1.63      christos 1481:        error = copyinstr(SCARG(uap, path), path, MAXPATHLEN, NULL);
                   1482:        if (error)
1.43      mycroft  1483:                goto out;
1.35      cgd      1484:        NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, SCARG(uap, link), p);
1.63      christos 1485:        if ((error = namei(&nd)) != 0)
1.43      mycroft  1486:                goto out;
1.31      cgd      1487:        if (nd.ni_vp) {
                   1488:                VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
                   1489:                if (nd.ni_dvp == nd.ni_vp)
                   1490:                        vrele(nd.ni_dvp);
                   1491:                else
                   1492:                        vput(nd.ni_dvp);
                   1493:                vrele(nd.ni_vp);
                   1494:                error = EEXIST;
1.43      mycroft  1495:                goto out;
1.31      cgd      1496:        }
                   1497:        VATTR_NULL(&vattr);
1.134     thorpej  1498:        vattr.va_mode = ACCESSPERMS &~ p->p_cwdi->cwdi_cmask;
1.42      mycroft  1499:        VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
1.31      cgd      1500:        error = VOP_SYMLINK(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr, path);
1.43      mycroft  1501: out:
1.31      cgd      1502:        FREE(path, M_NAMEI);
                   1503:        return (error);
                   1504: }
                   1505:
                   1506: /*
1.43      mycroft  1507:  * Delete a whiteout from the filesystem.
                   1508:  */
                   1509: /* ARGSUSED */
1.63      christos 1510: int
1.57      mycroft  1511: sys_undelete(p, v, retval)
1.43      mycroft  1512:        struct proc *p;
1.56      thorpej  1513:        void *v;
                   1514:        register_t *retval;
                   1515: {
1.155     augustss 1516:        struct sys_undelete_args /* {
1.74      cgd      1517:                syscallarg(const char *) path;
1.56      thorpej  1518:        } */ *uap = v;
1.43      mycroft  1519:        int error;
                   1520:        struct nameidata nd;
                   1521:
                   1522:        NDINIT(&nd, DELETE, LOCKPARENT|DOWHITEOUT, UIO_USERSPACE,
                   1523:            SCARG(uap, path), p);
                   1524:        error = namei(&nd);
                   1525:        if (error)
                   1526:                return (error);
                   1527:
                   1528:        if (nd.ni_vp != NULLVP || !(nd.ni_cnd.cn_flags & ISWHITEOUT)) {
                   1529:                VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
                   1530:                if (nd.ni_dvp == nd.ni_vp)
                   1531:                        vrele(nd.ni_dvp);
                   1532:                else
                   1533:                        vput(nd.ni_dvp);
                   1534:                if (nd.ni_vp)
                   1535:                        vrele(nd.ni_vp);
                   1536:                return (EEXIST);
                   1537:        }
                   1538:
                   1539:        VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
1.63      christos 1540:        if ((error = VOP_WHITEOUT(nd.ni_dvp, &nd.ni_cnd, DELETE)) != 0)
1.43      mycroft  1541:                VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
                   1542:        vput(nd.ni_dvp);
                   1543:        return (error);
                   1544: }
                   1545:
                   1546: /*
1.31      cgd      1547:  * Delete a name from the filesystem.
                   1548:  */
                   1549: /* ARGSUSED */
1.63      christos 1550: int
1.57      mycroft  1551: sys_unlink(p, v, retval)
1.31      cgd      1552:        struct proc *p;
1.56      thorpej  1553:        void *v;
                   1554:        register_t *retval;
                   1555: {
1.57      mycroft  1556:        struct sys_unlink_args /* {
1.74      cgd      1557:                syscallarg(const char *) path;
1.56      thorpej  1558:        } */ *uap = v;
1.155     augustss 1559:        struct vnode *vp;
1.31      cgd      1560:        int error;
                   1561:        struct nameidata nd;
                   1562:
1.67      mycroft  1563:        NDINIT(&nd, DELETE, LOCKPARENT | LOCKLEAF, UIO_USERSPACE,
                   1564:            SCARG(uap, path), p);
1.63      christos 1565:        if ((error = namei(&nd)) != 0)
1.31      cgd      1566:                return (error);
                   1567:        vp = nd.ni_vp;
                   1568:
1.66      mycroft  1569:        /*
                   1570:         * The root of a mounted filesystem cannot be deleted.
                   1571:         */
                   1572:        if (vp->v_flag & VROOT) {
1.43      mycroft  1573:                VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
                   1574:                if (nd.ni_dvp == vp)
                   1575:                        vrele(nd.ni_dvp);
                   1576:                else
                   1577:                        vput(nd.ni_dvp);
1.66      mycroft  1578:                vput(vp);
                   1579:                error = EBUSY;
                   1580:                goto out;
1.31      cgd      1581:        }
1.66      mycroft  1582:
1.110     mrg      1583:        (void)uvm_vnp_uncache(vp);
1.69      fvdl     1584:
1.66      mycroft  1585:        VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
1.67      mycroft  1586:        VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
1.66      mycroft  1587:        error = VOP_REMOVE(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd);
                   1588: out:
1.31      cgd      1589:        return (error);
                   1590: }
                   1591:
                   1592: /*
                   1593:  * Reposition read/write file offset.
                   1594:  */
1.63      christos 1595: int
1.57      mycroft  1596: sys_lseek(p, v, retval)
1.31      cgd      1597:        struct proc *p;
1.56      thorpej  1598:        void *v;
                   1599:        register_t *retval;
                   1600: {
1.155     augustss 1601:        struct sys_lseek_args /* {
1.35      cgd      1602:                syscallarg(int) fd;
                   1603:                syscallarg(int) pad;
                   1604:                syscallarg(off_t) offset;
                   1605:                syscallarg(int) whence;
1.56      thorpej  1606:        } */ *uap = v;
1.31      cgd      1607:        struct ucred *cred = p->p_ucred;
1.155     augustss 1608:        struct filedesc *fdp = p->p_fd;
                   1609:        struct file *fp;
1.84      kleink   1610:        struct vnode *vp;
1.31      cgd      1611:        struct vattr vattr;
1.155     augustss 1612:        off_t newoff;
1.31      cgd      1613:        int error;
                   1614:
1.35      cgd      1615:        if ((u_int)SCARG(uap, fd) >= fdp->fd_nfiles ||
1.135     thorpej  1616:            (fp = fdp->fd_ofiles[SCARG(uap, fd)]) == NULL ||
                   1617:            (fp->f_iflags & FIF_WANTCLOSE) != 0)
1.31      cgd      1618:                return (EBADF);
1.84      kleink   1619:
1.135     thorpej  1620:        FILE_USE(fp);
                   1621:
1.84      kleink   1622:        vp = (struct vnode *)fp->f_data;
1.135     thorpej  1623:        if (fp->f_type != DTYPE_VNODE || vp->v_type == VFIFO) {
                   1624:                error = ESPIPE;
                   1625:                goto out;
                   1626:        }
1.84      kleink   1627:
1.35      cgd      1628:        switch (SCARG(uap, whence)) {
1.92      kleink   1629:        case SEEK_CUR:
1.84      kleink   1630:                newoff = fp->f_offset + SCARG(uap, offset);
1.31      cgd      1631:                break;
1.92      kleink   1632:        case SEEK_END:
1.85      kleink   1633:                error = VOP_GETATTR(vp, &vattr, cred, p);
1.63      christos 1634:                if (error)
1.135     thorpej  1635:                        goto out;
1.84      kleink   1636:                newoff = SCARG(uap, offset) + vattr.va_size;
1.31      cgd      1637:                break;
1.92      kleink   1638:        case SEEK_SET:
1.84      kleink   1639:                newoff = SCARG(uap, offset);
1.31      cgd      1640:                break;
                   1641:        default:
1.135     thorpej  1642:                error = EINVAL;
                   1643:                goto out;
1.31      cgd      1644:        }
1.84      kleink   1645:        if ((error = VOP_SEEK(vp, fp->f_offset, newoff, cred)) != 0)
1.135     thorpej  1646:                goto out;
1.84      kleink   1647:
                   1648:        *(off_t *)retval = fp->f_offset = newoff;
1.135     thorpej  1649:  out:
                   1650:        FILE_UNUSE(fp, p);
                   1651:        return (error);
1.120     thorpej  1652: }
                   1653:
                   1654: /*
                   1655:  * Positional read system call.
                   1656:  */
                   1657: int
                   1658: sys_pread(p, v, retval)
                   1659:        struct proc *p;
                   1660:        void *v;
                   1661:        register_t *retval;
                   1662: {
                   1663:        struct sys_pread_args /* {
                   1664:                syscallarg(int) fd;
                   1665:                syscallarg(void *) buf;
                   1666:                syscallarg(size_t) nbyte;
                   1667:                syscallarg(off_t) offset;
                   1668:        } */ *uap = v;
                   1669:        struct filedesc *fdp = p->p_fd;
                   1670:        struct file *fp;
                   1671:        struct vnode *vp;
                   1672:        off_t offset;
                   1673:        int error, fd = SCARG(uap, fd);
                   1674:
                   1675:        if ((u_int)fd >= fdp->fd_nfiles ||
                   1676:            (fp = fdp->fd_ofiles[fd]) == NULL ||
1.135     thorpej  1677:            (fp->f_iflags & FIF_WANTCLOSE) != 0 ||
1.120     thorpej  1678:            (fp->f_flag & FREAD) == 0)
                   1679:                return (EBADF);
                   1680:
1.135     thorpej  1681:        FILE_USE(fp);
                   1682:
1.120     thorpej  1683:        vp = (struct vnode *)fp->f_data;
1.135     thorpej  1684:        if (fp->f_type != DTYPE_VNODE || vp->v_type == VFIFO) {
                   1685:                error = ESPIPE;
                   1686:                goto out;
                   1687:        }
1.120     thorpej  1688:
                   1689:        offset = SCARG(uap, offset);
                   1690:
                   1691:        /*
                   1692:         * XXX This works because no file systems actually
                   1693:         * XXX take any action on the seek operation.
                   1694:         */
                   1695:        if ((error = VOP_SEEK(vp, fp->f_offset, offset, fp->f_cred)) != 0)
1.135     thorpej  1696:                goto out;
1.120     thorpej  1697:
1.135     thorpej  1698:        /* dofileread() will unuse the descriptor for us */
1.120     thorpej  1699:        return (dofileread(p, fd, fp, SCARG(uap, buf), SCARG(uap, nbyte),
                   1700:            &offset, 0, retval));
1.135     thorpej  1701:
                   1702:  out:
                   1703:        FILE_UNUSE(fp, p);
                   1704:        return (error);
1.120     thorpej  1705: }
                   1706:
                   1707: /*
                   1708:  * Positional scatter read system call.
                   1709:  */
                   1710: int
                   1711: sys_preadv(p, v, retval)
                   1712:        struct proc *p;
                   1713:        void *v;
                   1714:        register_t *retval;
                   1715: {
                   1716:        struct sys_preadv_args /* {
                   1717:                syscallarg(int) fd;
                   1718:                syscallarg(const struct iovec *) iovp;
                   1719:                syscallarg(int) iovcnt;
                   1720:                syscallarg(off_t) offset;
                   1721:        } */ *uap = v;
                   1722:        struct filedesc *fdp = p->p_fd;
                   1723:        struct file *fp;
                   1724:        struct vnode *vp;
                   1725:        off_t offset;
                   1726:        int error, fd = SCARG(uap, fd);
                   1727:
                   1728:        if ((u_int)fd >= fdp->fd_nfiles ||
                   1729:            (fp = fdp->fd_ofiles[fd]) == NULL ||
1.135     thorpej  1730:            (fp->f_iflags & FIF_WANTCLOSE) != 0 ||
1.120     thorpej  1731:            (fp->f_flag & FREAD) == 0)
                   1732:                return (EBADF);
                   1733:
1.135     thorpej  1734:        FILE_USE(fp);
                   1735:
1.120     thorpej  1736:        vp = (struct vnode *)fp->f_data;
1.135     thorpej  1737:        if (fp->f_type != DTYPE_VNODE || vp->v_type == VFIFO) {
                   1738:                error = ESPIPE;
                   1739:                goto out;
                   1740:        }
1.120     thorpej  1741:
                   1742:        offset = SCARG(uap, offset);
                   1743:
                   1744:        /*
                   1745:         * XXX This works because no file systems actually
                   1746:         * XXX take any action on the seek operation.
                   1747:         */
                   1748:        if ((error = VOP_SEEK(vp, fp->f_offset, offset, fp->f_cred)) != 0)
1.135     thorpej  1749:                goto out;
1.120     thorpej  1750:
1.135     thorpej  1751:        /* dofilereadv() will unuse the descriptor for us */
1.120     thorpej  1752:        return (dofilereadv(p, fd, fp, SCARG(uap, iovp), SCARG(uap, iovcnt),
                   1753:            &offset, 0, retval));
1.135     thorpej  1754:
                   1755:  out:
                   1756:        FILE_UNUSE(fp, p);
                   1757:        return (error);
1.120     thorpej  1758: }
                   1759:
                   1760: /*
                   1761:  * Positional write system call.
                   1762:  */
                   1763: int
                   1764: sys_pwrite(p, v, retval)
                   1765:        struct proc *p;
                   1766:        void *v;
                   1767:        register_t *retval;
                   1768: {
                   1769:        struct sys_pwrite_args /* {
                   1770:                syscallarg(int) fd;
                   1771:                syscallarg(const void *) buf;
                   1772:                syscallarg(size_t) nbyte;
                   1773:                syscallarg(off_t) offset;
                   1774:        } */ *uap = v;
                   1775:        struct filedesc *fdp = p->p_fd;
                   1776:        struct file *fp;
                   1777:        struct vnode *vp;
                   1778:        off_t offset;
                   1779:        int error, fd = SCARG(uap, fd);
                   1780:
                   1781:        if ((u_int)fd >= fdp->fd_nfiles ||
                   1782:            (fp = fdp->fd_ofiles[fd]) == NULL ||
1.135     thorpej  1783:            (fp->f_iflags & FIF_WANTCLOSE) != 0 ||
1.120     thorpej  1784:            (fp->f_flag & FWRITE) == 0)
                   1785:                return (EBADF);
                   1786:
1.135     thorpej  1787:        FILE_USE(fp);
                   1788:
1.120     thorpej  1789:        vp = (struct vnode *)fp->f_data;
1.135     thorpej  1790:        if (fp->f_type != DTYPE_VNODE || vp->v_type == VFIFO) {
                   1791:                error = ESPIPE;
                   1792:                goto out;
                   1793:        }
1.120     thorpej  1794:
                   1795:        offset = SCARG(uap, offset);
                   1796:
                   1797:        /*
                   1798:         * XXX This works because no file systems actually
                   1799:         * XXX take any action on the seek operation.
                   1800:         */
                   1801:        if ((error = VOP_SEEK(vp, fp->f_offset, offset, fp->f_cred)) != 0)
1.135     thorpej  1802:                goto out;
1.120     thorpej  1803:
1.135     thorpej  1804:        /* dofilewrite() will unuse the descriptor for us */
1.120     thorpej  1805:        return (dofilewrite(p, fd, fp, SCARG(uap, buf), SCARG(uap, nbyte),
                   1806:            &offset, 0, retval));
1.135     thorpej  1807:
                   1808:  out:
                   1809:        FILE_UNUSE(fp, p);
                   1810:        return (error);
1.120     thorpej  1811: }
                   1812:
                   1813: /*
                   1814:  * Positional gather write system call.
                   1815:  */
                   1816: int
                   1817: sys_pwritev(p, v, retval)
                   1818:        struct proc *p;
                   1819:        void *v;
                   1820:        register_t *retval;
                   1821: {
                   1822:        struct sys_pwritev_args /* {
                   1823:                syscallarg(int) fd;
                   1824:                syscallarg(const struct iovec *) iovp;
                   1825:                syscallarg(int) iovcnt;
                   1826:                syscallarg(off_t) offset;
                   1827:        } */ *uap = v;
                   1828:        struct filedesc *fdp = p->p_fd;
                   1829:        struct file *fp;
                   1830:        struct vnode *vp;
                   1831:        off_t offset;
                   1832:        int error, fd = SCARG(uap, fd);
                   1833:
                   1834:        if ((u_int)fd >= fdp->fd_nfiles ||
                   1835:            (fp = fdp->fd_ofiles[fd]) == NULL ||
1.135     thorpej  1836:            (fp->f_iflags & FIF_WANTCLOSE) != 0 ||
1.120     thorpej  1837:            (fp->f_flag & FWRITE) == 0)
                   1838:                return (EBADF);
                   1839:
1.135     thorpej  1840:        FILE_USE(fp);
                   1841:
1.120     thorpej  1842:        vp = (struct vnode *)fp->f_data;
1.135     thorpej  1843:        if (fp->f_type != DTYPE_VNODE || vp->v_type == VFIFO) {
                   1844:                error = ESPIPE;
                   1845:                goto out;
                   1846:        }
1.120     thorpej  1847:
                   1848:        offset = SCARG(uap, offset);
                   1849:
                   1850:        /*
                   1851:         * XXX This works because no file systems actually
                   1852:         * XXX take any action on the seek operation.
                   1853:         */
                   1854:        if ((error = VOP_SEEK(vp, fp->f_offset, offset, fp->f_cred)) != 0)
1.135     thorpej  1855:                goto out;
1.120     thorpej  1856:
1.135     thorpej  1857:        /* dofilewritev() will unuse the descriptor for us */
1.120     thorpej  1858:        return (dofilewritev(p, fd, fp, SCARG(uap, iovp), SCARG(uap, iovcnt),
                   1859:            &offset, 0, retval));
1.135     thorpej  1860:
                   1861:  out:
                   1862:        FILE_UNUSE(fp, p);
                   1863:        return (error);
1.31      cgd      1864: }
                   1865:
                   1866: /*
                   1867:  * Check access permissions.
                   1868:  */
1.63      christos 1869: int
1.57      mycroft  1870: sys_access(p, v, retval)
1.31      cgd      1871:        struct proc *p;
1.56      thorpej  1872:        void *v;
                   1873:        register_t *retval;
                   1874: {
1.155     augustss 1875:        struct sys_access_args /* {
1.74      cgd      1876:                syscallarg(const char *) path;
1.35      cgd      1877:                syscallarg(int) flags;
1.56      thorpej  1878:        } */ *uap = v;
1.155     augustss 1879:        struct ucred *cred = p->p_ucred;
                   1880:        struct vnode *vp;
1.31      cgd      1881:        int error, flags, t_gid, t_uid;
                   1882:        struct nameidata nd;
                   1883:
                   1884:        t_uid = cred->cr_uid;
1.53      jtc      1885:        t_gid = cred->cr_gid;
1.31      cgd      1886:        cred->cr_uid = p->p_cred->p_ruid;
1.53      jtc      1887:        cred->cr_gid = p->p_cred->p_rgid;
1.35      cgd      1888:        NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
                   1889:            SCARG(uap, path), p);
1.63      christos 1890:        if ((error = namei(&nd)) != 0)
1.31      cgd      1891:                goto out1;
                   1892:        vp = nd.ni_vp;
                   1893:
                   1894:        /* Flags == 0 means only check for existence. */
1.35      cgd      1895:        if (SCARG(uap, flags)) {
1.31      cgd      1896:                flags = 0;
1.35      cgd      1897:                if (SCARG(uap, flags) & R_OK)
1.31      cgd      1898:                        flags |= VREAD;
1.35      cgd      1899:                if (SCARG(uap, flags) & W_OK)
1.31      cgd      1900:                        flags |= VWRITE;
1.89      mycroft  1901:                if (SCARG(uap, flags) & X_OK)
                   1902:                        flags |= VEXEC;
1.138     is       1903:
                   1904:                error = VOP_ACCESS(vp, flags, cred, p);
                   1905:                if (!error && (flags & VWRITE))
                   1906:                        error = vn_writechk(vp);
1.31      cgd      1907:        }
                   1908:        vput(vp);
                   1909: out1:
                   1910:        cred->cr_uid = t_uid;
1.53      jtc      1911:        cred->cr_gid = t_gid;
1.31      cgd      1912:        return (error);
                   1913: }
                   1914:
                   1915: /*
                   1916:  * Get file status; this version follows links.
                   1917:  */
                   1918: /* ARGSUSED */
1.63      christos 1919: int
1.105     thorpej  1920: sys___stat13(p, v, retval)
1.31      cgd      1921:        struct proc *p;
1.56      thorpej  1922:        void *v;
                   1923:        register_t *retval;
                   1924: {
1.155     augustss 1925:        struct sys___stat13_args /* {
1.74      cgd      1926:                syscallarg(const char *) path;
1.35      cgd      1927:                syscallarg(struct stat *) ub;
1.56      thorpej  1928:        } */ *uap = v;
1.31      cgd      1929:        struct stat sb;
                   1930:        int error;
                   1931:        struct nameidata nd;
                   1932:
1.35      cgd      1933:        NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
                   1934:            SCARG(uap, path), p);
1.63      christos 1935:        if ((error = namei(&nd)) != 0)
1.31      cgd      1936:                return (error);
                   1937:        error = vn_stat(nd.ni_vp, &sb, p);
                   1938:        vput(nd.ni_vp);
                   1939:        if (error)
                   1940:                return (error);
1.122     perry    1941:        error = copyout(&sb, SCARG(uap, ub), sizeof(sb));
1.31      cgd      1942:        return (error);
                   1943: }
                   1944:
                   1945: /*
                   1946:  * Get file status; this version does not follow links.
                   1947:  */
                   1948: /* ARGSUSED */
1.63      christos 1949: int
1.105     thorpej  1950: sys___lstat13(p, v, retval)
1.31      cgd      1951:        struct proc *p;
1.56      thorpej  1952:        void *v;
                   1953:        register_t *retval;
                   1954: {
1.155     augustss 1955:        struct sys___lstat13_args /* {
1.74      cgd      1956:                syscallarg(const char *) path;
1.35      cgd      1957:                syscallarg(struct stat *) ub;
1.56      thorpej  1958:        } */ *uap = v;
1.65      mycroft  1959:        struct stat sb;
1.31      cgd      1960:        int error;
                   1961:        struct nameidata nd;
                   1962:
1.65      mycroft  1963:        NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF, UIO_USERSPACE,
1.35      cgd      1964:            SCARG(uap, path), p);
1.63      christos 1965:        if ((error = namei(&nd)) != 0)
1.31      cgd      1966:                return (error);
1.65      mycroft  1967:        error = vn_stat(nd.ni_vp, &sb, p);
                   1968:        vput(nd.ni_vp);
1.64      jtc      1969:        if (error)
                   1970:                return (error);
1.122     perry    1971:        error = copyout(&sb, SCARG(uap, ub), sizeof(sb));
1.31      cgd      1972:        return (error);
                   1973: }
                   1974:
                   1975: /*
                   1976:  * Get configurable pathname variables.
                   1977:  */
                   1978: /* ARGSUSED */
1.63      christos 1979: int
1.57      mycroft  1980: sys_pathconf(p, v, retval)
1.31      cgd      1981:        struct proc *p;
1.56      thorpej  1982:        void *v;
                   1983:        register_t *retval;
                   1984: {
1.155     augustss 1985:        struct sys_pathconf_args /* {
1.74      cgd      1986:                syscallarg(const char *) path;
1.35      cgd      1987:                syscallarg(int) name;
1.56      thorpej  1988:        } */ *uap = v;
1.31      cgd      1989:        int error;
                   1990:        struct nameidata nd;
                   1991:
1.35      cgd      1992:        NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
                   1993:            SCARG(uap, path), p);
1.63      christos 1994:        if ((error = namei(&nd)) != 0)
1.31      cgd      1995:                return (error);
1.35      cgd      1996:        error = VOP_PATHCONF(nd.ni_vp, SCARG(uap, name), retval);
1.31      cgd      1997:        vput(nd.ni_vp);
                   1998:        return (error);
                   1999: }
                   2000:
                   2001: /*
                   2002:  * Return target name of a symbolic link.
                   2003:  */
                   2004: /* ARGSUSED */
1.63      christos 2005: int
1.57      mycroft  2006: sys_readlink(p, v, retval)
1.31      cgd      2007:        struct proc *p;
1.56      thorpej  2008:        void *v;
                   2009:        register_t *retval;
                   2010: {
1.155     augustss 2011:        struct sys_readlink_args /* {
1.74      cgd      2012:                syscallarg(const char *) path;
1.35      cgd      2013:                syscallarg(char *) buf;
1.115     kleink   2014:                syscallarg(size_t) count;
1.56      thorpej  2015:        } */ *uap = v;
1.155     augustss 2016:        struct vnode *vp;
1.31      cgd      2017:        struct iovec aiov;
                   2018:        struct uio auio;
                   2019:        int error;
                   2020:        struct nameidata nd;
                   2021:
1.35      cgd      2022:        NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF, UIO_USERSPACE,
                   2023:            SCARG(uap, path), p);
1.63      christos 2024:        if ((error = namei(&nd)) != 0)
1.31      cgd      2025:                return (error);
                   2026:        vp = nd.ni_vp;
                   2027:        if (vp->v_type != VLNK)
                   2028:                error = EINVAL;
1.106     enami    2029:        else if (!(vp->v_mount->mnt_flag & MNT_SYMPERM) ||
                   2030:            (error = VOP_ACCESS(vp, VREAD, p->p_ucred, p)) == 0) {
1.35      cgd      2031:                aiov.iov_base = SCARG(uap, buf);
                   2032:                aiov.iov_len = SCARG(uap, count);
1.31      cgd      2033:                auio.uio_iov = &aiov;
                   2034:                auio.uio_iovcnt = 1;
                   2035:                auio.uio_offset = 0;
                   2036:                auio.uio_rw = UIO_READ;
                   2037:                auio.uio_segflg = UIO_USERSPACE;
                   2038:                auio.uio_procp = p;
1.35      cgd      2039:                auio.uio_resid = SCARG(uap, count);
1.31      cgd      2040:                error = VOP_READLINK(vp, &auio, p->p_ucred);
                   2041:        }
                   2042:        vput(vp);
1.35      cgd      2043:        *retval = SCARG(uap, count) - auio.uio_resid;
1.31      cgd      2044:        return (error);
                   2045: }
                   2046:
                   2047: /*
                   2048:  * Change flags of a file given a path name.
                   2049:  */
                   2050: /* ARGSUSED */
1.63      christos 2051: int
1.57      mycroft  2052: sys_chflags(p, v, retval)
1.31      cgd      2053:        struct proc *p;
1.56      thorpej  2054:        void *v;
                   2055:        register_t *retval;
                   2056: {
1.155     augustss 2057:        struct sys_chflags_args /* {
1.74      cgd      2058:                syscallarg(const char *) path;
                   2059:                syscallarg(u_long) flags;
1.56      thorpej  2060:        } */ *uap = v;
1.155     augustss 2061:        struct vnode *vp;
1.31      cgd      2062:        struct vattr vattr;
                   2063:        int error;
                   2064:        struct nameidata nd;
                   2065:
1.35      cgd      2066:        NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
1.63      christos 2067:        if ((error = namei(&nd)) != 0)
1.31      cgd      2068:                return (error);
                   2069:        vp = nd.ni_vp;
1.42      mycroft  2070:        VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
1.113     fvdl     2071:        vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
1.146     christos 2072:        /* Non-superusers cannot change the flags on devices, even if they
                   2073:           own them. */
                   2074:        if (suser(p->p_ucred, &p->p_acflag)) {
                   2075:                if ((error = VOP_GETATTR(vp, &vattr, p->p_ucred, p)) != 0)
                   2076:                        goto out;
                   2077:                if (vattr.va_type == VCHR || vattr.va_type == VBLK) {
                   2078:                        error = EINVAL;
                   2079:                        goto out;
                   2080:                }
                   2081:        }
1.113     fvdl     2082:        VATTR_NULL(&vattr);
                   2083:        vattr.va_flags = SCARG(uap, flags);
                   2084:        error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
1.146     christos 2085: out:
1.31      cgd      2086:        vput(vp);
                   2087:        return (error);
                   2088: }
                   2089:
                   2090: /*
                   2091:  * Change flags of a file given a file descriptor.
                   2092:  */
                   2093: /* ARGSUSED */
1.63      christos 2094: int
1.57      mycroft  2095: sys_fchflags(p, v, retval)
1.31      cgd      2096:        struct proc *p;
1.56      thorpej  2097:        void *v;
                   2098:        register_t *retval;
                   2099: {
1.155     augustss 2100:        struct sys_fchflags_args /* {
1.35      cgd      2101:                syscallarg(int) fd;
1.74      cgd      2102:                syscallarg(u_long) flags;
1.56      thorpej  2103:        } */ *uap = v;
1.31      cgd      2104:        struct vattr vattr;
                   2105:        struct vnode *vp;
                   2106:        struct file *fp;
                   2107:        int error;
                   2108:
1.135     thorpej  2109:        /* getvnode() will use the descriptor for us */
1.63      christos 2110:        if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0)
1.31      cgd      2111:                return (error);
1.62      mycroft  2112:        vp = (struct vnode *)fp->f_data;
1.42      mycroft  2113:        VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
1.113     fvdl     2114:        vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
1.146     christos 2115:        /* Non-superusers cannot change the flags on devices, even if they
                   2116:           own them. */
                   2117:        if (suser(p->p_ucred, &p->p_acflag)) {
                   2118:                if ((error = VOP_GETATTR(vp, &vattr, p->p_ucred, p))
                   2119:                    != 0)
                   2120:                        goto out;
                   2121:                if (vattr.va_type == VCHR || vattr.va_type == VBLK) {
                   2122:                        error = EINVAL;
                   2123:                        goto out;
                   2124:                }
                   2125:        }
1.113     fvdl     2126:        VATTR_NULL(&vattr);
                   2127:        vattr.va_flags = SCARG(uap, flags);
                   2128:        error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
1.146     christos 2129: out:
1.113     fvdl     2130:        VOP_UNLOCK(vp, 0);
1.135     thorpej  2131:        FILE_UNUSE(fp, p);
1.156     mrg      2132:        return (error);
                   2133: }
                   2134:
                   2135: /*
                   2136:  * Change flags of a file given a file descriptor; this version does
                   2137:  * not follow links.
                   2138:  */
                   2139: int
                   2140: sys_lchflags(p, v, retval)
                   2141:        struct proc *p;
                   2142:        void *v;
                   2143:        register_t *retval;
                   2144: {
                   2145:        register struct sys_chflags_args /* {
                   2146:                syscallarg(const char *) path;
                   2147:                syscallarg(u_long) flags;
                   2148:        } */ *uap = v;
                   2149:        register struct vnode *vp;
                   2150:        struct vattr vattr;
                   2151:        int error;
                   2152:        struct nameidata nd;
                   2153:
                   2154:        NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
                   2155:        if ((error = namei(&nd)) != 0)
                   2156:                return (error);
                   2157:        vp = nd.ni_vp;
                   2158:        VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
                   2159:        vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
                   2160:        /* Non-superusers cannot change the flags on devices, even if they
                   2161:           own them. */
                   2162:        if (suser(p->p_ucred, &p->p_acflag)) {
                   2163:                if ((error = VOP_GETATTR(vp, &vattr, p->p_ucred, p)) != 0)
                   2164:                        goto out;
                   2165:                if (vattr.va_type == VCHR || vattr.va_type == VBLK) {
                   2166:                        error = EINVAL;
                   2167:                        goto out;
                   2168:                }
                   2169:        }
                   2170:        VATTR_NULL(&vattr);
                   2171:        vattr.va_flags = SCARG(uap, flags);
                   2172:        error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
                   2173: out:
                   2174:        vput(vp);
1.31      cgd      2175:        return (error);
                   2176: }
                   2177:
                   2178: /*
1.98      enami    2179:  * Change mode of a file given path name; this version follows links.
1.31      cgd      2180:  */
                   2181: /* ARGSUSED */
1.63      christos 2182: int
1.57      mycroft  2183: sys_chmod(p, v, retval)
1.31      cgd      2184:        struct proc *p;
1.56      thorpej  2185:        void *v;
                   2186:        register_t *retval;
                   2187: {
1.155     augustss 2188:        struct sys_chmod_args /* {
1.74      cgd      2189:                syscallarg(const char *) path;
1.35      cgd      2190:                syscallarg(int) mode;
1.56      thorpej  2191:        } */ *uap = v;
1.31      cgd      2192:        int error;
                   2193:        struct nameidata nd;
                   2194:
1.35      cgd      2195:        NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
1.63      christos 2196:        if ((error = namei(&nd)) != 0)
1.31      cgd      2197:                return (error);
1.97      enami    2198:
                   2199:        error = change_mode(nd.ni_vp, SCARG(uap, mode), p);
                   2200:
                   2201:        vrele(nd.ni_vp);
1.31      cgd      2202:        return (error);
                   2203: }
                   2204:
                   2205: /*
                   2206:  * Change mode of a file given a file descriptor.
                   2207:  */
                   2208: /* ARGSUSED */
1.63      christos 2209: int
1.57      mycroft  2210: sys_fchmod(p, v, retval)
1.31      cgd      2211:        struct proc *p;
1.56      thorpej  2212:        void *v;
                   2213:        register_t *retval;
                   2214: {
1.155     augustss 2215:        struct sys_fchmod_args /* {
1.35      cgd      2216:                syscallarg(int) fd;
                   2217:                syscallarg(int) mode;
1.56      thorpej  2218:        } */ *uap = v;
1.31      cgd      2219:        struct file *fp;
                   2220:        int error;
                   2221:
1.135     thorpej  2222:        /* getvnode() will use the descriptor for us */
1.63      christos 2223:        if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0)
1.31      cgd      2224:                return (error);
1.97      enami    2225:
1.135     thorpej  2226:        error = change_mode((struct vnode *)fp->f_data, SCARG(uap, mode), p);
                   2227:        FILE_UNUSE(fp, p);
                   2228:        return (error);
1.97      enami    2229: }
                   2230:
                   2231: /*
1.98      enami    2232:  * Change mode of a file given path name; this version does not follow links.
                   2233:  */
                   2234: /* ARGSUSED */
                   2235: int
                   2236: sys_lchmod(p, v, retval)
                   2237:        struct proc *p;
                   2238:        void *v;
                   2239:        register_t *retval;
                   2240: {
1.155     augustss 2241:        struct sys_lchmod_args /* {
1.98      enami    2242:                syscallarg(const char *) path;
                   2243:                syscallarg(int) mode;
                   2244:        } */ *uap = v;
                   2245:        int error;
                   2246:        struct nameidata nd;
                   2247:
                   2248:        NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
                   2249:        if ((error = namei(&nd)) != 0)
                   2250:                return (error);
                   2251:
                   2252:        error = change_mode(nd.ni_vp, SCARG(uap, mode), p);
                   2253:
                   2254:        vrele(nd.ni_vp);
                   2255:        return (error);
                   2256: }
                   2257:
                   2258: /*
1.97      enami    2259:  * Common routine to set mode given a vnode.
                   2260:  */
                   2261: static int
                   2262: change_mode(vp, mode, p)
                   2263:        struct vnode *vp;
                   2264:        int mode;
                   2265:        struct proc *p;
                   2266: {
                   2267:        struct vattr vattr;
                   2268:        int error;
                   2269:
1.42      mycroft  2270:        VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
1.113     fvdl     2271:        vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
                   2272:        VATTR_NULL(&vattr);
                   2273:        vattr.va_mode = mode & ALLPERMS;
                   2274:        error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
                   2275:        VOP_UNLOCK(vp, 0);
1.31      cgd      2276:        return (error);
                   2277: }
                   2278:
                   2279: /*
1.98      enami    2280:  * Set ownership given a path name; this version follows links.
1.31      cgd      2281:  */
                   2282: /* ARGSUSED */
1.63      christos 2283: int
1.57      mycroft  2284: sys_chown(p, v, retval)
1.31      cgd      2285:        struct proc *p;
1.56      thorpej  2286:        void *v;
                   2287:        register_t *retval;
                   2288: {
1.155     augustss 2289:        struct sys_chown_args /* {
1.74      cgd      2290:                syscallarg(const char *) path;
                   2291:                syscallarg(uid_t) uid;
                   2292:                syscallarg(gid_t) gid;
1.56      thorpej  2293:        } */ *uap = v;
1.31      cgd      2294:        int error;
                   2295:        struct nameidata nd;
                   2296:
1.35      cgd      2297:        NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
1.63      christos 2298:        if ((error = namei(&nd)) != 0)
1.31      cgd      2299:                return (error);
1.86      kleink   2300:
1.112     kleink   2301:        error = change_owner(nd.ni_vp, SCARG(uap, uid), SCARG(uap, gid), p, 0);
                   2302:
                   2303:        vrele(nd.ni_vp);
                   2304:        return (error);
                   2305: }
                   2306:
                   2307: /*
                   2308:  * Set ownership given a path name; this version follows links.
                   2309:  * Provides POSIX semantics.
                   2310:  */
                   2311: /* ARGSUSED */
                   2312: int
                   2313: sys___posix_chown(p, v, retval)
                   2314:        struct proc *p;
                   2315:        void *v;
                   2316:        register_t *retval;
                   2317: {
1.155     augustss 2318:        struct sys_chown_args /* {
1.112     kleink   2319:                syscallarg(const char *) path;
                   2320:                syscallarg(uid_t) uid;
                   2321:                syscallarg(gid_t) gid;
                   2322:        } */ *uap = v;
                   2323:        int error;
                   2324:        struct nameidata nd;
                   2325:
                   2326:        NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
                   2327:        if ((error = namei(&nd)) != 0)
                   2328:                return (error);
                   2329:
                   2330:        error = change_owner(nd.ni_vp, SCARG(uap, uid), SCARG(uap, gid), p, 1);
1.86      kleink   2331:
                   2332:        vrele(nd.ni_vp);
1.31      cgd      2333:        return (error);
                   2334: }
                   2335:
                   2336: /*
                   2337:  * Set ownership given a file descriptor.
                   2338:  */
                   2339: /* ARGSUSED */
1.63      christos 2340: int
1.57      mycroft  2341: sys_fchown(p, v, retval)
1.31      cgd      2342:        struct proc *p;
1.56      thorpej  2343:        void *v;
                   2344:        register_t *retval;
                   2345: {
1.155     augustss 2346:        struct sys_fchown_args /* {
1.35      cgd      2347:                syscallarg(int) fd;
1.74      cgd      2348:                syscallarg(uid_t) uid;
                   2349:                syscallarg(gid_t) gid;
1.56      thorpej  2350:        } */ *uap = v;
1.71      mycroft  2351:        int error;
1.31      cgd      2352:        struct file *fp;
                   2353:
1.135     thorpej  2354:        /* getvnode() will use the descriptor for us */
1.63      christos 2355:        if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0)
1.31      cgd      2356:                return (error);
1.86      kleink   2357:
1.135     thorpej  2358:        error = change_owner((struct vnode *)fp->f_data, SCARG(uap, uid),
                   2359:            SCARG(uap, gid), p, 0);
                   2360:        FILE_UNUSE(fp, p);
                   2361:        return (error);
1.112     kleink   2362: }
                   2363:
                   2364: /*
                   2365:  * Set ownership given a file descriptor, providing POSIX/XPG semantics.
                   2366:  */
                   2367: /* ARGSUSED */
                   2368: int
                   2369: sys___posix_fchown(p, v, retval)
                   2370:        struct proc *p;
                   2371:        void *v;
                   2372:        register_t *retval;
                   2373: {
1.155     augustss 2374:        struct sys_fchown_args /* {
1.112     kleink   2375:                syscallarg(int) fd;
                   2376:                syscallarg(uid_t) uid;
                   2377:                syscallarg(gid_t) gid;
                   2378:        } */ *uap = v;
                   2379:        int error;
                   2380:        struct file *fp;
                   2381:
1.135     thorpej  2382:        /* getvnode() will use the descriptor for us */
1.112     kleink   2383:        if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0)
                   2384:                return (error);
                   2385:
1.135     thorpej  2386:        error = change_owner((struct vnode *)fp->f_data, SCARG(uap, uid),
                   2387:            SCARG(uap, gid), p, 1);
                   2388:        FILE_UNUSE(fp, p);
                   2389:        return (error);
1.86      kleink   2390: }
                   2391:
                   2392: /*
1.98      enami    2393:  * Set ownership given a path name; this version does not follow links.
                   2394:  */
                   2395: /* ARGSUSED */
                   2396: int
                   2397: sys_lchown(p, v, retval)
                   2398:        struct proc *p;
                   2399:        void *v;
                   2400:        register_t *retval;
                   2401: {
1.155     augustss 2402:        struct sys_lchown_args /* {
1.98      enami    2403:                syscallarg(const char *) path;
                   2404:                syscallarg(uid_t) uid;
                   2405:                syscallarg(gid_t) gid;
                   2406:        } */ *uap = v;
                   2407:        int error;
                   2408:        struct nameidata nd;
                   2409:
                   2410:        NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
                   2411:        if ((error = namei(&nd)) != 0)
                   2412:                return (error);
                   2413:
1.112     kleink   2414:        error = change_owner(nd.ni_vp, SCARG(uap, uid), SCARG(uap, gid), p, 0);
                   2415:
                   2416:        vrele(nd.ni_vp);
                   2417:        return (error);
                   2418: }
                   2419:
                   2420: /*
                   2421:  * Set ownership given a path name; this version does not follow links.
                   2422:  * Provides POSIX/XPG semantics.
                   2423:  */
                   2424: /* ARGSUSED */
                   2425: int
                   2426: sys___posix_lchown(p, v, retval)
                   2427:        struct proc *p;
                   2428:        void *v;
                   2429:        register_t *retval;
                   2430: {
1.155     augustss 2431:        struct sys_lchown_args /* {
1.112     kleink   2432:                syscallarg(const char *) path;
                   2433:                syscallarg(uid_t) uid;
                   2434:                syscallarg(gid_t) gid;
                   2435:        } */ *uap = v;
                   2436:        int error;
                   2437:        struct nameidata nd;
                   2438:
                   2439:        NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
                   2440:        if ((error = namei(&nd)) != 0)
                   2441:                return (error);
                   2442:
                   2443:        error = change_owner(nd.ni_vp, SCARG(uap, uid), SCARG(uap, gid), p, 1);
1.98      enami    2444:
                   2445:        vrele(nd.ni_vp);
                   2446:        return (error);
                   2447: }
                   2448:
                   2449: /*
1.112     kleink   2450:  * Common routine to set ownership given a vnode.
1.86      kleink   2451:  */
                   2452: static int
1.112     kleink   2453: change_owner(vp, uid, gid, p, posix_semantics)
1.155     augustss 2454:        struct vnode *vp;
1.86      kleink   2455:        uid_t uid;
                   2456:        gid_t gid;
                   2457:        struct proc *p;
1.112     kleink   2458:        int posix_semantics;
1.86      kleink   2459: {
                   2460:        struct vattr vattr;
1.112     kleink   2461:        mode_t newmode;
1.86      kleink   2462:        int error;
                   2463:
1.42      mycroft  2464:        VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
1.113     fvdl     2465:        vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
1.93      enami    2466:        if ((error = VOP_GETATTR(vp, &vattr, p->p_ucred, p)) != 0)
1.86      kleink   2467:                goto out;
                   2468:
1.112     kleink   2469: #define CHANGED(x) ((x) != -1)
                   2470:        newmode = vattr.va_mode;
                   2471:        if (posix_semantics) {
                   2472:                /*
1.114     kleink   2473:                 * POSIX/XPG semantics: if the caller is not the super-user,
                   2474:                 * clear set-user-id and set-group-id bits.  Both POSIX and
                   2475:                 * the XPG consider the behaviour for calls by the super-user
                   2476:                 * implementation-defined; we leave the set-user-id and set-
                   2477:                 * group-id settings intact in that case.
1.112     kleink   2478:                 */
                   2479:                if (suser(p->p_ucred, NULL) != 0)
                   2480:                        newmode &= ~(S_ISUID | S_ISGID);
                   2481:        } else {
                   2482:                /*
                   2483:                 * NetBSD semantics: when changing owner and/or group,
                   2484:                 * clear the respective bit(s).
                   2485:                 */
                   2486:                if (CHANGED(uid))
                   2487:                        newmode &= ~S_ISUID;
                   2488:                if (CHANGED(gid))
                   2489:                        newmode &= ~S_ISGID;
                   2490:        }
                   2491:        /* Update va_mode iff altered. */
                   2492:        if (vattr.va_mode == newmode)
                   2493:                newmode = VNOVAL;
                   2494:
1.86      kleink   2495:        VATTR_NULL(&vattr);
1.112     kleink   2496:        vattr.va_uid = CHANGED(uid) ? uid : VNOVAL;
                   2497:        vattr.va_gid = CHANGED(gid) ? gid : VNOVAL;
1.86      kleink   2498:        vattr.va_mode = newmode;
                   2499:        error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
1.112     kleink   2500: #undef CHANGED
                   2501:
1.86      kleink   2502: out:
1.113     fvdl     2503:        VOP_UNLOCK(vp, 0);
1.31      cgd      2504:        return (error);
                   2505: }
                   2506:
                   2507: /*
1.98      enami    2508:  * Set the access and modification times given a path name; this
                   2509:  * version follows links.
1.31      cgd      2510:  */
                   2511: /* ARGSUSED */
1.63      christos 2512: int
1.57      mycroft  2513: sys_utimes(p, v, retval)
1.31      cgd      2514:        struct proc *p;
1.56      thorpej  2515:        void *v;
                   2516:        register_t *retval;
                   2517: {
1.155     augustss 2518:        struct sys_utimes_args /* {
1.74      cgd      2519:                syscallarg(const char *) path;
                   2520:                syscallarg(const struct timeval *) tptr;
1.56      thorpej  2521:        } */ *uap = v;
1.31      cgd      2522:        int error;
                   2523:        struct nameidata nd;
                   2524:
1.96      enami    2525:        NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
                   2526:        if ((error = namei(&nd)) != 0)
                   2527:                return (error);
1.97      enami    2528:
                   2529:        error = change_utimes(nd.ni_vp, SCARG(uap, tptr), p);
                   2530:
                   2531:        vrele(nd.ni_vp);
1.71      mycroft  2532:        return (error);
                   2533: }
                   2534:
                   2535: /*
                   2536:  * Set the access and modification times given a file descriptor.
                   2537:  */
                   2538: /* ARGSUSED */
                   2539: int
                   2540: sys_futimes(p, v, retval)
                   2541:        struct proc *p;
                   2542:        void *v;
                   2543:        register_t *retval;
                   2544: {
1.155     augustss 2545:        struct sys_futimes_args /* {
1.71      mycroft  2546:                syscallarg(int) fd;
1.74      cgd      2547:                syscallarg(const struct timeval *) tptr;
1.71      mycroft  2548:        } */ *uap = v;
                   2549:        int error;
                   2550:        struct file *fp;
                   2551:
1.135     thorpej  2552:        /* getvnode() will use the descriptor for us */
1.96      enami    2553:        if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0)
                   2554:                return (error);
1.97      enami    2555:
1.135     thorpej  2556:        error = change_utimes((struct vnode *)fp->f_data, SCARG(uap, tptr), p);
                   2557:        FILE_UNUSE(fp, p);
                   2558:        return (error);
1.98      enami    2559: }
                   2560:
                   2561: /*
                   2562:  * Set the access and modification times given a path name; this
                   2563:  * version does not follow links.
                   2564:  */
                   2565: /* ARGSUSED */
                   2566: int
                   2567: sys_lutimes(p, v, retval)
                   2568:        struct proc *p;
                   2569:        void *v;
                   2570:        register_t *retval;
                   2571: {
1.155     augustss 2572:        struct sys_lutimes_args /* {
1.98      enami    2573:                syscallarg(const char *) path;
                   2574:                syscallarg(const struct timeval *) tptr;
                   2575:        } */ *uap = v;
                   2576:        int error;
                   2577:        struct nameidata nd;
                   2578:
                   2579:        NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
                   2580:        if ((error = namei(&nd)) != 0)
                   2581:                return (error);
                   2582:
                   2583:        error = change_utimes(nd.ni_vp, SCARG(uap, tptr), p);
                   2584:
                   2585:        vrele(nd.ni_vp);
                   2586:        return (error);
1.97      enami    2587: }
                   2588:
                   2589: /*
                   2590:  * Common routine to set access and modification times given a vnode.
                   2591:  */
                   2592: static int
                   2593: change_utimes(vp, tptr, p)
                   2594:        struct vnode *vp;
                   2595:        const struct timeval *tptr;
                   2596:        struct proc *p;
                   2597: {
                   2598:        struct timeval tv[2];
                   2599:        struct vattr vattr;
                   2600:        int error;
                   2601:
1.71      mycroft  2602:        VATTR_NULL(&vattr);
1.97      enami    2603:        if (tptr == NULL) {
1.71      mycroft  2604:                microtime(&tv[0]);
                   2605:                tv[1] = tv[0];
                   2606:                vattr.va_vaflags |= VA_UTIMES_NULL;
                   2607:        } else {
1.122     perry    2608:                error = copyin(tptr, tv, sizeof(tv));
1.71      mycroft  2609:                if (error)
                   2610:                        return (error);
                   2611:        }
                   2612:        VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
1.113     fvdl     2613:        vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
                   2614:        vattr.va_atime.tv_sec = tv[0].tv_sec;
                   2615:        vattr.va_atime.tv_nsec = tv[0].tv_usec * 1000;
                   2616:        vattr.va_mtime.tv_sec = tv[1].tv_sec;
                   2617:        vattr.va_mtime.tv_nsec = tv[1].tv_usec * 1000;
                   2618:        error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
                   2619:        VOP_UNLOCK(vp, 0);
1.31      cgd      2620:        return (error);
                   2621: }
                   2622:
                   2623: /*
                   2624:  * Truncate a file given its path name.
                   2625:  */
                   2626: /* ARGSUSED */
1.63      christos 2627: int
1.57      mycroft  2628: sys_truncate(p, v, retval)
1.31      cgd      2629:        struct proc *p;
1.56      thorpej  2630:        void *v;
                   2631:        register_t *retval;
                   2632: {
1.155     augustss 2633:        struct sys_truncate_args /* {
1.74      cgd      2634:                syscallarg(const char *) path;
1.35      cgd      2635:                syscallarg(int) pad;
                   2636:                syscallarg(off_t) length;
1.56      thorpej  2637:        } */ *uap = v;
1.155     augustss 2638:        struct vnode *vp;
1.31      cgd      2639:        struct vattr vattr;
                   2640:        int error;
                   2641:        struct nameidata nd;
                   2642:
1.35      cgd      2643:        NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
1.63      christos 2644:        if ((error = namei(&nd)) != 0)
1.31      cgd      2645:                return (error);
                   2646:        vp = nd.ni_vp;
1.42      mycroft  2647:        VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
1.113     fvdl     2648:        vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
1.31      cgd      2649:        if (vp->v_type == VDIR)
                   2650:                error = EISDIR;
                   2651:        else if ((error = vn_writechk(vp)) == 0 &&
                   2652:            (error = VOP_ACCESS(vp, VWRITE, p->p_ucred, p)) == 0) {
                   2653:                VATTR_NULL(&vattr);
1.35      cgd      2654:                vattr.va_size = SCARG(uap, length);
1.31      cgd      2655:                error = VOP_SETATTR(vp, &vattr, p->p_ucred, p);
                   2656:        }
                   2657:        vput(vp);
                   2658:        return (error);
                   2659: }
                   2660:
                   2661: /*
                   2662:  * Truncate a file given a file descriptor.
                   2663:  */
                   2664: /* ARGSUSED */
1.63      christos 2665: int
1.57      mycroft  2666: sys_ftruncate(p, v, retval)
1.31      cgd      2667:        struct proc *p;
1.56      thorpej  2668:        void *v;
                   2669:        register_t *retval;
                   2670: {
1.155     augustss 2671:        struct sys_ftruncate_args /* {
1.35      cgd      2672:                syscallarg(int) fd;
                   2673:                syscallarg(int) pad;
                   2674:                syscallarg(off_t) length;
1.56      thorpej  2675:        } */ *uap = v;
1.31      cgd      2676:        struct vattr vattr;
                   2677:        struct vnode *vp;
                   2678:        struct file *fp;
                   2679:        int error;
                   2680:
1.135     thorpej  2681:        /* getvnode() will use the descriptor for us */
1.63      christos 2682:        if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0)
1.31      cgd      2683:                return (error);
1.135     thorpej  2684:        if ((fp->f_flag & FWRITE) == 0) {
                   2685:                error = EINVAL;
                   2686:                goto out;
                   2687:        }
1.62      mycroft  2688:        vp = (struct vnode *)fp->f_data;
1.42      mycroft  2689:        VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
1.113     fvdl     2690:        vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
1.31      cgd      2691:        if (vp->v_type == VDIR)
                   2692:                error = EISDIR;
                   2693:        else if ((error = vn_writechk(vp)) == 0) {
                   2694:                VATTR_NULL(&vattr);
1.35      cgd      2695:                vattr.va_size = SCARG(uap, length);
1.31      cgd      2696:                error = VOP_SETATTR(vp, &vattr, fp->f_cred, p);
                   2697:        }
1.113     fvdl     2698:        VOP_UNLOCK(vp, 0);
1.135     thorpej  2699:  out:
                   2700:        FILE_UNUSE(fp, p);
1.31      cgd      2701:        return (error);
                   2702: }
                   2703:
                   2704: /*
                   2705:  * Sync an open file.
                   2706:  */
                   2707: /* ARGSUSED */
1.63      christos 2708: int
1.57      mycroft  2709: sys_fsync(p, v, retval)
1.31      cgd      2710:        struct proc *p;
1.56      thorpej  2711:        void *v;
                   2712:        register_t *retval;
                   2713: {
1.57      mycroft  2714:        struct sys_fsync_args /* {
1.35      cgd      2715:                syscallarg(int) fd;
1.56      thorpej  2716:        } */ *uap = v;
1.155     augustss 2717:        struct vnode *vp;
1.31      cgd      2718:        struct file *fp;
                   2719:        int error;
                   2720:
1.135     thorpej  2721:        /* getvnode() will use the descriptor for us */
1.63      christos 2722:        if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0)
1.31      cgd      2723:                return (error);
1.62      mycroft  2724:        vp = (struct vnode *)fp->f_data;
1.113     fvdl     2725:        vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
1.116     kleink   2726:        error = VOP_FSYNC(vp, fp->f_cred, FSYNC_WAIT, p);
1.148     fvdl     2727:        if (error == 0 && bioops.io_fsync != NULL &&
                   2728:            vp->v_mount && (vp->v_mount->mnt_flag & MNT_SOFTDEP))
                   2729:                (*bioops.io_fsync)(vp);
1.113     fvdl     2730:        VOP_UNLOCK(vp, 0);
1.135     thorpej  2731:        FILE_UNUSE(fp, p);
1.31      cgd      2732:        return (error);
                   2733: }
                   2734:
                   2735: /*
1.117     kleink   2736:  * Sync the data of an open file.
                   2737:  */
                   2738: /* ARGSUSED */
                   2739: int
                   2740: sys_fdatasync(p, v, retval)
                   2741:        struct proc *p;
                   2742:        void *v;
                   2743:        register_t *retval;
                   2744: {
                   2745:        struct sys_fdatasync_args /* {
                   2746:                syscallarg(int) fd;
                   2747:        } */ *uap = v;
                   2748:        struct vnode *vp;
                   2749:        struct file *fp;
                   2750:        int error;
                   2751:
1.135     thorpej  2752:        /* getvnode() will use the descriptor for us */
1.117     kleink   2753:        if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0)
                   2754:                return (error);
                   2755:        vp = (struct vnode *)fp->f_data;
                   2756:        vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
                   2757:        error = VOP_FSYNC(vp, fp->f_cred, FSYNC_WAIT|FSYNC_DATAONLY, p);
                   2758:        VOP_UNLOCK(vp, 0);
1.135     thorpej  2759:        FILE_UNUSE(fp, p);
1.117     kleink   2760:        return (error);
                   2761: }
                   2762:
                   2763: /*
1.90      kleink   2764:  * Rename files, (standard) BSD semantics frontend.
1.31      cgd      2765:  */
                   2766: /* ARGSUSED */
1.63      christos 2767: int
1.57      mycroft  2768: sys_rename(p, v, retval)
1.31      cgd      2769:        struct proc *p;
1.56      thorpej  2770:        void *v;
                   2771:        register_t *retval;
                   2772: {
1.155     augustss 2773:        struct sys_rename_args /* {
1.74      cgd      2774:                syscallarg(const char *) from;
                   2775:                syscallarg(const char *) to;
1.56      thorpej  2776:        } */ *uap = v;
1.90      kleink   2777:
                   2778:        return (rename_files(SCARG(uap, from), SCARG(uap, to), p, 0));
                   2779: }
                   2780:
                   2781: /*
                   2782:  * Rename files, POSIX semantics frontend.
                   2783:  */
                   2784: /* ARGSUSED */
                   2785: int
1.112     kleink   2786: sys___posix_rename(p, v, retval)
1.90      kleink   2787:        struct proc *p;
                   2788:        void *v;
                   2789:        register_t *retval;
                   2790: {
1.155     augustss 2791:        struct sys___posix_rename_args /* {
1.90      kleink   2792:                syscallarg(const char *) from;
                   2793:                syscallarg(const char *) to;
                   2794:        } */ *uap = v;
                   2795:
                   2796:        return (rename_files(SCARG(uap, from), SCARG(uap, to), p, 1));
                   2797: }
                   2798:
                   2799: /*
                   2800:  * Rename files.  Source and destination must either both be directories,
                   2801:  * or both not be directories.  If target is a directory, it must be empty.
                   2802:  * If `from' and `to' refer to the same object, the value of the `retain'
                   2803:  * argument is used to determine whether `from' will be
                   2804:  *
                   2805:  * (retain == 0)       deleted unless `from' and `to' refer to the same
                   2806:  *                     object in the file system's name space (BSD).
                   2807:  * (retain == 1)       always retained (POSIX).
                   2808:  */
                   2809: static int
                   2810: rename_files(from, to, p, retain)
                   2811:        const char *from, *to;
                   2812:        struct proc *p;
                   2813:        int retain;
                   2814: {
1.155     augustss 2815:        struct vnode *tvp, *fvp, *tdvp;
1.31      cgd      2816:        struct nameidata fromnd, tond;
                   2817:        int error;
                   2818:
                   2819:        NDINIT(&fromnd, DELETE, WANTPARENT | SAVESTART, UIO_USERSPACE,
1.90      kleink   2820:            from, p);
1.63      christos 2821:        if ((error = namei(&fromnd)) != 0)
1.31      cgd      2822:                return (error);
                   2823:        fvp = fromnd.ni_vp;
                   2824:        NDINIT(&tond, RENAME, LOCKPARENT | LOCKLEAF | NOCACHE | SAVESTART,
1.90      kleink   2825:            UIO_USERSPACE, to, p);
1.63      christos 2826:        if ((error = namei(&tond)) != 0) {
1.31      cgd      2827:                VOP_ABORTOP(fromnd.ni_dvp, &fromnd.ni_cnd);
                   2828:                vrele(fromnd.ni_dvp);
                   2829:                vrele(fvp);
                   2830:                goto out1;
                   2831:        }
                   2832:        tdvp = tond.ni_dvp;
                   2833:        tvp = tond.ni_vp;
1.90      kleink   2834:
1.31      cgd      2835:        if (tvp != NULL) {
                   2836:                if (fvp->v_type == VDIR && tvp->v_type != VDIR) {
                   2837:                        error = ENOTDIR;
                   2838:                        goto out;
                   2839:                } else if (fvp->v_type != VDIR && tvp->v_type == VDIR) {
                   2840:                        error = EISDIR;
                   2841:                        goto out;
                   2842:                }
                   2843:        }
1.90      kleink   2844:
1.31      cgd      2845:        if (fvp == tdvp)
                   2846:                error = EINVAL;
1.90      kleink   2847:
1.82      kleink   2848:        /*
1.90      kleink   2849:         * Source and destination refer to the same object.
1.82      kleink   2850:         */
1.90      kleink   2851:        if (fvp == tvp) {
                   2852:                if (retain)
                   2853:                        error = -1;
                   2854:                else if (fromnd.ni_dvp == tdvp &&
                   2855:                    fromnd.ni_cnd.cn_namelen == tond.ni_cnd.cn_namelen &&
1.123     perry    2856:                    !memcmp(fromnd.ni_cnd.cn_nameptr,
1.90      kleink   2857:                          tond.ni_cnd.cn_nameptr,
                   2858:                          fromnd.ni_cnd.cn_namelen))
1.82      kleink   2859:                error = -1;
1.90      kleink   2860:        }
                   2861:
1.31      cgd      2862: out:
                   2863:        if (!error) {
1.42      mycroft  2864:                VOP_LEASE(tdvp, p, p->p_ucred, LEASE_WRITE);
1.31      cgd      2865:                if (fromnd.ni_dvp != tdvp)
1.42      mycroft  2866:                        VOP_LEASE(fromnd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
1.75      fvdl     2867:                if (tvp) {
1.110     mrg      2868:                        (void)uvm_vnp_uncache(tvp);
1.42      mycroft  2869:                        VOP_LEASE(tvp, p, p->p_ucred, LEASE_WRITE);
1.75      fvdl     2870:                }
1.31      cgd      2871:                error = VOP_RENAME(fromnd.ni_dvp, fromnd.ni_vp, &fromnd.ni_cnd,
                   2872:                                   tond.ni_dvp, tond.ni_vp, &tond.ni_cnd);
                   2873:        } else {
                   2874:                VOP_ABORTOP(tond.ni_dvp, &tond.ni_cnd);
                   2875:                if (tdvp == tvp)
                   2876:                        vrele(tdvp);
                   2877:                else
                   2878:                        vput(tdvp);
                   2879:                if (tvp)
                   2880:                        vput(tvp);
                   2881:                VOP_ABORTOP(fromnd.ni_dvp, &fromnd.ni_cnd);
                   2882:                vrele(fromnd.ni_dvp);
                   2883:                vrele(fvp);
                   2884:        }
                   2885:        vrele(tond.ni_startdir);
                   2886:        FREE(tond.ni_cnd.cn_pnbuf, M_NAMEI);
                   2887: out1:
                   2888:        if (fromnd.ni_startdir)
                   2889:                vrele(fromnd.ni_startdir);
                   2890:        FREE(fromnd.ni_cnd.cn_pnbuf, M_NAMEI);
1.80      kleink   2891:        return (error == -1 ? 0 : error);
1.31      cgd      2892: }
                   2893:
                   2894: /*
                   2895:  * Make a directory file.
                   2896:  */
                   2897: /* ARGSUSED */
1.63      christos 2898: int
1.57      mycroft  2899: sys_mkdir(p, v, retval)
1.31      cgd      2900:        struct proc *p;
1.56      thorpej  2901:        void *v;
                   2902:        register_t *retval;
                   2903: {
1.155     augustss 2904:        struct sys_mkdir_args /* {
1.74      cgd      2905:                syscallarg(const char *) path;
1.35      cgd      2906:                syscallarg(int) mode;
1.56      thorpej  2907:        } */ *uap = v;
1.155     augustss 2908:        struct vnode *vp;
1.31      cgd      2909:        struct vattr vattr;
                   2910:        int error;
                   2911:        struct nameidata nd;
                   2912:
1.35      cgd      2913:        NDINIT(&nd, CREATE, LOCKPARENT, UIO_USERSPACE, SCARG(uap, path), p);
1.63      christos 2914:        if ((error = namei(&nd)) != 0)
1.31      cgd      2915:                return (error);
                   2916:        vp = nd.ni_vp;
                   2917:        if (vp != NULL) {
                   2918:                VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
                   2919:                if (nd.ni_dvp == vp)
                   2920:                        vrele(nd.ni_dvp);
                   2921:                else
                   2922:                        vput(nd.ni_dvp);
                   2923:                vrele(vp);
                   2924:                return (EEXIST);
                   2925:        }
                   2926:        VATTR_NULL(&vattr);
                   2927:        vattr.va_type = VDIR;
1.134     thorpej  2928:        vattr.va_mode =
                   2929:            (SCARG(uap, mode) & ACCESSPERMS) &~ p->p_cwdi->cwdi_cmask;
1.42      mycroft  2930:        VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
1.31      cgd      2931:        error = VOP_MKDIR(nd.ni_dvp, &nd.ni_vp, &nd.ni_cnd, &vattr);
                   2932:        if (!error)
                   2933:                vput(nd.ni_vp);
                   2934:        return (error);
                   2935: }
                   2936:
                   2937: /*
                   2938:  * Remove a directory file.
                   2939:  */
                   2940: /* ARGSUSED */
1.63      christos 2941: int
1.57      mycroft  2942: sys_rmdir(p, v, retval)
1.31      cgd      2943:        struct proc *p;
1.56      thorpej  2944:        void *v;
                   2945:        register_t *retval;
                   2946: {
1.57      mycroft  2947:        struct sys_rmdir_args /* {
1.74      cgd      2948:                syscallarg(const char *) path;
1.56      thorpej  2949:        } */ *uap = v;
1.155     augustss 2950:        struct vnode *vp;
1.31      cgd      2951:        int error;
                   2952:        struct nameidata nd;
                   2953:
1.35      cgd      2954:        NDINIT(&nd, DELETE, LOCKPARENT | LOCKLEAF, UIO_USERSPACE,
                   2955:            SCARG(uap, path), p);
1.63      christos 2956:        if ((error = namei(&nd)) != 0)
1.31      cgd      2957:                return (error);
                   2958:        vp = nd.ni_vp;
                   2959:        if (vp->v_type != VDIR) {
                   2960:                error = ENOTDIR;
                   2961:                goto out;
                   2962:        }
                   2963:        /*
                   2964:         * No rmdir "." please.
                   2965:         */
                   2966:        if (nd.ni_dvp == vp) {
                   2967:                error = EINVAL;
                   2968:                goto out;
                   2969:        }
                   2970:        /*
                   2971:         * The root of a mounted filesystem cannot be deleted.
                   2972:         */
                   2973:        if (vp->v_flag & VROOT)
                   2974:                error = EBUSY;
                   2975: out:
                   2976:        if (!error) {
1.42      mycroft  2977:                VOP_LEASE(nd.ni_dvp, p, p->p_ucred, LEASE_WRITE);
                   2978:                VOP_LEASE(vp, p, p->p_ucred, LEASE_WRITE);
1.31      cgd      2979:                error = VOP_RMDIR(nd.ni_dvp, nd.ni_vp, &nd.ni_cnd);
                   2980:        } else {
                   2981:                VOP_ABORTOP(nd.ni_dvp, &nd.ni_cnd);
                   2982:                if (nd.ni_dvp == vp)
                   2983:                        vrele(nd.ni_dvp);
                   2984:                else
                   2985:                        vput(nd.ni_dvp);
                   2986:                vput(vp);
                   2987:        }
                   2988:        return (error);
                   2989: }
                   2990:
                   2991: /*
                   2992:  * Read a block of directory entries in a file system independent format.
                   2993:  */
1.63      christos 2994: int
1.101     fvdl     2995: sys_getdents(p, v, retval)
1.31      cgd      2996:        struct proc *p;
1.56      thorpej  2997:        void *v;
                   2998:        register_t *retval;
                   2999: {
1.155     augustss 3000:        struct sys_getdents_args /* {
1.35      cgd      3001:                syscallarg(int) fd;
                   3002:                syscallarg(char *) buf;
1.101     fvdl     3003:                syscallarg(size_t) count;
1.56      thorpej  3004:        } */ *uap = v;
1.31      cgd      3005:        struct file *fp;
1.101     fvdl     3006:        int error, done;
1.31      cgd      3007:
1.135     thorpej  3008:        /* getvnode() will use the descriptor for us */
1.63      christos 3009:        if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0)
1.31      cgd      3010:                return (error);
1.135     thorpej  3011:        if ((fp->f_flag & FREAD) == 0) {
                   3012:                error = EBADF;
                   3013:                goto out;
                   3014:        }
1.101     fvdl     3015:        error = vn_readdir(fp, SCARG(uap, buf), UIO_USERSPACE,
                   3016:                        SCARG(uap, count), &done, p, 0, 0);
                   3017:        *retval = done;
1.135     thorpej  3018:  out:
                   3019:        FILE_UNUSE(fp, p);
1.31      cgd      3020:        return (error);
                   3021: }
                   3022:
                   3023: /*
                   3024:  * Set the mode mask for creation of filesystem nodes.
                   3025:  */
1.56      thorpej  3026: int
1.57      mycroft  3027: sys_umask(p, v, retval)
1.31      cgd      3028:        struct proc *p;
1.56      thorpej  3029:        void *v;
                   3030:        register_t *retval;
                   3031: {
1.57      mycroft  3032:        struct sys_umask_args /* {
1.103     mycroft  3033:                syscallarg(mode_t) newmask;
1.56      thorpej  3034:        } */ *uap = v;
1.134     thorpej  3035:        struct cwdinfo *cwdi;
1.31      cgd      3036:
1.134     thorpej  3037:        cwdi = p->p_cwdi;
                   3038:        *retval = cwdi->cwdi_cmask;
                   3039:        cwdi->cwdi_cmask = SCARG(uap, newmask) & ALLPERMS;
1.31      cgd      3040:        return (0);
                   3041: }
                   3042:
                   3043: /*
                   3044:  * Void all references to file by ripping underlying filesystem
                   3045:  * away from vnode.
                   3046:  */
                   3047: /* ARGSUSED */
1.63      christos 3048: int
1.57      mycroft  3049: sys_revoke(p, v, retval)
1.31      cgd      3050:        struct proc *p;
1.56      thorpej  3051:        void *v;
                   3052:        register_t *retval;
                   3053: {
1.155     augustss 3054:        struct sys_revoke_args /* {
1.74      cgd      3055:                syscallarg(const char *) path;
1.56      thorpej  3056:        } */ *uap = v;
1.155     augustss 3057:        struct vnode *vp;
1.31      cgd      3058:        struct vattr vattr;
                   3059:        int error;
                   3060:        struct nameidata nd;
                   3061:
1.35      cgd      3062:        NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
1.63      christos 3063:        if ((error = namei(&nd)) != 0)
1.31      cgd      3064:                return (error);
                   3065:        vp = nd.ni_vp;
1.63      christos 3066:        if ((error = VOP_GETATTR(vp, &vattr, p->p_ucred, p)) != 0)
1.31      cgd      3067:                goto out;
                   3068:        if (p->p_ucred->cr_uid != vattr.va_uid &&
1.93      enami    3069:            (error = suser(p->p_ucred, &p->p_acflag)) != 0)
1.31      cgd      3070:                goto out;
1.145     wrstuden 3071:        if (vp->v_usecount > 1 || (vp->v_flag & (VALIASED | VLAYER)))
1.113     fvdl     3072:                VOP_REVOKE(vp, REVOKEALL);
1.31      cgd      3073: out:
                   3074:        vrele(vp);
                   3075:        return (error);
                   3076: }
                   3077:
                   3078: /*
                   3079:  * Convert a user file descriptor to a kernel file entry.
                   3080:  */
1.60      mycroft  3081: int
1.62      mycroft  3082: getvnode(fdp, fd, fpp)
1.31      cgd      3083:        struct filedesc *fdp;
1.60      mycroft  3084:        int fd;
1.31      cgd      3085:        struct file **fpp;
                   3086: {
1.60      mycroft  3087:        struct vnode *vp;
1.31      cgd      3088:        struct file *fp;
                   3089:
                   3090:        if ((u_int)fd >= fdp->fd_nfiles ||
1.135     thorpej  3091:            (fp = fdp->fd_ofiles[fd]) == NULL ||
                   3092:            (fp->f_iflags & FIF_WANTCLOSE) != 0)
1.31      cgd      3093:                return (EBADF);
1.135     thorpej  3094:
                   3095:        FILE_USE(fp);
                   3096:
                   3097:        if (fp->f_type != DTYPE_VNODE) {
                   3098:                FILE_UNUSE(fp, NULL);
1.31      cgd      3099:                return (EINVAL);
1.135     thorpej  3100:        }
                   3101:
1.60      mycroft  3102:        vp = (struct vnode *)fp->f_data;
1.135     thorpej  3103:        if (vp->v_type == VBAD) {
                   3104:                FILE_UNUSE(fp, NULL);
1.60      mycroft  3105:                return (EBADF);
1.135     thorpej  3106:        }
                   3107:
1.31      cgd      3108:        *fpp = fp;
                   3109:        return (0);
                   3110: }

CVSweb <webmaster@jp.NetBSD.org>