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>