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