/* 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 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 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; }
/* read directory info */ static inline void* record_readDInfo(void *p, DInfo* info) { info->frRect.top = bswabU16_inc(p); info->frRect.left = bswabU16_inc(p); info->frRect.bottom = bswabU16_inc(p); info->frRect.right = bswabU16_inc(p); info->frFlags = bswabU16_inc(p); info->frLocation.v = bswabU16_inc(p); info->frLocation.h = bswabU16_inc(p); info->frView = bswabU16_inc(p); return p; }
/* 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; }
/* 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; }
/* 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_entry from memory */ static void* record_readentry(void *p, hfsp_cat_entry* entry) { UInt16 type = bswabU16_inc(p); entry->type = type; switch (type) { case HFSP_FOLDER: return record_readfolder(p, &entry->u.folder); case HFSP_FILE: return record_readfile (p, &entry->u.file); case HFSP_FOLDER_THREAD: case HFSP_FILE_THREAD: return record_readthread(p, &entry->u.thread); default: HFSP_ERROR(-1, "Unexpected record type in record_readentry"); } ; fail: return NULL; }