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