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