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