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