/* read posix permission from memory */ static inline void* record_readperm(void *p, hfsp_perm* perm) { perm->owner= bswabU32_inc(p); perm->group= bswabU32_inc(p); perm->mode = bswabU32_inc(p); perm->dev = bswabU32_inc(p); return p; }
/* read posix permission from memory */ static inline char* record_readperm(char *p, hfsp_perm* perm) { perm->owner= bswabU32_inc(&p); perm->group= bswabU32_inc(&p); perm->mode = bswabU32_inc(&p); perm->dev = bswabU32_inc(&p); return p; }
/* Read a raw hfsp_fork from memory. * * return pointer right after the structure. */ void* volume_readfork(void *p, hfsp_fork_raw* f) { f->total_size = bswabU64_inc(p); f->clump_size = bswabU32_inc(p); f->total_blocks = bswabU32_inc(p); return volume_readextent(p, f->extents); }
/* read extra Directory info */ static inline void* record_readDXInfo(void *p, DXInfo* xinfo) { xinfo->frScroll.v = bswabU16_inc(p); xinfo->frScroll.h = bswabU16_inc(p); xinfo->frOpenChain = bswabU32_inc(p); xinfo->frUnused = bswabU16_inc(p); xinfo->frComment = bswabU16_inc(p); xinfo->frPutAway = bswabU32_inc(p); return p; }
/* read file info */ static inline void* record_readFInfo(void *p, FInfo* info) { info->fdType = bswabU32_inc(p); info->fdCreator = bswabU32_inc(p); info->fdFlags = bswabU16_inc(p); info->fdLocation.v = bswabU16_inc(p); info->fdLocation.h = bswabU16_inc(p); info->fdFldr = bswabU16_inc(p); return p; }
/* Read a raw hfsp_extent_rec from memory. * * return pointer right after the structure. */ void* volume_readextent(void *p, hfsp_extent_rec er) { int i; hfsp_extent *e; for( i=0; i < 8; i++) { e = &er[i]; e->start_block = bswabU32_inc(p); e->block_count = bswabU32_inc(p); } return p; }
/* read a hfsp_extent_key from memory */ void* record_extent_readkey(void* p, void* buf) { hfsp_extent_key* key = (hfsp_extent_key*) buf; UInt16 key_length; key->key_length = key_length = bswabU16_inc(p); key->fork_type = bswabU8_inc(p); key->filler = bswabU8_inc(p); if (key_length != 10) HFSP_ERROR(-1, "Invalid key length in record_extent_readkey"); key->file_id = bswabU32_inc(p); key->start_block = bswabU32_inc(p); return p; fail: return NULL; }
/* Position node in btree so that key might be inside */ static node_buf* record_find_node(btree* tree, void *key) { int start, end, mid, comp; // components of a binary search void *p = NULL; char curr_key[tree->head.max_key_len]; // The current key under examination hfsp_key_read readkey = tree->kread; hfsp_key_compare key_compare = tree->kcomp; UInt32 index; node_buf* node = btree_node_by_index(tree, tree->head.root); if (!node) HFSP_ERROR(-1, "record_find_node: Cant position to root node"); while (node->desc.kind == HFSP_NODE_NDX) { mid = start = 0; end = node->desc.num_rec; comp = -1; while (start < end) { mid = (start + end) >> 1; p = btree_key_by_index(tree, node, mid); if (!p) HFSP_ERROR(-1, "record_find_node: unexpected error"); p = readkey (p, curr_key); if (!p) HFSP_ERROR(-1, "record_find_node: unexpected error"); comp = key_compare(curr_key, key); if (comp > 0) start = mid + 1; else if (comp < 0) end = mid; else break; } if (!p) // Empty tree, fascinating ... HFSP_ERROR(-1, "record_find_node: unexpected empty node"); if (comp < 0) // mmh interesting key is before this key ... { if (mid == 0) return NULL; // nothing before this key .. p = btree_key_by_index(tree, node, mid-1); if (!p) HFSP_ERROR(-1, "record_find_node: unexpected error"); p = readkey (p, curr_key); if (!p) HFSP_ERROR(-1, "record_find_node: unexpected error"); } index = bswabU32_inc(p); node = btree_node_by_index(tree, index); } return node; // go on and use the found node fail: return NULL; }
/* read extra File info */ static inline void* record_readFXInfo(void *p, FXInfo* xinfo) { SInt16 *q; xinfo->fdIconID = bswabU16_inc(p); q=(SInt16*) p; q+=4; // skip unused p=(void *)q; xinfo->fdComment = bswabU16_inc(p); xinfo->fdPutAway = bswabU32_inc(p); return p; }
/* read extra File info */ static inline char* record_readFXInfo(char *p, FXInfo* xinfo) { xinfo->fdIconID = bswabU16_inc(&p); xinfo->fdUnused[0] = bswabU16_inc(&p); xinfo->fdUnused[1] = bswabU16_inc(&p); xinfo->fdUnused[2] = bswabU16_inc(&p); xinfo->fdUnused[3] = bswabU16_inc(&p); xinfo->fdComment = bswabU16_inc(&p); xinfo->fdPutAway = bswabU32_inc(&p); return p; }
/* read a hfsp_cat_folder from memory */ static void* record_readfolder(void *p, hfsp_cat_folder* folder) { folder->flags = bswabU16_inc(p); folder->valence = bswabU32_inc(p); folder->id = bswabU32_inc(p); folder->create_date = bswabU32_inc(p); folder->content_mod_date = bswabU32_inc(p); folder->attribute_mod_date = bswabU32_inc(p); folder->access_date = bswabU32_inc(p); folder->backup_date = bswabU32_inc(p); p = record_readperm (p, &folder->permissions); p = record_readDInfo (p, &folder->user_info); p = record_readDXInfo (p, &folder->finder_info); folder->text_encoding = bswabU32_inc(p); folder->reserved = bswabU32_inc(p); return p; }
/* read a hfsp_cat_file from memory */ static void* record_readfile(void *p, hfsp_cat_file* file) { file->flags = bswabU16_inc(p); file->reserved1 = bswabU32_inc(p); file->id = bswabU32_inc(p); file->create_date = bswabU32_inc(p); file->content_mod_date = bswabU32_inc(p); file->attribute_mod_date = bswabU32_inc(p); file->access_date = bswabU32_inc(p); file->backup_date = bswabU32_inc(p); p = record_readperm (p, &file->permissions); p = record_readFInfo (p, &file->user_info); p = record_readFXInfo (p, &file->finder_info); file->text_encoding = bswabU32_inc(p); file->reserved2 = bswabU32_inc(p); p = volume_readfork (p, &file->data_fork); return volume_readfork (p, &file->res_fork); }
/* read a hfsp_cat_thread from memory */ static void* record_readthread(void *p, hfsp_cat_thread* entry) { int i; UInt16 len; UInt16* cp; entry-> reserved = bswabU16_inc(p); entry-> parentID = bswabU32_inc(p); entry->nodeName.strlen = len= bswabU16_inc(p); cp = entry->nodeName.name; if (len > 255) HFSP_ERROR(-1, "Invalid key length in record thread"); for (i=0; i < len; i++, cp++) *cp = bswabU16_inc(p); return p; fail: return NULL; }
/* Find out wether the volume is wrapped and unwrap it eventually */ static int volume_read_wrapper(volume * vol, hfsp_vh* vh) { UInt16 signature; char buf[vol->blksize]; char *p = buf; if( volume_readinbuf(vol, buf, 2) ) // Wrapper or volume header starts here return -1; signature = bswabU16_inc(p); if( signature == HFS_VOLHEAD_SIG) { /* Wrapper */ UInt32 drAlBlkSiz; /* size (in bytes) of allocation blocks */ UInt32 sect_per_block; /* how may block build an hfs sector */ UInt16 drAlBlSt; /* first allocation block in volume */ UInt16 embeds, embedl; /* Start/lenght of embedded area in blocks */ p += 0x12; /* skip unneded HFS vol fields */ drAlBlkSiz = bswabU32_inc(p); /* offset 0x14 */ p += 0x4; /* skip unneded HFS vol fields */ drAlBlSt = bswabU16_inc(p); /* offset 0x1C */ p += 0x5E; /* skip unneded HFS vol fields */ signature = bswabU16_inc(p); /* offset 0x7C, drEmbedSigWord */ if( signature != HFSP_VOLHEAD_SIG) HFSP_ERROR(-1, "This looks like a normal HFS volume"); embeds = bswabU16_inc(p); embedl = bswabU16_inc(p); sect_per_block = (drAlBlkSiz / HFSP_BLOCKSZ); // end is absolute (not relative to HFS+ start) vol->maxblocks = embedl * sect_per_block; vol->startblock = drAlBlSt + embeds * sect_per_block; /* Now we can try to read the embedded HFS+ volume header */ return volume_read(vol,vh,2); } else if( signature == HFSP_VOLHEAD_SIG) { /* Native HFS+ volume */ p = buf; // Restore to begin of block return volume_readbuf(vh, p); } else HFSP_ERROR(-1, "Neither Wrapper nor native HFS+ volume header found"); fail: return -1; }
/* read a hfsp_cat_key from memory */ void* record_readkey(void* p, void* buf) { hfsp_cat_key* key = (hfsp_cat_key*) buf; const void* check; UInt16 key_length, len,i; UInt16* cp; key->key_length = key_length = bswabU16_inc(p); check = p; key->parent_cnid = bswabU32_inc(p); key->name.strlen = len = bswabU16_inc(p); cp = key->name.name; for (i=0; i < len; i++, cp++) *cp = bswabU16_inc(p); /* check if keylenght was correct */ if (key_length != ((char*) p) - ((char*) check)) HFSP_ERROR(EINVAL, "Invalid key length in record_readkey"); return p; fail: return NULL; }
/* Read the volume from the given buffer and swap the bytes. * * ToDo: add more consitency checks. */ static int volume_readbuf(hfsp_vh* vh, char * p) { if( (vh->signature = bswabU16_inc(p)) != HFSP_VOLHEAD_SIG) HFSP_ERROR(-1, "This is not a HFS+ volume"); vh->version = bswabU16_inc(p); vh->attributes = bswabU32_inc(p); vh->last_mount_vers = bswabU32_inc(p); vh->reserved = bswabU32_inc(p); vh->create_date = bswabU32_inc(p); vh->modify_date = bswabU32_inc(p); vh->backup_date = bswabU32_inc(p); vh->checked_date = bswabU32_inc(p); vh->file_count = bswabU32_inc(p); vh->folder_count = bswabU32_inc(p); vh->blocksize = bswabU32_inc(p); vh->total_blocks = bswabU32_inc(p); vh->free_blocks = bswabU32_inc(p); vh->next_alloc = bswabU32_inc(p); vh->rsrc_clump_sz = bswabU32_inc(p); vh->data_clump_sz = bswabU32_inc(p); vh->next_cnid = bswabU32_inc(p); vh->write_count = bswabU32_inc(p); vh->encodings_bmp = bswabU64_inc(p); memcpy(vh->finder_info, p, 32); p += 32; // So finderinfo must be swapped later, *** p = volume_readfork(p, &vh->alloc_file ); p = volume_readfork(p, &vh->ext_file ); p = volume_readfork(p, &vh->cat_file ); p = volume_readfork(p, &vh->attr_file ); p = volume_readfork(p, &vh->start_file ); return 0; fail: return -1; }