- case kCatalogFileNode:
- /* Files in an HFS+ catalog can represent many things (regular files, symlinks, block/character devices, ...) */
- if ((HTOVCB(hp)->vcbSigWord == kHFSPlusSigWord) &&
- (catalogInfo->nodeData.cnd_mode & IFMT)) {
- *((fsobj_type_t *)attrbufptr)++ =
- IFTOVT((mode_t)catalogInfo->nodeData.cnd_mode);
- } else {
- *((fsobj_type_t *)attrbufptr)++ = VREG;
- };
- break;
-
- default:
- *((fsobj_type_t *)attrbufptr)++ = VNON;
- break;
- };
- }
- if (a & ATTR_CMN_OBJTAG) *((fsobj_tag_t *)attrbufptr)++ = root_vp->v_tag;
- if (a & ATTR_CMN_OBJID) {
- u_int32_t cnid;
-
- /* For hard links use the link's cnid */
- if (catalogInfo->nodeData.cnd_iNodeNumCopy != 0)
- cnid = catalogInfo->nodeData.cnd_linkCNID;
- else
- cnid = catalogInfo->nodeData.cnd_nodeID;
- ((fsobj_id_t *)attrbufptr)->fid_objno = cnid;
- ((fsobj_id_t *)attrbufptr)->fid_generation = 0;
- ++((fsobj_id_t *)attrbufptr);
- };
- if (a & ATTR_CMN_OBJPERMANENTID) {
- u_int32_t cnid;
-
- /* For hard links use the link's cnid */
- if (catalogInfo->nodeData.cnd_iNodeNumCopy != 0)
- cnid = catalogInfo->nodeData.cnd_linkCNID;
- else
- cnid = catalogInfo->nodeData.cnd_nodeID;
- ((fsobj_id_t *)attrbufptr)->fid_objno = cnid;
- ((fsobj_id_t *)attrbufptr)->fid_generation = 0;
- ++((fsobj_id_t *)attrbufptr);
- };
- if (a & ATTR_CMN_PAROBJID)
- {
- ((fsobj_id_t *)attrbufptr)->fid_objno = catalogInfo->nodeData.cnm_parID;
- ((fsobj_id_t *)attrbufptr)->fid_generation = 0;
- ++((fsobj_id_t *)attrbufptr);
- };
- if (a & ATTR_CMN_SCRIPT)
- {
- if (HTOVCB(hp)->vcbSigWord == kHFSPlusSigWord) {
- *((text_encoding_t *)attrbufptr)++ = catalogInfo->nodeData.cnd_textEncoding;
- } else {
- *((text_encoding_t *)attrbufptr)++ = VTOHFS(root_vp)->hfs_encoding;
- }
- };
- if (a & ATTR_CMN_CRTIME)
- {
- ((struct timespec *)attrbufptr)->tv_sec = to_bsd_time(catalogInfo->nodeData.cnd_createDate);
- ((struct timespec *)attrbufptr)->tv_nsec = 0;
- ++((struct timespec *)attrbufptr);
- };
- if (a & ATTR_CMN_MODTIME)
- {
- ((struct timespec *)attrbufptr)->tv_sec = to_bsd_time(catalogInfo->nodeData.cnd_contentModDate);
- ((struct timespec *)attrbufptr)->tv_nsec = 0;
- ++((struct timespec *)attrbufptr);
- };
- if (a & ATTR_CMN_CHGTIME)
- {
- ((struct timespec *)attrbufptr)->tv_sec = to_bsd_time(catalogInfo->nodeData.cnd_attributeModDate);
- ((struct timespec *)attrbufptr)->tv_nsec = 0;
- ++((struct timespec *)attrbufptr);
- };
- if (a & ATTR_CMN_ACCTIME)
- {
- ((struct timespec *)attrbufptr)->tv_sec = to_bsd_time(catalogInfo->nodeData.cnd_accessDate);
- ((struct timespec *)attrbufptr)->tv_nsec = 0;
- ++((struct timespec *)attrbufptr);
- };
- if (a & ATTR_CMN_BKUPTIME)
- {
- ((struct timespec *)attrbufptr)->tv_sec = to_bsd_time(catalogInfo->nodeData.cnd_backupDate);
- ((struct timespec *)attrbufptr)->tv_nsec = 0;
- ++((struct timespec *)attrbufptr);
- };
- if (a & ATTR_CMN_FNDRINFO)
- {
- bcopy (&catalogInfo->nodeData.cnd_finderInfo, attrbufptr, sizeof(catalogInfo->nodeData.cnd_finderInfo));
- (char *)attrbufptr += sizeof(catalogInfo->nodeData.cnd_finderInfo);
- };
- if (a & ATTR_CMN_OWNERID) {
- if ((VTOVFS(root_vp)->mnt_flag & MNT_UNKNOWNPERMISSIONS) ||
- ((catalogInfo->nodeData.cnd_mode & IFMT) == 0)) {
- *((uid_t *)attrbufptr)++ =
- (VTOHFS(root_vp)->hfs_uid == UNKNOWNUID) ? console_user : VTOHFS(root_vp)->hfs_uid;
- } else {
- *((uid_t *)attrbufptr)++ =
- (catalogInfo->nodeData.cnd_ownerID == UNKNOWNUID) ? console_user : catalogInfo->nodeData.cnd_ownerID;
- };
- }
- if (a & ATTR_CMN_GRPID) {
- if ((VTOVFS(root_vp)->mnt_flag & MNT_UNKNOWNPERMISSIONS) ||
- ((catalogInfo->nodeData.cnd_mode & IFMT) == 0)) {
- *((gid_t *)attrbufptr)++ = VTOHFS(root_vp)->hfs_gid;
- } else {
- *((gid_t *)attrbufptr)++ = catalogInfo->nodeData.cnd_groupID;
- };
- }
- if (a & ATTR_CMN_ACCESSMASK) {
- if (((catalogInfo->nodeData.cnd_mode & IFMT) == 0)
-#if OVERRIDE_UNKNOWN_PERMISSIONS
- || (VTOVFS(root_vp)->mnt_flag & MNT_UNKNOWNPERMISSIONS)
-#endif
- ) {
- switch (catalogInfo->nodeData.cnd_type) {
- case kCatalogFileNode:
- /* Files in an HFS+ catalog can represent many things (regular files, symlinks, block/character devices, ...) */
- *((u_long *)attrbufptr)++ = (u_long)(IFREG | (ACCESSPERMS & (u_long)(VTOHFS(root_vp)->hfs_file_mask)));
- break;
-
- case kCatalogFolderNode:
- *((u_long *)attrbufptr)++ = (u_long)(IFDIR | (ACCESSPERMS & (u_long)(VTOHFS(root_vp)->hfs_dir_mask)));
- break;
-
- default:
- *((u_long *)attrbufptr)++ = (u_long)((catalogInfo->nodeData.cnd_mode & IFMT) |
- VTOHFS(root_vp)->hfs_dir_mask);
- };
- } else {
- *((u_long *)attrbufptr)++ =
- (u_long)catalogInfo->nodeData.cnd_mode;
- };
- }
- if (a & ATTR_CMN_NAMEDATTRCOUNT) *((u_long *)attrbufptr)++ = 0; /* XXX PPD TBC */
- if (a & ATTR_CMN_NAMEDATTRLIST)
- {
- attrlength = 0;
- ((struct attrreference *)attrbufptr)->attr_dataoffset = 0;
- ((struct attrreference *)attrbufptr)->attr_length = attrlength;
-
- /* Advance beyond the space just allocated and round up to the next 4-byte boundary: */
- (char *)varbufptr += attrlength + ((4 - (attrlength & 3)) & 3);
- ++((struct attrreference *)attrbufptr);
- };
- if (a & ATTR_CMN_FLAGS) {
- u_long flags;
-
- if (catalogInfo->nodeData.cnd_mode & IFMT)
- flags = catalogInfo->nodeData.cnd_ownerFlags |
- catalogInfo->nodeData.cnd_adminFlags << 16;
- else
- flags = 0;
-
- if (catalogInfo->nodeData.cnd_type == kCatalogFileNode) {
- if (catalogInfo->nodeData.cnd_flags & kHFSFileLockedMask)
- flags |= UF_IMMUTABLE;
- else
- flags &= ~UF_IMMUTABLE;
- };
- *((u_long *)attrbufptr)++ = flags;
- };
- if (a & ATTR_CMN_USERACCESS) {
- if ((VTOVFS(root_vp)->mnt_flag & MNT_UNKNOWNPERMISSIONS) ||
- ((catalogInfo->nodeData.cnd_mode & IFMT) == 0)) {
- *((u_long *)attrbufptr)++ =
- DerivePermissionSummary((VTOHFS(root_vp)->hfs_uid == UNKNOWNUID) ? console_user : VTOHFS(root_vp)->hfs_uid,
- VTOHFS(root_vp)->hfs_gid,
-#if OVERRIDE_UNKNOWN_PERMISSIONS
- (catalogInfo->nodeData.cnd_type == kCatalogFileNode) ? VTOHFS(root_vp)->hfs_file_mask : VTOHFS(root_vp)->hfs_dir_mask,
-#else
- (catalogInfo->nodeData.cnd_mode & IFMT) ?
- (u_long)catalogInfo->nodeData.cnd_mode :
- ((catalogInfo->nodeData.cnd_type == kCatalogFileNode) ?
- VTOHFS(root_vp)->hfs_file_mask :
- VTOHFS(root_vp)->hfs_dir_mask),
-#endif
- VTOVFS(root_vp),
- current_proc()->p_ucred,
- current_proc());
- } else {
- *((u_long *)attrbufptr)++ =
- DerivePermissionSummary((catalogInfo->nodeData.cnd_ownerID == UNKNOWNUID) ? console_user : catalogInfo->nodeData.cnd_ownerID,
- catalogInfo->nodeData.cnd_groupID,
- (mode_t)catalogInfo->nodeData.cnd_mode,
- VTOVFS(root_vp),
- current_proc()->p_ucred,
- current_proc());
- };
- };
- };
-
- *attrbufptrptr = attrbufptr;
- *varbufptrptr = varbufptr;
-}
-
-
-void PackCommonAttributeBlock(struct attrlist *alist,
- struct vnode *vp,
- struct hfsCatalogInfo *catInfo,
- void **attrbufptrptr,
- void **varbufptrptr) {
- struct hfsnode *hp;
- void *attrbufptr;
- void *varbufptr;
- attrgroup_t a;
- u_long attrlength;
-
- hp = VTOH(vp);
-
- attrbufptr = *attrbufptrptr;
- varbufptr = *varbufptrptr;
-
- if ((a = alist->commonattr) != 0) {
- if (a & ATTR_CMN_NAME) {
- PackObjectName(vp, H_NAME(hp), hp->h_meta->h_namelen, &attrbufptr, &varbufptr);
- };
- if (a & ATTR_CMN_DEVID) *((dev_t *)attrbufptr)++ = H_DEV(hp);
- if (a & ATTR_CMN_FSID) {
- *((fsid_t *)attrbufptr) = VTOVFS(vp)->mnt_stat.f_fsid;
- ++((fsid_t *)attrbufptr);
- };
- if (a & ATTR_CMN_OBJTYPE) *((fsobj_type_t *)attrbufptr)++ = vp->v_type;
- if (a & ATTR_CMN_OBJTAG) *((fsobj_tag_t *)attrbufptr)++ = vp->v_tag;
- if (a & ATTR_CMN_OBJID) {
- u_int32_t cnid;
-
- /* For hard links use the link's cnid */
- if (hp->h_meta->h_metaflags & IN_DATANODE)
- cnid = catInfo->nodeData.cnd_linkCNID;
- else
- cnid = H_FILEID(hp);
- ((fsobj_id_t *)attrbufptr)->fid_objno = cnid;
- ((fsobj_id_t *)attrbufptr)->fid_generation = 0;
- ++((fsobj_id_t *)attrbufptr);
- };
- if (a & ATTR_CMN_OBJPERMANENTID) {
- u_int32_t cnid;
-
- /* For hard links use the link's cnid */
- if (hp->h_meta->h_metaflags & IN_DATANODE)
- cnid = catInfo->nodeData.cnd_linkCNID;
- else
- cnid = H_FILEID(hp);
- ((fsobj_id_t *)attrbufptr)->fid_objno = cnid;
- ((fsobj_id_t *)attrbufptr)->fid_generation = 0;
- ++((fsobj_id_t *)attrbufptr);
- };
- if (a & ATTR_CMN_PAROBJID) {
- ((fsobj_id_t *)attrbufptr)->fid_objno = H_DIRID(hp);
- ((fsobj_id_t *)attrbufptr)->fid_generation = 0;
- ++((fsobj_id_t *)attrbufptr);
- };
- if (a & ATTR_CMN_SCRIPT)
- {
- if (HTOVCB(hp)->vcbSigWord == kHFSPlusSigWord) {
- *((text_encoding_t *)attrbufptr)++ = catInfo->nodeData.cnd_textEncoding;
- } else {
- *((text_encoding_t *)attrbufptr)++ = VTOHFS(vp)->hfs_encoding;
- }
- };
- if (a & ATTR_CMN_CRTIME) {
- ((struct timespec *)attrbufptr)->tv_sec = hp->h_meta->h_crtime;
- ((struct timespec *)attrbufptr)->tv_nsec = 0;
- ++((struct timespec *)attrbufptr);
- };
- if (a & ATTR_CMN_MODTIME) {
- ((struct timespec *)attrbufptr)->tv_sec = hp->h_meta->h_mtime;
- ((struct timespec *)attrbufptr)->tv_nsec = 0;
- ++((struct timespec *)attrbufptr);
- };
- if (a & ATTR_CMN_CHGTIME) {
- ((struct timespec *)attrbufptr)->tv_sec = hp->h_meta->h_ctime;
- ((struct timespec *)attrbufptr)->tv_nsec = 0;
- ++((struct timespec *)attrbufptr);
- };
- if (a & ATTR_CMN_ACCTIME) {
- ((struct timespec *)attrbufptr)->tv_sec = hp->h_meta->h_atime;
- ((struct timespec *)attrbufptr)->tv_nsec = 0;
- ++((struct timespec *)attrbufptr);
- };
- if (a & ATTR_CMN_BKUPTIME) {
- ((struct timespec *)attrbufptr)->tv_sec = hp->h_meta->h_butime;
- ((struct timespec *)attrbufptr)->tv_nsec = 0;
- ++((struct timespec *)attrbufptr);
- };
- if (a & ATTR_CMN_FNDRINFO) {
- bcopy (&catInfo->nodeData.cnd_finderInfo, attrbufptr, sizeof(catInfo->nodeData.cnd_finderInfo));
- (char *)attrbufptr += sizeof(catInfo->nodeData.cnd_finderInfo);
- };
- if (a & ATTR_CMN_OWNERID) {
- if (VTOVFS(vp)->mnt_flag & MNT_UNKNOWNPERMISSIONS) {
- *((uid_t *)attrbufptr)++ =
- (VTOHFS(vp)->hfs_uid == UNKNOWNUID) ? console_user : VTOHFS(vp)->hfs_uid;
- } else {
- *((uid_t *)attrbufptr)++ =
- (hp->h_meta->h_uid == UNKNOWNUID) ? console_user : hp->h_meta->h_uid;
- }
- };
- if (a & ATTR_CMN_GRPID) {
- if (VTOVFS(vp)->mnt_flag & MNT_UNKNOWNPERMISSIONS) {
- *((gid_t *)attrbufptr)++ = VTOHFS(vp)->hfs_gid;
- } else {
- *((gid_t *)attrbufptr)++ = hp->h_meta->h_gid;
- };
- };
- if (a & ATTR_CMN_ACCESSMASK) *((u_long *)attrbufptr)++ = (u_long)hp->h_meta->h_mode;
- if (a & ATTR_CMN_NAMEDATTRCOUNT) *((u_long *)attrbufptr)++ = 0; /* XXX PPD TBC */
- if (a & ATTR_CMN_NAMEDATTRLIST) {
- attrlength = 0;
- ((struct attrreference *)attrbufptr)->attr_dataoffset = 0;
- ((struct attrreference *)attrbufptr)->attr_length = attrlength;
-
- /* Advance beyond the space just allocated and round up to the next 4-byte boundary: */
- (char *)varbufptr += attrlength + ((4 - (attrlength & 3)) & 3);
- ++((struct attrreference *)attrbufptr);
- };
- if (a & ATTR_CMN_FLAGS) *((u_long *)attrbufptr)++ = hp->h_meta->h_pflags;
- if (a & ATTR_CMN_USERACCESS) {
- if (VTOVFS(vp)->mnt_flag & MNT_UNKNOWNPERMISSIONS) {
- *((u_long *)attrbufptr)++ =
- DerivePermissionSummary((VTOHFS(vp)->hfs_uid == UNKNOWNUID) ? console_user : VTOHFS(vp)->hfs_uid,
- VTOHFS(vp)->hfs_gid,
- hp->h_meta->h_mode,
- VTOVFS(vp),
- current_proc()->p_ucred,
- current_proc());
- } else {
- *((u_long *)attrbufptr)++ =
- DerivePermissionSummary((hp->h_meta->h_uid == UNKNOWNUID) ? console_user : hp->h_meta->h_uid,
- hp->h_meta->h_gid,
- hp->h_meta->h_mode,
- VTOVFS(vp),
- current_proc()->p_ucred,
- current_proc());
- };
- };
- };
-
- *attrbufptrptr = attrbufptr;
- *varbufptrptr = varbufptr;
-}
-
-
-// Pack the directory attributes given hfsCatalogInfo
-void PackCatalogInfoDirAttributeBlock( struct attrlist *alist, struct vnode *vp,
- struct hfsCatalogInfo *catInfo, void **attrbufptrptr, void **varbufptrptr )
-{
- void *attrbufptr;
- attrgroup_t a;
- u_long valence;
-
- attrbufptr = *attrbufptrptr;
- a = alist->dirattr;
-
- if ( (catInfo->nodeData.cnd_type == kCatalogFolderNode) && (a != 0) ) {
- valence = catInfo->nodeData.cnd_valence;
- if ((catInfo->nodeData.cnm_parID == kRootParID) &&
- (VTOHFS(vp)->hfs_private_metadata_dir != 0)) {
- --valence; /* hide private dir */
- }
- /* The 'link count' is faked */
- if (a & ATTR_DIR_LINKCOUNT)
- *((u_long *)attrbufptr)++ = 2 + valence;
- if (a & ATTR_DIR_ENTRYCOUNT)
- *((u_long *)attrbufptr)++ = valence;
- if (a & ATTR_DIR_MOUNTSTATUS)
- *((u_long *)attrbufptr)++ = 0;
- };
-
- *attrbufptrptr = attrbufptr;
-}
-
-
-void PackDirAttributeBlock(struct attrlist *alist,
- struct vnode *vp,
- struct hfsCatalogInfo *catInfo,
- void **attrbufptrptr,
- void **varbufptrptr) {
- void *attrbufptr;
- attrgroup_t a;
- u_long valence;
-
- attrbufptr = *attrbufptrptr;
-
- a = alist->dirattr;
- if ((vp->v_type == VDIR) && (a != 0)) {
- valence = catInfo->nodeData.cnd_valence;
- if ((catInfo->nodeData.cnm_parID == kRootParID) &&
- (VTOHFS(vp)->hfs_private_metadata_dir != 0)) {
- --valence; /* hide private dir */
- }
-
- /* The 'link count' is faked */
- if (a & ATTR_DIR_LINKCOUNT)
- *((u_long *)attrbufptr)++ = 2 + valence;
- if (a & ATTR_DIR_ENTRYCOUNT)
- *((u_long *)attrbufptr)++ = valence;
- if (a & ATTR_DIR_MOUNTSTATUS) {
- if (vp->v_mountedhere) {
- *((u_long *)attrbufptr)++ = DIR_MNTSTATUS_MNTPOINT;
- } else {
- *((u_long *)attrbufptr)++ = 0;
- };
- };
- };
-
- *attrbufptrptr = attrbufptr;
-}
-
-
-
-// Pack the file attributes from the hfsCatalogInfo for the file.
-void PackCatalogInfoFileAttributeBlock( struct attrlist *alist, struct vnode *root_vp, struct hfsCatalogInfo *catInfo, void **attrbufptrptr, void **varbufptrptr )
-{
- void *attrbufptr;
- void *varbufptr;
- attrgroup_t a;
- u_long attrlength;
- ExtendedVCB *vcb = VTOVCB(root_vp);
-
- attrbufptr = *attrbufptrptr;
- varbufptr = *varbufptrptr;
-
- a = alist->fileattr;
- if ( (catInfo->nodeData.cnd_type == kCatalogFileNode) && (a != 0) )
- {
-#if HFS_HARDLINKS
- if (a & ATTR_FILE_LINKCOUNT) {
- u_long linkcnt = catInfo->nodeData.cnd_linkCount;
-
- if (linkcnt < 1)
- linkcnt = 1;
- *((u_long *)attrbufptr)++ = linkcnt;
- }
-#else
- if (a & ATTR_FILE_LINKCOUNT) *((u_long *)attrbufptr)++ = 1;
-#endif
- if (a & ATTR_FILE_TOTALSIZE) {
- *((off_t *)attrbufptr)++ =
- (off_t)catInfo->nodeData.cnd_datafork.logicalSize +
- (off_t)catInfo->nodeData.cnd_rsrcfork.logicalSize;
- }
- if (a & ATTR_FILE_ALLOCSIZE) {
- *((off_t *)attrbufptr)++ =
- (off_t)((off_t)catInfo->nodeData.cnd_datafork.totalBlocks * (off_t)vcb->blockSize) +
- (off_t)((off_t)catInfo->nodeData.cnd_rsrcfork.totalBlocks * (off_t)vcb->blockSize);
- }
- if (a & ATTR_FILE_IOBLOCKSIZE) {
- *((u_long *)attrbufptr)++ = (u_long)(VTOHFS(root_vp)->hfs_logBlockSize);
- }
- if (a & ATTR_FILE_CLUMPSIZE) {
- *((u_long *)attrbufptr)++ = vcb->vcbClpSiz;
- }
- if (a & ATTR_FILE_DEVTYPE) {
- u_long rawdev;
- u_short filetype;
-
- filetype = (catInfo->nodeData.cnd_mode & IFMT);
- if (filetype == IFCHR || filetype == IFBLK)
- rawdev = (u_long)catInfo->nodeData.cnd_rawDevice;
- else
- rawdev = 0;
-
- *((u_long *)attrbufptr)++ = rawdev;
- }
- if (a & ATTR_FILE_FILETYPE) {
- *((u_long *)attrbufptr)++ = 0; /* XXX PPD */
- }
- if (a & ATTR_FILE_FORKCOUNT) {
- *((u_long *)attrbufptr)++ = 2; /* XXX PPD */
- }
- if (a & ATTR_FILE_FORKLIST) {
- attrlength = 0;
- ((struct attrreference *)attrbufptr)->attr_dataoffset = 0;
- ((struct attrreference *)attrbufptr)->attr_length = attrlength;
-
- /* Advance beyond the space just allocated and round up to the next 4-byte boundary: */
- (char *)varbufptr += attrlength + ((4 - (attrlength & 3)) & 3);
- ++((struct attrreference *)attrbufptr);
- };
- if (a & ATTR_FILE_DATALENGTH) {
- *((off_t *)attrbufptr)++ =
- (off_t)catInfo->nodeData.cnd_datafork.logicalSize;
- }
- if (a & ATTR_FILE_DATAALLOCSIZE) {
- *((off_t *)attrbufptr)++ =
- (off_t)((off_t)catInfo->nodeData.cnd_datafork.totalBlocks * (off_t)vcb->blockSize);
- }
- if (a & ATTR_FILE_DATAEXTENTS) {
- bcopy(&catInfo->nodeData.cnd_datafork.extents, attrbufptr, sizeof(extentrecord));
- (char *)attrbufptr += sizeof(extentrecord) + ((4 - (sizeof(extentrecord) & 3)) & 3);
- };
- if (a & ATTR_FILE_RSRCLENGTH) {
- *((off_t *)attrbufptr)++ =
- (off_t)catInfo->nodeData.cnd_rsrcfork.logicalSize;
- }
- if (a & ATTR_FILE_RSRCALLOCSIZE) {
- *((off_t *)attrbufptr)++ =
- (off_t)((off_t)catInfo->nodeData.cnd_rsrcfork.totalBlocks * (off_t)vcb->blockSize);
- }
- if (a & ATTR_FILE_RSRCEXTENTS) {
- bcopy(&catInfo->nodeData.cnd_rsrcfork.extents, attrbufptr, sizeof(extentrecord));
- (char *)attrbufptr += sizeof(extentrecord) + ((4 - (sizeof(extentrecord) & 3)) & 3);
- };
- };
-
- *attrbufptrptr = attrbufptr;
- *varbufptrptr = varbufptr;
-}
-
-
-void PackFileAttributeBlock(struct attrlist *alist,
- struct vnode *vp,
- struct hfsCatalogInfo *catInfo,
- void **attrbufptrptr,
- void **varbufptrptr) {
- struct hfsnode *hp = VTOH(vp);
- FCB *fcb = HTOFCB(hp);
- ExtendedVCB *vcb = HTOVCB(hp);
- Boolean isHFSPlus = (vcb->vcbSigWord == kHFSPlusSigWord);
- void *attrbufptr = *attrbufptrptr;
- void *varbufptr = *varbufptrptr;
- attrgroup_t a = alist->fileattr;
- u_long attrlength;
-
- if (a != 0) {
-#if HFS_HARDLINKS
- if (a & ATTR_FILE_LINKCOUNT) {
- u_long linkcnt = catInfo->nodeData.cnd_linkCount;
-
- if (linkcnt < 1)
- linkcnt = 1;
- *((u_long *)attrbufptr)++ = linkcnt;
- }
-#else
- if (a & ATTR_FILE_LINKCOUNT) *((u_long *)attrbufptr)++ = 1;
-#endif
- if (a & ATTR_FILE_TOTALSIZE) {
- *((off_t *)attrbufptr)++ =
- (off_t)catInfo->nodeData.cnd_datafork.logicalSize +
- (off_t)catInfo->nodeData.cnd_rsrcfork.logicalSize;
- }
- if (a & ATTR_FILE_ALLOCSIZE) {
- switch (H_FORKTYPE(hp)) {
- case kDataFork:
- *((off_t *)attrbufptr)++ =
- (off_t)fcb->fcbPLen +
- (off_t)((off_t)catInfo->nodeData.cnd_rsrcfork.totalBlocks * (off_t)vcb->blockSize);
- break;
- case kRsrcFork:
- *((off_t *)attrbufptr)++ =
- (off_t)fcb->fcbPLen +
- (off_t)((off_t)catInfo->nodeData.cnd_datafork.totalBlocks * (off_t)vcb->blockSize);
- break;
- default:
- *((off_t *)attrbufptr)++ =
- (off_t)((off_t)catInfo->nodeData.cnd_datafork.totalBlocks * (off_t)vcb->blockSize) +
- (off_t)((off_t)catInfo->nodeData.cnd_rsrcfork.totalBlocks * (off_t)vcb->blockSize);
- };
- };
- if (a & ATTR_FILE_IOBLOCKSIZE) *((u_long *)attrbufptr)++ = GetLogicalBlockSize(vp);
- if (a & ATTR_FILE_CLUMPSIZE) *((u_long *)attrbufptr)++ = fcb->fcbClmpSize;
- if (a & ATTR_FILE_DEVTYPE) {
- u_long rawdev;
-
- if ((vp->v_type == VBLK) || (vp->v_type == VCHR))
- rawdev = (u_long)catInfo->nodeData.cnd_rawDevice;
- else
- rawdev = 0;
- *((u_long *)attrbufptr)++ = rawdev;
- }
- if (a & ATTR_FILE_FILETYPE) *((u_long *)attrbufptr)++ = 0; /* XXX PPD */
- if (a & ATTR_FILE_FORKCOUNT) *((u_long *)attrbufptr)++ = 2; /* XXX PPD */
- if (a & ATTR_FILE_FORKLIST) {
- attrlength = 0;
- ((struct attrreference *)attrbufptr)->attr_dataoffset = 0;
- ((struct attrreference *)attrbufptr)->attr_length = attrlength;
-
- /* Advance beyond the space just allocated and round up to the next 4-byte boundary: */
- (char *)varbufptr += attrlength + ((4 - (attrlength & 3)) & 3);
- ++((struct attrreference *)attrbufptr);
- };
- if (H_FORKTYPE(hp) == kDataFork) {
- if (a & ATTR_FILE_DATALENGTH)
- *((off_t *)attrbufptr)++ = fcb->fcbEOF;
- if (a & ATTR_FILE_DATAALLOCSIZE) *((off_t *)attrbufptr)++ = fcb->fcbPLen;
- if (a & ATTR_FILE_DATAEXTENTS) {
- bcopy ( fcb->fcbExtents, attrbufptr, sizeof(extentrecord));
- (char *)attrbufptr += sizeof(extentrecord) + ((4 - (sizeof(extentrecord) & 3)) & 3);
- };
- } else {
- if (a & ATTR_FILE_DATALENGTH) {
- *((off_t *)attrbufptr)++ =
- (off_t)catInfo->nodeData.cnd_datafork.logicalSize;
- }
- if (a & ATTR_FILE_DATAALLOCSIZE) {
- *((off_t *)attrbufptr)++ =
- (off_t)((off_t)catInfo->nodeData.cnd_datafork.totalBlocks * (off_t)vcb->blockSize);
- }
- if (a & ATTR_FILE_DATAEXTENTS) {
- bcopy(&catInfo->nodeData.cnd_datafork.extents, attrbufptr, sizeof(extentrecord));
- (char *)attrbufptr += sizeof(extentrecord) + ((4 - (sizeof(extentrecord) & 3)) & 3);
- };
- };
- if (H_FORKTYPE(hp) == kRsrcFork) {
- if (a & ATTR_FILE_RSRCLENGTH)
- *((off_t *)attrbufptr)++ = fcb->fcbEOF;
- if (a & ATTR_FILE_RSRCALLOCSIZE) *((off_t *)attrbufptr)++ = fcb->fcbPLen;
- if (a & ATTR_FILE_RSRCEXTENTS) {
- bcopy ( fcb->fcbExtents, attrbufptr, sizeof(extentrecord));
- (char *)attrbufptr += sizeof(extentrecord) + ((4 - (sizeof(extentrecord) & 3)) & 3);
- };
- } else {
- if (a & ATTR_FILE_RSRCLENGTH) {
- *((off_t *)attrbufptr)++ =
- (off_t)catInfo->nodeData.cnd_rsrcfork.logicalSize;
- }
- if (a & ATTR_FILE_RSRCALLOCSIZE) {
- *((off_t *)attrbufptr)++ =
- (off_t)((off_t)catInfo->nodeData.cnd_rsrcfork.totalBlocks * (off_t)vcb->blockSize);
- }
- if (a & ATTR_FILE_RSRCEXTENTS) {
- bcopy(&catInfo->nodeData.cnd_rsrcfork.extents, attrbufptr, sizeof(extentrecord));
- (char *)attrbufptr += sizeof(extentrecord) + ((4 - (sizeof(extentrecord) & 3)) & 3);
- };
- };
- };
-
- *attrbufptrptr = attrbufptr;
- *varbufptrptr = varbufptr;
-}
-
-#if 0
-void PackForkAttributeBlock(struct attrlist *alist,
- struct vnode *vp,
- struct hfsCatalogInfo *catInfo,
- void **attrbufptrptr,
- void **varbufptrptr) {
- /* XXX PPD TBC */
-}
-#endif
-
-
-// This routine takes catInfo, and alist, as inputs and packs it into an attribute block.
-void PackCatalogInfoAttributeBlock ( struct attrlist *alist, struct vnode *root_vp, struct hfsCatalogInfo *catInfo, void **attrbufptrptr, void **varbufptrptr)
-{
- //XXX Preflight that alist only contains bits with fields in catInfo
-
- PackCommonCatalogInfoAttributeBlock( alist, root_vp, catInfo, attrbufptrptr, varbufptrptr );
-
- switch ( catInfo->nodeData.cnd_type )
- {
- case kCatalogFolderNode:
- PackCatalogInfoDirAttributeBlock( alist, root_vp, catInfo, attrbufptrptr, varbufptrptr );
- break;
-
- case kCatalogFileNode:
- PackCatalogInfoFileAttributeBlock( alist, root_vp, catInfo, attrbufptrptr, varbufptrptr );
- break;
-
- default: /* Without this the compiler complains about VNON,VBLK,VCHR,VLNK,VSOCK,VFIFO,VBAD and VSTR not being handled... */
- /* XXX PPD - Panic? */
- break;
- }
-}
-
-
-
-void PackAttributeBlock(struct attrlist *alist,
- struct vnode *vp,
- struct hfsCatalogInfo *catInfo,
- void **attrbufptrptr,
- void **varbufptrptr)
-{
- if (alist->volattr != 0) {
- DBG_ASSERT((vp->v_flag & VROOT) != 0);
- PackVolumeInfo(alist,vp, catInfo, attrbufptrptr, varbufptrptr);
- } else {
- PackCommonAttributeBlock(alist, vp, catInfo, attrbufptrptr, varbufptrptr);
-
- switch (vp->v_type) {
- case VDIR:
- PackDirAttributeBlock(alist, vp, catInfo, attrbufptrptr, varbufptrptr);
- break;
-
- case VREG:
- case VLNK:
- PackFileAttributeBlock(alist, vp, catInfo, attrbufptrptr, varbufptrptr);
- break;
-
- /* Without this the compiler complains about VNON,VBLK,VCHR,VLNK,VSOCK,VFIFO,VBAD and VSTR
- not being handled...
- */
- default:
- /* XXX PPD - Panic? */
- break;
- };
- };
-};
-
-
-
-void UnpackVolumeAttributeBlock(struct attrlist *alist,
- struct vnode *root_vp,
- ExtendedVCB *vcb,
- void **attrbufptrptr,
- void **varbufptrptr) {
- void *attrbufptr = *attrbufptrptr;
- attrgroup_t a;
-
- if ((alist->commonattr == 0) && (alist->volattr == 0)) {
- return; /* Get out without dirtying the VCB */
- };
-
- VCB_LOCK(vcb);
-
- a = alist->commonattr;
-
- if (a & ATTR_CMN_SCRIPT) {
- vcb->volumeNameEncodingHint = (u_int32_t)*(((text_encoding_t *)attrbufptr)++);
-#if HFS_DIAGNOSTIC
- a &= ~ATTR_CMN_SCRIPT;
-#endif
- };
- if (a & ATTR_CMN_CRTIME) {
- vcb->vcbCrDate = to_hfs_time((UInt32)((struct timespec *)attrbufptr)->tv_sec);
- /* Need to update the local time also */
- vcb->localCreateDate = UTCToLocal(vcb->vcbCrDate);
- ++((struct timespec *)attrbufptr);
-#if HFS_DIAGNOSTIC
- a &= ~ATTR_CMN_CRTIME;
-#endif
- };
- if (a & ATTR_CMN_MODTIME) {
- vcb->vcbLsMod = to_hfs_time((UInt32)((struct timespec *)attrbufptr)->tv_sec);
- ++((struct timespec *)attrbufptr);
-#if HFS_DIAGNOSTIC
- a &= ~ATTR_CMN_MODTIME;
-#endif
- };
- if (a & ATTR_CMN_BKUPTIME) {
- vcb->vcbVolBkUp = to_hfs_time((UInt32)((struct timespec *)attrbufptr)->tv_sec);
- ++((struct timespec *)attrbufptr);
-#if HFS_DIAGNOSTIC
- a &= ~ATTR_CMN_BKUPTIME;
-#endif
- };
- if (a & ATTR_CMN_FNDRINFO) {
- bcopy (attrbufptr, &vcb->vcbFndrInfo, sizeof(vcb->vcbFndrInfo));
- (char *)attrbufptr += sizeof(vcb->vcbFndrInfo);
-#if HFS_DIAGNOSTIC
- a &= ~ATTR_CMN_FNDRINFO;
-#endif
- };
-
- DBG_ASSERT(a == 0); /* All common attributes for volumes must've been handled by now... */
-
- a = alist->volattr & ~ATTR_VOL_INFO;
- if (a & ATTR_VOL_NAME) {
- copystr(((char *)attrbufptr) + *((u_long *)attrbufptr), vcb->vcbVN, sizeof(vcb->vcbVN), NULL);
- (char *)attrbufptr += sizeof(struct attrreference);
-#if HFS_DIAGNOSTIC
- a &= ~ATTR_VOL_NAME;
-#endif
- };
-
- DBG_ASSERT(a == 0); /* All common attributes for volumes must've been handled by now... */
-
- vcb->vcbFlags |= 0xFF00; // Mark the VCB dirty
-
- VCB_UNLOCK(vcb);
-}
-
-
-void UnpackCommonAttributeBlock(struct attrlist *alist,
- struct vnode *vp,
- struct hfsCatalogInfo *catInfo,
- void **attrbufptrptr,
- void **varbufptrptr) {
- struct hfsnode *hp = VTOH(vp);
- void *attrbufptr;
- attrgroup_t a;
-
- attrbufptr = *attrbufptrptr;
-
- DBG_ASSERT(catInfo != NULL);
-
- a = alist->commonattr;
- if (a & ATTR_CMN_SCRIPT) {
- catInfo->nodeData.cnd_textEncoding = (u_int32_t)*((text_encoding_t *)attrbufptr)++;
- UpdateVolumeEncodings(VTOVCB(vp), catInfo->nodeData.cnd_textEncoding); /* Update the volume encoding */
-#if HFS_DIAGNOSTIC
- a &= ~ATTR_CMN_SCRIPT;
-#endif
- };
- if (a & ATTR_CMN_CRTIME) {
- catInfo->nodeData.cnd_createDate = to_hfs_time((UInt32)((struct timespec *)attrbufptr)->tv_sec);
- VTOH(vp)->h_meta->h_crtime = (UInt32)((struct timespec *)attrbufptr)->tv_sec;
- ++((struct timespec *)attrbufptr);
-#if HFS_DIAGNOSTIC
- a &= ~ATTR_CMN_CRTIME;
-#endif
- };
- if (a & ATTR_CMN_MODTIME) {
- catInfo->nodeData.cnd_contentModDate = to_hfs_time((UInt32)((struct timespec *)attrbufptr)->tv_sec);
- VTOH(vp)->h_meta->h_mtime = (UInt32)((struct timespec *)attrbufptr)->tv_sec;
- ++((struct timespec *)attrbufptr);
- hp->h_nodeflags &= ~IN_UPDATE;
-#if HFS_DIAGNOSTIC
- a &= ~ATTR_CMN_MODTIME;
-#endif
- };
- if (a & ATTR_CMN_CHGTIME) {
- catInfo->nodeData.cnd_attributeModDate = to_hfs_time((UInt32)((struct timespec *)attrbufptr)->tv_sec);
- VTOH(vp)->h_meta->h_ctime = (UInt32)((struct timespec *)attrbufptr)->tv_sec;
- ++((struct timespec *)attrbufptr);
- hp->h_nodeflags &= ~IN_CHANGE;
-#if HFS_DIAGNOSTIC
- a &= ~ATTR_CMN_CHGTIME;
-#endif
- };
- if (a & ATTR_CMN_ACCTIME) {
- catInfo->nodeData.cnd_accessDate = to_hfs_time((UInt32)((struct timespec *)attrbufptr)->tv_sec);
- VTOH(vp)->h_meta->h_atime = (UInt32)((struct timespec *)attrbufptr)->tv_sec;
- ++((struct timespec *)attrbufptr);
- hp->h_nodeflags &= ~IN_ACCESS;
-#if HFS_DIAGNOSTIC
- a &= ~ATTR_CMN_ACCTIME;
-#endif
- };
- if (a & ATTR_CMN_BKUPTIME) {
- catInfo->nodeData.cnd_backupDate = to_hfs_time((UInt32)((struct timespec *)attrbufptr)->tv_sec);
- VTOH(vp)->h_meta->h_butime = (UInt32)((struct timespec *)attrbufptr)->tv_sec;
- ++((struct timespec *)attrbufptr);
-#if HFS_DIAGNOSTIC
- a &= ~ATTR_CMN_BKUPTIME;
-#endif
- };
- if (a & ATTR_CMN_FNDRINFO) {
- bcopy (attrbufptr, &catInfo->nodeData.cnd_finderInfo, sizeof(catInfo->nodeData.cnd_finderInfo));
- (char *)attrbufptr += sizeof(catInfo->nodeData.cnd_finderInfo);
-#if HFS_DIAGNOSTIC
- a &= ~ATTR_CMN_FNDRINFO;
-#endif
- };
- if (a & ATTR_CMN_OWNERID) {
- if (VTOVCB(vp)->vcbSigWord == kHFSPlusSigWord) {
- u_int32_t uid = (u_int32_t)*((uid_t *)attrbufptr)++;
- if (uid != (uid_t)VNOVAL)
- hp->h_meta->h_uid = uid; /* catalog will get updated by hfs_chown() */
- }
- else {
- ((uid_t *)attrbufptr)++;
- }
-#if HFS_DIAGNOSTIC
- a &= ~ATTR_CMN_OWNERID;
-#endif
- };
- if (a & ATTR_CMN_GRPID) {
- u_int32_t gid = (u_int32_t)*((gid_t *)attrbufptr)++;
- if (VTOVCB(vp)->vcbSigWord == kHFSPlusSigWord) {
- if (gid != (gid_t)VNOVAL)
- hp->h_meta->h_gid = gid; /* catalog will get updated by hfs_chown() */
- };
-#if HFS_DIAGNOSTIC
- a &= ~ATTR_CMN_GRPID;
-#endif
- };
- if (a & ATTR_CMN_ACCESSMASK) {
- u_int16_t mode = (u_int16_t)*((u_long *)attrbufptr)++;
- if (VTOVCB(vp)->vcbSigWord == kHFSPlusSigWord) {
- if (mode != (mode_t)VNOVAL) {
- hp->h_meta->h_mode &= ~ALLPERMS;
- hp->h_meta->h_mode |= (mode & ALLPERMS); /* catalog will get updated by hfs_chmod() */
- }
- };
-#if HFS_DIAGNOSTIC
- a &= ~ATTR_CMN_ACCESSMASK;
-#endif
- };
- if (a & ATTR_CMN_FLAGS) {
- u_long flags = *((u_long *)attrbufptr)++;
- /* Flags are settable only on HFS+ volumes. A special exception is made for the IMMUTABLE
- flags (SF_IMMUTABLE and UF_IMMUTABLE), which can be set on HFS volumes as well: */
- if ((VTOVCB(vp)->vcbSigWord == kHFSPlusSigWord) ||
- ((VTOVCB(vp)->vcbSigWord == kHFSSigWord) && ((flags & ~IMMUTABLE) == 0))) {
- if (flags != (u_long)VNOVAL) {
- hp->h_meta->h_pflags = flags; /* catalog will get updated by hfs_chflags */
- };
- };
-#if HFS_DIAGNOSTIC
- a &= ~ATTR_CMN_FLAGS;
-#endif
- };
-
-#if HFS_DIAGNOSTIC
- if (a != 0) {
- DEBUG_BREAK_MSG(("UnpackCommonAttributes: unhandled bit: 0x%08X\n", a));
- };
-#endif
-
- *attrbufptrptr = attrbufptr;
-// *varbufptrptr = varbufptr;
-}
-
-
-
-#if 0
-void UnpackDirAttributeBlock(struct attrlist *alist,
- struct vnode *vp,
- struct hfsCatalogInfo *catInfo,
- void **attrbufptrptr,
- void **varbufptrptr) {
- void *attrbufptr;
- void *varbufptr;
- attrgroup_t a;
- u_long attrlength;
-
- attrbufptr = *attrbufptrptr;
- varbufptr = *varbufptrptr;
-
- /* XXX PPD TBC */
-
- *attrbufptrptr = attrbufptr;
- *varbufptrptr = varbufptr;
-}
-#endif
-
-
-
-#if 0
-void UnpackFileAttributeBlock(struct attrlist *alist,
- struct vnode *vp,
- struct hfsCatalogInfo *catInfo,
- void **attrbufptrptr,
- void **varbufptrptr) {
- void *attrbufptr;
- void *varbufptr;
- attrgroup_t a;
- u_long attrlength;
-
- attrbufptr = *attrbufptrptr;
- varbufptr = *varbufptrptr;
-
- /* XXX PPD TBC */
-
- *attrbufptrptr = attrbufptr;
- *varbufptrptr = varbufptr;
-}
-#endif
-
-
-
-#if 0
-void UnpackForkAttributeBlock(struct attrlist *alist,
- struct vnode *vp,
- struct hfsCatalogInfo *catInfo,
- void **attrbufptrptr,
- void **varbufptrptr) {
- void *attrbufptr;
- void *varbufptr;
- attrgroup_t a;
- u_long attrlength;
-
- attrbufptr = *attrbufptrptr;
- varbufptr = *varbufptrptr;
-
- /* XXX PPD TBC */
-
- *attrbufptrptr = attrbufptr;
- *varbufptrptr = varbufptr;
-}
-#endif
-
-
-
-void UnpackAttributeBlock(struct attrlist *alist,
- struct vnode *vp,
- struct hfsCatalogInfo *catInfo,
- void **attrbufptrptr,
- void **varbufptrptr) {
-
-
- if (alist->volattr != 0) {
- UnpackVolumeAttributeBlock(alist, vp, VTOVCB(vp), attrbufptrptr, varbufptrptr);
- return;
- };
-
- /* We're dealing with a vnode object here: */
- UnpackCommonAttributeBlock(alist, vp, catInfo, attrbufptrptr, varbufptrptr);
-
-#if 0
- switch (vp->v_type) {
- case VDIR:
- UnpackDirAttributeBlock(alist, vp, catInfo, attrbufptrptr, varbufptrptr);
- break;
-
- case VREG:
- /* case VCPLX: */ /* XXX PPD TBC */
- UnpackFileAttributeBlock(alist, vp, catInfo, attrbufptrptr, varbufptrptr);
- break;
-
- case VFORK:
- UnpackForkAttributeBlock(alist, vp, catInfo, attrbufptrptr, varbufptrptr);
- break;
-
- /* Without this the compiler complains about VNON,VBLK,VCHR,VLNK,VSOCK,VFIFO,VBAD and VSTR
- not being handled...
- */
- default:
- /* XXX PPD - Panic? */
- break;
- };
-#endif
-
-};
-
-
-unsigned long BestBlockSizeFit(unsigned long allocationBlockSize,
- unsigned long blockSizeLimit,
- unsigned long baseMultiple) {
- /*
- Compute the optimal (largest) block size (no larger than allocationBlockSize) that is less than the
- specified limit but still an even multiple of the baseMultiple.
- */
- int baseBlockCount, blockCount;
- unsigned long trialBlockSize;
-
- if (allocationBlockSize % baseMultiple != 0) {
- /*
- Whoops: the allocation blocks aren't even multiples of the specified base:
- no amount of dividing them into even parts will be a multiple, either then!
- */
- return 512; /* Hope for the best */
- };
-
- /* Try the obvious winner first, to prevent 12K allocation blocks, for instance,
- from being handled as two 6K logical blocks instead of 3 4K logical blocks.
- Even though the former (the result of the loop below) is the larger allocation
- block size, the latter is more efficient: */
- if (allocationBlockSize % PAGE_SIZE == 0) return PAGE_SIZE;
-
- /* No clear winner exists: pick the largest even fraction <= MAXBSIZE: */
- baseBlockCount = allocationBlockSize / baseMultiple; /* Now guaranteed to be an even multiple */
-
- for (blockCount = baseBlockCount; blockCount > 0; --blockCount) {
- trialBlockSize = blockCount * baseMultiple;
- if (allocationBlockSize % trialBlockSize == 0) { /* An even multiple? */
- if ((trialBlockSize <= blockSizeLimit) &&
- (trialBlockSize % baseMultiple == 0)) {
- return trialBlockSize;
- };
- };
- };