1 /* $NetBSD: darwin_attr.c,v 1.24 2008/04/28 20:23:41 martin Exp $ */
2
3 /*-
4 * Copyright (c) 2003, 2008 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Emmanuel Dreyfus.
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 *
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.
30 */
31
32 #include <sys/cdefs.h>
33 __KERNEL_RCSID(0, "$NetBSD: darwin_attr.c,v 1.24 2008/04/28 20:23:41 martin Exp $");
34
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>
50
51 #include <compat/sys/signal.h>
52 #include <compat/sys/mount.h>
53
54 #include <compat/common/compat_util.h>
55
56 #include <compat/mach/mach_types.h>
57 #include <compat/mach/mach_vm.h>
58
59 #include <compat/darwin/darwin_audit.h>
60 #include <compat/darwin/darwin_attr.h>
61 #include <compat/darwin/darwin_syscallargs.h>
62
63 #define DARWIN_ATTR_MAXBUFLEN 4096
64
65 static int darwin_attr_append(const char *, size_t, char **, size_t *);
66
67 #define ATTR_APPEND(x, bp, len) \
68 darwin_attr_append((char *)&(x), sizeof(x), &(bp), &(len))
69
70
71 static int
72 darwin_attr_append(const char *x, size_t size, char **bp, size_t *len)
73 {
74 if (*len < size)
75 return -1;
76
77 (void)memcpy(*bp, x, size);
78
79 *bp += size;
80 *len -= size;
81
82 return 0;
83 }
84
85 int
86 darwin_sys_getattrlist(struct lwp *l, const struct darwin_sys_getattrlist_args *uap, register_t *retval)
87 {
88 /* {
89 syscallarg(const char *) path;
90 syscallarg(struct darwin_attrlist *) alist;
91 syscallarg(void *) attributes;
92 syscallarg(size_t) buflen;
93 syscallarg(unsigned long) options;
94 } */
95 struct darwin_attrlist kalist;
96 char *tbuf;
97 char *bp;
98 size_t len;
99 size_t shift = 0;
100 int null = 0;
101 int error = 0;
102 int follow = NOFOLLOW;
103 u_long *whole_len_p = NULL;
104 darwin_attrreference_t *cmn_name_p = NULL;
105 darwin_attrreference_t *vol_mountpoint_p = NULL;
106 darwin_attrreference_t *vol_name_p = NULL;
107 darwin_attrreference_t *vol_mounteddevice_p = NULL;
108 struct stat st;
109 struct statvfs *f;
110 struct nameidata nd;
111 struct vnode *vp;
112 kauth_cred_t cred;
113
114 if ((error = copyin(SCARG(uap, alist), &kalist, sizeof(kalist))) != 0)
115 return error;
116
117 if (kalist.bitmapcount != DARWIN_ATTR_BIT_MAP_COUNT)
118 return EINVAL;
119
120 len = SCARG(uap, buflen);
121 if (len > DARWIN_ATTR_MAXBUFLEN)
122 return E2BIG;
123
124 if ((SCARG(uap, options) & DARWIN_FSOPT_NOFOLLOW) != 0)
125 follow = FOLLOW;
126
127 #ifdef DEBUG_DARWIN
128 printf("getattrlist: %08x %08x %08x %08x %08x\n",
129 kalist.commonattr, kalist.volattr, kalist.dirattr,
130 kalist.fileattr, kalist.forkattr);
131 #endif
132
133 /* Allocate buffers now... */
134 f = STATVFSBUF_GET();
135 tbuf = malloc(len, M_TEMP, M_WAITOK);
136
137 /* We are going to need the vnode itself... */
138
139 cred = kauth_cred_dup(l->l_cred);
140 kauth_cred_seteuid(cred, kauth_cred_getuid(l->l_cred));
141 kauth_cred_setegid(cred, kauth_cred_getgid(l->l_cred));
142
143 NDINIT(&nd, LOOKUP, follow | LOCKLEAF | TRYEMULROOT, UIO_USERSPACE,
144 SCARG(uap, path));
145 if ((error = namei(&nd)) != 0)
146 goto out2;
147
148 vp = nd.ni_vp;
149 if ((error = VOP_ACCESS(vp, VREAD | VEXEC, cred)) != 0)
150 goto out3;
151
152 /* Get the informations for path: file related info */
153 error = vn_stat(vp, &st);
154 if (error != 0)
155 goto out3;
156
157 /* filesystem related info */
158 error = dostatvfs(vp->v_mount, f, l, 0, 1);
159 if (error != 0)
160 goto out3;
161
162 /*
163 * Prepare the buffer
164 */
165 bp = tbuf;
166
167 /*
168 * Buffer whole length: is always present
169 */
170 if (1) {
171 u_long whole_len;
172
173 whole_len = 0;
174 whole_len_p = (u_long *)bp;
175 if (ATTR_APPEND(whole_len, bp, len) != 0)
176 goto out3;
177 }
178
179 if (kalist.commonattr & DARWIN_ATTR_CMN_NAME) {
180 darwin_attrreference_t dar;
181
182 cmn_name_p = (darwin_attrreference_t *)bp;
183 if (ATTR_APPEND(dar, bp, len) != 0)
184 goto out3;
185 }
186
187 if (kalist.commonattr & DARWIN_ATTR_CMN_DEVID) {
188 dev_t device;
189
190 device = st.st_dev;
191 if (ATTR_APPEND(device, bp, len) != 0)
192 goto out3;
193 }
194
195 if (kalist.commonattr & DARWIN_ATTR_CMN_FSID) {
196 fsid_t fs;
197 fs = f->f_fsidx;
198 if (ATTR_APPEND(fs, bp, len) != 0)
199 goto out3;
200 }
201
202 if (kalist.commonattr & DARWIN_ATTR_CMN_OBJTYPE) {
203 darwin_fsobj_type_t dft;
204
205 dft = vp->v_type;
206 if (ATTR_APPEND(dft, bp, len) != 0)
207 goto out3;
208 }
209
210 if (kalist.commonattr & DARWIN_ATTR_CMN_OBJTAG) {
211 darwin_fsobj_tag_t dft;
212
213 dft = vp->v_tag;
214 if (ATTR_APPEND(dft, bp, len) != 0)
215 goto out3;
216 }
217
218 if (kalist.commonattr & DARWIN_ATTR_CMN_OBJID) {
219 darwin_fsobj_id_t dfi;
220
221 dfi.fid_objno = st.st_ino;
222 dfi.fid_generation = 0; /* XXX root can read real value */
223 if (ATTR_APPEND(dfi, bp, len) != 0)
224 goto out3;
225 }
226
227 if (kalist.commonattr & DARWIN_ATTR_CMN_OBJPERMANENTID) {
228 darwin_fsobj_id_t dfi;
229
230 dfi.fid_objno = st.st_ino; /* This is not really persistent */
231 dfi.fid_generation = 0; /* XXX root can read real value */
232 if (ATTR_APPEND(dfi, bp, len) != 0)
233 goto out3;
234 }
235
236 if (kalist.commonattr & DARWIN_ATTR_CMN_PAROBJID) {
237 darwin_fsobj_id_t dfi;
238
239 dfi.fid_objno = 0; /* XXX do me */
240 dfi.fid_generation = 0; /* XXX root can read real value */
241 if (ATTR_APPEND(dfi, bp, len) != 0)
242 goto out3;
243 }
244
245 if (kalist.commonattr & DARWIN_ATTR_CMN_SCRIPT) {
246 darwin_text_encoding_t dte;
247
248 dte = DARWIN_US_ASCII;
249 if (ATTR_APPEND(dte, bp, len) != 0)
250 goto out3;
251 }
252
253 if (kalist.commonattr & DARWIN_ATTR_CMN_CRTIME) {
254 if (ATTR_APPEND(st.st_ctimespec, bp, len) != 0)
255 goto out3;
256 }
257
258 if (kalist.commonattr & DARWIN_ATTR_CMN_MODTIME) {
259 if (ATTR_APPEND(st.st_mtimespec, bp, len) != 0)
260 goto out3;
261 }
262
263 if (kalist.commonattr & DARWIN_ATTR_CMN_CHGTIME) {
264 if (ATTR_APPEND(st.st_ctimespec, bp, len) != 0)
265 goto out3;
266 }
267
268 if (kalist.commonattr & DARWIN_ATTR_CMN_ACCTIME) {
269 if (ATTR_APPEND(st.st_atimespec, bp, len) != 0)
270 goto out3;
271 }
272
273 if (kalist.commonattr & DARWIN_ATTR_CMN_BKUPTIME) {
274 struct timespec ts;
275
276 /* XXX no way I can do that one */
277
278 (void)bzero(&ts, sizeof(ts));
279 if (ATTR_APPEND(ts, bp, len) != 0)
280 goto out3;
281 }
282
283 if (kalist.commonattr & DARWIN_ATTR_CMN_FNDRINFO) { /* XXX */
284 char data[32];
285
286 (void)bzero(&data, sizeof(data));
287 if (ATTR_APPEND(data, bp, len) != 0)
288 goto out3;
289 }
290
291 if (kalist.commonattr & DARWIN_ATTR_CMN_OWNERID) {
292 uid_t uid;
293
294 uid = st.st_uid;
295 if (ATTR_APPEND(uid, bp, len) != 0)
296 goto out3;
297 }
298
299 if (kalist.commonattr & DARWIN_ATTR_CMN_GRPID) {
300 gid_t gid;
301
302 gid = st.st_gid;
303 if (ATTR_APPEND(gid, bp, len) != 0)
304 goto out3;
305 }
306
307 if (kalist.commonattr & DARWIN_ATTR_CMN_ACCESSMASK) {
308 mode_t mode;
309
310 mode = st.st_mode;
311 if (ATTR_APPEND(mode, bp, len) != 0)
312 goto out3;
313 }
314
315 if (kalist.commonattr & DARWIN_ATTR_CMN_NAMEDATTRCOUNT) {
316 /* Data is unsigned long. Unsupported in Darwin */
317 error = EINVAL;
318 goto out3;
319 }
320
321 if (kalist.commonattr & DARWIN_ATTR_CMN_NAMEDATTRLIST) {
322 /* Data is darwin_attrreference_t. Unsupported in Darwin */
323
324 error = EINVAL;
325 goto out3;
326 }
327
328 if (kalist.commonattr & DARWIN_ATTR_CMN_FLAGS) {
329 unsigned long flags;
330
331 flags = st.st_flags; /* XXX need convertion */
332 if (ATTR_APPEND(flags, bp, len) != 0)
333 goto out3;
334 }
335
336 if (kalist.commonattr & DARWIN_ATTR_CMN_USERACCESS) {
337 unsigned long ua = 0;
338 struct sys_access_args cup3;
339 register_t rv;
340
341 SCARG(&cup3, path) = SCARG(uap, path);
342
343 SCARG(&cup3, flags) = R_OK;
344 if (sys_access(l, &cup3, &rv) == 0)
345 ua |= R_OK;
346
347 SCARG(&cup3, flags) = W_OK;
348 if (sys_access(l, &cup3, &rv) == 0)
349 ua |= W_OK;
350
351 SCARG(&cup3, flags) = X_OK;
352 if (sys_access(l, &cup3, &rv) == 0)
353 ua |= X_OK;
354
355 if (ATTR_APPEND(ua, bp, len) != 0)
356 goto out3;
357 }
358
359
360 if (kalist.volattr & DARWIN_ATTR_VOL_INFO) {
361 /* Nothing added, just skip */
362 }
363
364 if (kalist.volattr & DARWIN_ATTR_VOL_FSTYPE) {
365 unsigned long fstype;
366
367 /* We'd need to convert f_fstypename - done for COMPAT_09 */
368 fstype = 0; /* f->f_type; */
369 if (ATTR_APPEND(fstype, bp, len) != 0)
370 goto out3;
371 }
372
373 if (kalist.volattr & DARWIN_ATTR_VOL_SIGNATURE) {
374 unsigned long sign;
375
376 /*
377 * XXX Volume signature, used to distinguish
378 * between volumes inside the same filesystem.
379 */
380 sign = f->f_fsidx.__fsid_val[0];
381 if (ATTR_APPEND(sign, bp, len) != 0)
382 goto out3;
383 }
384
385 if (kalist.volattr & DARWIN_ATTR_VOL_SIZE) {
386 off_t size;
387
388 size = f->f_blocks * f->f_bsize;
389 if (ATTR_APPEND(size, bp, len) != 0)
390 goto out3;
391 }
392
393 if (kalist.volattr & DARWIN_ATTR_VOL_SPACEFREE) {
394 off_t ofree;
395
396 ofree = f->f_bfree * f->f_bsize;
397 if (ATTR_APPEND(ofree, bp, len) != 0)
398 goto out3;
399 }
400
401 if (kalist.volattr & DARWIN_ATTR_VOL_SPACEAVAIL) {
402 off_t avail;
403
404 avail = f->f_bavail * f->f_bsize;
405 if (ATTR_APPEND(avail, bp, len) != 0)
406 goto out3;
407 }
408
409 if (kalist.volattr & DARWIN_ATTR_VOL_MINALLOCATION) {
410 off_t omin;
411
412 omin = f->f_bsize; /* XXX probably wrong */
413 if (ATTR_APPEND(omin, bp, len) != 0)
414 goto out3;
415 }
416
417 if (kalist.volattr & DARWIN_ATTR_VOL_ALLOCATIONCLUMP) {
418 off_t clump;
419
420 clump = f->f_bsize; /* XXX proably wrong */
421 if (ATTR_APPEND(clump, bp, len) != 0)
422 goto out3;
423 }
424
425 if (kalist.volattr & DARWIN_ATTR_VOL_IOBLOCKSIZE) {
426 unsigned long size;
427
428 size = f->f_iosize;
429 if (ATTR_APPEND(size, bp, len) != 0)
430 goto out3;
431 }
432
433 if (kalist.volattr & DARWIN_ATTR_VOL_OBJCOUNT) {
434 unsigned long cnt;
435
436 cnt = f->f_files;
437 if (ATTR_APPEND(cnt, bp, len) != 0)
438 goto out3;
439 }
440
441 if (kalist.volattr & DARWIN_ATTR_VOL_FILECOUNT) {
442 unsigned long cnt;
443
444 cnt = f->f_files; /* XXX only files */
445 if (ATTR_APPEND(cnt, bp, len) != 0)
446 goto out3;
447 }
448
449 if (kalist.volattr & DARWIN_ATTR_VOL_DIRCOUNT) {
450 unsigned long cnt;
451
452 cnt = 0; /* XXX wrong, of course */
453 if (ATTR_APPEND(cnt, bp, len) != 0)
454 goto out3;
455 }
456
457 if (kalist.volattr & DARWIN_ATTR_VOL_MAXOBJCOUNT) {
458 unsigned long cnt;
459
460 cnt = f->f_files + f->f_ffree;
461 if (ATTR_APPEND(cnt, bp, len) != 0)
462 goto out3;
463 }
464
465 if (kalist.volattr & DARWIN_ATTR_VOL_MOUNTPOINT) {
466 darwin_attrreference_t dar;
467
468 vol_mountpoint_p = (darwin_attrreference_t *)bp;
469 if (ATTR_APPEND(dar, bp, len) != 0)
470 goto out3;
471 }
472
473 if (kalist.volattr & DARWIN_ATTR_VOL_NAME) {
474 darwin_attrreference_t dar;
475
476 vol_name_p = (darwin_attrreference_t *)bp;
477 if (ATTR_APPEND(dar, bp, len) != 0)
478 goto out3;
479 }
480
481 if (kalist.volattr & DARWIN_ATTR_VOL_MOUNTFLAGS) {
482 unsigned long flags;
483
484 flags = f->f_flag; /* XXX need convertion? */
485 if (ATTR_APPEND(flags, bp, len) != 0)
486 goto out3;
487 }
488
489 if (kalist.volattr & DARWIN_ATTR_VOL_MOUNTEDDEVICE) {
490 darwin_attrreference_t dar;
491
492 vol_mounteddevice_p = (darwin_attrreference_t *)bp;
493 if (ATTR_APPEND(dar, bp, len) != 0)
494 goto out3;
495 }
496
497 if (kalist.volattr & DARWIN_ATTR_VOL_ENCODINGSUSED) {
498 unsigned long long data;
499
500 /*
501 * XXX bitmap of encoding used in this volume
502 */
503 (void)bzero(&data, sizeof(data));
504 if (ATTR_APPEND(data, bp, len) != 0)
505 goto out3;
506 }
507
508 if (kalist.volattr & DARWIN_ATTR_VOL_CAPABILITIES) { /* XXX */
509 darwin_vol_capabilities_attr_t data;
510
511 (void)bzero(&data, sizeof(data));
512 if (ATTR_APPEND(data, bp, len) != 0)
513 goto out3;
514 }
515
516 if (kalist.volattr & DARWIN_ATTR_VOL_ATTRIBUTES) { /* XXX */
517 darwin_vol_attributes_attr_t data;
518
519 (void)bzero(&data, sizeof(data));
520 if (ATTR_APPEND(data, bp, len) != 0)
521 goto out3;
522 }
523
524 if (kalist.dirattr & DARWIN_ATTR_DIR_LINKCOUNT) {
525 unsigned long cnt;
526
527 cnt = st.st_nlink;
528 if (ATTR_APPEND(cnt, bp, len) != 0)
529 goto out3;
530 }
531
532 if (kalist.dirattr & DARWIN_ATTR_DIR_ENTRYCOUNT) { /* XXX */
533 unsigned long data;
534
535 (void)bzero(&data, sizeof(data));
536 if (ATTR_APPEND(data, bp, len) != 0)
537 goto out3;
538 }
539
540 if (kalist.dirattr & DARWIN_ATTR_DIR_MOUNTSTATUS) { /* XXX */
541 unsigned long data;
542
543 (void)bzero(&data, sizeof(data));
544 if (ATTR_APPEND(data, bp, len) != 0)
545 goto out3;
546 }
547
548 if (kalist.fileattr & DARWIN_ATTR_FILE_LINKCOUNT) {
549 unsigned long cnt;
550
551 cnt = st.st_nlink;
552 if (ATTR_APPEND(cnt, bp, len) != 0)
553 goto out3;
554 }
555
556 if (kalist.fileattr & DARWIN_ATTR_FILE_TOTALSIZE) {
557 off_t size;
558
559 size = st.st_size;
560 if (ATTR_APPEND(size, bp, len) != 0)
561 goto out3;
562 }
563
564 if (kalist.fileattr & DARWIN_ATTR_FILE_ALLOCSIZE) {
565 off_t size;
566
567 size = st.st_blocks * f->f_bsize;
568 if (ATTR_APPEND(size, bp, len) != 0)
569 goto out3;
570 }
571
572 if (kalist.fileattr & DARWIN_ATTR_FILE_IOBLOCKSIZE) {
573 unsigned long size;
574
575 size = st.st_blksize;
576 if (ATTR_APPEND(size, bp, len) != 0)
577 goto out3;
578 }
579
580 if (kalist.fileattr & DARWIN_ATTR_FILE_CLUMPSIZE) {
581 unsigned long size;
582
583 size = st.st_blksize; /* XXX probably wrong */
584 if (ATTR_APPEND(size, bp, len) != 0)
585 goto out3;
586 }
587
588 if (kalist.fileattr & DARWIN_ATTR_FILE_DEVTYPE) {
589 unsigned long type;
590
591 type = st.st_rdev;
592 if (ATTR_APPEND(type, bp, len) != 0)
593 goto out3;
594 }
595
596 if (kalist.fileattr & DARWIN_ATTR_FILE_FILETYPE) {
597 unsigned long data;
598
599 /* Reserved, returns 0 */
600 (void)bzero(&data, sizeof(data));
601 if (ATTR_APPEND(data, bp, len) != 0)
602 goto out3;
603 }
604
605 if (kalist.fileattr & DARWIN_ATTR_FILE_FORKCOUNT) { /* XXX */
606 unsigned long cnt;
607
608 cnt = 1; /* Only one fork, of course */
609 if (ATTR_APPEND(cnt, bp, len) != 0)
610 goto out3;
611 }
612
613 if (kalist.fileattr & DARWIN_ATTR_FILE_FORKLIST) {
614 /* Unsupported in Darwin */
615 error = EINVAL;
616 goto out3;
617 }
618
619 if (kalist.fileattr & DARWIN_ATTR_FILE_DATALENGTH) { /* All forks */
620 off_t size;
621
622 size = st.st_size;
623 if (ATTR_APPEND(size, bp, len) != 0)
624 goto out3;
625 }
626
627 if (kalist.fileattr & DARWIN_ATTR_FILE_DATAALLOCSIZE) { /* All forks */
628 off_t size;
629
630 size = st.st_blocks * f->f_bsize;
631 if (ATTR_APPEND(size, bp, len) != 0)
632 goto out3;
633 }
634
635 if (kalist.fileattr & DARWIN_ATTR_FILE_DATAEXTENTS) {
636 darwin_extentrecord data;
637
638 /* Obsolete in Darwin */
639 (void)bzero(&data, sizeof(data));
640 if (ATTR_APPEND(data, bp, len) != 0)
641 goto out3;
642 }
643
644 if (kalist.fileattr & DARWIN_ATTR_FILE_RSRCLENGTH) {
645 off_t size;
646
647 size = 0;
648 if (ATTR_APPEND(size, bp, len) != 0)
649 goto out3;
650 }
651
652 if (kalist.fileattr & DARWIN_ATTR_FILE_RSRCALLOCSIZE) {
653 off_t size;
654
655 size = 0;
656 if (ATTR_APPEND(size, bp, len) != 0)
657 goto out3;
658 }
659
660 if (kalist.fileattr & DARWIN_ATTR_FILE_RSRCEXTENTS) {
661 darwin_extentrecord data;
662
663 /* Obsolete in Darwin */
664 (void)bzero(&data, sizeof(data));
665 if (ATTR_APPEND(data, bp, len) != 0)
666 goto out3;
667 }
668
669 if (kalist.forkattr & DARWIN_ATTR_FORK_TOTALSIZE) {
670 off_t size;
671
672 size = st.st_size;
673 if (ATTR_APPEND(size, bp, len) != 0)
674 goto out3;
675 }
676
677 if (kalist.forkattr & DARWIN_ATTR_FORK_ALLOCSIZE) {
678 off_t size;
679
680 size = st.st_blocks * f->f_bsize;
681 if (ATTR_APPEND(size, bp, len) != 0)
682 goto out3;
683 }
684
685 /*
686 * Now the variable length fields
687 */
688
689 if (cmn_name_p) { /* DARWIN_ATTR_CMN_NAME */
690 cmn_name_p->attr_dataoffset = (u_long)bp - (u_long)cmn_name_p;
691 cmn_name_p->attr_length = nd.ni_cnd.cn_namelen;
692 if (darwin_attr_append(nd.ni_cnd.cn_nameptr,
693 cmn_name_p->attr_length, &bp, &len) != 0)
694 goto out3;
695
696 /* word alignement */
697 shift = (((u_long)bp & ~0x3UL) + 4) - (u_long)bp;
698 if (darwin_attr_append((char *)null, shift, &bp, &len) != 0)
699 goto out3;
700 }
701
702 if (vol_mountpoint_p) { /* DARWIN_ATTR_VOL_MOUNTPOINT */
703 vol_mountpoint_p->attr_dataoffset =
704 (u_long)bp - (u_long)vol_mountpoint_p;
705 vol_mountpoint_p->attr_length = strlen(f->f_mntonname);
706 if (darwin_attr_append(f->f_mntonname,
707 vol_mountpoint_p->attr_length, &bp, &len) != 0)
708 goto out3;
709
710 /* word alignement */
711 shift = (((u_long)bp & ~0x3UL) + 4) - (u_long)bp;
712 if (darwin_attr_append((char *)null, shift, &bp, &len) != 0)
713 goto out3;
714 }
715
716 if (vol_mounteddevice_p) { /* DARWIN_ATTR_VOL_MOUNTEDDEVICE */
717 vol_mounteddevice_p->attr_dataoffset =
718 (u_long)bp - (u_long)vol_mounteddevice_p;
719 vol_mounteddevice_p->attr_length = strlen(f->f_mntfromname);
720 if (darwin_attr_append(f->f_mntfromname,
721 vol_mounteddevice_p->attr_length, &bp, &len) != 0)
722 goto out3;
723
724 /* word alignement */
725 shift = (((u_long)bp & ~0x3UL) + 4) - (u_long)bp;
726 if (darwin_attr_append((char *)null, shift, &bp, &len) != 0)
727 goto out3;
728 }
729
730 if (vol_name_p) { /* DARWIN_ATTR_VOL_NAME */
731 char name[] = "Volume"; /* XXX We have no volume names... */
732 size_t namelen = strlen(name);
733
734 vol_name_p->attr_dataoffset = (u_long)bp - (u_long)vol_name_p;
735 vol_name_p->attr_length = namelen;
736 if (darwin_attr_append(name, namelen, &bp, &len) != 0)
737 goto out3;
738
739 /* word alignement */
740 shift = (((u_long)bp & ~0x3UL) + 4) - (u_long)bp;
741 if (darwin_attr_append((char *)null, shift, &bp, &len) != 0)
742 goto out3;
743 }
744
745 /* And, finnally, the whole buffer length */
746 if (whole_len_p) {
747 *whole_len_p = SCARG(uap, buflen) - len;
748 }
749
750 /*
751 * We are done! Copyout the stuff and get away
752 */
753 if (error == 0)
754 error = copyout(tbuf, SCARG(uap, attributes), *whole_len_p);
755 out3:
756 vput(vp);
757 out2:
758 kauth_cred_free(cred);
759 free(tbuf, M_TEMP);
760
761 STATVFSBUF_PUT(f);
762 return error;
763 }
Cache object: cdd5916ee53b26cc75badf3381a9a96c
|