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