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