Sync usage with man page.
[netbsd-mini2440.git] / sys / compat / darwin / darwin_attr.c
blob09c6fb83b33d7660779b954c264a8faf97b00de5
1 /* $NetBSD: darwin_attr.c,v 1.25 2009/01/11 02:45:47 christos Exp $ */
3 /*-
4 * Copyright (c) 2003, 2008 The NetBSD Foundation, Inc.
5 * All rights reserved.
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Emmanuel Dreyfus.
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.
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
32 #include <sys/cdefs.h>
33 __KERNEL_RCSID(0, "$NetBSD: darwin_attr.c,v 1.25 2009/01/11 02:45:47 christos Exp $");
35 #include <sys/param.h>
36 #include <sys/systm.h>
37 #include <sys/types.h>
38 #include <sys/proc.h>
39 #include <sys/mount.h>
40 #include <sys/lwp.h>
41 #include <sys/file.h>
42 #include <sys/filedesc.h>
43 #include <sys/namei.h>
44 #include <sys/vnode.h>
45 #include <sys/malloc.h>
46 #include <sys/stat.h>
47 #include <sys/syscallargs.h>
48 #include <sys/vfs_syscalls.h>
49 #include <sys/kauth.h>
51 #include <compat/sys/signal.h>
52 #include <compat/sys/mount.h>
54 #include <compat/common/compat_util.h>
56 #include <compat/mach/mach_types.h>
57 #include <compat/mach/mach_vm.h>
59 #include <compat/darwin/darwin_types.h>
60 #include <compat/darwin/darwin_audit.h>
61 #include <compat/darwin/darwin_attr.h>
62 #include <compat/darwin/darwin_syscallargs.h>
64 #define DARWIN_ATTR_MAXBUFLEN 4096
66 static int darwin_attr_append(const char *, size_t, char **, size_t *);
68 #define ATTR_APPEND(x, bp, len) \
69 darwin_attr_append((char *)&(x), sizeof(x), &(bp), &(len))
72 static int
73 darwin_attr_append(const char *x, size_t size, char **bp, size_t *len)
75 if (*len < size)
76 return -1;
78 (void)memcpy(*bp, x, size);
80 *bp += size;
81 *len -= size;
83 return 0;
86 int
87 darwin_sys_getattrlist(struct lwp *l, const struct darwin_sys_getattrlist_args *uap, register_t *retval)
89 /* {
90 syscallarg(const char *) path;
91 syscallarg(struct darwin_attrlist *) alist;
92 syscallarg(void *) attributes;
93 syscallarg(size_t) buflen;
94 syscallarg(unsigned long) options;
95 } */
96 struct darwin_attrlist kalist;
97 char *tbuf;
98 char *bp;
99 size_t len;
100 size_t shift = 0;
101 int null = 0;
102 int error = 0;
103 int follow = NOFOLLOW;
104 u_long *whole_len_p = NULL;
105 darwin_attrreference_t *cmn_name_p = NULL;
106 darwin_attrreference_t *vol_mountpoint_p = NULL;
107 darwin_attrreference_t *vol_name_p = NULL;
108 darwin_attrreference_t *vol_mounteddevice_p = NULL;
109 struct stat st;
110 struct statvfs *f;
111 struct nameidata nd;
112 struct vnode *vp;
113 kauth_cred_t cred;
115 if ((error = copyin(SCARG(uap, alist), &kalist, sizeof(kalist))) != 0)
116 return error;
118 if (kalist.bitmapcount != DARWIN_ATTR_BIT_MAP_COUNT)
119 return EINVAL;
121 len = SCARG(uap, buflen);
122 if (len > DARWIN_ATTR_MAXBUFLEN)
123 return E2BIG;
125 if ((SCARG(uap, options) & DARWIN_FSOPT_NOFOLLOW) != 0)
126 follow = FOLLOW;
128 #ifdef DEBUG_DARWIN
129 printf("getattrlist: %08x %08x %08x %08x %08x\n",
130 kalist.commonattr, kalist.volattr, kalist.dirattr,
131 kalist.fileattr, kalist.forkattr);
132 #endif
134 /* Allocate buffers now... */
135 f = STATVFSBUF_GET();
136 tbuf = malloc(len, M_TEMP, M_WAITOK);
138 /* We are going to need the vnode itself... */
140 cred = kauth_cred_dup(l->l_cred);
141 kauth_cred_seteuid(cred, kauth_cred_getuid(l->l_cred));
142 kauth_cred_setegid(cred, kauth_cred_getgid(l->l_cred));
144 NDINIT(&nd, LOOKUP, follow | LOCKLEAF | TRYEMULROOT, UIO_USERSPACE,
145 SCARG(uap, path));
146 if ((error = namei(&nd)) != 0)
147 goto out2;
149 vp = nd.ni_vp;
150 if ((error = VOP_ACCESS(vp, VREAD | VEXEC, cred)) != 0)
151 goto out3;
153 /* Get the informations for path: file related info */
154 error = vn_stat(vp, &st);
155 if (error != 0)
156 goto out3;
158 /* filesystem related info */
159 error = dostatvfs(vp->v_mount, f, l, 0, 1);
160 if (error != 0)
161 goto out3;
164 * Prepare the buffer
166 bp = tbuf;
169 * Buffer whole length: is always present
171 if (1) {
172 u_long whole_len;
174 whole_len = 0;
175 whole_len_p = (u_long *)bp;
176 if (ATTR_APPEND(whole_len, bp, len) != 0)
177 goto out3;
180 if (kalist.commonattr & DARWIN_ATTR_CMN_NAME) {
181 darwin_attrreference_t dar;
183 cmn_name_p = (darwin_attrreference_t *)bp;
184 if (ATTR_APPEND(dar, bp, len) != 0)
185 goto out3;
188 if (kalist.commonattr & DARWIN_ATTR_CMN_DEVID) {
189 darwin_dev_t device;
191 device = st.st_dev;
192 if (ATTR_APPEND(device, bp, len) != 0)
193 goto out3;
196 if (kalist.commonattr & DARWIN_ATTR_CMN_FSID) {
197 fsid_t fs;
198 fs = f->f_fsidx;
199 if (ATTR_APPEND(fs, bp, len) != 0)
200 goto out3;
203 if (kalist.commonattr & DARWIN_ATTR_CMN_OBJTYPE) {
204 darwin_fsobj_type_t dft;
206 dft = vp->v_type;
207 if (ATTR_APPEND(dft, bp, len) != 0)
208 goto out3;
211 if (kalist.commonattr & DARWIN_ATTR_CMN_OBJTAG) {
212 darwin_fsobj_tag_t dft;
214 dft = vp->v_tag;
215 if (ATTR_APPEND(dft, bp, len) != 0)
216 goto out3;
219 if (kalist.commonattr & DARWIN_ATTR_CMN_OBJID) {
220 darwin_fsobj_id_t dfi;
222 dfi.fid_objno = st.st_ino;
223 dfi.fid_generation = 0; /* XXX root can read real value */
224 if (ATTR_APPEND(dfi, bp, len) != 0)
225 goto out3;
228 if (kalist.commonattr & DARWIN_ATTR_CMN_OBJPERMANENTID) {
229 darwin_fsobj_id_t dfi;
231 dfi.fid_objno = st.st_ino; /* This is not really persistent */
232 dfi.fid_generation = 0; /* XXX root can read real value */
233 if (ATTR_APPEND(dfi, bp, len) != 0)
234 goto out3;
237 if (kalist.commonattr & DARWIN_ATTR_CMN_PAROBJID) {
238 darwin_fsobj_id_t dfi;
240 dfi.fid_objno = 0; /* XXX do me */
241 dfi.fid_generation = 0; /* XXX root can read real value */
242 if (ATTR_APPEND(dfi, bp, len) != 0)
243 goto out3;
246 if (kalist.commonattr & DARWIN_ATTR_CMN_SCRIPT) {
247 darwin_text_encoding_t dte;
249 dte = DARWIN_US_ASCII;
250 if (ATTR_APPEND(dte, bp, len) != 0)
251 goto out3;
254 if (kalist.commonattr & DARWIN_ATTR_CMN_CRTIME) {
255 if (ATTR_APPEND(st.st_ctimespec, bp, len) != 0)
256 goto out3;
259 if (kalist.commonattr & DARWIN_ATTR_CMN_MODTIME) {
260 if (ATTR_APPEND(st.st_mtimespec, bp, len) != 0)
261 goto out3;
264 if (kalist.commonattr & DARWIN_ATTR_CMN_CHGTIME) {
265 if (ATTR_APPEND(st.st_ctimespec, bp, len) != 0)
266 goto out3;
269 if (kalist.commonattr & DARWIN_ATTR_CMN_ACCTIME) {
270 if (ATTR_APPEND(st.st_atimespec, bp, len) != 0)
271 goto out3;
274 if (kalist.commonattr & DARWIN_ATTR_CMN_BKUPTIME) {
275 struct timespec ts;
277 /* XXX no way I can do that one */
279 (void)memset(&ts, 0, sizeof(ts));
280 if (ATTR_APPEND(ts, bp, len) != 0)
281 goto out3;
284 if (kalist.commonattr & DARWIN_ATTR_CMN_FNDRINFO) { /* XXX */
285 char data[32];
287 (void)memset(&data, 0, sizeof(data));
288 if (ATTR_APPEND(data, bp, len) != 0)
289 goto out3;
292 if (kalist.commonattr & DARWIN_ATTR_CMN_OWNERID) {
293 uid_t uid;
295 uid = st.st_uid;
296 if (ATTR_APPEND(uid, bp, len) != 0)
297 goto out3;
300 if (kalist.commonattr & DARWIN_ATTR_CMN_GRPID) {
301 gid_t gid;
303 gid = st.st_gid;
304 if (ATTR_APPEND(gid, bp, len) != 0)
305 goto out3;
308 if (kalist.commonattr & DARWIN_ATTR_CMN_ACCESSMASK) {
309 mode_t mode;
311 mode = st.st_mode;
312 if (ATTR_APPEND(mode, bp, len) != 0)
313 goto out3;
316 if (kalist.commonattr & DARWIN_ATTR_CMN_NAMEDATTRCOUNT) {
317 /* Data is unsigned long. Unsupported in Darwin */
318 error = EINVAL;
319 goto out3;
322 if (kalist.commonattr & DARWIN_ATTR_CMN_NAMEDATTRLIST) {
323 /* Data is darwin_attrreference_t. Unsupported in Darwin */
325 error = EINVAL;
326 goto out3;
329 if (kalist.commonattr & DARWIN_ATTR_CMN_FLAGS) {
330 unsigned long flags;
332 flags = st.st_flags; /* XXX need convertion */
333 if (ATTR_APPEND(flags, bp, len) != 0)
334 goto out3;
337 if (kalist.commonattr & DARWIN_ATTR_CMN_USERACCESS) {
338 unsigned long ua = 0;
339 struct sys_access_args cup3;
340 register_t rv;
342 SCARG(&cup3, path) = SCARG(uap, path);
344 SCARG(&cup3, flags) = R_OK;
345 if (sys_access(l, &cup3, &rv) == 0)
346 ua |= R_OK;
348 SCARG(&cup3, flags) = W_OK;
349 if (sys_access(l, &cup3, &rv) == 0)
350 ua |= W_OK;
352 SCARG(&cup3, flags) = X_OK;
353 if (sys_access(l, &cup3, &rv) == 0)
354 ua |= X_OK;
356 if (ATTR_APPEND(ua, bp, len) != 0)
357 goto out3;
361 if (kalist.volattr & DARWIN_ATTR_VOL_INFO) {
362 /* Nothing added, just skip */
365 if (kalist.volattr & DARWIN_ATTR_VOL_FSTYPE) {
366 unsigned long fstype;
368 /* We'd need to convert f_fstypename - done for COMPAT_09 */
369 fstype = 0; /* f->f_type; */
370 if (ATTR_APPEND(fstype, bp, len) != 0)
371 goto out3;
374 if (kalist.volattr & DARWIN_ATTR_VOL_SIGNATURE) {
375 unsigned long sign;
378 * XXX Volume signature, used to distinguish
379 * between volumes inside the same filesystem.
381 sign = f->f_fsidx.__fsid_val[0];
382 if (ATTR_APPEND(sign, bp, len) != 0)
383 goto out3;
386 if (kalist.volattr & DARWIN_ATTR_VOL_SIZE) {
387 off_t size;
389 size = f->f_blocks * f->f_bsize;
390 if (ATTR_APPEND(size, bp, len) != 0)
391 goto out3;
394 if (kalist.volattr & DARWIN_ATTR_VOL_SPACEFREE) {
395 off_t ofree;
397 ofree = f->f_bfree * f->f_bsize;
398 if (ATTR_APPEND(ofree, bp, len) != 0)
399 goto out3;
402 if (kalist.volattr & DARWIN_ATTR_VOL_SPACEAVAIL) {
403 off_t avail;
405 avail = f->f_bavail * f->f_bsize;
406 if (ATTR_APPEND(avail, bp, len) != 0)
407 goto out3;
410 if (kalist.volattr & DARWIN_ATTR_VOL_MINALLOCATION) {
411 off_t omin;
413 omin = f->f_bsize; /* XXX probably wrong */
414 if (ATTR_APPEND(omin, bp, len) != 0)
415 goto out3;
418 if (kalist.volattr & DARWIN_ATTR_VOL_ALLOCATIONCLUMP) {
419 off_t clump;
421 clump = f->f_bsize; /* XXX proably wrong */
422 if (ATTR_APPEND(clump, bp, len) != 0)
423 goto out3;
426 if (kalist.volattr & DARWIN_ATTR_VOL_IOBLOCKSIZE) {
427 unsigned long size;
429 size = f->f_iosize;
430 if (ATTR_APPEND(size, bp, len) != 0)
431 goto out3;
434 if (kalist.volattr & DARWIN_ATTR_VOL_OBJCOUNT) {
435 unsigned long cnt;
437 cnt = f->f_files;
438 if (ATTR_APPEND(cnt, bp, len) != 0)
439 goto out3;
442 if (kalist.volattr & DARWIN_ATTR_VOL_FILECOUNT) {
443 unsigned long cnt;
445 cnt = f->f_files; /* XXX only files */
446 if (ATTR_APPEND(cnt, bp, len) != 0)
447 goto out3;
450 if (kalist.volattr & DARWIN_ATTR_VOL_DIRCOUNT) {
451 unsigned long cnt;
453 cnt = 0; /* XXX wrong, of course */
454 if (ATTR_APPEND(cnt, bp, len) != 0)
455 goto out3;
458 if (kalist.volattr & DARWIN_ATTR_VOL_MAXOBJCOUNT) {
459 unsigned long cnt;
461 cnt = f->f_files + f->f_ffree;
462 if (ATTR_APPEND(cnt, bp, len) != 0)
463 goto out3;
466 if (kalist.volattr & DARWIN_ATTR_VOL_MOUNTPOINT) {
467 darwin_attrreference_t dar;
469 vol_mountpoint_p = (darwin_attrreference_t *)bp;
470 if (ATTR_APPEND(dar, bp, len) != 0)
471 goto out3;
474 if (kalist.volattr & DARWIN_ATTR_VOL_NAME) {
475 darwin_attrreference_t dar;
477 vol_name_p = (darwin_attrreference_t *)bp;
478 if (ATTR_APPEND(dar, bp, len) != 0)
479 goto out3;
482 if (kalist.volattr & DARWIN_ATTR_VOL_MOUNTFLAGS) {
483 unsigned long flags;
485 flags = f->f_flag; /* XXX need convertion? */
486 if (ATTR_APPEND(flags, bp, len) != 0)
487 goto out3;
490 if (kalist.volattr & DARWIN_ATTR_VOL_MOUNTEDDEVICE) {
491 darwin_attrreference_t dar;
493 vol_mounteddevice_p = (darwin_attrreference_t *)bp;
494 if (ATTR_APPEND(dar, bp, len) != 0)
495 goto out3;
498 if (kalist.volattr & DARWIN_ATTR_VOL_ENCODINGSUSED) {
499 unsigned long long data;
502 * XXX bitmap of encoding used in this volume
504 (void)memset(&data, 0, sizeof(data));
505 if (ATTR_APPEND(data, bp, len) != 0)
506 goto out3;
509 if (kalist.volattr & DARWIN_ATTR_VOL_CAPABILITIES) { /* XXX */
510 darwin_vol_capabilities_attr_t data;
512 (void)memset(&data, 0, sizeof(data));
513 if (ATTR_APPEND(data, bp, len) != 0)
514 goto out3;
517 if (kalist.volattr & DARWIN_ATTR_VOL_ATTRIBUTES) { /* XXX */
518 darwin_vol_attributes_attr_t data;
520 (void)memset(&data, 0, sizeof(data));
521 if (ATTR_APPEND(data, bp, len) != 0)
522 goto out3;
525 if (kalist.dirattr & DARWIN_ATTR_DIR_LINKCOUNT) {
526 unsigned long cnt;
528 cnt = st.st_nlink;
529 if (ATTR_APPEND(cnt, bp, len) != 0)
530 goto out3;
533 if (kalist.dirattr & DARWIN_ATTR_DIR_ENTRYCOUNT) { /* XXX */
534 unsigned long data;
536 (void)memset(&data, 0, sizeof(data));
537 if (ATTR_APPEND(data, bp, len) != 0)
538 goto out3;
541 if (kalist.dirattr & DARWIN_ATTR_DIR_MOUNTSTATUS) { /* XXX */
542 unsigned long data;
544 (void)memset(&data, 0, sizeof(data));
545 if (ATTR_APPEND(data, bp, len) != 0)
546 goto out3;
549 if (kalist.fileattr & DARWIN_ATTR_FILE_LINKCOUNT) {
550 unsigned long cnt;
552 cnt = st.st_nlink;
553 if (ATTR_APPEND(cnt, bp, len) != 0)
554 goto out3;
557 if (kalist.fileattr & DARWIN_ATTR_FILE_TOTALSIZE) {
558 off_t size;
560 size = st.st_size;
561 if (ATTR_APPEND(size, bp, len) != 0)
562 goto out3;
565 if (kalist.fileattr & DARWIN_ATTR_FILE_ALLOCSIZE) {
566 off_t size;
568 size = st.st_blocks * f->f_bsize;
569 if (ATTR_APPEND(size, bp, len) != 0)
570 goto out3;
573 if (kalist.fileattr & DARWIN_ATTR_FILE_IOBLOCKSIZE) {
574 unsigned long size;
576 size = st.st_blksize;
577 if (ATTR_APPEND(size, bp, len) != 0)
578 goto out3;
581 if (kalist.fileattr & DARWIN_ATTR_FILE_CLUMPSIZE) {
582 unsigned long size;
584 size = st.st_blksize; /* XXX probably wrong */
585 if (ATTR_APPEND(size, bp, len) != 0)
586 goto out3;
589 if (kalist.fileattr & DARWIN_ATTR_FILE_DEVTYPE) {
590 unsigned long type;
592 type = st.st_rdev;
593 if (ATTR_APPEND(type, bp, len) != 0)
594 goto out3;
597 if (kalist.fileattr & DARWIN_ATTR_FILE_FILETYPE) {
598 unsigned long data;
600 /* Reserved, returns 0 */
601 (void)memset(&data, 0, sizeof(data));
602 if (ATTR_APPEND(data, bp, len) != 0)
603 goto out3;
606 if (kalist.fileattr & DARWIN_ATTR_FILE_FORKCOUNT) { /* XXX */
607 unsigned long cnt;
609 cnt = 1; /* Only one fork, of course */
610 if (ATTR_APPEND(cnt, bp, len) != 0)
611 goto out3;
614 if (kalist.fileattr & DARWIN_ATTR_FILE_FORKLIST) {
615 /* Unsupported in Darwin */
616 error = EINVAL;
617 goto out3;
620 if (kalist.fileattr & DARWIN_ATTR_FILE_DATALENGTH) { /* All forks */
621 off_t size;
623 size = st.st_size;
624 if (ATTR_APPEND(size, bp, len) != 0)
625 goto out3;
628 if (kalist.fileattr & DARWIN_ATTR_FILE_DATAALLOCSIZE) { /* All forks */
629 off_t size;
631 size = st.st_blocks * f->f_bsize;
632 if (ATTR_APPEND(size, bp, len) != 0)
633 goto out3;
636 if (kalist.fileattr & DARWIN_ATTR_FILE_DATAEXTENTS) {
637 darwin_extentrecord data;
639 /* Obsolete in Darwin */
640 (void)memset(&data, 0, sizeof(data));
641 if (ATTR_APPEND(data, bp, len) != 0)
642 goto out3;
645 if (kalist.fileattr & DARWIN_ATTR_FILE_RSRCLENGTH) {
646 off_t size;
648 size = 0;
649 if (ATTR_APPEND(size, bp, len) != 0)
650 goto out3;
653 if (kalist.fileattr & DARWIN_ATTR_FILE_RSRCALLOCSIZE) {
654 off_t size;
656 size = 0;
657 if (ATTR_APPEND(size, bp, len) != 0)
658 goto out3;
661 if (kalist.fileattr & DARWIN_ATTR_FILE_RSRCEXTENTS) {
662 darwin_extentrecord data;
664 /* Obsolete in Darwin */
665 (void)memset(&data, 0, sizeof(data));
666 if (ATTR_APPEND(data, bp, len) != 0)
667 goto out3;
670 if (kalist.forkattr & DARWIN_ATTR_FORK_TOTALSIZE) {
671 off_t size;
673 size = st.st_size;
674 if (ATTR_APPEND(size, bp, len) != 0)
675 goto out3;
678 if (kalist.forkattr & DARWIN_ATTR_FORK_ALLOCSIZE) {
679 off_t size;
681 size = st.st_blocks * f->f_bsize;
682 if (ATTR_APPEND(size, bp, len) != 0)
683 goto out3;
687 * Now the variable length fields
690 if (cmn_name_p) { /* DARWIN_ATTR_CMN_NAME */
691 cmn_name_p->attr_dataoffset = (u_long)bp - (u_long)cmn_name_p;
692 cmn_name_p->attr_length = nd.ni_cnd.cn_namelen;
693 if (darwin_attr_append(nd.ni_cnd.cn_nameptr,
694 cmn_name_p->attr_length, &bp, &len) != 0)
695 goto out3;
697 /* word alignement */
698 shift = (((u_long)bp & ~0x3UL) + 4) - (u_long)bp;
699 if (darwin_attr_append((char *)null, shift, &bp, &len) != 0)
700 goto out3;
703 if (vol_mountpoint_p) { /* DARWIN_ATTR_VOL_MOUNTPOINT */
704 vol_mountpoint_p->attr_dataoffset =
705 (u_long)bp - (u_long)vol_mountpoint_p;
706 vol_mountpoint_p->attr_length = strlen(f->f_mntonname);
707 if (darwin_attr_append(f->f_mntonname,
708 vol_mountpoint_p->attr_length, &bp, &len) != 0)
709 goto out3;
711 /* word alignement */
712 shift = (((u_long)bp & ~0x3UL) + 4) - (u_long)bp;
713 if (darwin_attr_append((char *)null, shift, &bp, &len) != 0)
714 goto out3;
717 if (vol_mounteddevice_p) { /* DARWIN_ATTR_VOL_MOUNTEDDEVICE */
718 vol_mounteddevice_p->attr_dataoffset =
719 (u_long)bp - (u_long)vol_mounteddevice_p;
720 vol_mounteddevice_p->attr_length = strlen(f->f_mntfromname);
721 if (darwin_attr_append(f->f_mntfromname,
722 vol_mounteddevice_p->attr_length, &bp, &len) != 0)
723 goto out3;
725 /* word alignement */
726 shift = (((u_long)bp & ~0x3UL) + 4) - (u_long)bp;
727 if (darwin_attr_append((char *)null, shift, &bp, &len) != 0)
728 goto out3;
731 if (vol_name_p) { /* DARWIN_ATTR_VOL_NAME */
732 char name[] = "Volume"; /* XXX We have no volume names... */
733 size_t namelen = strlen(name);
735 vol_name_p->attr_dataoffset = (u_long)bp - (u_long)vol_name_p;
736 vol_name_p->attr_length = namelen;
737 if (darwin_attr_append(name, namelen, &bp, &len) != 0)
738 goto out3;
740 /* word alignement */
741 shift = (((u_long)bp & ~0x3UL) + 4) - (u_long)bp;
742 if (darwin_attr_append((char *)null, shift, &bp, &len) != 0)
743 goto out3;
746 /* And, finnally, the whole buffer length */
747 if (whole_len_p) {
748 *whole_len_p = SCARG(uap, buflen) - len;
752 * We are done! Copyout the stuff and get away
754 if (error == 0)
755 error = copyout(tbuf, SCARG(uap, attributes), *whole_len_p);
756 out3:
757 vput(vp);
758 out2:
759 kauth_cred_free(cred);
760 free(tbuf, M_TEMP);
762 STATVFSBUF_PUT(f);
763 return error;