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>