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