[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.20.2.1

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

CVSweb <webmaster@jp.NetBSD.org>