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