print more junk
[freebsd-src/fkvm-freebsd.git] / sys / kern / vfs_extattr.c
blobcd2b9cceac91f010aeec06b4a434f689ff418581
1 /*-
2 * Copyright (c) 1999-2001 Robert N. M. Watson
3 * All rights reserved.
5 * This software was developed by Robert Watson for the TrustedBSD Project.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
29 #include <sys/cdefs.h>
30 __FBSDID("$FreeBSD$");
32 #include "opt_mac.h"
34 #include <sys/param.h>
35 #include <sys/systm.h>
36 #include <sys/lock.h>
37 #include <sys/mount.h>
38 #include <sys/mutex.h>
39 #include <sys/sysproto.h>
40 #include <sys/fcntl.h>
41 #include <sys/namei.h>
42 #include <sys/filedesc.h>
43 #include <sys/limits.h>
44 #include <sys/vnode.h>
45 #include <sys/proc.h>
46 #include <sys/extattr.h>
48 #include <security/audit/audit.h>
49 #include <security/mac/mac_framework.h>
52 * Syscall to push extended attribute configuration information into the VFS.
53 * Accepts a path, which it converts to a mountpoint, as well as a command
54 * (int cmd), and attribute name and misc data.
56 * Currently this is used only by UFS1 extended attributes.
58 int
59 extattrctl(td, uap)
60 struct thread *td;
61 struct extattrctl_args /* {
62 const char *path;
63 int cmd;
64 const char *filename;
65 int attrnamespace;
66 const char *attrname;
67 } */ *uap;
69 struct vnode *filename_vp;
70 struct nameidata nd;
71 struct mount *mp, *mp_writable;
72 char attrname[EXTATTR_MAXNAMELEN];
73 int vfslocked, fnvfslocked, error;
75 AUDIT_ARG(cmd, uap->cmd);
76 AUDIT_ARG(value, uap->attrnamespace);
78 * uap->attrname is not always defined. We check again later when we
79 * invoke the VFS call so as to pass in NULL there if needed.
81 if (uap->attrname != NULL) {
82 error = copyinstr(uap->attrname, attrname, EXTATTR_MAXNAMELEN,
83 NULL);
84 if (error)
85 return (error);
87 AUDIT_ARG(text, attrname);
89 vfslocked = fnvfslocked = 0;
91 * uap->filename is not always defined. If it is, grab a vnode lock,
92 * which VFS_EXTATTRCTL() will later release.
94 filename_vp = NULL;
95 if (uap->filename != NULL) {
96 NDINIT(&nd, LOOKUP, MPSAFE | FOLLOW | LOCKLEAF |
97 AUDITVNODE2, UIO_USERSPACE, uap->filename, td);
98 error = namei(&nd);
99 if (error)
100 return (error);
101 fnvfslocked = NDHASGIANT(&nd);
102 filename_vp = nd.ni_vp;
103 NDFREE(&nd, NDF_NO_VP_RELE | NDF_NO_VP_UNLOCK);
106 /* uap->path is always defined. */
107 NDINIT(&nd, LOOKUP, MPSAFE | FOLLOW | AUDITVNODE1, UIO_USERSPACE,
108 uap->path, td);
109 error = namei(&nd);
110 if (error) {
111 if (filename_vp != NULL)
112 vput(filename_vp);
113 goto out;
115 vfslocked = NDHASGIANT(&nd);
116 mp = nd.ni_vp->v_mount;
117 error = vn_start_write(nd.ni_vp, &mp_writable, V_WAIT | PCATCH);
118 NDFREE(&nd, 0);
119 if (error) {
120 if (filename_vp != NULL)
121 vput(filename_vp);
122 goto out;
125 error = VFS_EXTATTRCTL(mp, uap->cmd, filename_vp, uap->attrnamespace,
126 uap->attrname != NULL ? attrname : NULL, td);
128 vn_finished_write(mp_writable);
130 * VFS_EXTATTRCTL will have unlocked, but not de-ref'd, filename_vp,
131 * so vrele it if it is defined.
133 if (filename_vp != NULL)
134 vrele(filename_vp);
135 out:
136 VFS_UNLOCK_GIANT(fnvfslocked);
137 VFS_UNLOCK_GIANT(vfslocked);
138 return (error);
142 * Set a named extended attribute on a file or directory
144 * Arguments: unlocked vnode "vp", attribute namespace "attrnamespace",
145 * kernelspace string pointer "attrname", userspace buffer
146 * pointer "data", buffer length "nbytes", thread "td".
147 * Returns: 0 on success, an error number otherwise
148 * Locks: none
149 * References: vp must be a valid reference for the duration of the call
151 static int
152 extattr_set_vp(struct vnode *vp, int attrnamespace, const char *attrname,
153 void *data, size_t nbytes, struct thread *td)
155 struct mount *mp;
156 struct uio auio;
157 struct iovec aiov;
158 ssize_t cnt;
159 int error;
161 VFS_ASSERT_GIANT(vp->v_mount);
162 error = vn_start_write(vp, &mp, V_WAIT | PCATCH);
163 if (error)
164 return (error);
165 VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE);
166 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
168 aiov.iov_base = data;
169 aiov.iov_len = nbytes;
170 auio.uio_iov = &aiov;
171 auio.uio_iovcnt = 1;
172 auio.uio_offset = 0;
173 if (nbytes > INT_MAX) {
174 error = EINVAL;
175 goto done;
177 auio.uio_resid = nbytes;
178 auio.uio_rw = UIO_WRITE;
179 auio.uio_segflg = UIO_USERSPACE;
180 auio.uio_td = td;
181 cnt = nbytes;
183 #ifdef MAC
184 error = mac_vnode_check_setextattr(td->td_ucred, vp, attrnamespace,
185 attrname, &auio);
186 if (error)
187 goto done;
188 #endif
190 error = VOP_SETEXTATTR(vp, attrnamespace, attrname, &auio,
191 td->td_ucred, td);
192 cnt -= auio.uio_resid;
193 td->td_retval[0] = cnt;
195 done:
196 VOP_UNLOCK(vp, 0);
197 vn_finished_write(mp);
198 return (error);
202 extattr_set_fd(td, uap)
203 struct thread *td;
204 struct extattr_set_fd_args /* {
205 int fd;
206 int attrnamespace;
207 const char *attrname;
208 void *data;
209 size_t nbytes;
210 } */ *uap;
212 struct file *fp;
213 char attrname[EXTATTR_MAXNAMELEN];
214 int vfslocked, error;
216 AUDIT_ARG(fd, uap->fd);
217 AUDIT_ARG(value, uap->attrnamespace);
218 error = copyinstr(uap->attrname, attrname, EXTATTR_MAXNAMELEN, NULL);
219 if (error)
220 return (error);
221 AUDIT_ARG(text, attrname);
223 error = getvnode(td->td_proc->p_fd, uap->fd, &fp);
224 if (error)
225 return (error);
227 vfslocked = VFS_LOCK_GIANT(fp->f_vnode->v_mount);
228 error = extattr_set_vp(fp->f_vnode, uap->attrnamespace,
229 attrname, uap->data, uap->nbytes, td);
230 fdrop(fp, td);
231 VFS_UNLOCK_GIANT(vfslocked);
233 return (error);
237 extattr_set_file(td, uap)
238 struct thread *td;
239 struct extattr_set_file_args /* {
240 const char *path;
241 int attrnamespace;
242 const char *attrname;
243 void *data;
244 size_t nbytes;
245 } */ *uap;
247 struct nameidata nd;
248 char attrname[EXTATTR_MAXNAMELEN];
249 int vfslocked, error;
251 AUDIT_ARG(value, uap->attrnamespace);
252 error = copyinstr(uap->attrname, attrname, EXTATTR_MAXNAMELEN, NULL);
253 if (error)
254 return (error);
255 AUDIT_ARG(text, attrname);
257 NDINIT(&nd, LOOKUP, MPSAFE | FOLLOW | AUDITVNODE1, UIO_USERSPACE,
258 uap->path, td);
259 error = namei(&nd);
260 if (error)
261 return (error);
262 NDFREE(&nd, NDF_ONLY_PNBUF);
264 vfslocked = NDHASGIANT(&nd);
265 error = extattr_set_vp(nd.ni_vp, uap->attrnamespace, attrname,
266 uap->data, uap->nbytes, td);
268 vrele(nd.ni_vp);
269 VFS_UNLOCK_GIANT(vfslocked);
270 return (error);
274 extattr_set_link(td, uap)
275 struct thread *td;
276 struct extattr_set_link_args /* {
277 const char *path;
278 int attrnamespace;
279 const char *attrname;
280 void *data;
281 size_t nbytes;
282 } */ *uap;
284 struct nameidata nd;
285 char attrname[EXTATTR_MAXNAMELEN];
286 int vfslocked, error;
288 AUDIT_ARG(value, uap->attrnamespace);
289 error = copyinstr(uap->attrname, attrname, EXTATTR_MAXNAMELEN, NULL);
290 if (error)
291 return (error);
292 AUDIT_ARG(text, attrname);
294 NDINIT(&nd, LOOKUP, MPSAFE | NOFOLLOW | AUDITVNODE1, UIO_USERSPACE,
295 uap->path, td);
296 error = namei(&nd);
297 if (error)
298 return (error);
299 NDFREE(&nd, NDF_ONLY_PNBUF);
301 vfslocked = NDHASGIANT(&nd);
302 error = extattr_set_vp(nd.ni_vp, uap->attrnamespace, attrname,
303 uap->data, uap->nbytes, td);
305 vrele(nd.ni_vp);
306 VFS_UNLOCK_GIANT(vfslocked);
307 return (error);
311 * Get a named extended attribute on a file or directory
313 * Arguments: unlocked vnode "vp", attribute namespace "attrnamespace",
314 * kernelspace string pointer "attrname", userspace buffer
315 * pointer "data", buffer length "nbytes", thread "td".
316 * Returns: 0 on success, an error number otherwise
317 * Locks: none
318 * References: vp must be a valid reference for the duration of the call
320 static int
321 extattr_get_vp(struct vnode *vp, int attrnamespace, const char *attrname,
322 void *data, size_t nbytes, struct thread *td)
324 struct uio auio, *auiop;
325 struct iovec aiov;
326 ssize_t cnt;
327 size_t size, *sizep;
328 int error;
330 VFS_ASSERT_GIANT(vp->v_mount);
331 VOP_LEASE(vp, td, td->td_ucred, LEASE_READ);
332 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
335 * Slightly unusual semantics: if the user provides a NULL data
336 * pointer, they don't want to receive the data, just the maximum
337 * read length.
339 auiop = NULL;
340 sizep = NULL;
341 cnt = 0;
342 if (data != NULL) {
343 aiov.iov_base = data;
344 aiov.iov_len = nbytes;
345 auio.uio_iov = &aiov;
346 auio.uio_iovcnt = 1;
347 auio.uio_offset = 0;
348 if (nbytes > INT_MAX) {
349 error = EINVAL;
350 goto done;
352 auio.uio_resid = nbytes;
353 auio.uio_rw = UIO_READ;
354 auio.uio_segflg = UIO_USERSPACE;
355 auio.uio_td = td;
356 auiop = &auio;
357 cnt = nbytes;
358 } else
359 sizep = &size;
361 #ifdef MAC
362 error = mac_vnode_check_getextattr(td->td_ucred, vp, attrnamespace,
363 attrname, &auio);
364 if (error)
365 goto done;
366 #endif
368 error = VOP_GETEXTATTR(vp, attrnamespace, attrname, auiop, sizep,
369 td->td_ucred, td);
371 if (auiop != NULL) {
372 cnt -= auio.uio_resid;
373 td->td_retval[0] = cnt;
374 } else
375 td->td_retval[0] = size;
377 done:
378 VOP_UNLOCK(vp, 0);
379 return (error);
383 extattr_get_fd(td, uap)
384 struct thread *td;
385 struct extattr_get_fd_args /* {
386 int fd;
387 int attrnamespace;
388 const char *attrname;
389 void *data;
390 size_t nbytes;
391 } */ *uap;
393 struct file *fp;
394 char attrname[EXTATTR_MAXNAMELEN];
395 int vfslocked, error;
397 AUDIT_ARG(fd, uap->fd);
398 AUDIT_ARG(value, uap->attrnamespace);
399 error = copyinstr(uap->attrname, attrname, EXTATTR_MAXNAMELEN, NULL);
400 if (error)
401 return (error);
402 AUDIT_ARG(text, attrname);
404 error = getvnode(td->td_proc->p_fd, uap->fd, &fp);
405 if (error)
406 return (error);
408 vfslocked = VFS_LOCK_GIANT(fp->f_vnode->v_mount);
409 error = extattr_get_vp(fp->f_vnode, uap->attrnamespace,
410 attrname, uap->data, uap->nbytes, td);
412 fdrop(fp, td);
413 VFS_UNLOCK_GIANT(vfslocked);
414 return (error);
418 extattr_get_file(td, uap)
419 struct thread *td;
420 struct extattr_get_file_args /* {
421 const char *path;
422 int attrnamespace;
423 const char *attrname;
424 void *data;
425 size_t nbytes;
426 } */ *uap;
428 struct nameidata nd;
429 char attrname[EXTATTR_MAXNAMELEN];
430 int vfslocked, error;
432 AUDIT_ARG(value, uap->attrnamespace);
433 error = copyinstr(uap->attrname, attrname, EXTATTR_MAXNAMELEN, NULL);
434 if (error)
435 return (error);
436 AUDIT_ARG(text, attrname);
438 NDINIT(&nd, LOOKUP, MPSAFE | FOLLOW | AUDITVNODE1, UIO_USERSPACE,
439 uap->path, td);
440 error = namei(&nd);
441 if (error)
442 return (error);
443 NDFREE(&nd, NDF_ONLY_PNBUF);
445 vfslocked = NDHASGIANT(&nd);
446 error = extattr_get_vp(nd.ni_vp, uap->attrnamespace, attrname,
447 uap->data, uap->nbytes, td);
449 vrele(nd.ni_vp);
450 VFS_UNLOCK_GIANT(vfslocked);
451 return (error);
455 extattr_get_link(td, uap)
456 struct thread *td;
457 struct extattr_get_link_args /* {
458 const char *path;
459 int attrnamespace;
460 const char *attrname;
461 void *data;
462 size_t nbytes;
463 } */ *uap;
465 struct nameidata nd;
466 char attrname[EXTATTR_MAXNAMELEN];
467 int vfslocked, error;
469 AUDIT_ARG(value, uap->attrnamespace);
470 error = copyinstr(uap->attrname, attrname, EXTATTR_MAXNAMELEN, NULL);
471 if (error)
472 return (error);
473 AUDIT_ARG(text, attrname);
475 NDINIT(&nd, LOOKUP, MPSAFE | NOFOLLOW | AUDITVNODE1, UIO_USERSPACE,
476 uap->path, td);
477 error = namei(&nd);
478 if (error)
479 return (error);
480 NDFREE(&nd, NDF_ONLY_PNBUF);
482 vfslocked = NDHASGIANT(&nd);
483 error = extattr_get_vp(nd.ni_vp, uap->attrnamespace, attrname,
484 uap->data, uap->nbytes, td);
486 vrele(nd.ni_vp);
487 VFS_UNLOCK_GIANT(vfslocked);
488 return (error);
492 * extattr_delete_vp(): Delete a named extended attribute on a file or
493 * directory
495 * Arguments: unlocked vnode "vp", attribute namespace "attrnamespace",
496 * kernelspace string pointer "attrname", proc "p"
497 * Returns: 0 on success, an error number otherwise
498 * Locks: none
499 * References: vp must be a valid reference for the duration of the call
501 static int
502 extattr_delete_vp(struct vnode *vp, int attrnamespace, const char *attrname,
503 struct thread *td)
505 struct mount *mp;
506 int error;
508 VFS_ASSERT_GIANT(vp->v_mount);
509 error = vn_start_write(vp, &mp, V_WAIT | PCATCH);
510 if (error)
511 return (error);
512 VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE);
513 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
515 #ifdef MAC
516 error = mac_vnode_check_deleteextattr(td->td_ucred, vp, attrnamespace,
517 attrname);
518 if (error)
519 goto done;
520 #endif
522 error = VOP_DELETEEXTATTR(vp, attrnamespace, attrname, td->td_ucred,
523 td);
524 if (error == EOPNOTSUPP)
525 error = VOP_SETEXTATTR(vp, attrnamespace, attrname, NULL,
526 td->td_ucred, td);
527 #ifdef MAC
528 done:
529 #endif
530 VOP_UNLOCK(vp, 0);
531 vn_finished_write(mp);
532 return (error);
536 extattr_delete_fd(td, uap)
537 struct thread *td;
538 struct extattr_delete_fd_args /* {
539 int fd;
540 int attrnamespace;
541 const char *attrname;
542 } */ *uap;
544 struct file *fp;
545 char attrname[EXTATTR_MAXNAMELEN];
546 int vfslocked, error;
548 AUDIT_ARG(fd, uap->fd);
549 AUDIT_ARG(value, uap->attrnamespace);
550 error = copyinstr(uap->attrname, attrname, EXTATTR_MAXNAMELEN, NULL);
551 if (error)
552 return (error);
553 AUDIT_ARG(text, attrname);
555 error = getvnode(td->td_proc->p_fd, uap->fd, &fp);
556 if (error)
557 return (error);
559 vfslocked = VFS_LOCK_GIANT(fp->f_vnode->v_mount);
560 error = extattr_delete_vp(fp->f_vnode, uap->attrnamespace,
561 attrname, td);
562 fdrop(fp, td);
563 VFS_UNLOCK_GIANT(vfslocked);
564 return (error);
568 extattr_delete_file(td, uap)
569 struct thread *td;
570 struct extattr_delete_file_args /* {
571 const char *path;
572 int attrnamespace;
573 const char *attrname;
574 } */ *uap;
576 struct nameidata nd;
577 char attrname[EXTATTR_MAXNAMELEN];
578 int vfslocked, error;
580 AUDIT_ARG(value, uap->attrnamespace);
581 error = copyinstr(uap->attrname, attrname, EXTATTR_MAXNAMELEN, NULL);
582 if (error)
583 return(error);
584 AUDIT_ARG(text, attrname);
586 NDINIT(&nd, LOOKUP, MPSAFE | FOLLOW | AUDITVNODE1, UIO_USERSPACE,
587 uap->path, td);
588 error = namei(&nd);
589 if (error)
590 return(error);
591 NDFREE(&nd, NDF_ONLY_PNBUF);
593 vfslocked = NDHASGIANT(&nd);
594 error = extattr_delete_vp(nd.ni_vp, uap->attrnamespace, attrname, td);
595 vrele(nd.ni_vp);
596 VFS_UNLOCK_GIANT(vfslocked);
597 return(error);
601 extattr_delete_link(td, uap)
602 struct thread *td;
603 struct extattr_delete_link_args /* {
604 const char *path;
605 int attrnamespace;
606 const char *attrname;
607 } */ *uap;
609 struct nameidata nd;
610 char attrname[EXTATTR_MAXNAMELEN];
611 int vfslocked, error;
613 AUDIT_ARG(value, uap->attrnamespace);
614 error = copyinstr(uap->attrname, attrname, EXTATTR_MAXNAMELEN, NULL);
615 if (error)
616 return(error);
617 AUDIT_ARG(text, attrname);
619 NDINIT(&nd, LOOKUP, MPSAFE | NOFOLLOW | AUDITVNODE1, UIO_USERSPACE,
620 uap->path, td);
621 error = namei(&nd);
622 if (error)
623 return(error);
624 NDFREE(&nd, NDF_ONLY_PNBUF);
626 vfslocked = NDHASGIANT(&nd);
627 error = extattr_delete_vp(nd.ni_vp, uap->attrnamespace, attrname, td);
628 vrele(nd.ni_vp);
629 VFS_UNLOCK_GIANT(vfslocked);
630 return(error);
634 * Retrieve a list of extended attributes on a file or directory.
636 * Arguments: unlocked vnode "vp", attribute namespace 'attrnamespace",
637 * userspace buffer pointer "data", buffer length "nbytes",
638 * thread "td".
639 * Returns: 0 on success, an error number otherwise
640 * Locks: none
641 * References: vp must be a valid reference for the duration of the call
643 static int
644 extattr_list_vp(struct vnode *vp, int attrnamespace, void *data,
645 size_t nbytes, struct thread *td)
647 struct uio auio, *auiop;
648 size_t size, *sizep;
649 struct iovec aiov;
650 ssize_t cnt;
651 int error;
653 VFS_ASSERT_GIANT(vp->v_mount);
654 VOP_LEASE(vp, td, td->td_ucred, LEASE_READ);
655 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
657 auiop = NULL;
658 sizep = NULL;
659 cnt = 0;
660 if (data != NULL) {
661 aiov.iov_base = data;
662 aiov.iov_len = nbytes;
663 auio.uio_iov = &aiov;
664 auio.uio_iovcnt = 1;
665 auio.uio_offset = 0;
666 if (nbytes > INT_MAX) {
667 error = EINVAL;
668 goto done;
670 auio.uio_resid = nbytes;
671 auio.uio_rw = UIO_READ;
672 auio.uio_segflg = UIO_USERSPACE;
673 auio.uio_td = td;
674 auiop = &auio;
675 cnt = nbytes;
676 } else
677 sizep = &size;
679 #ifdef MAC
680 error = mac_vnode_check_listextattr(td->td_ucred, vp, attrnamespace);
681 if (error)
682 goto done;
683 #endif
685 error = VOP_LISTEXTATTR(vp, attrnamespace, auiop, sizep,
686 td->td_ucred, td);
688 if (auiop != NULL) {
689 cnt -= auio.uio_resid;
690 td->td_retval[0] = cnt;
691 } else
692 td->td_retval[0] = size;
694 done:
695 VOP_UNLOCK(vp, 0);
696 return (error);
701 extattr_list_fd(td, uap)
702 struct thread *td;
703 struct extattr_list_fd_args /* {
704 int fd;
705 int attrnamespace;
706 void *data;
707 size_t nbytes;
708 } */ *uap;
710 struct file *fp;
711 int vfslocked, error;
713 AUDIT_ARG(fd, uap->fd);
714 AUDIT_ARG(value, uap->attrnamespace);
715 error = getvnode(td->td_proc->p_fd, uap->fd, &fp);
716 if (error)
717 return (error);
719 vfslocked = VFS_LOCK_GIANT(fp->f_vnode->v_mount);
720 error = extattr_list_vp(fp->f_vnode, uap->attrnamespace, uap->data,
721 uap->nbytes, td);
723 fdrop(fp, td);
724 VFS_UNLOCK_GIANT(vfslocked);
725 return (error);
729 extattr_list_file(td, uap)
730 struct thread*td;
731 struct extattr_list_file_args /* {
732 const char *path;
733 int attrnamespace;
734 void *data;
735 size_t nbytes;
736 } */ *uap;
738 struct nameidata nd;
739 int vfslocked, error;
741 AUDIT_ARG(value, uap->attrnamespace);
742 NDINIT(&nd, LOOKUP, MPSAFE | FOLLOW | AUDITVNODE1, UIO_USERSPACE,
743 uap->path, td);
744 error = namei(&nd);
745 if (error)
746 return (error);
747 NDFREE(&nd, NDF_ONLY_PNBUF);
749 vfslocked = NDHASGIANT(&nd);
750 error = extattr_list_vp(nd.ni_vp, uap->attrnamespace, uap->data,
751 uap->nbytes, td);
753 vrele(nd.ni_vp);
754 VFS_UNLOCK_GIANT(vfslocked);
755 return (error);
759 extattr_list_link(td, uap)
760 struct thread*td;
761 struct extattr_list_link_args /* {
762 const char *path;
763 int attrnamespace;
764 void *data;
765 size_t nbytes;
766 } */ *uap;
768 struct nameidata nd;
769 int vfslocked, error;
771 AUDIT_ARG(value, uap->attrnamespace);
772 NDINIT(&nd, LOOKUP, MPSAFE | NOFOLLOW | AUDITVNODE1, UIO_USERSPACE,
773 uap->path, td);
774 error = namei(&nd);
775 if (error)
776 return (error);
777 NDFREE(&nd, NDF_ONLY_PNBUF);
779 vfslocked = NDHASGIANT(&nd);
780 error = extattr_list_vp(nd.ni_vp, uap->attrnamespace, uap->data,
781 uap->nbytes, td);
783 vrele(nd.ni_vp);
784 VFS_UNLOCK_GIANT(vfslocked);
785 return (error);