1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29#include <sys/param.h>
30#include <sys/systm.h>
31#include <sys/kernel.h>
32#include <sys/malloc.h>
33#include <sys/attr.h>
34#include <sys/stat.h>
35#include <sys/unistd.h>
36#include <sys/mount_internal.h>
37#include <sys/kauth.h>
38
39#include <kern/locks.h>
40
41#include "hfs.h"
42#include "hfs_cnode.h"
43#include "hfs_mount.h"
44#include "hfs_dbg.h"
45#include "hfs_attrlist.h"
46
47
48
49
50extern int hfs_write_access(struct vnode *vp, kauth_cred_t cred,
51 struct proc *p, Boolean considerFlags);
52
53extern int hfs_chflags(struct vnode *vp, uint32_t flags, kauth_cred_t cred,
54 struct proc *p);
55
56extern int hfs_chmod(struct vnode *vp, int mode, kauth_cred_t cred,
57 struct proc *p);
58
59extern int hfs_chown(struct vnode *vp, uid_t uid, gid_t gid, kauth_cred_t cred,
60 struct proc *p);
61
62__private_extern__ int hfs_vnop_readdirattr(struct vnop_readdirattr_args *ap);
63
64__private_extern__ int hfs_vnop_setattrlist(struct vnop_setattrlist_args *ap);
65
66__private_extern__ int hfs_vnop_getattrlist(struct vnop_getattrlist_args *ap);
67
68
69
70
71static void packvolcommonattr(struct attrblock *abp, struct hfsmount *hfsmp,
72 struct vnode *vp, struct proc *p);
73
74static void packvolattr(struct attrblock *abp, struct hfsmount *hfsmp,
75 struct vnode *vp);
76
77static void packcommonattr(struct attrblock *abp, struct hfsmount *hfsmp,
78 struct vnode *vp, struct cat_desc * cdp,
79 struct cat_attr * cap, struct proc *p);
80
81static void packfileattr(struct attrblock *abp, struct hfsmount *hfsmp,
82 struct cat_attr *cattrp, struct cat_fork *datafork,
83 struct cat_fork *rsrcfork);
84
85static void packdirattr(struct attrblock *abp, struct hfsmount *hfsmp,
86 struct vnode *vp, struct cat_desc * descp,
87 struct cat_attr * cattrp);
88
89
90#if 0
91static int unpackattrblk(struct attrblock *abp, struct vnode *vp);
92
93static void unpackcommonattr(struct attrblock *abp, struct vnode *vp);
94
95static int unpackvolattr(struct attrblock *abp, struct hfsmount *hfsmp,
96 struct vnode *root_vp);
97
98
99
100
101
102__private_extern__
103int
104hfs_vnop_getattrlist(ap)
105 struct vnop_getattrlist_args
106
107
108
109
110
111 *ap;
112{
113 struct vnode *vp = ap->a_vp;
114 struct cnode *cp;
115 struct hfsmount *hfsmp;
116 struct attrlist *alist = ap->a_alist;
117 proc_t p = vfs_context_proc(ap->a_context);
118 int fixedblocksize;
119 int attrblocksize;
120 int attrbufsize;
121 void *attrbufptr = NULL;
122 void *attrptr;
123 void *varptr;
124 struct attrblock attrblk;
125 struct cat_fork *datafp = NULL;
126 struct cat_fork *rsrcfp = NULL;
127 struct cat_fork rsrcfork;
128 int lockflags;
129 int error = 0;
130
131 if ((alist->bitmapcount != ATTR_BIT_MAP_COUNT) ||
132 ((alist->commonattr & ~ATTR_CMN_VALIDMASK) != 0) ||
133 ((alist->volattr & ~ATTR_VOL_VALIDMASK) != 0) ||
134 ((alist->dirattr & ~ATTR_DIR_VALIDMASK) != 0) ||
135 ((alist->fileattr & ~ATTR_FILE_VALIDMASK) != 0)) {
136 return (EINVAL);
137 }
138
139
140
141
142
143
144 if ((alist->volattr != 0) &&
145 (((alist->volattr & ATTR_VOL_INFO) == 0) ||
146 (alist->dirattr != 0) || (alist->fileattr != 0))) {
147 return (EINVAL);
148 }
149
150
151 if ((alist->commonattr & (ATTR_CMN_NAMEDATTRCOUNT | ATTR_CMN_NAMEDATTRLIST)) ||
152 (alist->fileattr & (ATTR_FILE_FILETYPE | ATTR_FILE_FORKCOUNT | ATTR_FILE_FORKLIST))) {
153 return (EINVAL);
154 }
155
156 if ((error = hfs_lock(VTOC(vp), HFS_EXCLUSIVE_LOCK)))
157 return (error);
158 cp = VTOC(vp);
159 hfsmp = VTOHFS(vp);
160
161
162 if ((alist->volattr) && cp->c_fileid != kHFSRootFolderID) {
163 error = EINVAL;
164 goto exit;
165 }
166
167 if (VNODE_IS_RSRC(vp) && (alist->fileattr & ATTR_DATAFORK_MASK)) {
168 error = EINVAL;
169 goto exit;
170 }
171
172 if (cp->c_flag & (C_NOEXISTS | C_DELETED)) {
173 error = ENOENT;
174 goto exit;
175 }
176
177 if ((cp->c_desc.cd_namelen == 0) && (alist->commonattr & ATTR_CMN_NAME)) {
178 error = ENOENT;
179 goto exit;
180 }
181
182
183 hfs_touchtimes(hfsmp, cp);
184
185
186
187
188
189
190 if (vnode_isreg(vp) &&
191 (alist->commonattr & ATTR_CMN_OBJPERMANENTID) &&
192 (VTOVCB(vp)->vcbSigWord != kHFSPlusSigWord)) {
193
194 cat_cookie_t cookie;
195
196 if (hfsmp->hfs_flags & HFS_READ_ONLY) {
197 error = EROFS;
198 goto exit;
199 }
200 if ((error = hfs_write_access(vp, vfs_context_ucred(ap->a_context),
201 p, false)) != 0) {
202 goto exit;
203 }
204
205
206
207 bzero(&cookie, sizeof(cookie));
208 error = cat_preflight(hfsmp, CAT_CREATE, &cookie, p);
209 if (error) {
210 goto exit;
211 }
212
213 lockflags = hfs_systemfile_lock(hfsmp, SFL_CATALOG, HFS_EXCLUSIVE_LOCK);
214
215 error = cat_insertfilethread(hfsmp, &cp->c_desc);
216
217 hfs_systemfile_unlock(hfsmp, lockflags);
218
219 cat_postflight(hfsmp, &cookie, p);
220
221 if (error)
222 goto exit;
223 }
224 bzero(&rsrcfork, sizeof(rsrcfork));
225
226 if (cp->c_datafork != NULL) {
227 datafp = &cp->c_datafork->ff_data;
228 if ((cp->c_rsrcfork == NULL) &&
229 (cp->c_blocks == datafp->cf_blocks))
230 rsrcfp = &rsrcfork;
231 }
232 if (cp->c_rsrcfork != NULL)
233 rsrcfp = &cp->c_rsrcfork->ff_data;
234
235
236
237
238
239
240 if ((alist->fileattr & ATTR_RSRCFORK_MASK) && (rsrcfp == NULL)) {
241
242 lockflags = hfs_systemfile_lock(hfsmp, SFL_CATALOG, HFS_SHARED_LOCK);
243
244
245 error = cat_lookup(hfsmp, &cp->c_desc, 1,
246 (struct cat_desc *)0, (struct cat_attr *)0, &rsrcfork, NULL);
247
248 hfs_systemfile_unlock(hfsmp, lockflags);
249
250 if (error)
251 goto exit;
252
253 rsrcfp = &rsrcfork;
254 }
255
256 fixedblocksize = hfs_attrblksize(alist);
257 attrblocksize = fixedblocksize + (sizeof(uint32_t));
258 if (alist->commonattr & ATTR_CMN_NAME)
259 attrblocksize += kHFSPlusMaxFileNameBytes + 1;
260 if (alist->volattr & ATTR_VOL_MOUNTPOINT)
261 attrblocksize += PATH_MAX;
262 if (alist->volattr & ATTR_VOL_NAME)
263 attrblocksize += kHFSPlusMaxFileNameBytes + 1;
264#if 0
265 if (alist->commonattr & ATTR_CMN_NAMEDATTRLIST)
266 attrblocksize += 0;
267 if (alist->fileattr & ATTR_FILE_FORKLIST)
268 attrblocksize += 0;
269#endif
270 attrbufsize = MIN(uio_resid(ap->a_uio), attrblocksize);
271 MALLOC(attrbufptr, void *, attrblocksize, M_TEMP, M_WAITOK);
272 attrptr = attrbufptr;
273 *((uint32_t *)attrptr) = 0;
274 ++((uint32_t *)attrptr);
275 varptr = ((char *)attrptr) + fixedblocksize;
276
277 attrblk.ab_attrlist = alist;
278 attrblk.ab_attrbufpp = &attrptr;
279 attrblk.ab_varbufpp = &varptr;
280 attrblk.ab_flags = 0;
281 attrblk.ab_blocksize = attrblocksize;
282
283 hfs_packattrblk(&attrblk, hfsmp, vp, &cp->c_desc, &cp->c_attr,
284 datafp, rsrcfp, p);
285
286
287 attrbufsize = MIN((u_int)attrbufsize, (u_int)varptr - (u_int)attrbufptr);
288
289 *((uint32_t *)attrbufptr) = attrbufsize;
290 error = uiomove((caddr_t)attrbufptr, attrbufsize, ap->a_uio);
291exit:
292 if (attrbufptr)
293 FREE(attrbufptr, M_TEMP);
294 hfs_unlock(cp);
295 return (error);
296}
297
298
299
300
301
302__private_extern__
303int
304hfs_vnop_setattrlist(ap)
305 struct vnop_setattrlist_args
306
307
308
309
310
311 *ap;
312{
313 struct vnode *vp = ap->a_vp;
314 struct cnode *cp;
315 struct hfsmount * hfsmp;
316 struct attrlist *alist = ap->a_alist;
317 kauth_cred_t cred = vfs_context_ucred(ap->a_context);
318 struct proc *p = vfs_context_proc(ap->a_context);
319 int attrblocksize;
320 void *attrbufptr = NULL;
321 void *attrptr;
322 void *varptr = NULL;
323 struct attrblock attrblk;
324 uid_t saved_uid;
325 gid_t saved_gid;
326 mode_t saved_mode;
327 uint32_t saved_flags;
328 int error = 0;
329
330 hfsmp = VTOHFS(vp);
331
332 if (hfsmp->hfs_flags & HFS_READ_ONLY)
333 return (EROFS);
334 if ((alist->bitmapcount != ATTR_BIT_MAP_COUNT) ||
335 ((alist->commonattr & ~ATTR_CMN_SETMASK) != 0) ||
336 ((alist->volattr & ~ATTR_VOL_SETMASK) != 0) ||
337 ((alist->dirattr & ~ATTR_DIR_SETMASK) != 0) ||
338 ((alist->fileattr & ~ATTR_FILE_SETMASK) != 0)) {
339 return (EINVAL);
340 }
341 if ((error = hfs_lock(VTOC(vp), HFS_EXCLUSIVE_LOCK)))
342 return (error);
343 cp = VTOC(vp);
344
345
346
347
348
349
350 if ((alist->volattr != 0) &&
351 (((alist->volattr & ATTR_VOL_INFO) == 0) ||
352 (alist->commonattr & ~ATTR_CMN_VOLSETMASK) ||
353 (cp->c_fileid != kHFSRootFolderID))) {
354 if ((alist->volattr & ATTR_VOL_INFO) == 0)
355 printf("hfs_setattrlist: you forgot to set ATTR_VOL_INFO bit!\n");
356 else
357 printf("hfs_setattrlist: you cannot set bits 0x%08X!\n",
358 alist->commonattr & ~ATTR_CMN_VOLSETMASK);
359 error = EINVAL;
360 goto ErrorExit;
361 }
362 if (cp->c_flag & (C_NOEXISTS | C_DELETED)) {
363 error = ENOENT;
364 goto ErrorExit;
365 }
366
367 if (hfsmp->jnl && cp->c_datafork) {
368 struct HFSPlusExtentDescriptor *extd;
369
370 extd = &cp->c_datafork->ff_extents[0];
371 if (extd->startBlock == HFSTOVCB(hfsmp)->vcbJinfoBlock || extd->startBlock == hfsmp->jnl_start) {
372 error = EPERM;
373 goto ErrorExit;
374 }
375 }
376
377
378
379
380
381
382
383
384
385
386 if ((alist->commonattr & (ATTR_OWNERSHIP_SETMASK & ~ATTR_CMN_FLAGS)) ||
387 ((alist->commonattr & ATTR_CMN_FLAGS) &&
388 (VTOVCB(vp)->vcbSigWord != kHFSSigWord))) {
389
390
391
392
393
394
395
396
397 if ((error = hfs_owner_rights(hfsmp, cp->c_uid, cred, p, true)) != 0)
398 goto ErrorExit;
399 }
400
401
402
403
404
405 if (((alist->commonattr & ~ATTR_OWNERSHIP_SETMASK) != 0) ||
406 (alist->volattr != 0) || (alist->dirattr != 0) ||
407 (alist->fileattr != 0)) {
408 if ((error = hfs_write_access(vp, cred, p, false)) != 0)
409 goto ErrorExit;
410 }
411
412
413
414
415
416
417 attrblocksize = uio_resid(ap->a_uio);
418 if (attrblocksize < hfs_attrblksize(alist)) {
419 error = EINVAL;
420 goto ErrorExit;
421 }
422
423 MALLOC(attrbufptr, void *, attrblocksize, M_TEMP, M_WAITOK);
424
425 error = uiomove((caddr_t)attrbufptr, attrblocksize, ap->a_uio);
426 if (error)
427 goto ErrorExit;
428
429
430 saved_uid = cp->c_uid;
431 saved_gid = cp->c_gid;
432 saved_mode = cp->c_mode;
433 saved_flags = cp->c_flags;
434
435 attrptr = attrbufptr;
436 attrblk.ab_attrlist = alist;
437 attrblk.ab_attrbufpp = &attrptr;
438 attrblk.ab_varbufpp = &varptr;
439 attrblk.ab_flags = 0;
440 attrblk.ab_blocksize = attrblocksize;
441 error = unpackattrblk(&attrblk, vp);
442 if (error)
443 goto ErrorExit;
444
445
446 if ((saved_uid != cp->c_uid) || (saved_gid != cp->c_gid)) {
447 uid_t uid;
448 gid_t gid;
449
450 uid = cp->c_uid;
451 cp->c_uid = saved_uid;
452 gid = cp->c_gid;
453 cp->c_gid = saved_gid;
454 if ((error = hfs_chown(vp, uid, gid, cred, p)))
455 goto ErrorExit;
456 }
457
458 if (saved_mode != cp->c_mode) {
459 mode_t mode;
460
461 mode = cp->c_mode;
462 cp->c_mode = saved_mode;
463 if ((error = hfs_chmod(vp, mode, cred, p)))
464 goto ErrorExit;
465 }
466
467 if (saved_flags !=cp->c_flags) {
468 uint32_t flags;
469
470 flags = cp->c_flags;
471 cp->c_flags = saved_flags;
472 if ((error = hfs_chflags(vp, flags, cred, p)))
473 goto ErrorExit;
474 }
475
476
477
478 if (alist->volattr == 0) {
479 cp->c_flag |= C_MODIFIED;
480 if ((error = hfs_update(vp, TRUE))) {
481 goto ErrorExit;
482 }
483 }
484
485 if (alist->volattr & ATTR_VOL_NAME) {
486 ExtendedVCB *vcb = VTOVCB(vp);
487
488 if (vcb->vcbVN[0] == 0) {
489
490
491
492
493 copystr(cp->c_desc.cd_nameptr, vcb->vcbVN, sizeof(vcb->vcbVN), NULL);
494 } else {
495 struct cat_desc to_desc;
496 struct cat_desc todir_desc;
497 struct cat_desc new_desc;
498 cat_cookie_t cookie;
499 int catreserve = 0;
500 int catlocked = 0;
501 int started_tr = 0;
502 int lockflags;
503
504 bzero(&to_desc, sizeof(to_desc));
505 bzero(&todir_desc, sizeof(todir_desc));
506 bzero(&new_desc, sizeof(new_desc));
507 bzero(&cookie, sizeof(cookie));
508
509 todir_desc.cd_parentcnid = kHFSRootParentID;
510 todir_desc.cd_cnid = kHFSRootFolderID;
511 todir_desc.cd_flags = CD_ISDIR;
512
513 to_desc.cd_nameptr = vcb->vcbVN;
514 to_desc.cd_namelen = strlen(vcb->vcbVN);
515 to_desc.cd_parentcnid = kHFSRootParentID;
516 to_desc.cd_cnid = cp->c_cnid;
517 to_desc.cd_flags = CD_ISDIR;
518
519 if ((error = hfs_start_transaction(hfsmp) != 0)) {
520 goto rename_out;
521 }
522 started_tr = 1;
523
524
525
526
527 error = cat_preflight(hfsmp, CAT_RENAME, &cookie, p);
528 if (error) {
529 goto rename_out;
530 }
531 catreserve = 1;
532
533 lockflags = hfs_systemfile_lock(hfsmp, SFL_CATALOG, HFS_EXCLUSIVE_LOCK);
534 catlocked = 1;
535
536 error = cat_rename(hfsmp, &cp->c_desc, &todir_desc, &to_desc, &new_desc);
537rename_out:
538 if (catlocked) {
539 hfs_systemfile_unlock(hfsmp, lockflags);
540 }
541 if (catreserve) {
542 cat_postflight(hfsmp, &cookie, p);
543 }
544 (void) hfs_flushvolumeheader(hfsmp, MNT_WAIT, 0);
545 if (started_tr) {
546 hfs_end_transaction(hfsmp);
547 }
548
549 if (error) {
550
551 copystr(cp->c_desc.cd_nameptr, vcb->vcbVN, sizeof(vcb->vcbVN), NULL);
552 vcb->vcbFlags |= 0xFF00;
553 goto ErrorExit;
554 }
555
556 if (cp->c_desc.cd_flags & CD_HASBUF) {
557 char *name = cp->c_desc.cd_nameptr;
558
559 cp->c_desc.cd_nameptr = 0;
560 cp->c_desc.cd_namelen = 0;
561 cp->c_desc.cd_flags &= ~CD_HASBUF;
562 vfs_removename(name);
563 }
564
565 replace_desc(cp, &new_desc);
566 vcb->volumeNameEncodingHint = new_desc.cd_encoding;
567 cp->c_touch_chgtime = TRUE;
568 }
569 }
570
571
572
573
574
575 if ((alist->volattr & ATTR_VOL_INFO) &&
576 ((alist->volattr & ATTR_VOL_NAME) ||
577 (alist->commonattr & ATTR_CMN_FNDRINFO))) {
578 (void) hfs_flushvolumeheader(hfsmp, MNT_WAIT, 0);
579 }
580ErrorExit:
581 if (attrbufptr)
582 FREE(attrbufptr, M_TEMP);
583
584 hfs_unlock(cp);
585 return (error);
586}
587#endif
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622__private_extern__
623int
624hfs_vnop_readdirattr(ap)
625 struct vnop_readdirattr_args
626
627
628
629
630
631
632
633
634
635 *ap;
636{
637 struct vnode *dvp = ap->a_vp;
638 struct cnode *dcp;
639 struct hfsmount * hfsmp;
640 struct attrlist *alist = ap->a_alist;
641 uio_t uio = ap->a_uio;
642 int maxcount = ap->a_maxcount;
643 struct proc *p = vfs_context_proc(ap->a_context);
644 uint32_t fixedblocksize;
645 uint32_t maxattrblocksize;
646 uint32_t currattrbufsize;
647 void *attrbufptr = NULL;
648 void *attrptr;
649 void *varptr;
650 struct attrblock attrblk;
651 int error = 0;
652 int depleted = 0;
653 int index;
654 int i, dir_entries;
655 struct cat_desc *lastdescp = NULL;
656 struct cat_entrylist *ce_list = NULL;
657 directoryhint_t *dirhint = NULL;
658 unsigned int tag;
659 int shared_cnode_lock = 0;
660
661 *(ap->a_actualcount) = 0;
662 *(ap->a_eofflag) = 0;
663
664
665 if (((ap->a_options & ~(FSOPT_NOINMEMUPDATE | FSOPT_NOFOLLOW)) != 0)
666 || (uio_resid(uio) <= 0) || (uio_iovcnt(uio) > 1) || (maxcount <= 0))
667 return (EINVAL);
668
669
670 if ((alist->bitmapcount != ATTR_BIT_MAP_COUNT) ||
671 ((alist->commonattr & ~ATTR_CMN_VALIDMASK) != 0) ||
672 (alist->volattr != 0) ||
673 ((alist->dirattr & ~ATTR_DIR_VALIDMASK) != 0) ||
674 ((alist->fileattr & ~ATTR_FILE_VALIDMASK) != 0))
675 return (EINVAL);
676
677 if ((error = hfs_lock(VTOC(dvp), HFS_EXCLUSIVE_LOCK)))
678 return (error);
679 dcp = VTOC(dvp);
680 hfsmp = VTOHFS(dvp);
681
682
683 if ((alist->commonattr & (ATTR_CMN_NAMEDATTRCOUNT | ATTR_CMN_NAMEDATTRLIST |
684 ATTR_CMN_OBJPERMANENTID)) ||
685 (alist->fileattr & (ATTR_FILE_FILETYPE | ATTR_FILE_FORKCOUNT |
686 ATTR_FILE_FORKLIST | ATTR_FILE_DATAEXTENTS | ATTR_FILE_RSRCEXTENTS))) {
687 printf("readdirattr: unsupported attributes! (%s)\n", dcp->c_desc.cd_nameptr);
688 error = EINVAL;
689 goto exit;
690 }
691
692 dir_entries = dcp->c_entries;
693 if (dcp->c_attr.ca_fileid == kHFSRootFolderID && hfsmp->jnl) {
694 dir_entries -= 3;
695 }
696
697
698 index = uio_offset(uio) & HFS_INDEX_MASK;
699 tag = uio_offset(uio) & ~HFS_INDEX_MASK;
700 if ((index + 1) > dir_entries) {
701 *(ap->a_eofflag) = 1;
702 error = 0;
703 goto exit;
704 }
705
706
707 fixedblocksize = (sizeof(uint32_t) + hfs_attrblksize(alist));
708 maxattrblocksize = fixedblocksize;
709 if (alist->commonattr & ATTR_CMN_NAME)
710 maxattrblocksize += kHFSPlusMaxFileNameBytes + 1;
711 MALLOC(attrbufptr, void *, maxattrblocksize, M_TEMP, M_WAITOK);
712 attrptr = attrbufptr;
713 varptr = (char *)attrbufptr + fixedblocksize;
714
715
716 MALLOC(ce_list, struct cat_entrylist *, sizeof(*ce_list), M_TEMP, M_WAITOK);
717 bzero(ce_list, sizeof(*ce_list));
718 ce_list->maxentries = MAXCATENTRIES;
719
720
721 dirhint = hfs_getdirhint(dcp, ((index - 1) & HFS_INDEX_MASK) | tag);
722
723
724 dirhint->dh_index &= HFS_INDEX_MASK;
725 if (dirhint->dh_index == HFS_INDEX_MASK) {
726 dirhint->dh_index = -1;
727 }
728
729
730
731
732
733
734
735
736 if (alist->commonattr & ATTR_CMN_USERACCESS) {
737 lck_rw_lock_exclusive_to_shared(&dcp->c_rwlock);
738 dcp->c_lockowner = HFS_SHARED_OWNER;
739 shared_cnode_lock = 1;
740 }
741
742
743
744
745 while (!depleted) {
746 int maxentries;
747 int lockflags;
748
749
750 maxentries = uio_resid(uio) / (fixedblocksize + HFS_AVERAGE_NAME_SIZE);
751 maxentries = min(maxentries, dcp->c_entries - index);
752 maxentries = min(maxentries, maxcount);
753 ce_list->maxentries = min(maxentries, ce_list->maxentries);
754 lastdescp = NULL;
755
756 lockflags = hfs_systemfile_lock(hfsmp, SFL_CATALOG, HFS_SHARED_LOCK);
757
758 error = cat_getentriesattr(hfsmp, dirhint, ce_list);
759
760
761 hfs_systemfile_unlock(hfsmp, lockflags);
762
763 if (error == ENOENT) {
764 *(ap->a_eofflag) = TRUE;
765 error = 0;
766 depleted = 1;
767 }
768 if (error)
769 break;
770
771
772 for (i = 0; i < (int)ce_list->realentries; ++i) {
773 struct cnode *cp = NULL;
774 struct vnode *vp = NULL;
775 struct cat_desc * cdescp;
776 struct cat_attr * cattrp;
777 struct cat_fork c_datafork;
778 struct cat_fork c_rsrcfork;
779
780 bzero(&c_datafork, sizeof(c_datafork));
781 bzero(&c_rsrcfork, sizeof(c_rsrcfork));
782 cdescp = &ce_list->entry[i].ce_desc;
783 cattrp = &ce_list->entry[i].ce_attr;
784 c_datafork.cf_size = ce_list->entry[i].ce_datasize;
785 c_datafork.cf_blocks = ce_list->entry[i].ce_datablks;
786 c_rsrcfork.cf_size = ce_list->entry[i].ce_rsrcsize;
787 c_rsrcfork.cf_blocks = ce_list->entry[i].ce_rsrcblks;
788
789
790
791 if (!(ap->a_options & FSOPT_NOINMEMUPDATE)) {
792 vp = hfs_chash_getvnode(dcp->c_dev, cattrp->ca_fileid, 0, 0);
793
794 if (vp != NULL) {
795 cp = VTOC(vp);
796
797 if (!(cp->c_flag & C_HARDLINK))
798 cdescp = &cp->c_desc;
799 cattrp = &cp->c_attr;
800 if (cp->c_datafork) {
801 c_datafork.cf_size = cp->c_datafork->ff_size;
802 c_datafork.cf_blocks = cp->c_datafork->ff_blocks;
803 }
804 if (cp->c_rsrcfork) {
805 c_rsrcfork.cf_size = cp->c_rsrcfork->ff_size;
806 c_rsrcfork.cf_blocks = cp->c_rsrcfork->ff_blocks;
807 }
808 }
809 }
810 *((uint32_t *)attrptr)++ = 0;
811 attrblk.ab_attrlist = alist;
812 attrblk.ab_attrbufpp = &attrptr;
813 attrblk.ab_varbufpp = &varptr;
814 attrblk.ab_flags = 0;
815 attrblk.ab_blocksize = maxattrblocksize;
816
817
818 hfs_packattrblk(&attrblk, hfsmp, vp, cdescp, cattrp,
819 &c_datafork, &c_rsrcfork, p);
820 currattrbufsize = ((char *)varptr - (char *)attrbufptr);
821
822
823 if (vp != NULL) {
824 hfs_unlock(VTOC(vp));
825 vnode_put(vp);
826 vp = NULL;
827 cp = NULL;
828 }
829
830
831
832 if (uio_resid(uio) < 0 || currattrbufsize > (uint32_t)uio_resid(uio)) {
833 depleted = 1;
834 break;
835 } else {
836 *((uint32_t *)attrbufptr) = currattrbufsize;
837 error = uiomove((caddr_t)attrbufptr, currattrbufsize, ap->a_uio);
838 if (error != E_NONE) {
839 depleted = 1;
840 break;
841 }
842 attrptr = attrbufptr;
843 varptr = (char *)attrbufptr + fixedblocksize;
844
845 lastdescp = &ce_list->entry[i].ce_desc;
846 index++;
847 *ap->a_actualcount += 1;
848
849
850 if ((--maxcount <= 0) ||
851
852 uio_resid(uio) < 0 ||
853 ((uint32_t)uio_resid(uio) < (fixedblocksize + HFS_AVERAGE_NAME_SIZE)) ||
854 (index >= dir_entries)) {
855 depleted = 1;
856 break;
857 }
858 }
859 }
860
861
862 if (index < dir_entries
863 && !(*(ap->a_eofflag))
864 && lastdescp != NULL) {
865
866
867 if (dirhint->dh_desc.cd_nameptr != NULL) {
868 vfs_removename(dirhint->dh_desc.cd_nameptr);
869 }
870 dirhint->dh_desc.cd_namelen = lastdescp->cd_namelen;
871 dirhint->dh_desc.cd_nameptr =
872 vfs_addname(lastdescp->cd_nameptr, lastdescp->cd_namelen, 0, 0);
873 dirhint->dh_index = index - 1;
874 dirhint->dh_desc.cd_cnid = lastdescp->cd_cnid;
875 dirhint->dh_desc.cd_hint = lastdescp->cd_hint;
876 dirhint->dh_desc.cd_encoding = lastdescp->cd_encoding;
877 }
878
879
880 for (i = 0; i < (int)ce_list->realentries; ++i)
881 cat_releasedesc(&ce_list->entry[i].ce_desc);
882 ce_list->realentries = 0;
883
884 }
885
886 *ap->a_newstate = dcp->c_mtime;
887
888
889 if (shared_cnode_lock) {
890 lck_rw_lock_shared_to_exclusive(&dcp->c_rwlock);
891 dcp->c_lockowner = current_thread();
892 shared_cnode_lock = 0;
893 }
894
895
896 while (tag == 0) tag = (++dcp->c_dirhinttag) << HFS_INDEX_BITS;
897 uio_setoffset(uio, index | tag);
898 dirhint->dh_index |= tag;
899
900exit:
901
902 if (dirhint && (error || index >= dir_entries)) {
903 if (shared_cnode_lock) {
904 lck_rw_lock_shared_to_exclusive(&dcp->c_rwlock);
905 dcp->c_lockowner = current_thread();
906 }
907 hfs_reldirhint(dcp, dirhint);
908 }
909 if (attrbufptr)
910 FREE(attrbufptr, M_TEMP);
911 if (ce_list)
912 FREE(ce_list, M_TEMP);
913
914 hfs_unlock(dcp);
915 return (error);
916}
917
918
919
920
921
922
923
924 __private_extern__
925void
926hfs_packattrblk(struct attrblock *abp,
927 struct hfsmount *hfsmp,
928 struct vnode *vp,
929 struct cat_desc *descp,
930 struct cat_attr *attrp,
931 struct cat_fork *datafork,
932 struct cat_fork *rsrcfork,
933 struct proc *p)
934{
935 struct attrlist *attrlistp = abp->ab_attrlist;
936
937 if (attrlistp->volattr) {
938 if (attrlistp->commonattr)
939 packvolcommonattr(abp, hfsmp, vp, p);
940
941 if (attrlistp->volattr & ~ATTR_VOL_INFO)
942 packvolattr(abp, hfsmp, vp);
943 } else {
944 if (attrlistp->commonattr)
945 packcommonattr(abp, hfsmp, vp, descp, attrp, p);
946
947 if (attrlistp->dirattr && S_ISDIR(attrp->ca_mode))
948 packdirattr(abp, hfsmp, vp, descp,attrp);
949
950 if (attrlistp->fileattr && !S_ISDIR(attrp->ca_mode))
951 packfileattr(abp, hfsmp, attrp, datafork, rsrcfork);
952 }
953}
954
955
956static char*
957mountpointname(struct mount *mp)
958{
959 size_t namelength = strlen(mp->mnt_vfsstat.f_mntonname);
960 int foundchars = 0;
961 char *c;
962
963 if (namelength == 0)
964 return (NULL);
965
966
967
968
969
970
971 for (c = mp->mnt_vfsstat.f_mntonname + namelength - 1;
972 namelength > 0; --c, --namelength) {
973 if (*c != '/') {
974 foundchars = 1;
975 } else if (foundchars) {
976 return (c + 1);
977 }
978 }
979
980 return (mp->mnt_vfsstat.f_mntonname);
981}
982
983
984static void
985packnameattr(
986 struct attrblock *abp,
987 struct vnode *vp,
988 char *name,
989 int namelen)
990{
991 void *varbufptr;
992 struct attrreference * attr_refptr;
993 char *mpname;
994 size_t mpnamelen;
995 uint32_t attrlength;
996 char empty = 0;
997
998
999
1000
1001
1002
1003
1004 if ((vp != NULL) && vnode_isvroot(vp) &&
1005 (mpname = mountpointname(vnode_mount(vp)))) {
1006 mpnamelen = strlen(mpname);
1007
1008
1009 while ((mpnamelen > 0) && (mpname[mpnamelen-1] == '/'))
1010 --mpnamelen;
1011
1012
1013 if (mpnamelen > 0) {
1014 name = mpname;
1015 namelen = mpnamelen;
1016 }
1017 }
1018 if (name == NULL) {
1019 name = ∅
1020 namelen = 0;
1021 }
1022
1023 varbufptr = *abp->ab_varbufpp;
1024 attr_refptr = (struct attrreference *)(*abp->ab_attrbufpp);
1025
1026 attrlength = namelen + 1;
1027 attr_refptr->attr_dataoffset = (char *)varbufptr - (char *)attr_refptr;
1028 attr_refptr->attr_length = attrlength;
1029 (void) strncpy((unsigned char *)varbufptr, name, attrlength);
1030
1031
1032
1033
1034 (char *)(varbufptr) += attrlength + ((4 - (attrlength & 3)) & 3);
1035 ++attr_refptr;
1036
1037 *abp->ab_attrbufpp = attr_refptr;
1038 *abp->ab_varbufpp = varbufptr;
1039}
1040
1041
1042
1043
1044static void
1045packvolcommonattr(struct attrblock *abp, struct hfsmount *hfsmp, struct vnode *vp, struct proc *p)
1046{
1047 attrgroup_t attr;
1048 void *attrbufptr = *abp->ab_attrbufpp;
1049 void *varbufptr = *abp->ab_varbufpp;
1050 struct cnode *cp = VTOC(vp);
1051 struct mount *mp = VTOVFS(vp);
1052 ExtendedVCB *vcb = HFSTOVCB(hfsmp);
1053 u_int32_t attrlength;
1054 boolean_t is_64_bit = proc_is64bit(p);
1055
1056 attr = abp->ab_attrlist->commonattr;
1057
1058 if (ATTR_CMN_NAME & attr) {
1059 packnameattr(abp, vp, cp->c_desc.cd_nameptr, cp->c_desc.cd_namelen);
1060 attrbufptr = *abp->ab_attrbufpp;
1061 varbufptr = *abp->ab_varbufpp;
1062 }
1063 if (ATTR_CMN_DEVID & attr) {
1064 *((dev_t *)attrbufptr)++ = hfsmp->hfs_raw_dev;
1065 }
1066 if (ATTR_CMN_FSID & attr) {
1067 fsid_t fsid;
1068
1069 fsid.val[0] = (long)hfsmp->hfs_raw_dev;
1070 fsid.val[1] = (long)vfs_typenum(mp);
1071 *((fsid_t *)attrbufptr) = fsid;
1072 ++((fsid_t *)attrbufptr);
1073 }
1074 if (ATTR_CMN_OBJTYPE & attr) {
1075 *((fsobj_type_t *)attrbufptr)++ = 0;
1076 }
1077 if (ATTR_CMN_OBJTAG & attr) {
1078 *((fsobj_tag_t *)attrbufptr)++ = VT_HFS;
1079 }
1080 if (ATTR_CMN_OBJID & attr) {
1081 ((fsobj_id_t *)attrbufptr)->fid_objno = 0;
1082 ((fsobj_id_t *)attrbufptr)->fid_generation = 0;
1083 ++((fsobj_id_t *)attrbufptr);
1084 }
1085 if (ATTR_CMN_OBJPERMANENTID & attr) {
1086 ((fsobj_id_t *)attrbufptr)->fid_objno = 0;
1087 ((fsobj_id_t *)attrbufptr)->fid_generation = 0;
1088 ++((fsobj_id_t *)attrbufptr);
1089 }
1090 if (ATTR_CMN_PAROBJID & attr) {
1091 ((fsobj_id_t *)attrbufptr)->fid_objno = 0;
1092 ((fsobj_id_t *)attrbufptr)->fid_generation = 0;
1093 ++((fsobj_id_t *)attrbufptr);
1094 }
1095 if (ATTR_CMN_SCRIPT & attr) {
1096 uint32_t encoding;
1097
1098 if (vcb->vcbSigWord == kHFSPlusSigWord)
1099 encoding = vcb->volumeNameEncodingHint;
1100 else
1101 encoding = hfsmp->hfs_encoding;
1102 *((text_encoding_t *)attrbufptr)++ = encoding;
1103 }
1104 if (ATTR_CMN_CRTIME & attr) {
1105 if (is_64_bit) {
1106 ((struct user_timespec *)attrbufptr)->tv_sec = vcb->vcbCrDate;
1107 ((struct user_timespec *)attrbufptr)->tv_nsec = 0;
1108 ++((struct user_timespec *)attrbufptr);
1109 }
1110 else {
1111 ((struct timespec *)attrbufptr)->tv_sec = vcb->vcbCrDate;
1112 ((struct timespec *)attrbufptr)->tv_nsec = 0;
1113 ++((struct timespec *)attrbufptr);
1114 }
1115 }
1116 if (ATTR_CMN_MODTIME & attr) {
1117 if (is_64_bit) {
1118 ((struct user_timespec *)attrbufptr)->tv_sec = vcb->vcbLsMod;
1119 ((struct user_timespec *)attrbufptr)->tv_nsec = 0;
1120 ++((struct user_timespec *)attrbufptr);
1121 }
1122 else {
1123 ((struct timespec *)attrbufptr)->tv_sec = vcb->vcbLsMod;
1124 ((struct timespec *)attrbufptr)->tv_nsec = 0;
1125 ++((struct timespec *)attrbufptr);
1126 }
1127 }
1128 if (ATTR_CMN_CHGTIME & attr) {
1129 if (is_64_bit) {
1130 ((struct user_timespec *)attrbufptr)->tv_sec = vcb->vcbLsMod;
1131 ((struct user_timespec *)attrbufptr)->tv_nsec = 0;
1132 ++((struct user_timespec *)attrbufptr);
1133 }
1134 else {
1135 ((struct timespec *)attrbufptr)->tv_sec = vcb->vcbLsMod;
1136 ((struct timespec *)attrbufptr)->tv_nsec = 0;
1137 ++((struct timespec *)attrbufptr);
1138 }
1139 }
1140 if (ATTR_CMN_ACCTIME & attr) {
1141 if (is_64_bit) {
1142 ((struct user_timespec *)attrbufptr)->tv_sec = vcb->vcbLsMod;
1143 ((struct user_timespec *)attrbufptr)->tv_nsec = 0;
1144 ++((struct user_timespec *)attrbufptr);
1145 }
1146 else {
1147 ((struct timespec *)attrbufptr)->tv_sec = vcb->vcbLsMod;
1148 ((struct timespec *)attrbufptr)->tv_nsec = 0;
1149 ++((struct timespec *)attrbufptr);
1150 }
1151 }
1152 if (ATTR_CMN_BKUPTIME & attr) {
1153 if (is_64_bit) {
1154 ((struct user_timespec *)attrbufptr)->tv_sec = vcb->vcbVolBkUp;
1155 ((struct user_timespec *)attrbufptr)->tv_nsec = 0;
1156 ++((struct user_timespec *)attrbufptr);
1157 }
1158 else {
1159 ((struct timespec *)attrbufptr)->tv_sec = vcb->vcbVolBkUp;
1160 ((struct timespec *)attrbufptr)->tv_nsec = 0;
1161 ++((struct timespec *)attrbufptr);
1162 }
1163 }
1164 if (ATTR_CMN_FNDRINFO & attr) {
1165 bcopy (&vcb->vcbFndrInfo, attrbufptr, sizeof(vcb->vcbFndrInfo));
1166 (char *)attrbufptr += sizeof(vcb->vcbFndrInfo);
1167 }
1168 if (ATTR_CMN_OWNERID & attr) {
1169 if (cp->c_uid == UNKNOWNUID)
1170 *((uid_t *)attrbufptr)++ = kauth_cred_getuid(proc_ucred(p));
1171 else
1172 *((uid_t *)attrbufptr)++ = cp->c_uid;
1173 }
1174 if (ATTR_CMN_GRPID & attr) {
1175 *((gid_t *)attrbufptr)++ = cp->c_gid;
1176 }
1177
1178 if (ATTR_CMN_ACCESSMASK & attr) {
1179
1180
1181
1182
1183
1184
1185
1186 *((uint32_t *)attrbufptr)++ =
1187 (cp->c_uid == UNKNOWNUID) ? cp->c_mode & ~(S_ISUID | S_ISGID) : cp->c_mode;
1188 }
1189 if (ATTR_CMN_NAMEDATTRCOUNT & attr) {
1190 *((uint32_t *)attrbufptr)++ = 0;
1191 }
1192 if (ATTR_CMN_NAMEDATTRLIST & attr) {
1193 attrlength = 0;
1194 ((struct attrreference *)attrbufptr)->attr_dataoffset = 0;
1195 ((struct attrreference *)attrbufptr)->attr_length = attrlength;
1196
1197
1198
1199
1200 (char *)varbufptr += attrlength + ((4 - (attrlength & 3)) & 3);
1201 ++((struct attrreference *)attrbufptr);
1202 }
1203 if (ATTR_CMN_FLAGS & attr) {
1204 *((uint32_t *)attrbufptr)++ = cp->c_flags;
1205 }
1206 if (ATTR_CMN_USERACCESS & attr) {
1207 *((uint32_t *)attrbufptr)++ =
1208 DerivePermissionSummary(cp->c_uid, cp->c_gid, cp->c_mode,
1209 VTOVFS(vp), kauth_cred_get(), proc_self());
1210 }
1211
1212 *abp->ab_attrbufpp = attrbufptr;
1213 *abp->ab_varbufpp = varbufptr;
1214}
1215
1216
1217static void
1218packvolattr(struct attrblock *abp, struct hfsmount *hfsmp, struct vnode *vp)
1219{
1220 attrgroup_t attr;
1221 void *attrbufptr = *abp->ab_attrbufpp;
1222 void *varbufptr = *abp->ab_varbufpp;
1223 struct cnode *cp = VTOC(vp);
1224 struct mount *mp = VTOVFS(vp);
1225 ExtendedVCB *vcb = HFSTOVCB(hfsmp);
1226 uint32_t attrlength;
1227
1228 attr = abp->ab_attrlist->volattr;
1229
1230 if (ATTR_VOL_FSTYPE & attr) {
1231 *((uint32_t *)attrbufptr)++ = (uint32_t)vfs_typenum(mp);
1232 }
1233 if (ATTR_VOL_SIGNATURE & attr) {
1234 *((uint32_t *)attrbufptr)++ = (uint32_t)vcb->vcbSigWord;
1235 }
1236 if (ATTR_VOL_SIZE & attr) {
1237 *((off_t *)attrbufptr)++ =
1238 (off_t)vcb->totalBlocks * (off_t)vcb->blockSize;
1239 }
1240 if (ATTR_VOL_SPACEFREE & attr) {
1241 *((off_t *)attrbufptr)++ = (off_t)hfs_freeblks(hfsmp, 0) *
1242 (off_t)vcb->blockSize;
1243 }
1244 if (ATTR_VOL_SPACEAVAIL & attr) {
1245 *((off_t *)attrbufptr)++ = (off_t)hfs_freeblks(hfsmp, 1) *
1246 (off_t)vcb->blockSize;
1247 }
1248 if (ATTR_VOL_MINALLOCATION & attr) {
1249 *((off_t *)attrbufptr)++ = (off_t)vcb->blockSize;
1250 }
1251 if (ATTR_VOL_ALLOCATIONCLUMP & attr) {
1252 *((off_t *)attrbufptr)++ = (off_t)(vcb->vcbClpSiz);
1253 }
1254 if (ATTR_VOL_IOBLOCKSIZE & attr) {
1255 *((uint32_t *)attrbufptr)++ = hfsmp->hfs_logBlockSize;
1256 }
1257 if (ATTR_VOL_OBJCOUNT & attr) {
1258 *((uint32_t *)attrbufptr)++ =
1259 (uint32_t)vcb->vcbFilCnt + (uint32_t)vcb->vcbDirCnt;
1260 }
1261 if (ATTR_VOL_FILECOUNT & attr) {
1262 *((uint32_t *)attrbufptr)++ = (uint32_t)vcb->vcbFilCnt;
1263 }
1264 if (ATTR_VOL_DIRCOUNT & attr) {
1265 *((uint32_t *)attrbufptr)++ = (uint32_t)vcb->vcbDirCnt;
1266 }
1267 if (ATTR_VOL_MAXOBJCOUNT & attr) {
1268 *((uint32_t *)attrbufptr)++ = 0xFFFFFFFF;
1269 }
1270 if (ATTR_VOL_MOUNTPOINT & attr) {
1271 ((struct attrreference *)attrbufptr)->attr_dataoffset =
1272 (char *)varbufptr - (char *)attrbufptr;
1273 ((struct attrreference *)attrbufptr)->attr_length =
1274 strlen(mp->mnt_vfsstat.f_mntonname) + 1;
1275 attrlength = ((struct attrreference *)attrbufptr)->attr_length;
1276
1277 attrlength = attrlength + ((4 - (attrlength & 3)) & 3);
1278 (void) bcopy(mp->mnt_vfsstat.f_mntonname, varbufptr, attrlength);
1279
1280
1281 (char *)varbufptr += attrlength;
1282 ++((struct attrreference *)attrbufptr);
1283 }
1284 if (ATTR_VOL_NAME & attr) {
1285 ((struct attrreference *)attrbufptr)->attr_dataoffset =
1286 (char *)varbufptr - (char *)attrbufptr;
1287 ((struct attrreference *)attrbufptr)->attr_length =
1288 cp->c_desc.cd_namelen + 1;
1289 attrlength = ((struct attrreference *)attrbufptr)->attr_length;
1290
1291 attrlength = attrlength + ((4 - (attrlength & 3)) & 3);
1292
1293 bcopy(cp->c_desc.cd_nameptr, varbufptr, attrlength);
1294
1295
1296 (char *)varbufptr += attrlength;
1297 ++((struct attrreference *)attrbufptr);
1298 }
1299 if (ATTR_VOL_MOUNTFLAGS & attr) {
1300 *((uint32_t *)attrbufptr)++ = (uint32_t)vfs_flags(mp);
1301 }
1302 if (ATTR_VOL_MOUNTEDDEVICE & attr) {
1303 ((struct attrreference *)attrbufptr)->attr_dataoffset =
1304 (char *)varbufptr - (char *)attrbufptr;
1305 ((struct attrreference *)attrbufptr)->attr_length =
1306 strlen(mp->mnt_vfsstat.f_mntfromname) + 1;
1307 attrlength = ((struct attrreference *)attrbufptr)->attr_length;
1308
1309 attrlength = attrlength + ((4 - (attrlength & 3)) & 3);
1310 (void) bcopy(mp->mnt_vfsstat.f_mntfromname, varbufptr, attrlength);
1311
1312
1313 (char *)varbufptr += attrlength;
1314 ++((struct attrreference *)attrbufptr);
1315 }
1316 if (ATTR_VOL_ENCODINGSUSED & attr) {
1317 *((unsigned long long *)attrbufptr)++ =
1318 (unsigned long long)vcb->encodingsBitmap;
1319 }
1320 if (ATTR_VOL_CAPABILITIES & attr) {
1321 vol_capabilities_attr_t *vcapattrptr;
1322
1323 vcapattrptr = (vol_capabilities_attr_t *)attrbufptr;
1324
1325 if (vcb->vcbSigWord == kHFSPlusSigWord) {
1326 u_int32_t journal_active_cap;
1327 u_int32_t case_sensitive;
1328
1329 if (hfsmp->jnl)
1330 journal_active_cap = VOL_CAP_FMT_JOURNAL_ACTIVE;
1331 else
1332 journal_active_cap = 0;
1333
1334 if (hfsmp->hfs_flags & HFS_CASE_SENSITIVE)
1335 case_sensitive = VOL_CAP_FMT_CASE_SENSITIVE;
1336 else
1337 case_sensitive = 0;
1338
1339 vcapattrptr->capabilities[VOL_CAPABILITIES_FORMAT] =
1340 VOL_CAP_FMT_PERSISTENTOBJECTIDS |
1341 VOL_CAP_FMT_SYMBOLICLINKS |
1342 VOL_CAP_FMT_HARDLINKS |
1343 VOL_CAP_FMT_JOURNAL |
1344 journal_active_cap |
1345 case_sensitive |
1346 VOL_CAP_FMT_CASE_PRESERVING |
1347 VOL_CAP_FMT_FAST_STATFS |
1348 VOL_CAP_FMT_2TB_FILESIZE;
1349 } else {
1350 vcapattrptr->capabilities[VOL_CAPABILITIES_FORMAT] =
1351 VOL_CAP_FMT_PERSISTENTOBJECTIDS |
1352 VOL_CAP_FMT_CASE_PRESERVING |
1353 VOL_CAP_FMT_FAST_STATFS ;
1354 }
1355 vcapattrptr->capabilities[VOL_CAPABILITIES_INTERFACES] =
1356 VOL_CAP_INT_SEARCHFS |
1357 VOL_CAP_INT_ATTRLIST |
1358 VOL_CAP_INT_NFSEXPORT |
1359 VOL_CAP_INT_READDIRATTR |
1360 VOL_CAP_INT_EXCHANGEDATA |
1361 VOL_CAP_INT_ALLOCATE |
1362 VOL_CAP_INT_VOL_RENAME |
1363 VOL_CAP_INT_ADVLOCK |
1364 VOL_CAP_INT_FLOCK ;
1365 vcapattrptr->capabilities[VOL_CAPABILITIES_RESERVED1] = 0;
1366 vcapattrptr->capabilities[VOL_CAPABILITIES_RESERVED2] = 0;
1367
1368 vcapattrptr->valid[VOL_CAPABILITIES_FORMAT] =
1369 VOL_CAP_FMT_PERSISTENTOBJECTIDS |
1370 VOL_CAP_FMT_SYMBOLICLINKS |
1371 VOL_CAP_FMT_HARDLINKS |
1372 VOL_CAP_FMT_JOURNAL |
1373 VOL_CAP_FMT_JOURNAL_ACTIVE |
1374 VOL_CAP_FMT_NO_ROOT_TIMES |
1375 VOL_CAP_FMT_SPARSE_FILES |
1376 VOL_CAP_FMT_ZERO_RUNS |
1377 VOL_CAP_FMT_CASE_SENSITIVE |
1378 VOL_CAP_FMT_CASE_PRESERVING |
1379 VOL_CAP_FMT_FAST_STATFS |
1380 VOL_CAP_FMT_2TB_FILESIZE;
1381 vcapattrptr->valid[VOL_CAPABILITIES_INTERFACES] =
1382 VOL_CAP_INT_SEARCHFS |
1383 VOL_CAP_INT_ATTRLIST |
1384 VOL_CAP_INT_NFSEXPORT |
1385 VOL_CAP_INT_READDIRATTR |
1386 VOL_CAP_INT_EXCHANGEDATA |
1387 VOL_CAP_INT_COPYFILE |
1388 VOL_CAP_INT_ALLOCATE |
1389 VOL_CAP_INT_VOL_RENAME |
1390 VOL_CAP_INT_ADVLOCK |
1391 VOL_CAP_INT_FLOCK ;
1392 vcapattrptr->valid[VOL_CAPABILITIES_RESERVED1] = 0;
1393 vcapattrptr->valid[VOL_CAPABILITIES_RESERVED2] = 0;
1394
1395 ++((vol_capabilities_attr_t *)attrbufptr);
1396 }
1397 if (ATTR_VOL_ATTRIBUTES & attr) {
1398 vol_attributes_attr_t *volattrattrp;
1399
1400 volattrattrp = (vol_attributes_attr_t *)attrbufptr;
1401 volattrattrp->validattr.commonattr = ATTR_CMN_VALIDMASK;
1402 volattrattrp->validattr.volattr = ATTR_VOL_VALIDMASK;
1403 volattrattrp->validattr.dirattr = ATTR_DIR_VALIDMASK;
1404 volattrattrp->validattr.fileattr = ATTR_FILE_VALIDMASK;
1405 volattrattrp->validattr.forkattr = ATTR_FORK_VALIDMASK;
1406
1407 volattrattrp->nativeattr.commonattr = ATTR_CMN_VALIDMASK;
1408 volattrattrp->nativeattr.volattr = ATTR_VOL_VALIDMASK;
1409 volattrattrp->nativeattr.dirattr = ATTR_DIR_VALIDMASK;
1410 volattrattrp->nativeattr.fileattr = ATTR_FILE_VALIDMASK;
1411 volattrattrp->nativeattr.forkattr = ATTR_FORK_VALIDMASK;
1412 ++((vol_attributes_attr_t *)attrbufptr);
1413 }
1414
1415 *abp->ab_attrbufpp = attrbufptr;
1416 *abp->ab_varbufpp = varbufptr;
1417}
1418
1419
1420static void
1421packcommonattr(
1422 struct attrblock *abp,
1423 struct hfsmount *hfsmp,
1424 struct vnode *vp,
1425 struct cat_desc * cdp,
1426 struct cat_attr * cap,
1427 struct proc *p)
1428{
1429 attrgroup_t attr = abp->ab_attrlist->commonattr;
1430 struct mount *mp = HFSTOVFS(hfsmp);
1431 void *attrbufptr = *abp->ab_attrbufpp;
1432 void *varbufptr = *abp->ab_varbufpp;
1433 uint32_t attrlength = 0;
1434 boolean_t is_64_bit = proc_is64bit(p);
1435
1436 if (ATTR_CMN_NAME & attr) {
1437 packnameattr(abp, vp, cdp->cd_nameptr, cdp->cd_namelen);
1438 attrbufptr = *abp->ab_attrbufpp;
1439 varbufptr = *abp->ab_varbufpp;
1440 }
1441 if (ATTR_CMN_DEVID & attr) {
1442 *((dev_t *)attrbufptr)++ = hfsmp->hfs_raw_dev;
1443 }
1444 if (ATTR_CMN_FSID & attr) {
1445 fsid_t fsid;
1446
1447 fsid.val[0] = (long)hfsmp->hfs_raw_dev;
1448 fsid.val[1] = (long)vfs_typenum(mp);
1449 *((fsid_t *)attrbufptr) = fsid;
1450 ++((fsid_t *)attrbufptr);
1451 }
1452 if (ATTR_CMN_OBJTYPE & attr) {
1453 *((fsobj_type_t *)attrbufptr)++ = IFTOVT(cap->ca_mode);
1454 }
1455 if (ATTR_CMN_OBJTAG & attr) {
1456 *((fsobj_tag_t *)attrbufptr)++ = VT_HFS;
1457 }
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470 if (ATTR_CMN_OBJID & attr) {
1471 ((fsobj_id_t *)attrbufptr)->fid_objno = cdp->cd_cnid;
1472 ((fsobj_id_t *)attrbufptr)->fid_generation = 0;
1473 ++((fsobj_id_t *)attrbufptr);
1474 }
1475 if (ATTR_CMN_OBJPERMANENTID & attr) {
1476 ((fsobj_id_t *)attrbufptr)->fid_objno = cdp->cd_cnid;
1477 ((fsobj_id_t *)attrbufptr)->fid_generation = 0;
1478 ++((fsobj_id_t *)attrbufptr);
1479 }
1480 if (ATTR_CMN_PAROBJID & attr) {
1481 ((fsobj_id_t *)attrbufptr)->fid_objno = cdp->cd_parentcnid;
1482 ((fsobj_id_t *)attrbufptr)->fid_generation = 0;
1483 ++((fsobj_id_t *)attrbufptr);
1484 }
1485 if (ATTR_CMN_SCRIPT & attr) {
1486 *((text_encoding_t *)attrbufptr)++ = cdp->cd_encoding;
1487 }
1488 if (ATTR_CMN_CRTIME & attr) {
1489 if (is_64_bit) {
1490 ((struct user_timespec *)attrbufptr)->tv_sec = cap->ca_itime;
1491 ((struct user_timespec *)attrbufptr)->tv_nsec = 0;
1492 ++((struct user_timespec *)attrbufptr);
1493 }
1494 else {
1495 ((struct timespec *)attrbufptr)->tv_sec = cap->ca_itime;
1496 ((struct timespec *)attrbufptr)->tv_nsec = 0;
1497 ++((struct timespec *)attrbufptr);
1498 }
1499 }
1500 if (ATTR_CMN_MODTIME & attr) {
1501 if (is_64_bit) {
1502 ((struct user_timespec *)attrbufptr)->tv_sec = cap->ca_mtime;
1503 ((struct user_timespec *)attrbufptr)->tv_nsec = 0;
1504 ++((struct user_timespec *)attrbufptr);
1505 }
1506 else {
1507 ((struct timespec *)attrbufptr)->tv_sec = cap->ca_mtime;
1508 ((struct timespec *)attrbufptr)->tv_nsec = 0;
1509 ++((struct timespec *)attrbufptr);
1510 }
1511 }
1512 if (ATTR_CMN_CHGTIME & attr) {
1513 if (is_64_bit) {
1514 ((struct user_timespec *)attrbufptr)->tv_sec = cap->ca_ctime;
1515 ((struct user_timespec *)attrbufptr)->tv_nsec = 0;
1516 ++((struct user_timespec *)attrbufptr);
1517 }
1518 else {
1519 ((struct timespec *)attrbufptr)->tv_sec = cap->ca_ctime;
1520 ((struct timespec *)attrbufptr)->tv_nsec = 0;
1521 ++((struct timespec *)attrbufptr);
1522 }
1523 }
1524 if (ATTR_CMN_ACCTIME & attr) {
1525 if (is_64_bit) {
1526 ((struct user_timespec *)attrbufptr)->tv_sec = cap->ca_atime;
1527 ((struct user_timespec *)attrbufptr)->tv_nsec = 0;
1528 ++((struct user_timespec *)attrbufptr);
1529 }
1530 else {
1531 ((struct timespec *)attrbufptr)->tv_sec = cap->ca_atime;
1532 ((struct timespec *)attrbufptr)->tv_nsec = 0;
1533 ++((struct timespec *)attrbufptr);
1534 }
1535 }
1536 if (ATTR_CMN_BKUPTIME & attr) {
1537 if (is_64_bit) {
1538 ((struct user_timespec *)attrbufptr)->tv_sec = cap->ca_btime;
1539 ((struct user_timespec *)attrbufptr)->tv_nsec = 0;
1540 ++((struct user_timespec *)attrbufptr);
1541 }
1542 else {
1543 ((struct timespec *)attrbufptr)->tv_sec = cap->ca_btime;
1544 ((struct timespec *)attrbufptr)->tv_nsec = 0;
1545 ++((struct timespec *)attrbufptr);
1546 }
1547 }
1548 if (ATTR_CMN_FNDRINFO & attr) {
1549 bcopy(&cap->ca_finderinfo, attrbufptr, sizeof(u_int8_t) * 32);
1550 (char *)attrbufptr += sizeof(u_int8_t) * 32;
1551 }
1552 if (ATTR_CMN_OWNERID & attr) {
1553 *((uid_t *)attrbufptr)++ =
1554 (cap->ca_uid == UNKNOWNUID) ? kauth_cred_getuid(proc_ucred(p)) : cap->ca_uid;
1555 }
1556 if (ATTR_CMN_GRPID & attr) {
1557 *((gid_t *)attrbufptr)++ = cap->ca_gid;
1558 }
1559 if (ATTR_CMN_ACCESSMASK & attr) {
1560
1561
1562
1563
1564
1565
1566
1567 *((uint32_t *)attrbufptr)++ =
1568 (cap->ca_uid == UNKNOWNUID) ? cap->ca_mode & ~(S_ISUID | S_ISGID) : cap->ca_mode;
1569 }
1570 if (ATTR_CMN_NAMEDATTRCOUNT & attr) {
1571 *((uint32_t *)attrbufptr)++ = 0;
1572 }
1573 if (ATTR_CMN_NAMEDATTRLIST & attr) {
1574 attrlength = 0;
1575 ((struct attrreference *)attrbufptr)->attr_dataoffset = 0;
1576 ((struct attrreference *)attrbufptr)->attr_length = attrlength;
1577
1578
1579
1580
1581 (char *)varbufptr += attrlength + ((4 - (attrlength & 3)) & 3);
1582 ++((struct attrreference *)attrbufptr);
1583 }
1584 if (ATTR_CMN_FLAGS & attr) {
1585 *((uint32_t *)attrbufptr)++ = cap->ca_flags;
1586 }
1587 if (ATTR_CMN_USERACCESS & attr) {
1588 *((uint32_t *)attrbufptr)++ =
1589 DerivePermissionSummary(cap->ca_uid, cap->ca_gid,
1590 cap->ca_mode, mp, proc_ucred(current_proc()),
1591 current_proc());
1592 }
1593
1594 *abp->ab_attrbufpp = attrbufptr;
1595 *abp->ab_varbufpp = varbufptr;
1596}
1597
1598static void
1599packdirattr(
1600 struct attrblock *abp,
1601 struct hfsmount *hfsmp,
1602 struct vnode *vp,
1603 struct cat_desc * descp,
1604 struct cat_attr * cattrp)
1605{
1606 attrgroup_t attr = abp->ab_attrlist->dirattr;
1607 void *attrbufptr = *abp->ab_attrbufpp;
1608
1609 if (ATTR_DIR_LINKCOUNT & attr)
1610 *((uint32_t *)attrbufptr)++ = cattrp->ca_nlink;
1611 if (ATTR_DIR_ENTRYCOUNT & attr) {
1612 uint32_t entries = cattrp->ca_entries;
1613
1614 if (descp->cd_parentcnid == kHFSRootParentID) {
1615 if (hfsmp->hfs_privdir_desc.cd_cnid != 0)
1616 --entries;
1617 if (hfsmp->jnl)
1618 entries -= 2;
1619 }
1620
1621 *((uint32_t *)attrbufptr)++ = entries;
1622 }
1623 if (ATTR_DIR_MOUNTSTATUS & attr) {
1624 if (vp != NULL && vnode_mountedhere(vp) != NULL)
1625 *((uint32_t *)attrbufptr)++ = DIR_MNTSTATUS_MNTPOINT;
1626 else
1627 *((uint32_t *)attrbufptr)++ = 0;
1628 }
1629 *abp->ab_attrbufpp = attrbufptr;
1630}
1631
1632static void
1633packfileattr(
1634 struct attrblock *abp,
1635 struct hfsmount *hfsmp,
1636 struct cat_attr *cattrp,
1637 struct cat_fork *datafork,
1638 struct cat_fork *rsrcfork)
1639{
1640 attrgroup_t attr = abp->ab_attrlist->fileattr;
1641 void *attrbufptr = *abp->ab_attrbufpp;
1642 void *varbufptr = *abp->ab_varbufpp;
1643 uint32_t attrlength;
1644 uint32_t allocblksize;
1645
1646 allocblksize = HFSTOVCB(hfsmp)->blockSize;
1647
1648 if (ATTR_FILE_LINKCOUNT & attr) {
1649 *((uint32_t *)attrbufptr)++ = cattrp->ca_nlink;
1650 }
1651 if (ATTR_FILE_TOTALSIZE & attr) {
1652 *((off_t *)attrbufptr)++ = datafork->cf_size + rsrcfork->cf_size;
1653 }
1654 if (ATTR_FILE_ALLOCSIZE & attr) {
1655 *((off_t *)attrbufptr)++ =
1656 (off_t)cattrp->ca_blocks * (off_t)allocblksize;
1657 }
1658 if (ATTR_FILE_IOBLOCKSIZE & attr) {
1659 *((uint32_t *)attrbufptr)++ = hfsmp->hfs_logBlockSize;
1660 }
1661 if (ATTR_FILE_CLUMPSIZE & attr) {
1662 *((uint32_t *)attrbufptr)++ = HFSTOVCB(hfsmp)->vcbClpSiz;
1663 }
1664 if (ATTR_FILE_DEVTYPE & attr) {
1665 if (S_ISBLK(cattrp->ca_mode) || S_ISCHR(cattrp->ca_mode))
1666 *((uint32_t *)attrbufptr)++ = (uint32_t)cattrp->ca_rdev;
1667 else
1668 *((uint32_t *)attrbufptr)++ = 0;
1669 }
1670 if (ATTR_FILE_FILETYPE & attr) {
1671 *((uint32_t *)attrbufptr)++ = 0;
1672 }
1673 if (ATTR_FILE_FORKCOUNT & attr) {
1674 *((uint32_t *)attrbufptr)++ = 2;
1675 }
1676 if (ATTR_FILE_FORKLIST & attr) {
1677 attrlength = 0;
1678 ((struct attrreference *)attrbufptr)->attr_dataoffset = 0;
1679 ((struct attrreference *)attrbufptr)->attr_length = attrlength;
1680
1681
1682
1683
1684 (char *)varbufptr += attrlength + ((4 - (attrlength & 3)) & 3);
1685 ++((struct attrreference *)attrbufptr);
1686 }
1687 if (ATTR_FILE_DATALENGTH & attr) {
1688 *((off_t *)attrbufptr)++ = datafork->cf_size;
1689 }
1690 if (ATTR_FILE_DATAALLOCSIZE & attr) {
1691 *((off_t *)attrbufptr)++ =
1692 (off_t)datafork->cf_blocks * (off_t)allocblksize;
1693 }
1694 if (ATTR_FILE_DATAEXTENTS & attr) {
1695 bcopy(&datafork->cf_extents, attrbufptr, sizeof(extentrecord));
1696 (char *)attrbufptr += sizeof(extentrecord);
1697 }
1698 if (ATTR_FILE_RSRCLENGTH & attr) {
1699 *((off_t *)attrbufptr)++ = rsrcfork->cf_size;
1700 }
1701 if (ATTR_FILE_RSRCALLOCSIZE & attr) {
1702 *((off_t *)attrbufptr)++ =
1703 (off_t)rsrcfork->cf_blocks * (off_t)allocblksize;
1704 }
1705 if (ATTR_FILE_RSRCEXTENTS & attr) {
1706 bcopy(&rsrcfork->cf_extents, attrbufptr, sizeof(extentrecord));
1707 (char *)attrbufptr += sizeof(extentrecord);
1708 }
1709 *abp->ab_attrbufpp = attrbufptr;
1710 *abp->ab_varbufpp = varbufptr;
1711}
1712
1713#if 0
1714static int
1715unpackattrblk(struct attrblock *abp, struct vnode *vp)
1716{
1717 struct attrlist *attrlistp = abp->ab_attrlist;
1718 int error;
1719
1720 if (attrlistp->volattr) {
1721 error = unpackvolattr(abp, VTOHFS(vp), vp);
1722 if (error)
1723 return (error);
1724 } else if (attrlistp->commonattr) {
1725 unpackcommonattr(abp, vp);
1726 }
1727 return (0);
1728}
1729
1730
1731static void
1732unpackcommonattr(
1733 struct attrblock *abp,
1734 struct vnode *vp)
1735{
1736 attrgroup_t attr = abp->ab_attrlist->commonattr;
1737 void *attrbufptr = *abp->ab_attrbufpp;
1738 struct cnode *cp = VTOC(vp);
1739 boolean_t is_64_bit = proc_is64bit(current_proc());
1740
1741 if (ATTR_CMN_SCRIPT & attr) {
1742 cp->c_encoding = (u_int32_t)*((text_encoding_t *)attrbufptr)++;
1743 hfs_setencodingbits(VTOHFS(vp), cp->c_encoding);
1744 }
1745 if (ATTR_CMN_CRTIME & attr) {
1746 if (is_64_bit) {
1747 cp->c_itime = ((struct user_timespec *)attrbufptr)->tv_sec;
1748 ++((struct user_timespec *)attrbufptr);
1749 }
1750 else {
1751 cp->c_itime = ((struct timespec *)attrbufptr)->tv_sec;
1752 ++((struct timespec *)attrbufptr);
1753 }
1754 }
1755 if (ATTR_CMN_MODTIME & attr) {
1756 cp->c_mtime = ((struct timespec *)attrbufptr)->tv_sec;
1757 ++((struct timespec *)attrbufptr);
1758 cp->c_touch_modtime = FALSE;
1759 }
1760 if (ATTR_CMN_CHGTIME & attr) {
1761 cp->c_ctime = ((struct timespec *)attrbufptr)->tv_sec;
1762 ++((struct timespec *)attrbufptr);
1763 cp->c_touch_chgtime = FALSE;
1764 }
1765 if (ATTR_CMN_ACCTIME & attr) {
1766 cp->c_atime = ((struct timespec *)attrbufptr)->tv_sec;
1767 ++((struct timespec *)attrbufptr);
1768 cp->c_touch_acctime = FALSE;
1769 }
1770 if (ATTR_CMN_BKUPTIME & attr) {
1771 cp->c_btime = ((struct timespec *)attrbufptr)->tv_sec;
1772 ++((struct timespec *)attrbufptr);
1773 }
1774 if (ATTR_CMN_FNDRINFO & attr) {
1775 bcopy(attrbufptr, &cp->c_attr.ca_finderinfo,
1776 sizeof(cp->c_attr.ca_finderinfo));
1777 (char *)attrbufptr += sizeof(cp->c_attr.ca_finderinfo);
1778 }
1779 if (ATTR_CMN_OWNERID & attr) {
1780 if (VTOVCB(vp)->vcbSigWord == kHFSPlusSigWord) {
1781 u_int32_t uid = (u_int32_t)*((uid_t *)attrbufptr)++;
1782 if (uid != (uid_t)VNOVAL)
1783 cp->c_uid = uid;
1784 } else {
1785 ((uid_t *)attrbufptr)++;
1786 }
1787 }
1788 if (ATTR_CMN_GRPID & attr) {
1789 u_int32_t gid = (u_int32_t)*((gid_t *)attrbufptr)++;
1790 if (VTOVCB(vp)->vcbSigWord == kHFSPlusSigWord) {
1791 if (gid != (gid_t)VNOVAL)
1792 cp->c_gid = gid;
1793 }
1794 }
1795 if (ATTR_CMN_ACCESSMASK & attr) {
1796 u_int16_t mode = (u_int16_t)*((uint32_t *)attrbufptr)++;
1797 if (VTOVCB(vp)->vcbSigWord == kHFSPlusSigWord) {
1798 if (mode != (mode_t)VNOVAL) {
1799 cp->c_mode &= ~ALLPERMS;
1800 cp->c_mode |= (mode & ALLPERMS);
1801 }
1802 }
1803 }
1804 if (ATTR_CMN_FLAGS & attr) {
1805 uint32_t flags = *((uint32_t *)attrbufptr)++;
1806
1807
1808
1809
1810
1811
1812 if ((VTOVCB(vp)->vcbSigWord == kHFSPlusSigWord) ||
1813 ((VTOVCB(vp)->vcbSigWord == kHFSSigWord) &&
1814 ((flags & ~IMMUTABLE) == 0))) {
1815 if (flags != (uint32_t)VNOVAL) {
1816 cp->c_flags = flags;
1817 }
1818 }
1819 }
1820 *abp->ab_attrbufpp = attrbufptr;
1821}
1822
1823
1824static int
1825unpackvolattr(
1826 struct attrblock *abp,
1827 struct hfsmount *hfsmp,
1828 struct vnode *root_vp)
1829{
1830 void *attrbufptr = *abp->ab_attrbufpp;
1831 attrgroup_t attr;
1832 int error = 0;
1833 boolean_t is_64_bit = proc_is64bit(current_proc());
1834
1835 HFS_MOUNT_LOCK(hfsmp, TRUE);
1836
1837 attr = abp->ab_attrlist->commonattr;
1838 if (attr == 0)
1839 goto volattr;
1840
1841 if (ATTR_CMN_SCRIPT & attr) {
1842 hfsmp->volumeNameEncodingHint =
1843 (u_int32_t)*(((text_encoding_t *)attrbufptr)++);
1844 }
1845 if (ATTR_CMN_CRTIME & attr) {
1846 if (is_64_bit) {
1847 hfsmp->vcbCrDate = ((struct user_timespec *)attrbufptr)->tv_sec;
1848 ++((struct user_timespec *)attrbufptr);
1849 }
1850 else {
1851 hfsmp->vcbCrDate = ((struct timespec *)attrbufptr)->tv_sec;
1852 ++((struct timespec *)attrbufptr);
1853 }
1854
1855
1856 VTOC(root_vp)->c_itime = hfsmp->vcbCrDate;
1857 VTOC(root_vp)->c_flag |= C_MODIFIED;
1858
1859
1860
1861
1862 }
1863 if (ATTR_CMN_MODTIME & attr) {
1864 hfsmp->vcbLsMod = ((struct timespec *)attrbufptr)->tv_sec;
1865 ++((struct timespec *)attrbufptr);
1866 }
1867 if (ATTR_CMN_BKUPTIME & attr) {
1868 hfsmp->vcbVolBkUp = ((struct timespec *)attrbufptr)->tv_sec;
1869 ++((struct timespec *)attrbufptr);
1870 }
1871 if (ATTR_CMN_FNDRINFO & attr) {
1872 bcopy(attrbufptr, &hfsmp->vcbFndrInfo, sizeof(hfsmp->vcbFndrInfo));
1873 (char *)attrbufptr += sizeof(hfsmp->vcbFndrInfo);
1874 }
1875
1876volattr:
1877 attr = abp->ab_attrlist->volattr & ~ATTR_VOL_INFO;
1878
1879
1880
1881
1882 if (ATTR_VOL_NAME & attr) {
1883 attrreference_t * attr_refp = (attrreference_t *) attrbufptr;
1884
1885 error = copystr(((char *)attrbufptr) + attr_refp->attr_dataoffset,
1886 hfsmp->vcbVN, MIN(attr_refp->attr_length, sizeof(hfsmp->vcbVN)),
1887 NULL);
1888 if (error == 0)
1889 (char *)attrbufptr += sizeof(struct attrreference);
1890 }
1891 *abp->ab_attrbufpp = attrbufptr;
1892
1893 hfsmp->vcbFlags |= 0xFF00;
1894 HFS_MOUNT_UNLOCK(hfsmp, TRUE);
1895
1896 return (error);
1897}
1898#endif
1899
1900
1901
1902
1903 __private_extern__
1904int
1905hfs_attrblksize(struct attrlist *attrlist)
1906{
1907 int size;
1908 attrgroup_t a;
1909 int sizeof_timespec;
1910 boolean_t is_64_bit = proc_is64bit(current_proc());
1911
1912 if (is_64_bit)
1913 sizeof_timespec = sizeof(struct user_timespec);
1914 else
1915 sizeof_timespec = sizeof(struct timespec);
1916
1917#if ((ATTR_CMN_NAME | ATTR_CMN_DEVID | ATTR_CMN_FSID | ATTR_CMN_OBJTYPE | \
1918 ATTR_CMN_OBJTAG | ATTR_CMN_OBJID | ATTR_CMN_OBJPERMANENTID | \
1919 ATTR_CMN_PAROBJID | ATTR_CMN_SCRIPT | ATTR_CMN_CRTIME | \
1920 ATTR_CMN_MODTIME | ATTR_CMN_CHGTIME | ATTR_CMN_ACCTIME | \
1921 ATTR_CMN_BKUPTIME | ATTR_CMN_FNDRINFO | ATTR_CMN_OWNERID | \
1922 ATTR_CMN_GRPID | ATTR_CMN_ACCESSMASK | ATTR_CMN_NAMEDATTRCOUNT | \
1923 ATTR_CMN_NAMEDATTRLIST | ATTR_CMN_FLAGS | ATTR_CMN_USERACCESS) \
1924 != ATTR_CMN_VALIDMASK)
1925#error hfs_attrblksize: Missing bits in common mask computation!
1926#endif
1927 DBG_ASSERT((attrlist->commonattr & ~ATTR_CMN_VALIDMASK) == 0);
1928
1929#if ((ATTR_VOL_FSTYPE | ATTR_VOL_SIGNATURE | ATTR_VOL_SIZE | \
1930 ATTR_VOL_SPACEFREE | ATTR_VOL_SPACEAVAIL | ATTR_VOL_MINALLOCATION | \
1931 ATTR_VOL_ALLOCATIONCLUMP | ATTR_VOL_IOBLOCKSIZE | \
1932 ATTR_VOL_OBJCOUNT | ATTR_VOL_FILECOUNT | ATTR_VOL_DIRCOUNT | \
1933 ATTR_VOL_MAXOBJCOUNT | ATTR_VOL_MOUNTPOINT | ATTR_VOL_NAME | \
1934 ATTR_VOL_MOUNTFLAGS | ATTR_VOL_INFO | ATTR_VOL_MOUNTEDDEVICE | \
1935 ATTR_VOL_ENCODINGSUSED | ATTR_VOL_CAPABILITIES | ATTR_VOL_ATTRIBUTES) \
1936 != ATTR_VOL_VALIDMASK)
1937#error hfs_attrblksize: Missing bits in volume mask computation!
1938#endif
1939 DBG_ASSERT((attrlist->volattr & ~ATTR_VOL_VALIDMASK) == 0);
1940
1941#if ((ATTR_DIR_LINKCOUNT | ATTR_DIR_ENTRYCOUNT | ATTR_DIR_MOUNTSTATUS) \
1942 != ATTR_DIR_VALIDMASK)
1943#error hfs_attrblksize: Missing bits in directory mask computation!
1944#endif
1945 DBG_ASSERT((attrlist->dirattr & ~ATTR_DIR_VALIDMASK) == 0);
1946
1947#if ((ATTR_FILE_LINKCOUNT | ATTR_FILE_TOTALSIZE | ATTR_FILE_ALLOCSIZE | \
1948 ATTR_FILE_IOBLOCKSIZE | ATTR_FILE_CLUMPSIZE | ATTR_FILE_DEVTYPE | \
1949 ATTR_FILE_FILETYPE | ATTR_FILE_FORKCOUNT | ATTR_FILE_FORKLIST | \
1950 ATTR_FILE_DATALENGTH | ATTR_FILE_DATAALLOCSIZE | ATTR_FILE_DATAEXTENTS | \
1951 ATTR_FILE_RSRCLENGTH | ATTR_FILE_RSRCALLOCSIZE | ATTR_FILE_RSRCEXTENTS) \
1952 != ATTR_FILE_VALIDMASK)
1953#error hfs_attrblksize: Missing bits in file mask computation!
1954#endif
1955 DBG_ASSERT((attrlist->fileattr & ~ATTR_FILE_VALIDMASK) == 0);
1956
1957#if ((ATTR_FORK_TOTALSIZE | ATTR_FORK_ALLOCSIZE) != ATTR_FORK_VALIDMASK)
1958#error hfs_attrblksize: Missing bits in fork mask computation!
1959#endif
1960 DBG_ASSERT((attrlist->forkattr & ~ATTR_FORK_VALIDMASK) == 0);
1961
1962 size = 0;
1963
1964 if ((a = attrlist->commonattr) != 0) {
1965 if (a & ATTR_CMN_NAME) size += sizeof(struct attrreference);
1966 if (a & ATTR_CMN_DEVID) size += sizeof(dev_t);
1967 if (a & ATTR_CMN_FSID) size += sizeof(fsid_t);
1968 if (a & ATTR_CMN_OBJTYPE) size += sizeof(fsobj_type_t);
1969 if (a & ATTR_CMN_OBJTAG) size += sizeof(fsobj_tag_t);
1970 if (a & ATTR_CMN_OBJID) size += sizeof(fsobj_id_t);
1971 if (a & ATTR_CMN_OBJPERMANENTID) size += sizeof(fsobj_id_t);
1972 if (a & ATTR_CMN_PAROBJID) size += sizeof(fsobj_id_t);
1973 if (a & ATTR_CMN_SCRIPT) size += sizeof(text_encoding_t);
1974 if (a & ATTR_CMN_CRTIME) size += sizeof_timespec;
1975 if (a & ATTR_CMN_MODTIME) size += sizeof_timespec;
1976 if (a & ATTR_CMN_CHGTIME) size += sizeof_timespec;
1977 if (a & ATTR_CMN_ACCTIME) size += sizeof_timespec;
1978 if (a & ATTR_CMN_BKUPTIME) size += sizeof_timespec;
1979 if (a & ATTR_CMN_FNDRINFO) size += 32 * sizeof(u_int8_t);
1980 if (a & ATTR_CMN_OWNERID) size += sizeof(uid_t);
1981 if (a & ATTR_CMN_GRPID) size += sizeof(gid_t);
1982 if (a & ATTR_CMN_ACCESSMASK) size += sizeof(uint32_t);
1983 if (a & ATTR_CMN_NAMEDATTRCOUNT) size += sizeof(uint32_t);
1984 if (a & ATTR_CMN_NAMEDATTRLIST) size += sizeof(struct attrreference);
1985 if (a & ATTR_CMN_FLAGS) size += sizeof(uint32_t);
1986 if (a & ATTR_CMN_USERACCESS) size += sizeof(uint32_t);
1987 };
1988 if ((a = attrlist->volattr) != 0) {
1989 if (a & ATTR_VOL_FSTYPE) size += sizeof(uint32_t);
1990 if (a & ATTR_VOL_SIGNATURE) size += sizeof(uint32_t);
1991 if (a & ATTR_VOL_SIZE) size += sizeof(off_t);
1992 if (a & ATTR_VOL_SPACEFREE) size += sizeof(off_t);
1993 if (a & ATTR_VOL_SPACEAVAIL) size += sizeof(off_t);
1994 if (a & ATTR_VOL_MINALLOCATION) size += sizeof(off_t);
1995 if (a & ATTR_VOL_ALLOCATIONCLUMP) size += sizeof(off_t);
1996 if (a & ATTR_VOL_IOBLOCKSIZE) size += sizeof(uint32_t);
1997 if (a & ATTR_VOL_OBJCOUNT) size += sizeof(uint32_t);
1998 if (a & ATTR_VOL_FILECOUNT) size += sizeof(uint32_t);
1999 if (a & ATTR_VOL_DIRCOUNT) size += sizeof(uint32_t);
2000 if (a & ATTR_VOL_MAXOBJCOUNT) size += sizeof(uint32_t);
2001 if (a & ATTR_VOL_MOUNTPOINT) size += sizeof(struct attrreference);
2002 if (a & ATTR_VOL_NAME) size += sizeof(struct attrreference);
2003 if (a & ATTR_VOL_MOUNTFLAGS) size += sizeof(uint32_t);
2004 if (a & ATTR_VOL_MOUNTEDDEVICE) size += sizeof(struct attrreference);
2005 if (a & ATTR_VOL_ENCODINGSUSED) size += sizeof(unsigned long long);
2006 if (a & ATTR_VOL_CAPABILITIES) size += sizeof(vol_capabilities_attr_t);
2007 if (a & ATTR_VOL_ATTRIBUTES) size += sizeof(vol_attributes_attr_t);
2008 };
2009 if ((a = attrlist->dirattr) != 0) {
2010 if (a & ATTR_DIR_LINKCOUNT) size += sizeof(uint32_t);
2011 if (a & ATTR_DIR_ENTRYCOUNT) size += sizeof(uint32_t);
2012 if (a & ATTR_DIR_MOUNTSTATUS) size += sizeof(uint32_t);
2013 };
2014 if ((a = attrlist->fileattr) != 0) {
2015 if (a & ATTR_FILE_LINKCOUNT) size += sizeof(uint32_t);
2016 if (a & ATTR_FILE_TOTALSIZE) size += sizeof(off_t);
2017 if (a & ATTR_FILE_ALLOCSIZE) size += sizeof(off_t);
2018 if (a & ATTR_FILE_IOBLOCKSIZE) size += sizeof(uint32_t);
2019 if (a & ATTR_FILE_CLUMPSIZE) size += sizeof(uint32_t);
2020 if (a & ATTR_FILE_DEVTYPE) size += sizeof(uint32_t);
2021 if (a & ATTR_FILE_FILETYPE) size += sizeof(uint32_t);
2022 if (a & ATTR_FILE_FORKCOUNT) size += sizeof(uint32_t);
2023 if (a & ATTR_FILE_FORKLIST) size += sizeof(struct attrreference);
2024 if (a & ATTR_FILE_DATALENGTH) size += sizeof(off_t);
2025 if (a & ATTR_FILE_DATAALLOCSIZE) size += sizeof(off_t);
2026 if (a & ATTR_FILE_DATAEXTENTS) size += sizeof(extentrecord);
2027 if (a & ATTR_FILE_RSRCLENGTH) size += sizeof(off_t);
2028 if (a & ATTR_FILE_RSRCALLOCSIZE) size += sizeof(off_t);
2029 if (a & ATTR_FILE_RSRCEXTENTS) size += sizeof(extentrecord);
2030 };
2031 if ((a = attrlist->forkattr) != 0) {
2032 if (a & ATTR_FORK_TOTALSIZE) size += sizeof(off_t);
2033 if (a & ATTR_FORK_ALLOCSIZE) size += sizeof(off_t);
2034 };
2035
2036 return size;
2037}
2038
2039
2040__private_extern__
2041unsigned long
2042DerivePermissionSummary(uid_t obj_uid, gid_t obj_gid, mode_t obj_mode,
2043 struct mount *mp, kauth_cred_t cred, struct proc *p)
2044{
2045 unsigned long permissions;
2046
2047 if (obj_uid == UNKNOWNUID)
2048 obj_uid = kauth_cred_getuid(proc_ucred(p));
2049
2050
2051 if (!suser(cred, NULL)) {
2052 permissions = R_OK | W_OK | X_OK;
2053 goto Exit;
2054 };
2055
2056
2057 if (hfs_owner_rights(VFSTOHFS(mp), obj_uid, cred, p, false) == 0) {
2058 permissions = ((unsigned long)obj_mode & S_IRWXU) >> 6;
2059 goto Exit;
2060 }
2061
2062
2063 if (! (((unsigned int)vfs_flags(mp)) & MNT_UNKNOWNPERMISSIONS)) {
2064 int is_member;
2065
2066 if (kauth_cred_ismember_gid(cred, obj_gid, &is_member) == 0 && is_member) {
2067 permissions = ((unsigned long)obj_mode & S_IRWXG) >> 3;
2068 goto Exit;
2069 }
2070 }
2071
2072
2073 permissions = (unsigned long)obj_mode & S_IRWXO;
2074
2075Exit:
2076 return (permissions);
2077}
2078
2079