vfs_xattr.c revision 1.3 1 /* $NetBSD: vfs_xattr.c,v 1.3 2005/07/10 22:10:00 thorpej 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.3 2005/07/10 22:10:00 thorpej 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 proc *p, 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, &p->p_acflag));
117
118 case EXTATTR_NAMESPACE_USER:
119 return (VOP_ACCESS(vp, access, cred, p));
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 proc *p)
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 proc *p = l->l_proc;
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), p);
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), p);
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, p);
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 proc *p, 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, p, p->p_ucred, 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 auio.uio_segflg = UIO_USERSPACE;
250 auio.uio_procp = p;
251 cnt = nbytes;
252
253 error = VOP_SETEXTATTR(vp, attrnamespace, attrname, &auio,
254 p->p_ucred, p);
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 proc *p, 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, p, p->p_ucred, 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 auio.uio_segflg = UIO_USERSPACE;
302 auio.uio_procp = p;
303 auiop = &auio;
304 cnt = nbytes;
305 } else
306 sizep = &size;
307
308 error = VOP_GETEXTATTR(vp, attrnamespace, attrname, auiop, sizep,
309 p->p_ucred, p);
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 proc *p)
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, p, p->p_ucred, LEASE_WRITE);
338 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
339
340 error = VOP_DELETEEXTATTR(vp, attrnamespace, attrname, p->p_ucred, p);
341 if (error == EOPNOTSUPP)
342 error = VOP_SETEXTATTR(vp, attrnamespace, attrname, NULL,
343 p->p_ucred, p);
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 proc *p, 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, p, p->p_ucred, 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 auio.uio_segflg = UIO_USERSPACE;
383 auio.uio_procp = p;
384 auiop = &auio;
385 cnt = nbytes;
386 } else
387 sizep = &size;
388
389 error = VOP_LISTEXTATTR(vp, attrnamespace, auiop, sizep,
390 p->p_ucred, p);
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 proc *p = l->l_proc;
418 struct file *fp;
419 struct vnode *vp;
420 char attrname[EXTATTR_MAXNAMELEN];
421 int error;
422
423 error = copyinstr(SCARG(uap, attrname), attrname, sizeof(attrname),
424 NULL);
425 if (error)
426 return (error);
427
428 error = getvnode(p->p_fd, SCARG(uap, fd), &fp);
429 if (error)
430 return (error);
431 vp = (struct vnode *) fp->f_data;
432
433 error = extattr_set_vp(vp, SCARG(uap, attrnamespace), attrname,
434 SCARG(uap, data), SCARG(uap, nbytes), p, retval);
435
436 FILE_UNUSE(fp, p);
437 return (error);
438 }
439
440 int
441 sys_extattr_set_file(struct lwp *l, void *v, register_t *retval)
442 {
443 struct sys_extattr_set_file_args /* {
444 syscallarg(const char *) path;
445 syscallarg(int) attrnamespace;
446 syscallarg(const char *) attrname;
447 syscallarg(const void *) data;
448 syscallarg(size_t) nbytes;
449 } */ *uap = v;
450 struct proc *p = l->l_proc;
451 struct nameidata nd;
452 char attrname[EXTATTR_MAXNAMELEN];
453 int error;
454
455 error = copyinstr(SCARG(uap, attrname), attrname, sizeof(attrname),
456 NULL);
457 if (error)
458 return (error);
459
460 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
461 error = namei(&nd);
462 if (error)
463 return (error);
464
465 error = extattr_set_vp(nd.ni_vp, SCARG(uap, attrnamespace), attrname,
466 SCARG(uap, data), SCARG(uap, nbytes), p, retval);
467
468 vrele(nd.ni_vp);
469 return (error);
470 }
471
472 int
473 sys_extattr_set_link(struct lwp *l, void *v, register_t *retval)
474 {
475 struct sys_extattr_set_link_args /* {
476 syscallarg(const char *) path;
477 syscallarg(int) attrnamespace;
478 syscallarg(const char *) attrname;
479 syscallarg(const void *) data;
480 syscallarg(size_t) nbytes;
481 } */ *uap = v;
482 struct proc *p = l->l_proc;
483 struct nameidata nd;
484 char attrname[EXTATTR_MAXNAMELEN];
485 int error;
486
487 error = copyinstr(SCARG(uap, attrname), attrname, sizeof(attrname),
488 NULL);
489 if (error)
490 return (error);
491
492 NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
493 error = namei(&nd);
494 if (error)
495 return (error);
496
497 error = extattr_set_vp(nd.ni_vp, SCARG(uap, attrnamespace), attrname,
498 SCARG(uap, data), SCARG(uap, nbytes), p, retval);
499
500 vrele(nd.ni_vp);
501 return (error);
502 }
503
504 int
505 sys_extattr_get_fd(struct lwp *l, void *v, register_t *retval)
506 {
507 struct sys_extattr_get_fd_args /* {
508 syscallarg(int) fd;
509 syscallarg(int) attrnamespace;
510 syscallarg(const char *) attrname;
511 syscallarg(void *) data;
512 syscallarg(size_t) nbytes;
513 } */ *uap = v;
514 struct proc *p = l->l_proc;
515 struct file *fp;
516 struct vnode *vp;
517 char attrname[EXTATTR_MAXNAMELEN];
518 int error;
519
520 error = copyinstr(SCARG(uap, attrname), attrname, sizeof(attrname),
521 NULL);
522 if (error)
523 return (error);
524
525 error = getvnode(p->p_fd, SCARG(uap, fd), &fp);
526 if (error)
527 return (error);
528 vp = (struct vnode *) fp->f_data;
529
530 error = extattr_get_vp(vp, SCARG(uap, attrnamespace), attrname,
531 SCARG(uap, data), SCARG(uap, nbytes), p, retval);
532
533 FILE_UNUSE(fp, p);
534 return (error);
535 }
536
537 int
538 sys_extattr_get_file(struct lwp *l, void *v, register_t *retval)
539 {
540 struct sys_extattr_get_file_args /* {
541 syscallarg(const char *) path;
542 syscallarg(int) attrnamespace;
543 syscallarg(const char *) attrname;
544 syscallarg(void *) data;
545 syscallarg(size_t) nbytes;
546 } */ *uap = v;
547 struct proc *p = l->l_proc;
548 struct nameidata nd;
549 char attrname[EXTATTR_MAXNAMELEN];
550 int error;
551
552 error = copyinstr(SCARG(uap, attrname), attrname, sizeof(attrname),
553 NULL);
554 if (error)
555 return (error);
556
557 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
558 error = namei(&nd);
559 if (error)
560 return (error);
561
562 error = extattr_get_vp(nd.ni_vp, SCARG(uap, attrnamespace), attrname,
563 SCARG(uap, data), SCARG(uap, nbytes), p, retval);
564
565 vrele(nd.ni_vp);
566 return (error);
567 }
568
569 int
570 sys_extattr_get_link(struct lwp *l, void *v, register_t *retval)
571 {
572 struct sys_extattr_get_link_args /* {
573 syscallarg(const char *) path;
574 syscallarg(int) attrnamespace;
575 syscallarg(const char *) attrname;
576 syscallarg(void *) data;
577 syscallarg(size_t) nbytes;
578 } */ *uap = v;
579 struct proc *p = l->l_proc;
580 struct nameidata nd;
581 char attrname[EXTATTR_MAXNAMELEN];
582 int error;
583
584 error = copyinstr(SCARG(uap, attrname), attrname, sizeof(attrname),
585 NULL);
586 if (error)
587 return (error);
588
589 NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
590 error = namei(&nd);
591 if (error)
592 return (error);
593
594 error = extattr_get_vp(nd.ni_vp, SCARG(uap, attrnamespace), attrname,
595 SCARG(uap, data), SCARG(uap, nbytes), p, retval);
596
597 vrele(nd.ni_vp);
598 return (error);
599 }
600
601 int
602 sys_extattr_delete_fd(struct lwp *l, void *v, register_t *retval)
603 {
604 struct sys_extattr_delete_fd_args /* {
605 syscallarg(int) fd;
606 syscallarg(int) attrnamespace;
607 syscallarg(const char *) attrname;
608 } */ *uap = v;
609 struct proc *p = l->l_proc;
610 struct file *fp;
611 struct vnode *vp;
612 char attrname[EXTATTR_MAXNAMELEN];
613 int error;
614
615 error = copyinstr(SCARG(uap, attrname), attrname, sizeof(attrname),
616 NULL);
617 if (error)
618 return (error);
619
620 error = getvnode(p->p_fd, SCARG(uap, fd), &fp);
621 if (error)
622 return (error);
623 vp = (struct vnode *) fp->f_data;
624
625 error = extattr_delete_vp(vp, SCARG(uap, attrnamespace), attrname, p);
626
627 FILE_UNUSE(fp, p);
628 return (error);
629 }
630
631 int
632 sys_extattr_delete_file(struct lwp *l, void *v, register_t *retval)
633 {
634 struct sys_extattr_delete_file_args /* {
635 syscallarg(const char *) path;
636 syscallarg(int) attrnamespace;
637 syscallarg(const char *) attrname;
638 } */ *uap = v;
639 struct proc *p = l->l_proc;
640 struct nameidata nd;
641 char attrname[EXTATTR_MAXNAMELEN];
642 int error;
643
644 error = copyinstr(SCARG(uap, attrname), attrname, sizeof(attrname),
645 NULL);
646 if (error)
647 return (error);
648
649 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
650 error = namei(&nd);
651 if (error)
652 return (error);
653
654 error = extattr_delete_vp(nd.ni_vp, SCARG(uap, attrnamespace), attrname,
655 p);
656
657 vrele(nd.ni_vp);
658 return (error);
659 }
660
661 int
662 sys_extattr_delete_link(struct lwp *l, void *v, register_t *retval)
663 {
664 struct sys_extattr_delete_link_args /* {
665 syscallarg(const char *) path;
666 syscallarg(int) attrnamespace;
667 syscallarg(const char *) attrname;
668 } */ *uap = v;
669 struct proc *p = l->l_proc;
670 struct nameidata nd;
671 char attrname[EXTATTR_MAXNAMELEN];
672 int error;
673
674 error = copyinstr(SCARG(uap, attrname), attrname, sizeof(attrname),
675 NULL);
676 if (error)
677 return (error);
678
679 NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
680 error = namei(&nd);
681 if (error)
682 return (error);
683
684 error = extattr_delete_vp(nd.ni_vp, SCARG(uap, attrnamespace), attrname,
685 p);
686
687 vrele(nd.ni_vp);
688 return (error);
689 }
690
691 int
692 sys_extattr_list_fd(struct lwp *l, void *v, register_t *retval)
693 {
694 struct sys_extattr_list_fd_args /* {
695 syscallarg(int) fd;
696 syscallarg(int) attrnamespace;
697 syscallarg(void *) data;
698 syscallarg(size_t) nbytes;
699 } */ *uap = v;
700 struct proc *p = l->l_proc;
701 struct file *fp;
702 struct vnode *vp;
703 int error;
704
705 error = getvnode(p->p_fd, SCARG(uap, fd), &fp);
706 if (error)
707 return (error);
708 vp = (struct vnode *) fp->f_data;
709
710 error = extattr_list_vp(vp, SCARG(uap, attrnamespace),
711 SCARG(uap, data), SCARG(uap, nbytes), p, retval);
712
713 FILE_UNUSE(fp, p);
714 return (error);
715 }
716
717 int
718 sys_extattr_list_file(struct lwp *l, void *v, register_t *retval)
719 {
720 struct sys_extattr_list_file_args /* {
721 syscallarg(const char *) path;
722 syscallarg(int) attrnamespace;
723 syscallarg(void *) data;
724 syscallarg(size_t) nbytes;
725 } */ *uap = v;
726 struct proc *p = l->l_proc;
727 struct nameidata nd;
728 int error;
729
730 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
731 error = namei(&nd);
732 if (error)
733 return (error);
734
735 error = extattr_list_vp(nd.ni_vp, SCARG(uap, attrnamespace),
736 SCARG(uap, data), SCARG(uap, nbytes), p, retval);
737
738 vrele(nd.ni_vp);
739 return (error);
740 }
741
742 int
743 sys_extattr_list_link(struct lwp *l, void *v, register_t *retval)
744 {
745 struct sys_extattr_list_link_args /* {
746 syscallarg(const char *) path;
747 syscallarg(int) attrnamespace;
748 syscallarg(void *) data;
749 syscallarg(size_t) nbytes;
750 } */ *uap = v;
751 struct proc *p = l->l_proc;
752 struct nameidata nd;
753 int error;
754
755 NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
756 error = namei(&nd);
757 if (error)
758 return (error);
759
760 error = extattr_list_vp(nd.ni_vp, SCARG(uap, attrnamespace),
761 SCARG(uap, data), SCARG(uap, nbytes), p, retval);
762
763 vrele(nd.ni_vp);
764 return (error);
765 }
766
767 /*****************************************************************************
768 * Linux-compatible <sys/xattr.h> API for file system extended attributes
769 *****************************************************************************/
770
771 int
772 sys_setxattr(struct lwp *l, void *v, register_t *retval)
773 {
774 struct sys_setxattr_args /* {
775 syscallarg(const char *) path;
776 syscallarg(const char *) name;
777 syscallarg(void *) value;
778 syscallarg(size_t) size;
779 syscallarg(int) flags;
780 } */ *uap = v;
781 struct proc *p = l->l_proc;
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, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
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), p, retval);
800
801 vrele(nd.ni_vp);
802 return (error);
803 }
804
805 int
806 sys_lsetxattr(struct lwp *l, void *v, register_t *retval)
807 {
808 struct sys_lsetxattr_args /* {
809 syscallarg(const char *) path;
810 syscallarg(const char *) name;
811 syscallarg(void *) value;
812 syscallarg(size_t) size;
813 syscallarg(int) flags;
814 } */ *uap = v;
815 struct proc *p = l->l_proc;
816 struct nameidata nd;
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 NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
826 error = namei(&nd);
827 if (error)
828 return (error);
829
830 /* XXX flags */
831
832 error = extattr_set_vp(nd.ni_vp, EXTATTR_NAMESPACE_USER,
833 attrname, SCARG(uap, value), SCARG(uap, size), p, retval);
834
835 vrele(nd.ni_vp);
836 return (error);
837 }
838
839 int
840 sys_fsetxattr(struct lwp *l, void *v, register_t *retval)
841 {
842 struct sys_fsetxattr_args /* {
843 syscallarg(int) fd;
844 syscallarg(const char *) name;
845 syscallarg(void *) value;
846 syscallarg(size_t) size;
847 syscallarg(int) flags;
848 } */ *uap = v;
849 struct proc *p = l->l_proc;
850 struct file *fp;
851 struct vnode *vp;
852 char attrname[XATTR_NAME_MAX];
853 int error;
854
855 error = copyinstr(SCARG(uap, name), attrname, sizeof(attrname),
856 NULL);
857 if (error)
858 return (error);
859
860 error = getvnode(p->p_fd, SCARG(uap, fd), &fp);
861 if (error)
862 return (error);
863 vp = (struct vnode *) fp->f_data;
864
865 /* XXX flags */
866
867 error = extattr_set_vp(vp, EXTATTR_NAMESPACE_USER,
868 attrname, SCARG(uap, value), SCARG(uap, size), p, retval);
869
870 FILE_UNUSE(fp, p);
871 return (error);
872 }
873
874 int
875 sys_getxattr(struct lwp *l, void *v, register_t *retval)
876 {
877 struct sys_getxattr_args /* {
878 syscallarg(const char *) path;
879 syscallarg(const char *) name;
880 syscallarg(void *) value;
881 syscallarg(size_t) size;
882 } */ *uap = v;
883 struct proc *p = l->l_proc;
884 struct nameidata nd;
885 char attrname[XATTR_NAME_MAX];
886 int error;
887
888 error = copyinstr(SCARG(uap, name), attrname, sizeof(attrname),
889 NULL);
890 if (error)
891 return (error);
892
893 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
894 error = namei(&nd);
895 if (error)
896 return (error);
897
898 error = extattr_get_vp(nd.ni_vp, EXTATTR_NAMESPACE_USER,
899 attrname, SCARG(uap, value), SCARG(uap, size), p, retval);
900
901 vrele(nd.ni_vp);
902 return (error);
903 }
904
905 int
906 sys_lgetxattr(struct lwp *l, void *v, register_t *retval)
907 {
908 struct sys_lgetxattr_args /* {
909 syscallarg(const char *) path;
910 syscallarg(const char *) name;
911 syscallarg(void *) value;
912 syscallarg(size_t) size;
913 } */ *uap = v;
914 struct proc *p = l->l_proc;
915 struct nameidata nd;
916 char attrname[XATTR_NAME_MAX];
917 int error;
918
919 error = copyinstr(SCARG(uap, name), attrname, sizeof(attrname),
920 NULL);
921 if (error)
922 return (error);
923
924 NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
925 error = namei(&nd);
926 if (error)
927 return (error);
928
929 error = extattr_get_vp(nd.ni_vp, EXTATTR_NAMESPACE_USER,
930 attrname, SCARG(uap, value), SCARG(uap, size), p, retval);
931
932 vrele(nd.ni_vp);
933 return (error);
934 }
935
936 int
937 sys_fgetxattr(struct lwp *l, void *v, register_t *retval)
938 {
939 struct sys_fgetxattr_args /* {
940 syscallarg(int) fd;
941 syscallarg(const char *) name;
942 syscallarg(void *) value;
943 syscallarg(size_t) size;
944 } */ *uap = v;
945 struct proc *p = l->l_proc;
946 struct file *fp;
947 struct vnode *vp;
948 char attrname[XATTR_NAME_MAX];
949 int error;
950
951 error = copyinstr(SCARG(uap, name), attrname, sizeof(attrname),
952 NULL);
953 if (error)
954 return (error);
955
956 error = getvnode(p->p_fd, SCARG(uap, fd), &fp);
957 if (error)
958 return (error);
959 vp = (struct vnode *) fp->f_data;
960
961 error = extattr_get_vp(vp, EXTATTR_NAMESPACE_USER,
962 attrname, SCARG(uap, value), SCARG(uap, size), p, retval);
963
964 FILE_UNUSE(fp, p);
965 return (error);
966 }
967
968 int
969 sys_listxattr(struct lwp *l, void *v, register_t *retval)
970 {
971 struct sys_listxattr_args /* {
972 syscallarg(const char *) path;
973 syscallarg(char *) list;
974 syscallarg(size_t) size;
975 } */ *uap = v;
976 struct proc *p = l->l_proc;
977 struct nameidata nd;
978 int error;
979
980 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
981 error = namei(&nd);
982 if (error)
983 return (error);
984
985 error = extattr_list_vp(nd.ni_vp, EXTATTR_NAMESPACE_USER,
986 SCARG(uap, list), SCARG(uap, size), p, retval);
987
988 vrele(nd.ni_vp);
989 return (error);
990 }
991
992 int
993 sys_llistxattr(struct lwp *l, void *v, register_t *retval)
994 {
995 struct sys_llistxattr_args /* {
996 syscallarg(const char *) path;
997 syscallarg(char *) list;
998 syscallarg(size_t) size;
999 } */ *uap = v;
1000 struct proc *p = l->l_proc;
1001 struct nameidata nd;
1002 int error;
1003
1004 NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
1005 error = namei(&nd);
1006 if (error)
1007 return (error);
1008
1009 error = extattr_list_vp(nd.ni_vp, EXTATTR_NAMESPACE_USER,
1010 SCARG(uap, list), SCARG(uap, size), p, retval);
1011
1012 vrele(nd.ni_vp);
1013 return (error);
1014 }
1015
1016 int
1017 sys_flistxattr(struct lwp *l, void *v, register_t *retval)
1018 {
1019 struct sys_flistxattr_args /* {
1020 syscallarg(int) fd;
1021 syscallarg(char *) list;
1022 syscallarg(size_t) size;
1023 } */ *uap = v;
1024 struct proc *p = l->l_proc;
1025 struct file *fp;
1026 struct vnode *vp;
1027 int error;
1028
1029 error = getvnode(p->p_fd, SCARG(uap, fd), &fp);
1030 if (error)
1031 return (error);
1032 vp = (struct vnode *) fp->f_data;
1033
1034 error = extattr_list_vp(vp, EXTATTR_NAMESPACE_USER,
1035 SCARG(uap, list), SCARG(uap, size), p, retval);
1036
1037 FILE_UNUSE(fp, p);
1038 return (error);
1039 }
1040
1041 int
1042 sys_removexattr(struct lwp *l, void *v, register_t *retval)
1043 {
1044 struct sys_removexattr_args /* {
1045 syscallarg(const char *) path;
1046 syscallarg(const char *) name;
1047 } */ *uap = v;
1048 struct proc *p = l->l_proc;
1049 struct nameidata nd;
1050 char attrname[XATTR_NAME_MAX];
1051 int error;
1052
1053 error = copyinstr(SCARG(uap, name), attrname, sizeof(attrname),
1054 NULL);
1055 if (error)
1056 return (error);
1057
1058 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
1059 error = namei(&nd);
1060 if (error)
1061 return (error);
1062
1063 error = extattr_delete_vp(nd.ni_vp, EXTATTR_NAMESPACE_USER,
1064 attrname, p);
1065
1066 vrele(nd.ni_vp);
1067 return (error);
1068 }
1069
1070 int
1071 sys_lremovexattr(struct lwp *l, void *v, register_t *retval)
1072 {
1073 struct sys_lremovexattr_args /* {
1074 syscallarg(const char *) path;
1075 syscallarg(const char *) name;
1076 } */ *uap = v;
1077 struct proc *p = l->l_proc;
1078 struct nameidata nd;
1079 char attrname[XATTR_NAME_MAX];
1080 int error;
1081
1082 error = copyinstr(SCARG(uap, name), attrname, sizeof(attrname),
1083 NULL);
1084 if (error)
1085 return (error);
1086
1087 NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
1088 error = namei(&nd);
1089 if (error)
1090 return (error);
1091
1092 error = extattr_delete_vp(nd.ni_vp, EXTATTR_NAMESPACE_USER,
1093 attrname, p);
1094
1095 vrele(nd.ni_vp);
1096 return (error);
1097 }
1098
1099 int
1100 sys_fremovexattr(struct lwp *l, void *v, register_t *retval)
1101 {
1102 struct sys_fremovexattr_args /* {
1103 syscallarg(int) fd;
1104 syscallarg(const char *) name;
1105 } */ *uap = v;
1106 struct proc *p = l->l_proc;
1107 struct file *fp;
1108 struct vnode *vp;
1109 char attrname[XATTR_NAME_MAX];
1110 int error;
1111
1112 error = copyinstr(SCARG(uap, name), attrname, sizeof(attrname),
1113 NULL);
1114 if (error)
1115 return (error);
1116
1117 error = getvnode(p->p_fd, SCARG(uap, fd), &fp);
1118 if (error)
1119 return (error);
1120 vp = (struct vnode *) fp->f_data;
1121
1122 error = extattr_delete_vp(vp, EXTATTR_NAMESPACE_USER,
1123 attrname, p);
1124
1125 FILE_UNUSE(fp, p);
1126 return (error);
1127 }
1128