[BACK]Return to vfs_syscalls_30.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / sys / compat / common

Annotation of src/sys/compat/common/vfs_syscalls_30.c, Revision 1.7.2.2

1.7.2.2 ! yamt        1: /*     $NetBSD: vfs_syscalls_30.c,v 1.7.2.1 2006/05/24 10:57:27 yamt Exp $     */
1.1       christos    2:
                      3: /*-
                      4:  * Copyright (c) 2005 The NetBSD Foundation, Inc.
                      5:  * All rights reserved.
                      6:  *
                      7:  * This code is derived from software contributed to The NetBSD Foundation
                      8:  * by Christos Zoulas.
                      9:  *
                     10:  * Redistribution and use in source and binary forms, with or without
                     11:  * modification, are permitted provided that the following conditions
                     12:  * are met:
                     13:  * 1. Redistributions of source code must retain the above copyright
                     14:  *    notice, this list of conditions and the following disclaimer.
                     15:  * 2. Redistributions in binary form must reproduce the above copyright
                     16:  *    notice, this list of conditions and the following disclaimer in the
                     17:  *    documentation and/or other materials provided with the distribution.
                     18:  * 3. All advertising materials mentioning features or use of this software
                     19:  *    must display the following acknowledgement:
                     20:  *        This product includes software developed by the NetBSD
                     21:  *        Foundation, Inc. and its contributors.
                     22:  * 4. Neither the name of The NetBSD Foundation nor the names of its
                     23:  *    contributors may be used to endorse or promote products derived
                     24:  *    from this software without specific prior written permission.
                     25:  *
                     26:  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
                     27:  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
                     28:  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
                     29:  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
                     30:  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
                     31:  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
                     32:  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
                     33:  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
                     34:  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
                     35:  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
                     36:  * POSSIBILITY OF SUCH DAMAGE.
                     37:  */
                     38: #include <sys/cdefs.h>
1.7.2.2 ! yamt       39: __KERNEL_RCSID(0, "$NetBSD: vfs_syscalls_30.c,v 1.7.2.1 2006/05/24 10:57:27 yamt Exp $");
1.1       christos   40:
                     41: #include <sys/param.h>
                     42: #include <sys/systm.h>
                     43: #include <sys/namei.h>
                     44: #include <sys/filedesc.h>
                     45: #include <sys/kernel.h>
                     46: #include <sys/file.h>
                     47: #include <sys/stat.h>
                     48: #include <sys/socketvar.h>
                     49: #include <sys/vnode.h>
                     50: #include <sys/mount.h>
                     51: #include <sys/proc.h>
                     52: #include <sys/uio.h>
                     53: #include <sys/dirent.h>
                     54: #include <sys/malloc.h>
1.7.2.1   yamt       55: #include <sys/kauth.h>
1.1       christos   56:
                     57: #include <sys/sa.h>
                     58: #include <sys/syscallargs.h>
                     59:
                     60: #include <compat/common/compat_util.h>
1.5       christos   61: #include <compat/sys/stat.h>
                     62: #include <compat/sys/dirent.h>
1.7.2.2 ! yamt       63: #include <compat/sys/mount.h>
1.1       christos   64:
                     65: static void cvtstat(struct stat13 *, const struct stat *);
                     66:
                     67: /*
                     68:  * Convert from a new to an old stat structure.
                     69:  */
                     70: static void
                     71: cvtstat(struct stat13 *ost, const struct stat *st)
                     72: {
                     73:
                     74:        ost->st_dev = st->st_dev;
                     75:        ost->st_ino = (uint32_t)st->st_ino;
                     76:        ost->st_mode = st->st_mode;
                     77:        ost->st_nlink = st->st_nlink;
                     78:        ost->st_uid = st->st_uid;
                     79:        ost->st_gid = st->st_gid;
                     80:        ost->st_rdev = st->st_rdev;
                     81:        ost->st_atimespec = st->st_atimespec;
                     82:        ost->st_mtimespec = st->st_mtimespec;
                     83:        ost->st_ctimespec = st->st_ctimespec;
                     84:        ost->st_birthtimespec = st->st_birthtimespec;
                     85:        ost->st_size = st->st_size;
                     86:        ost->st_blocks = st->st_blocks;
                     87:        ost->st_blksize = st->st_blksize;
                     88:        ost->st_flags = st->st_flags;
                     89:        ost->st_gen = st->st_gen;
                     90: }
                     91:
                     92: /*
                     93:  * Get file status; this version follows links.
                     94:  */
                     95: /* ARGSUSED */
                     96: int
                     97: compat_30_sys___stat13(struct lwp *l, void *v, register_t *retval)
                     98: {
                     99:        struct compat_30_sys___stat13_args /* {
                    100:                syscallarg(const char *) path;
                    101:                syscallarg(struct stat13 *) ub;
                    102:        } */ *uap = v;
                    103:        struct stat sb;
                    104:        struct stat13 osb;
                    105:        int error;
                    106:        struct nameidata nd;
                    107:
                    108:        NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
1.6       christos  109:            SCARG(uap, path), l);
1.1       christos  110:        if ((error = namei(&nd)) != 0)
                    111:                return error;
1.6       christos  112:        error = vn_stat(nd.ni_vp, &sb, l);
1.1       christos  113:        vput(nd.ni_vp);
                    114:        if (error)
                    115:                return error;
                    116:        cvtstat(&osb, &sb);
                    117:        error = copyout(&osb, SCARG(uap, ub), sizeof (osb));
                    118:        return error;
                    119: }
                    120:
                    121:
                    122: /*
                    123:  * Get file status; this version does not follow links.
                    124:  */
                    125: /* ARGSUSED */
                    126: int
                    127: compat_30_sys___lstat13(struct lwp *l, void *v, register_t *retval)
                    128: {
                    129:        struct compat_30_sys___lstat13_args /* {
                    130:                syscallarg(const char *) path;
                    131:                syscallarg(struct stat13 *) ub;
                    132:        } */ *uap = v;
                    133:        struct stat sb;
                    134:        struct stat13 osb;
                    135:        int error;
                    136:        struct nameidata nd;
                    137:
                    138:        NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF, UIO_USERSPACE,
1.6       christos  139:            SCARG(uap, path), l);
1.1       christos  140:        if ((error = namei(&nd)) != 0)
                    141:                return error;
1.6       christos  142:        error = vn_stat(nd.ni_vp, &sb, l);
1.1       christos  143:        vput(nd.ni_vp);
                    144:        if (error)
                    145:                return error;
                    146:        cvtstat(&osb, &sb);
                    147:        error = copyout(&osb, SCARG(uap, ub), sizeof (osb));
                    148:        return error;
                    149: }
                    150:
1.7.2.1   yamt      151: /* ARGSUSED */
                    152: int
                    153: compat_30_sys_fhstat(struct lwp *l, void *v, register_t *retval)
                    154: {
                    155:        struct compat_30_sys_fhstat_args /* {
1.7.2.2 ! yamt      156:                syscallarg(const struct compat_30_fhandle *) fhp;
1.7.2.1   yamt      157:                syscallarg(struct stat13 *) sb;
                    158:        } */ *uap = v;
                    159:        struct stat sb;
                    160:        struct stat13 osb;
                    161:        int error;
1.7.2.2 ! yamt      162:        struct compat_30_fhandle fh;
1.7.2.1   yamt      163:        struct mount *mp;
                    164:        struct vnode *vp;
                    165:
                    166:        /*
                    167:         * Must be super user
                    168:         */
1.7.2.2 ! yamt      169:        if ((error = kauth_authorize_generic(l->l_cred, KAUTH_GENERIC_ISSUSER,
        !           170:            &l->l_acflag)))
1.7.2.1   yamt      171:                return (error);
                    172:
1.7.2.2 ! yamt      173:        if ((error = copyin(SCARG(uap, fhp), &fh, sizeof(fh))) != 0)
1.7.2.1   yamt      174:                return (error);
                    175:
                    176:        if ((mp = vfs_getvfs(&fh.fh_fsid)) == NULL)
                    177:                return (ESTALE);
                    178:        if (mp->mnt_op->vfs_fhtovp == NULL)
                    179:                return EOPNOTSUPP;
1.7.2.2 ! yamt      180:        if ((error = VFS_FHTOVP(mp, (struct fid*)&fh.fh_fid, &vp)))
1.7.2.1   yamt      181:                return (error);
                    182:        error = vn_stat(vp, &sb, l);
                    183:        vput(vp);
                    184:        if (error)
                    185:                return (error);
                    186:        cvtstat(&osb, &sb);
                    187:        error = copyout(&osb, SCARG(uap, sb), sizeof(sb));
                    188:        return (error);
                    189: }
                    190:
1.1       christos  191: /*
                    192:  * Return status information about a file descriptor.
                    193:  */
                    194: /* ARGSUSED */
                    195: int
                    196: compat_30_sys___fstat13(struct lwp *l, void *v, register_t *retval)
                    197: {
                    198:        struct compat_30_sys___fstat13_args /* {
                    199:                syscallarg(int) fd;
                    200:                syscallarg(struct stat13 *) sb;
                    201:        } */ *uap = v;
                    202:        struct proc *p = l->l_proc;
                    203:        int fd = SCARG(uap, fd);
                    204:        struct filedesc *fdp = p->p_fd;
                    205:        struct file *fp;
                    206:        struct stat sb;
                    207:        struct stat13 osb;
                    208:        int error;
                    209:
                    210:        if ((fp = fd_getfile(fdp, fd)) == NULL)
                    211:                return EBADF;
                    212:
                    213:        FILE_USE(fp);
1.6       christos  214:        error = (*fp->f_ops->fo_stat)(fp, &sb, l);
                    215:        FILE_UNUSE(fp, l);
1.1       christos  216:
                    217:        if (error)
                    218:                return error;
                    219:        cvtstat(&osb, &sb);
                    220:        error = copyout(&osb, SCARG(uap, sb), sizeof (osb));
                    221:        return error;
                    222: }
                    223:
                    224: /*
                    225:  * Read a block of directory entries in a file system independent format.
                    226:  */
                    227: int
                    228: compat_30_sys_getdents(struct lwp *l, void *v, register_t *retval)
                    229: {
                    230:        struct compat_30_sys_getdents_args /* {
                    231:                syscallarg(int) fd;
                    232:                syscallarg(char *) buf;
                    233:                syscallarg(size_t) count;
                    234:        } */ *uap = v;
                    235:        struct proc *p = l->l_proc;
                    236:        struct dirent *bdp;
                    237:        struct vnode *vp;
                    238:        caddr_t inp, tbuf;      /* BSD-format */
                    239:        int len, reclen;        /* BSD-format */
1.4       yamt      240:        caddr_t outp;           /* NetBSD-3.0-format */
1.1       christos  241:        int resid;
                    242:        struct file *fp;
                    243:        struct uio auio;
                    244:        struct iovec aiov;
                    245:        struct dirent12 idb;
                    246:        off_t off;              /* true file offset */
                    247:        int buflen, error, eofflag;
                    248:        off_t *cookiebuf = NULL, *cookie;
                    249:        int ncookies;
                    250:
                    251:        /* getvnode() will use the descriptor for us */
                    252:        if ((error = getvnode(p->p_fd, SCARG(uap, fd), &fp)) != 0)
                    253:                return error;
                    254:
                    255:        if ((fp->f_flag & FREAD) == 0) {
                    256:                error = EBADF;
                    257:                goto out1;
                    258:        }
                    259:
                    260:        vp = (struct vnode *)fp->f_data;
                    261:        if (vp->v_type != VDIR) {
                    262:                error = EINVAL;
                    263:                goto out1;
                    264:        }
                    265:
                    266:        buflen = min(MAXBSIZE, SCARG(uap, count));
                    267:        tbuf = malloc(buflen, M_TEMP, M_WAITOK);
                    268:        vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
                    269:        off = fp->f_offset;
                    270: again:
                    271:        aiov.iov_base = tbuf;
                    272:        aiov.iov_len = buflen;
                    273:        auio.uio_iov = &aiov;
                    274:        auio.uio_iovcnt = 1;
                    275:        auio.uio_rw = UIO_READ;
                    276:        auio.uio_resid = buflen;
                    277:        auio.uio_offset = off;
1.7       yamt      278:        UIO_SETUP_SYSSPACE(&auio);
1.1       christos  279:        /*
                    280:          * First we read into the malloc'ed buffer, then
                    281:          * we massage it into user space, one record at a time.
                    282:          */
                    283:        error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag, &cookiebuf,
                    284:            &ncookies);
                    285:        if (error)
                    286:                goto out;
                    287:
                    288:        inp = tbuf;
                    289:        outp = SCARG(uap, buf);
                    290:        resid = SCARG(uap, count);
                    291:        if ((len = buflen - auio.uio_resid) == 0)
                    292:                goto eof;
                    293:
                    294:        for (cookie = cookiebuf; len > 0; len -= reclen) {
                    295:                bdp = (struct dirent *)inp;
                    296:                reclen = bdp->d_reclen;
1.2       christos  297:                if (reclen & _DIRENT_ALIGN(bdp))
1.1       christos  298:                        panic("netbsd30_getdents: bad reclen %d", reclen);
                    299:                if (cookie)
                    300:                        off = *cookie++; /* each entry points to the next */
                    301:                else
                    302:                        off += reclen;
                    303:                if ((off >> 32) != 0) {
1.4       yamt      304:                        compat_offseterr(vp, "netbsd30_getdents");
1.1       christos  305:                        error = EINVAL;
                    306:                        goto out;
                    307:                }
                    308:                if (bdp->d_namlen >= sizeof(idb.d_name))
                    309:                        idb.d_namlen = sizeof(idb.d_name) - 1;
                    310:                else
                    311:                        idb.d_namlen = bdp->d_namlen;
                    312:                idb.d_reclen = _DIRENT_SIZE(&idb);
                    313:                if (reclen > len || resid < idb.d_reclen) {
                    314:                        /* entry too big for buffer, so just stop */
                    315:                        outp++;
                    316:                        break;
                    317:                }
                    318:                /*
1.4       yamt      319:                 * Massage in place to make a NetBSD-3.0-shaped dirent
1.1       christos  320:                 * (otherwise we have to worry about touching user memory
                    321:                 * outside of the copyout() call).
                    322:                 */
                    323:                idb.d_fileno = (u_int32_t)bdp->d_fileno;
                    324:                idb.d_type = bdp->d_type;
                    325:                (void)memcpy(idb.d_name, bdp->d_name, idb.d_namlen);
1.3       yamt      326:                memset(idb.d_name + idb.d_namlen, 0,
                    327:                    idb.d_reclen - _DIRENT_NAMEOFF(&idb) - idb.d_namlen);
1.1       christos  328:                if ((error = copyout(&idb, outp, idb.d_reclen)) != 0)
                    329:                        goto out;
                    330:                /* advance past this real entry */
                    331:                inp += reclen;
1.4       yamt      332:                /* advance output past NetBSD-3.0-shaped entry */
1.1       christos  333:                outp += idb.d_reclen;
                    334:                resid -= idb.d_reclen;
                    335:        }
                    336:
                    337:        /* if we squished out the whole block, try again */
                    338:        if (outp == SCARG(uap, buf))
                    339:                goto again;
                    340:        fp->f_offset = off;     /* update the vnode offset */
                    341:
                    342: eof:
                    343:        *retval = SCARG(uap, count) - resid;
                    344: out:
                    345:        VOP_UNLOCK(vp, 0);
                    346:        if (cookiebuf)
                    347:                free(cookiebuf, M_TEMP);
                    348:        free(tbuf, M_TEMP);
                    349: out1:
1.6       christos  350:        FILE_UNUSE(fp, l);
1.1       christos  351:        return error;
                    352: }
1.7.2.2 ! yamt      353:
        !           354: /*
        !           355:  * Get file handle system call
        !           356:  */
        !           357: int
        !           358: compat_30_sys_getfh(struct lwp *l, void *v, register_t *retval)
        !           359: {
        !           360:        struct compat_30_sys_getfh_args /* {
        !           361:                syscallarg(char *) fname;
        !           362:                syscallarg(struct compat_30_fhandle *) fhp;
        !           363:        } */ *uap = v;
        !           364:        struct vnode *vp;
        !           365:        struct compat_30_fhandle fh;
        !           366:        int error;
        !           367:        struct nameidata nd;
        !           368:        size_t sz;
        !           369:
        !           370:        /*
        !           371:         * Must be super user
        !           372:         */
        !           373:        error = kauth_authorize_generic(l->l_cred, KAUTH_GENERIC_ISSUSER,
        !           374:            &l->l_acflag);
        !           375:        if (error)
        !           376:                return (error);
        !           377:        NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
        !           378:            SCARG(uap, fname), l);
        !           379:        error = namei(&nd);
        !           380:        if (error)
        !           381:                return (error);
        !           382:        vp = nd.ni_vp;
        !           383:        sz = sizeof(struct compat_30_fhandle);
        !           384:        error = vfs_composefh(vp, (void *)&fh, &sz);
        !           385:        vput(vp);
        !           386:        if (sz != FHANDLE_SIZE_COMPAT) {
        !           387:                error = EINVAL;
        !           388:        }
        !           389:        if (error)
        !           390:                return (error);
        !           391:        error = copyout(&fh, SCARG(uap, fhp), sizeof(struct compat_30_fhandle));
        !           392:        return (error);
        !           393: }
        !           394:
        !           395: /*
        !           396:  * Open a file given a file handle.
        !           397:  *
        !           398:  * Check permissions, allocate an open file structure,
        !           399:  * and call the device open routine if any.
        !           400:  */
        !           401: int
        !           402: compat_30_sys_fhopen(struct lwp *l, void *v, register_t *retval)
        !           403: {
        !           404:        struct compat_30_sys_fhopen_args /* {
        !           405:                syscallarg(const fhandle_t *) fhp;
        !           406:                syscallarg(int) flags;
        !           407:        } */ *uap = v;
        !           408:
        !           409:        return dofhopen(l, SCARG(uap, fhp), FHANDLE_SIZE_COMPAT,
        !           410:            SCARG(uap, flags), retval);
        !           411: }
        !           412:
        !           413: /* ARGSUSED */
        !           414: int
        !           415: compat_30_sys___fhstat30(struct lwp *l, void *v, register_t *retval)
        !           416: {
        !           417:        struct compat_30_sys___fhstat30_args /* {
        !           418:                syscallarg(const fhandle_t *) fhp;
        !           419:                syscallarg(struct stat *) sb;
        !           420:        } */ *uap = v;
        !           421:
        !           422:        return dofhstat(l, SCARG(uap, fhp), FHANDLE_SIZE_COMPAT,
        !           423:            SCARG(uap, sb), retval);
        !           424: }
        !           425:
        !           426: /* ARGSUSED */
        !           427: int
        !           428: compat_30_sys_fhstatvfs1(struct lwp *l, void *v, register_t *retval)
        !           429: {
        !           430:        struct compat_30_sys_fhstatvfs1_args /* {
        !           431:                syscallarg(const fhandle_t *) fhp;
        !           432:                syscallarg(struct statvfs *) buf;
        !           433:                syscallarg(int) flags;
        !           434:        } */ *uap = v;
        !           435:
        !           436:        return dofhstatvfs(l, SCARG(uap, fhp), FHANDLE_SIZE_COMPAT,
        !           437:            SCARG(uap, buf), SCARG(uap, flags), retval);
        !           438: }

CVSweb <webmaster@jp.NetBSD.org>