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