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

Annotation of src/sys/kern/vfs_xattr.c, Revision 1.10

1.10    ! elad        1: /*     $NetBSD: vfs_xattr.c,v 1.9 2006/11/01 10:17:59 yamt Exp $       */
1.2       thorpej     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 Jason R. Thorpe.
                      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:  */
1.1       thorpej    38:
                     39: /*
                     40:  * Copyright (c) 1989, 1993
                     41:  *     The Regents of the University of California.  All rights reserved.
                     42:  * (c) UNIX System Laboratories, Inc.
                     43:  * All or some portions of this file are derived from material licensed
                     44:  * to the University of California by American Telephone and Telegraph
                     45:  * Co. or Unix System Laboratories, Inc. and are reproduced herein with
                     46:  * the permission of UNIX System Laboratories, Inc.
                     47:  *
                     48:  * Redistribution and use in source and binary forms, with or without
                     49:  * modification, are permitted provided that the following conditions
                     50:  * are met:
                     51:  * 1. Redistributions of source code must retain the above copyright
                     52:  *    notice, this list of conditions and the following disclaimer.
                     53:  * 2. Redistributions in binary form must reproduce the above copyright
                     54:  *    notice, this list of conditions and the following disclaimer in the
                     55:  *    documentation and/or other materials provided with the distribution.
                     56:  * 3. Neither the name of the University nor the names of its contributors
                     57:  *    may be used to endorse or promote products derived from this software
                     58:  *    without specific prior written permission.
                     59:  *
                     60:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
                     61:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     62:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     63:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                     64:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     65:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     66:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     67:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     68:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     69:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     70:  * SUCH DAMAGE.
                     71:  */
                     72:
                     73: /*
                     74:  * VFS extended attribute support.
                     75:  */
                     76:
                     77: #include <sys/cdefs.h>
1.10    ! elad       78: __KERNEL_RCSID(0, "$NetBSD: vfs_xattr.c,v 1.9 2006/11/01 10:17:59 yamt Exp $");
1.1       thorpej    79:
                     80: #include <sys/param.h>
                     81: #include <sys/systm.h>
                     82: #include <sys/namei.h>
                     83: #include <sys/filedesc.h>
                     84: #include <sys/kernel.h>
                     85: #include <sys/file.h>
                     86: #include <sys/vnode.h>
                     87: #include <sys/mount.h>
                     88: #include <sys/proc.h>
                     89: #include <sys/uio.h>
                     90: #include <sys/extattr.h>
1.2       thorpej    91: #include <sys/xattr.h>
1.1       thorpej    92: #include <sys/sysctl.h>
                     93: #include <sys/sa.h>
                     94: #include <sys/syscallargs.h>
1.6       elad       95: #include <sys/kauth.h>
1.1       thorpej    96:
                     97: /*
1.3       thorpej    98:  * Credential check based on process requesting service, and per-attribute
                     99:  * permissions.
                    100:  *
                    101:  * NOTE: Vnode must be locked.
                    102:  */
                    103: int
                    104: extattr_check_cred(struct vnode *vp, int attrnamespace,
1.6       elad      105:     kauth_cred_t cred, struct lwp *l, int access)
1.3       thorpej   106: {
                    107:
                    108:        if (cred == NOCRED)
                    109:                return (0);
                    110:
                    111:        switch (attrnamespace) {
                    112:        case EXTATTR_NAMESPACE_SYSTEM:
                    113:                /*
                    114:                 * Do we really want to allow this, or just require that
                    115:                 * these requests come from kernel code (NOCRED case above)?
                    116:                 */
1.6       elad      117:                return (kauth_authorize_generic(cred, KAUTH_GENERIC_ISSUSER,
1.10    ! elad      118:                    NULL));
1.3       thorpej   119:
                    120:        case EXTATTR_NAMESPACE_USER:
1.4       christos  121:                return (VOP_ACCESS(vp, access, cred, l));
1.3       thorpej   122:
                    123:        default:
                    124:                return (EPERM);
                    125:        }
                    126: }
                    127:
                    128: /*
                    129:  * Default vfs_extattrctl routine for file systems that do not support
                    130:  * it.
                    131:  */
                    132: /*ARGSUSED*/
                    133: int
1.9       yamt      134: vfs_stdextattrctl(struct mount *mp, int cmt, struct vnode *vp,
                    135:     int attrnamespace, const char *attrname, struct lwp *l)
1.3       thorpej   136: {
                    137:
                    138:        if (vp != NULL)
                    139:                VOP_UNLOCK(vp, 0);
                    140:        return (EOPNOTSUPP);
                    141: }
                    142:
                    143: /*
1.2       thorpej   144:  * Push extended attribute configuration information into the file
                    145:  * system.
1.1       thorpej   146:  *
                    147:  * NOTE: Not all file systems that support extended attributes will
                    148:  * require the use of this system call.
                    149:  */
                    150: int
1.9       yamt      151: sys_extattrctl(struct lwp *l, void *v, register_t *retval)
1.1       thorpej   152: {
                    153:        struct sys_extattrctl_args /* {
                    154:                syscallarg(const char *) path;
                    155:                syscallarg(int) cmd;
                    156:                syscallarg(const char *) filename;
                    157:                syscallarg(int) attrnamespace;
                    158:                syscallarg(const char *) attrname;
                    159:        } */ *uap = v;
                    160:        struct vnode *vp;
                    161:        struct nameidata nd;
                    162:        struct mount *mp;
                    163:        char attrname[EXTATTR_MAXNAMELEN];
                    164:        int error;
                    165:
                    166:        if (SCARG(uap, attrname) != NULL) {
                    167:                error = copyinstr(SCARG(uap, attrname), attrname,
                    168:                    sizeof(attrname), NULL);
                    169:                if (error)
                    170:                        return (error);
                    171:        }
                    172:
                    173:        vp = NULL;
                    174:        if (SCARG(uap, filename) != NULL) {
                    175:                NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
1.4       christos  176:                    SCARG(uap, filename), l);
1.1       thorpej   177:                error = namei(&nd);
                    178:                if (error)
                    179:                        return (error);
                    180:                vp = nd.ni_vp;
                    181:        }
                    182:
1.4       christos  183:        NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), l);
1.1       thorpej   184:        error = namei(&nd);
                    185:        if (error) {
                    186:                if (vp != NULL)
                    187:                        vput(vp);
                    188:                return (error);
                    189:        }
                    190:
                    191:        error = vn_start_write(nd.ni_vp, &mp, V_WAIT | V_PCATCH);
                    192:        if (error) {
                    193:                if (vp != NULL)
                    194:                        vput(vp);
                    195:                return (error);
                    196:        }
                    197:
                    198:        error = VFS_EXTATTRCTL(mp, SCARG(uap, cmd), vp,
                    199:            SCARG(uap, attrnamespace),
1.4       christos  200:            SCARG(uap, attrname) != NULL ? attrname : NULL, l);
1.1       thorpej   201:
                    202:        vn_finished_write(mp, 0);
                    203:
                    204:        if (vp != NULL)
                    205:                vrele(vp);
                    206:
                    207:        return (error);
                    208: }
                    209:
                    210: /*****************************************************************************
                    211:  * Internal routines to manipulate file system extended attributes:
                    212:  *     - set
                    213:  *     - get
                    214:  *     - delete
                    215:  *     - list
                    216:  *****************************************************************************/
                    217:
                    218: /*
                    219:  * extattr_set_vp:
                    220:  *
                    221:  *     Set a named extended attribute on a file or directory.
                    222:  */
                    223: static int
                    224: extattr_set_vp(struct vnode *vp, int attrnamespace, const char *attrname,
1.4       christos  225:     const void *data, size_t nbytes, struct lwp *l, register_t *retval)
1.1       thorpej   226: {
                    227:        struct mount *mp;
                    228:        struct uio auio;
                    229:        struct iovec aiov;
                    230:        ssize_t cnt;
                    231:        int error;
                    232:
                    233:        error = vn_start_write(vp, &mp, V_WAIT | V_PCATCH);
                    234:        if (error)
                    235:                return (error);
1.7       ad        236:        VOP_LEASE(vp, l, l->l_cred, LEASE_WRITE);
1.1       thorpej   237:        vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
                    238:
                    239:        aiov.iov_base = __UNCONST(data);        /* XXXUNCONST kills const */
                    240:        aiov.iov_len = nbytes;
                    241:        auio.uio_iov = &aiov;
                    242:        auio.uio_iovcnt = 1;
                    243:        auio.uio_offset = 0;
                    244:        if (nbytes > INT_MAX) {
                    245:                error = EINVAL;
                    246:                goto done;
                    247:        }
                    248:        auio.uio_resid = nbytes;
                    249:        auio.uio_rw = UIO_WRITE;
1.5       yamt      250:        KASSERT(l == curlwp);
                    251:        auio.uio_vmspace = l->l_proc->p_vmspace;
1.1       thorpej   252:        cnt = nbytes;
                    253:
                    254:        error = VOP_SETEXTATTR(vp, attrnamespace, attrname, &auio,
1.7       ad        255:            l->l_cred, l);
1.1       thorpej   256:        cnt -= auio.uio_resid;
                    257:        retval[0] = cnt;
                    258:
                    259:  done:
                    260:        VOP_UNLOCK(vp, 0);
                    261:        vn_finished_write(mp, 0);
                    262:        return (error);
                    263: }
                    264:
                    265: /*
                    266:  * extattr_get_vp:
                    267:  *
                    268:  *     Get a named extended attribute on a file or directory.
                    269:  */
                    270: static int
                    271: extattr_get_vp(struct vnode *vp, int attrnamespace, const char *attrname,
1.4       christos  272:     void *data, size_t nbytes, struct lwp *l, register_t *retval)
1.1       thorpej   273: {
                    274:        struct uio auio, *auiop;
                    275:        struct iovec aiov;
                    276:        ssize_t cnt;
                    277:        size_t size, *sizep;
                    278:        int error;
                    279:
1.7       ad        280:        VOP_LEASE(vp, l, l->l_cred, LEASE_READ);
1.1       thorpej   281:        vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
                    282:
                    283:        /*
                    284:         * Slightly unusual semantics: if the user provides a NULL data
                    285:         * pointer, they don't want to receive the data, just the maximum
                    286:         * read length.
                    287:         */
                    288:        auiop = NULL;
                    289:        sizep = NULL;
                    290:        cnt = 0;
                    291:        if (data != NULL) {
                    292:                aiov.iov_base = data;
                    293:                aiov.iov_len = nbytes;
                    294:                auio.uio_iov = &aiov;
                    295:                auio.uio_offset = 0;
                    296:                if (nbytes > INT_MAX) {
                    297:                        error = EINVAL;
                    298:                        goto done;
                    299:                }
                    300:                auio.uio_resid = nbytes;
                    301:                auio.uio_rw = UIO_READ;
1.5       yamt      302:                KASSERT(l == curlwp);
                    303:                auio.uio_vmspace = l->l_proc->p_vmspace;
1.1       thorpej   304:                auiop = &auio;
                    305:                cnt = nbytes;
                    306:        } else
                    307:                sizep = &size;
                    308:
                    309:        error = VOP_GETEXTATTR(vp, attrnamespace, attrname, auiop, sizep,
1.7       ad        310:            l->l_cred, l);
1.1       thorpej   311:
                    312:        if (auiop != NULL) {
                    313:                cnt -= auio.uio_resid;
                    314:                retval[0] = cnt;
                    315:        } else
                    316:                retval[0] = size;
                    317:
                    318:  done:
                    319:        VOP_UNLOCK(vp, 0);
                    320:        return (error);
                    321: }
                    322:
                    323: /*
                    324:  * extattr_delete_vp:
                    325:  *
                    326:  *     Delete a named extended attribute on a file or directory.
                    327:  */
                    328: static int
                    329: extattr_delete_vp(struct vnode *vp, int attrnamespace, const char *attrname,
1.4       christos  330:     struct lwp *l)
1.1       thorpej   331: {
                    332:        struct mount *mp;
                    333:        int error;
                    334:
                    335:        error = vn_start_write(vp, &mp, V_WAIT | V_PCATCH);
                    336:        if (error)
                    337:                return (error);
1.7       ad        338:        VOP_LEASE(vp, l, l->l_cred, LEASE_WRITE);
1.1       thorpej   339:        vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
                    340:
1.7       ad        341:        error = VOP_DELETEEXTATTR(vp, attrnamespace, attrname, l->l_cred, l);
1.1       thorpej   342:        if (error == EOPNOTSUPP)
                    343:                error = VOP_SETEXTATTR(vp, attrnamespace, attrname, NULL,
1.7       ad        344:                    l->l_cred, l);
1.1       thorpej   345:
                    346:        VOP_UNLOCK(vp, 0);
                    347:        vn_finished_write(mp, 0);
                    348:        return (error);
                    349: }
                    350:
                    351: /*
                    352:  * extattr_list_vp:
                    353:  *
                    354:  *     Retrieve a list of extended attributes on a file or directory.
                    355:  */
                    356: static int
                    357: extattr_list_vp(struct vnode *vp, int attrnamespace, void *data, size_t nbytes,
1.4       christos  358:     struct lwp *l, register_t *retval)
1.1       thorpej   359: {
                    360:        struct uio auio, *auiop;
                    361:        size_t size, *sizep;
                    362:        struct iovec aiov;
                    363:        ssize_t cnt;
                    364:        int error;
                    365:
1.7       ad        366:        VOP_LEASE(vp, l, l->l_cred, LEASE_READ);
1.1       thorpej   367:        vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
                    368:
                    369:        auiop = NULL;
                    370:        sizep = NULL;
                    371:        cnt = 0;
                    372:        if (data != NULL) {
                    373:                aiov.iov_base = data;
                    374:                aiov.iov_len = nbytes;
                    375:                auio.uio_iov = &aiov;
                    376:                auio.uio_offset = 0;
                    377:                if (nbytes > INT_MAX) {
                    378:                        error = EINVAL;
                    379:                        goto done;
                    380:                }
                    381:                auio.uio_resid = nbytes;
                    382:                auio.uio_rw = UIO_READ;
1.5       yamt      383:                KASSERT(l == curlwp);
                    384:                auio.uio_vmspace = l->l_proc->p_vmspace;
1.1       thorpej   385:                auiop = &auio;
                    386:                cnt = nbytes;
                    387:        } else
                    388:                sizep = &size;
                    389:
                    390:        error = VOP_LISTEXTATTR(vp, attrnamespace, auiop, sizep,
1.7       ad        391:            l->l_cred, l);
1.1       thorpej   392:
                    393:        if (auiop != NULL) {
                    394:                cnt -= auio.uio_resid;
                    395:                retval[0] = cnt;
                    396:        } else
                    397:                retval[0] = size;
                    398:
                    399:  done:
                    400:        VOP_UNLOCK(vp, 0);
                    401:        return (error);
                    402: }
                    403:
                    404: /*****************************************************************************
                    405:  * BSD <sys/extattr.h> API for file system extended attributes
                    406:  *****************************************************************************/
                    407:
                    408: int
                    409: sys_extattr_set_fd(struct lwp *l, void *v, register_t *retval)
                    410: {
                    411:        struct sys_extattr_set_fd_args /* {
                    412:                syscallarg(int) fd;
                    413:                syscallarg(int) attrnamespace;
                    414:                syscallarg(const char *) attrname;
                    415:                syscallarg(const void *) data;
                    416:                syscallarg(size_t) nbytes;
                    417:        } */ *uap = v;
                    418:        struct file *fp;
                    419:        struct vnode *vp;
                    420:        char attrname[EXTATTR_MAXNAMELEN];
                    421:        int error;
                    422:
                    423:        error = copyinstr(SCARG(uap, attrname), attrname, sizeof(attrname),
                    424:            NULL);
                    425:        if (error)
                    426:                return (error);
                    427:
1.4       christos  428:        error = getvnode(l->l_proc->p_fd, SCARG(uap, fd), &fp);
1.1       thorpej   429:        if (error)
                    430:                return (error);
                    431:        vp = (struct vnode *) fp->f_data;
                    432:
                    433:        error = extattr_set_vp(vp, SCARG(uap, attrnamespace), attrname,
1.4       christos  434:            SCARG(uap, data), SCARG(uap, nbytes), l, retval);
1.1       thorpej   435:
1.4       christos  436:        FILE_UNUSE(fp, l);
1.1       thorpej   437:        return (error);
                    438: }
                    439:
                    440: int
                    441: sys_extattr_set_file(struct lwp *l, void *v, register_t *retval)
                    442: {
                    443:        struct sys_extattr_set_file_args /* {
                    444:                syscallarg(const char *) path;
                    445:                syscallarg(int) attrnamespace;
                    446:                syscallarg(const char *) attrname;
                    447:                syscallarg(const void *) data;
                    448:                syscallarg(size_t) nbytes;
                    449:        } */ *uap = v;
                    450:        struct nameidata nd;
                    451:        char attrname[EXTATTR_MAXNAMELEN];
                    452:        int error;
                    453:
                    454:        error = copyinstr(SCARG(uap, attrname), attrname, sizeof(attrname),
                    455:            NULL);
                    456:        if (error)
                    457:                return (error);
                    458:
1.4       christos  459:        NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), l);
1.1       thorpej   460:        error = namei(&nd);
                    461:        if (error)
                    462:                return (error);
                    463:
                    464:        error = extattr_set_vp(nd.ni_vp, SCARG(uap, attrnamespace), attrname,
1.4       christos  465:            SCARG(uap, data), SCARG(uap, nbytes), l, retval);
1.1       thorpej   466:
                    467:        vrele(nd.ni_vp);
                    468:        return (error);
                    469: }
                    470:
                    471: int
                    472: sys_extattr_set_link(struct lwp *l, void *v, register_t *retval)
                    473: {
                    474:        struct sys_extattr_set_link_args /* {
                    475:                syscallarg(const char *) path;
                    476:                syscallarg(int) attrnamespace;
                    477:                syscallarg(const char *) attrname;
                    478:                syscallarg(const void *) data;
                    479:                syscallarg(size_t) nbytes;
                    480:        } */ *uap = v;
                    481:        struct nameidata nd;
                    482:        char attrname[EXTATTR_MAXNAMELEN];
                    483:        int error;
                    484:
                    485:        error = copyinstr(SCARG(uap, attrname), attrname, sizeof(attrname),
                    486:            NULL);
                    487:        if (error)
                    488:                return (error);
                    489:
1.4       christos  490:        NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_USERSPACE, SCARG(uap, path), l);
1.1       thorpej   491:        error = namei(&nd);
                    492:        if (error)
                    493:                return (error);
                    494:
                    495:        error = extattr_set_vp(nd.ni_vp, SCARG(uap, attrnamespace), attrname,
1.4       christos  496:            SCARG(uap, data), SCARG(uap, nbytes), l, retval);
1.1       thorpej   497:
                    498:        vrele(nd.ni_vp);
                    499:        return (error);
                    500: }
                    501:
                    502: int
                    503: sys_extattr_get_fd(struct lwp *l, void *v, register_t *retval)
                    504: {
                    505:        struct sys_extattr_get_fd_args /* {
                    506:                syscallarg(int) fd;
                    507:                syscallarg(int) attrnamespace;
                    508:                syscallarg(const char *) attrname;
                    509:                syscallarg(void *) data;
                    510:                syscallarg(size_t) nbytes;
                    511:        } */ *uap = v;
                    512:        struct file *fp;
                    513:        struct vnode *vp;
                    514:        char attrname[EXTATTR_MAXNAMELEN];
                    515:        int error;
                    516:
                    517:        error = copyinstr(SCARG(uap, attrname), attrname, sizeof(attrname),
                    518:            NULL);
                    519:        if (error)
                    520:                return (error);
                    521:
1.4       christos  522:        error = getvnode(l->l_proc->p_fd, SCARG(uap, fd), &fp);
1.1       thorpej   523:        if (error)
                    524:                return (error);
                    525:        vp = (struct vnode *) fp->f_data;
                    526:
                    527:        error = extattr_get_vp(vp, SCARG(uap, attrnamespace), attrname,
1.4       christos  528:            SCARG(uap, data), SCARG(uap, nbytes), l, retval);
1.1       thorpej   529:
1.4       christos  530:        FILE_UNUSE(fp, l);
1.1       thorpej   531:        return (error);
                    532: }
                    533:
                    534: int
                    535: sys_extattr_get_file(struct lwp *l, void *v, register_t *retval)
                    536: {
                    537:        struct sys_extattr_get_file_args /* {
                    538:                syscallarg(const char *) path;
                    539:                syscallarg(int) attrnamespace;
                    540:                syscallarg(const char *) attrname;
                    541:                syscallarg(void *) data;
                    542:                syscallarg(size_t) nbytes;
                    543:        } */ *uap = v;
                    544:        struct nameidata nd;
                    545:        char attrname[EXTATTR_MAXNAMELEN];
                    546:        int error;
                    547:
                    548:        error = copyinstr(SCARG(uap, attrname), attrname, sizeof(attrname),
                    549:            NULL);
                    550:        if (error)
                    551:                return (error);
                    552:
1.4       christos  553:        NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), l);
1.1       thorpej   554:        error = namei(&nd);
                    555:        if (error)
                    556:                return (error);
                    557:
                    558:        error = extattr_get_vp(nd.ni_vp, SCARG(uap, attrnamespace), attrname,
1.4       christos  559:            SCARG(uap, data), SCARG(uap, nbytes), l, retval);
1.1       thorpej   560:
                    561:        vrele(nd.ni_vp);
                    562:        return (error);
                    563: }
                    564:
                    565: int
                    566: sys_extattr_get_link(struct lwp *l, void *v, register_t *retval)
                    567: {
                    568:        struct sys_extattr_get_link_args /* {
                    569:                syscallarg(const char *) path;
                    570:                syscallarg(int) attrnamespace;
                    571:                syscallarg(const char *) attrname;
                    572:                syscallarg(void *) data;
                    573:                syscallarg(size_t) nbytes;
                    574:        } */ *uap = v;
                    575:        struct nameidata nd;
                    576:        char attrname[EXTATTR_MAXNAMELEN];
                    577:        int error;
                    578:
                    579:        error = copyinstr(SCARG(uap, attrname), attrname, sizeof(attrname),
                    580:            NULL);
                    581:        if (error)
                    582:                return (error);
                    583:
1.4       christos  584:        NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_USERSPACE, SCARG(uap, path), l);
1.1       thorpej   585:        error = namei(&nd);
                    586:        if (error)
                    587:                return (error);
                    588:
                    589:        error = extattr_get_vp(nd.ni_vp, SCARG(uap, attrnamespace), attrname,
1.4       christos  590:            SCARG(uap, data), SCARG(uap, nbytes), l, retval);
1.1       thorpej   591:
                    592:        vrele(nd.ni_vp);
                    593:        return (error);
                    594: }
                    595:
                    596: int
1.9       yamt      597: sys_extattr_delete_fd(struct lwp *l, void *v, register_t *retval)
1.1       thorpej   598: {
                    599:        struct sys_extattr_delete_fd_args /* {
                    600:                syscallarg(int) fd;
                    601:                syscallarg(int) attrnamespace;
                    602:                syscallarg(const char *) attrname;
                    603:        } */ *uap = v;
                    604:        struct file *fp;
                    605:        struct vnode *vp;
                    606:        char attrname[EXTATTR_MAXNAMELEN];
                    607:        int error;
                    608:
                    609:        error = copyinstr(SCARG(uap, attrname), attrname, sizeof(attrname),
                    610:            NULL);
                    611:        if (error)
                    612:                return (error);
                    613:
1.4       christos  614:        error = getvnode(l->l_proc->p_fd, SCARG(uap, fd), &fp);
1.1       thorpej   615:        if (error)
                    616:                return (error);
                    617:        vp = (struct vnode *) fp->f_data;
                    618:
1.4       christos  619:        error = extattr_delete_vp(vp, SCARG(uap, attrnamespace), attrname, l);
1.1       thorpej   620:
1.4       christos  621:        FILE_UNUSE(fp, l);
1.1       thorpej   622:        return (error);
                    623: }
                    624:
                    625: int
1.9       yamt      626: sys_extattr_delete_file(struct lwp *l, void *v, register_t *retval)
1.1       thorpej   627: {
                    628:        struct sys_extattr_delete_file_args /* {
                    629:                syscallarg(const char *) path;
                    630:                syscallarg(int) attrnamespace;
                    631:                syscallarg(const char *) attrname;
                    632:        } */ *uap = v;
                    633:        struct nameidata nd;
                    634:        char attrname[EXTATTR_MAXNAMELEN];
                    635:        int error;
                    636:
                    637:        error = copyinstr(SCARG(uap, attrname), attrname, sizeof(attrname),
                    638:            NULL);
                    639:        if (error)
                    640:                return (error);
                    641:
1.4       christos  642:        NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), l);
1.1       thorpej   643:        error = namei(&nd);
                    644:        if (error)
                    645:                return (error);
                    646:
                    647:        error = extattr_delete_vp(nd.ni_vp, SCARG(uap, attrnamespace), attrname,
1.4       christos  648:            l);
1.1       thorpej   649:
                    650:        vrele(nd.ni_vp);
                    651:        return (error);
                    652: }
                    653:
                    654: int
1.9       yamt      655: sys_extattr_delete_link(struct lwp *l, void *v, register_t *retval)
1.1       thorpej   656: {
                    657:        struct sys_extattr_delete_link_args /* {
                    658:                syscallarg(const char *) path;
                    659:                syscallarg(int) attrnamespace;
                    660:                syscallarg(const char *) attrname;
                    661:        } */ *uap = v;
                    662:        struct nameidata nd;
                    663:        char attrname[EXTATTR_MAXNAMELEN];
                    664:        int error;
                    665:
                    666:        error = copyinstr(SCARG(uap, attrname), attrname, sizeof(attrname),
                    667:            NULL);
                    668:        if (error)
                    669:                return (error);
                    670:
1.4       christos  671:        NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_USERSPACE, SCARG(uap, path), l);
1.1       thorpej   672:        error = namei(&nd);
                    673:        if (error)
                    674:                return (error);
                    675:
                    676:        error = extattr_delete_vp(nd.ni_vp, SCARG(uap, attrnamespace), attrname,
1.4       christos  677:            l);
1.1       thorpej   678:
                    679:        vrele(nd.ni_vp);
                    680:        return (error);
                    681: }
                    682:
                    683: int
                    684: sys_extattr_list_fd(struct lwp *l, void *v, register_t *retval)
                    685: {
                    686:        struct sys_extattr_list_fd_args /* {
                    687:                syscallarg(int) fd;
                    688:                syscallarg(int) attrnamespace;
                    689:                syscallarg(void *) data;
                    690:                syscallarg(size_t) nbytes;
                    691:        } */ *uap = v;
                    692:        struct file *fp;
                    693:        struct vnode *vp;
                    694:        int error;
                    695:
1.4       christos  696:        error = getvnode(l->l_proc->p_fd, SCARG(uap, fd), &fp);
1.1       thorpej   697:        if (error)
                    698:                return (error);
                    699:        vp = (struct vnode *) fp->f_data;
                    700:
                    701:        error = extattr_list_vp(vp, SCARG(uap, attrnamespace),
1.4       christos  702:            SCARG(uap, data), SCARG(uap, nbytes), l, retval);
1.1       thorpej   703:
1.4       christos  704:        FILE_UNUSE(fp, l);
1.1       thorpej   705:        return (error);
                    706: }
                    707:
                    708: int
                    709: sys_extattr_list_file(struct lwp *l, void *v, register_t *retval)
                    710: {
                    711:        struct sys_extattr_list_file_args /* {
                    712:                syscallarg(const char *) path;
                    713:                syscallarg(int) attrnamespace;
                    714:                syscallarg(void *) data;
                    715:                syscallarg(size_t) nbytes;
                    716:        } */ *uap = v;
                    717:        struct nameidata nd;
                    718:        int error;
                    719:
1.4       christos  720:        NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), l);
1.1       thorpej   721:        error = namei(&nd);
                    722:        if (error)
                    723:                return (error);
                    724:
                    725:        error = extattr_list_vp(nd.ni_vp, SCARG(uap, attrnamespace),
1.4       christos  726:            SCARG(uap, data), SCARG(uap, nbytes), l, retval);
1.1       thorpej   727:
                    728:        vrele(nd.ni_vp);
                    729:        return (error);
                    730: }
                    731:
                    732: int
                    733: sys_extattr_list_link(struct lwp *l, void *v, register_t *retval)
                    734: {
                    735:        struct sys_extattr_list_link_args /* {
                    736:                syscallarg(const char *) path;
                    737:                syscallarg(int) attrnamespace;
                    738:                syscallarg(void *) data;
                    739:                syscallarg(size_t) nbytes;
                    740:        } */ *uap = v;
                    741:        struct nameidata nd;
                    742:        int error;
                    743:
1.4       christos  744:        NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_USERSPACE, SCARG(uap, path), l);
1.1       thorpej   745:        error = namei(&nd);
                    746:        if (error)
                    747:                return (error);
                    748:
                    749:        error = extattr_list_vp(nd.ni_vp, SCARG(uap, attrnamespace),
1.4       christos  750:            SCARG(uap, data), SCARG(uap, nbytes), l, retval);
1.1       thorpej   751:
                    752:        vrele(nd.ni_vp);
                    753:        return (error);
                    754: }
1.2       thorpej   755:
                    756: /*****************************************************************************
                    757:  * Linux-compatible <sys/xattr.h> API for file system extended attributes
                    758:  *****************************************************************************/
                    759:
                    760: int
                    761: sys_setxattr(struct lwp *l, void *v, register_t *retval)
                    762: {
                    763:        struct sys_setxattr_args /* {
                    764:                syscallarg(const char *) path;
                    765:                syscallarg(const char *) name;
                    766:                syscallarg(void *) value;
                    767:                syscallarg(size_t) size;
                    768:                syscallarg(int) flags;
                    769:        } */ *uap = v;
                    770:        struct nameidata nd;
                    771:        char attrname[XATTR_NAME_MAX];
                    772:        int error;
                    773:
                    774:        error = copyinstr(SCARG(uap, name), attrname, sizeof(attrname),
                    775:            NULL);
                    776:        if (error)
                    777:                return (error);
                    778:
1.4       christos  779:        NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), l);
1.2       thorpej   780:        error = namei(&nd);
                    781:        if (error)
                    782:                return (error);
                    783:
                    784:        /* XXX flags */
                    785:
                    786:        error = extattr_set_vp(nd.ni_vp, EXTATTR_NAMESPACE_USER,
1.4       christos  787:            attrname, SCARG(uap, value), SCARG(uap, size), l, retval);
1.2       thorpej   788:
                    789:        vrele(nd.ni_vp);
                    790:        return (error);
                    791: }
                    792:
                    793: int
                    794: sys_lsetxattr(struct lwp *l, void *v, register_t *retval)
                    795: {
                    796:        struct sys_lsetxattr_args /* {
                    797:                syscallarg(const char *) path;
                    798:                syscallarg(const char *) name;
                    799:                syscallarg(void *) value;
                    800:                syscallarg(size_t) size;
                    801:                syscallarg(int) flags;
                    802:        } */ *uap = v;
                    803:        struct nameidata nd;
                    804:        char attrname[XATTR_NAME_MAX];
                    805:        int error;
                    806:
                    807:        error = copyinstr(SCARG(uap, name), attrname, sizeof(attrname),
                    808:            NULL);
                    809:        if (error)
                    810:                return (error);
                    811:
1.4       christos  812:        NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_USERSPACE, SCARG(uap, path), l);
1.2       thorpej   813:        error = namei(&nd);
                    814:        if (error)
                    815:                return (error);
                    816:
                    817:        /* XXX flags */
                    818:
                    819:        error = extattr_set_vp(nd.ni_vp, EXTATTR_NAMESPACE_USER,
1.4       christos  820:            attrname, SCARG(uap, value), SCARG(uap, size), l, retval);
1.2       thorpej   821:
                    822:        vrele(nd.ni_vp);
                    823:        return (error);
                    824: }
                    825:
                    826: int
                    827: sys_fsetxattr(struct lwp *l, void *v, register_t *retval)
                    828: {
                    829:        struct sys_fsetxattr_args /* {
                    830:                syscallarg(int) fd;
                    831:                syscallarg(const char *) name;
                    832:                syscallarg(void *) value;
                    833:                syscallarg(size_t) size;
                    834:                syscallarg(int) flags;
                    835:        } */ *uap = v;
                    836:        struct file *fp;
                    837:        struct vnode *vp;
                    838:        char attrname[XATTR_NAME_MAX];
                    839:        int error;
                    840:
                    841:        error = copyinstr(SCARG(uap, name), attrname, sizeof(attrname),
                    842:            NULL);
                    843:        if (error)
                    844:                return (error);
                    845:
1.4       christos  846:        error = getvnode(l->l_proc->p_fd, SCARG(uap, fd), &fp);
1.2       thorpej   847:        if (error)
                    848:                return (error);
                    849:        vp = (struct vnode *) fp->f_data;
                    850:
                    851:        /* XXX flags */
                    852:
                    853:        error = extattr_set_vp(vp, EXTATTR_NAMESPACE_USER,
1.4       christos  854:            attrname, SCARG(uap, value), SCARG(uap, size), l, retval);
1.2       thorpej   855:
1.4       christos  856:        FILE_UNUSE(fp, l);
1.2       thorpej   857:        return (error);
                    858: }
                    859:
                    860: int
                    861: sys_getxattr(struct lwp *l, void *v, register_t *retval)
                    862: {
                    863:        struct sys_getxattr_args /* {
                    864:                syscallarg(const char *) path;
                    865:                syscallarg(const char *) name;
                    866:                syscallarg(void *) value;
                    867:                syscallarg(size_t) size;
                    868:        } */ *uap = v;
                    869:        struct nameidata nd;
                    870:        char attrname[XATTR_NAME_MAX];
                    871:        int error;
                    872:
                    873:        error = copyinstr(SCARG(uap, name), attrname, sizeof(attrname),
                    874:            NULL);
                    875:        if (error)
                    876:                return (error);
                    877:
1.4       christos  878:        NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), l);
1.2       thorpej   879:        error = namei(&nd);
                    880:        if (error)
                    881:                return (error);
                    882:
                    883:        error = extattr_get_vp(nd.ni_vp, EXTATTR_NAMESPACE_USER,
1.4       christos  884:            attrname, SCARG(uap, value), SCARG(uap, size), l, retval);
1.2       thorpej   885:
                    886:        vrele(nd.ni_vp);
                    887:        return (error);
                    888: }
                    889:
                    890: int
                    891: sys_lgetxattr(struct lwp *l, void *v, register_t *retval)
                    892: {
                    893:        struct sys_lgetxattr_args /* {
                    894:                syscallarg(const char *) path;
                    895:                syscallarg(const char *) name;
                    896:                syscallarg(void *) value;
                    897:                syscallarg(size_t) size;
                    898:        } */ *uap = v;
                    899:        struct nameidata nd;
                    900:        char attrname[XATTR_NAME_MAX];
                    901:        int error;
                    902:
                    903:        error = copyinstr(SCARG(uap, name), attrname, sizeof(attrname),
                    904:            NULL);
                    905:        if (error)
                    906:                return (error);
                    907:
1.4       christos  908:        NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_USERSPACE, SCARG(uap, path), l);
1.2       thorpej   909:        error = namei(&nd);
                    910:        if (error)
                    911:                return (error);
                    912:
                    913:        error = extattr_get_vp(nd.ni_vp, EXTATTR_NAMESPACE_USER,
1.4       christos  914:            attrname, SCARG(uap, value), SCARG(uap, size), l, retval);
1.2       thorpej   915:
                    916:        vrele(nd.ni_vp);
                    917:        return (error);
                    918: }
                    919:
                    920: int
                    921: sys_fgetxattr(struct lwp *l, void *v, register_t *retval)
                    922: {
                    923:        struct sys_fgetxattr_args /* {
                    924:                syscallarg(int) fd;
                    925:                syscallarg(const char *) name;
                    926:                syscallarg(void *) value;
                    927:                syscallarg(size_t) size;
                    928:        } */ *uap = v;
                    929:        struct file *fp;
                    930:        struct vnode *vp;
                    931:        char attrname[XATTR_NAME_MAX];
                    932:        int error;
                    933:
                    934:        error = copyinstr(SCARG(uap, name), attrname, sizeof(attrname),
                    935:            NULL);
                    936:        if (error)
                    937:                return (error);
                    938:
1.4       christos  939:        error = getvnode(l->l_proc->p_fd, SCARG(uap, fd), &fp);
1.2       thorpej   940:        if (error)
                    941:                return (error);
                    942:        vp = (struct vnode *) fp->f_data;
                    943:
                    944:        error = extattr_get_vp(vp, EXTATTR_NAMESPACE_USER,
1.4       christos  945:            attrname, SCARG(uap, value), SCARG(uap, size), l, retval);
1.2       thorpej   946:
1.4       christos  947:        FILE_UNUSE(fp, l);
1.2       thorpej   948:        return (error);
                    949: }
                    950:
                    951: int
                    952: sys_listxattr(struct lwp *l, void *v, register_t *retval)
                    953: {
                    954:        struct sys_listxattr_args /* {
                    955:                syscallarg(const char *) path;
                    956:                syscallarg(char *) list;
                    957:                syscallarg(size_t) size;
                    958:        } */ *uap = v;
                    959:        struct nameidata nd;
                    960:        int error;
                    961:
1.4       christos  962:        NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), l);
1.2       thorpej   963:        error = namei(&nd);
                    964:        if (error)
                    965:                return (error);
                    966:
                    967:        error = extattr_list_vp(nd.ni_vp, EXTATTR_NAMESPACE_USER,
1.4       christos  968:            SCARG(uap, list), SCARG(uap, size), l, retval);
1.2       thorpej   969:
                    970:        vrele(nd.ni_vp);
                    971:        return (error);
                    972: }
                    973:
                    974: int
                    975: sys_llistxattr(struct lwp *l, void *v, register_t *retval)
                    976: {
                    977:        struct sys_llistxattr_args /* {
                    978:                syscallarg(const char *) path;
                    979:                syscallarg(char *) list;
                    980:                syscallarg(size_t) size;
                    981:        } */ *uap = v;
                    982:        struct nameidata nd;
                    983:        int error;
                    984:
1.4       christos  985:        NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_USERSPACE, SCARG(uap, path), l);
1.2       thorpej   986:        error = namei(&nd);
                    987:        if (error)
                    988:                return (error);
                    989:
                    990:        error = extattr_list_vp(nd.ni_vp, EXTATTR_NAMESPACE_USER,
1.4       christos  991:            SCARG(uap, list), SCARG(uap, size), l, retval);
1.2       thorpej   992:
                    993:        vrele(nd.ni_vp);
                    994:        return (error);
                    995: }
                    996:
                    997: int
                    998: sys_flistxattr(struct lwp *l, void *v, register_t *retval)
                    999: {
                   1000:        struct sys_flistxattr_args /* {
                   1001:                syscallarg(int) fd;
                   1002:                syscallarg(char *) list;
                   1003:                syscallarg(size_t) size;
                   1004:        } */ *uap = v;
                   1005:        struct file *fp;
                   1006:        struct vnode *vp;
                   1007:        int error;
                   1008:
1.4       christos 1009:        error = getvnode(l->l_proc->p_fd, SCARG(uap, fd), &fp);
1.2       thorpej  1010:        if (error)
                   1011:                return (error);
                   1012:        vp = (struct vnode *) fp->f_data;
                   1013:
                   1014:        error = extattr_list_vp(vp, EXTATTR_NAMESPACE_USER,
1.4       christos 1015:            SCARG(uap, list), SCARG(uap, size), l, retval);
1.2       thorpej  1016:
1.4       christos 1017:        FILE_UNUSE(fp, l);
1.2       thorpej  1018:        return (error);
                   1019: }
                   1020:
                   1021: int
1.9       yamt     1022: sys_removexattr(struct lwp *l, void *v, register_t *retval)
1.2       thorpej  1023: {
                   1024:        struct sys_removexattr_args /* {
                   1025:                syscallarg(const char *) path;
                   1026:                syscallarg(const char *) name;
                   1027:        } */ *uap = v;
                   1028:        struct nameidata nd;
                   1029:        char attrname[XATTR_NAME_MAX];
                   1030:        int error;
                   1031:
                   1032:        error = copyinstr(SCARG(uap, name), attrname, sizeof(attrname),
                   1033:            NULL);
                   1034:        if (error)
                   1035:                return (error);
                   1036:
1.4       christos 1037:        NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), l);
1.2       thorpej  1038:        error = namei(&nd);
                   1039:        if (error)
                   1040:                return (error);
                   1041:
                   1042:        error = extattr_delete_vp(nd.ni_vp, EXTATTR_NAMESPACE_USER,
1.4       christos 1043:            attrname, l);
1.2       thorpej  1044:
                   1045:        vrele(nd.ni_vp);
                   1046:        return (error);
                   1047: }
                   1048:
                   1049: int
1.9       yamt     1050: sys_lremovexattr(struct lwp *l, void *v, register_t *retval)
1.2       thorpej  1051: {
                   1052:        struct sys_lremovexattr_args /* {
                   1053:                syscallarg(const char *) path;
                   1054:                syscallarg(const char *) name;
                   1055:        } */ *uap = v;
                   1056:        struct nameidata nd;
                   1057:        char attrname[XATTR_NAME_MAX];
                   1058:        int error;
                   1059:
                   1060:        error = copyinstr(SCARG(uap, name), attrname, sizeof(attrname),
                   1061:            NULL);
                   1062:        if (error)
                   1063:                return (error);
                   1064:
1.4       christos 1065:        NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_USERSPACE, SCARG(uap, path), l);
1.2       thorpej  1066:        error = namei(&nd);
                   1067:        if (error)
                   1068:                return (error);
                   1069:
                   1070:        error = extattr_delete_vp(nd.ni_vp, EXTATTR_NAMESPACE_USER,
1.4       christos 1071:            attrname, l);
1.2       thorpej  1072:
                   1073:        vrele(nd.ni_vp);
                   1074:        return (error);
                   1075: }
                   1076:
                   1077: int
1.9       yamt     1078: sys_fremovexattr(struct lwp *l, void *v, register_t *retval)
1.2       thorpej  1079: {
                   1080:        struct sys_fremovexattr_args /* {
                   1081:                syscallarg(int) fd;
                   1082:                syscallarg(const char *) name;
                   1083:        } */ *uap = v;
                   1084:        struct file *fp;
                   1085:        struct vnode *vp;
                   1086:        char attrname[XATTR_NAME_MAX];
                   1087:        int error;
                   1088:
                   1089:        error = copyinstr(SCARG(uap, name), attrname, sizeof(attrname),
                   1090:            NULL);
                   1091:        if (error)
                   1092:                return (error);
                   1093:
1.4       christos 1094:        error = getvnode(l->l_proc->p_fd, SCARG(uap, fd), &fp);
1.2       thorpej  1095:        if (error)
                   1096:                return (error);
                   1097:        vp = (struct vnode *) fp->f_data;
                   1098:
                   1099:        error = extattr_delete_vp(vp, EXTATTR_NAMESPACE_USER,
1.4       christos 1100:            attrname, l);
1.2       thorpej  1101:
1.4       christos 1102:        FILE_UNUSE(fp, l);
1.2       thorpej  1103:        return (error);
                   1104: }

CVSweb <webmaster@jp.NetBSD.org>