/* Read the volume from the given block */ static int volume_read(volume * vol, hfsp_vh* vh, UInt32 block) { char buf[vol->blksize]; if( volume_readinbuf(vol, buf, block)) return -1; return volume_readbuf(vh, buf); }
/* ( buf len -- actlen ) */ static void hfsp_files_read( hfsp_info_t *mi ) { int count = POP(); char *buf = (char *)cell2pointer(POP()); hfsp_file_t *t = mi->hfspfile; volume *vol = t->rec.tree->vol; UInt32 blksize = vol->blksize; hfsp_cat_file *file = &t->rec.record.u.file; blockiter iter; char buf2[blksize]; int act_count, curpos=0; blockiter_init( &iter, vol, &file->data_fork, HFSP_EXTENT_DATA, file->id ); while( curpos + blksize < t->pos ) { if( blockiter_next( &iter ) ) { RET ( -1 ); return; } curpos += blksize; } act_count = 0; while( act_count < count ){ UInt32 block = blockiter_curr(&iter); int max = blksize, add = 0, size; if( volume_readinbuf( vol, buf2, block ) ) break; if( curpos < t->pos ){ add += t->pos - curpos; max -= t->pos - curpos; } size = (count-act_count > max)? max : count-act_count; memcpy( (char *)buf + act_count, &buf2[add], size ); curpos += blksize; act_count += size; if( blockiter_next( &iter ) ) break; } t->pos += act_count; RET ( act_count ); }
/* 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 multiple blocks into given memory. * * returns given pinter or NULL on failure. */ void* volume_readfromfork(volume* vol, void* buf, hfsp_fork_raw* f, UInt32 block, UInt32 count, UInt8 forktype, UInt32 fileId) { blockiter iter; char *cbuf = buf; blockiter_init(&iter, vol, f, forktype, fileId); if( blockiter_skip(&iter, block)) return NULL; while( count > 0) { --count; if( volume_readinbuf(vol, cbuf, blockiter_curr(&iter))) return NULL; cbuf += vol->blksize; if( count > 0 && blockiter_next(&iter)) return NULL; } return buf; }
/* ( addr -- size ) */ static void hfsp_files_load( hfsp_info_t *mi ) { char *buf = (char *)cell2pointer(POP()); hfsp_file_t *t = mi->hfspfile; volume *vol = t->rec.tree->vol; UInt32 blksize = vol->blksize; hfsp_cat_file *file = &t->rec.record.u.file; int total = file->data_fork.total_size; blockiter iter; char buf2[blksize]; int act_count; blockiter_init( &iter, vol, &file->data_fork, HFSP_EXTENT_DATA, file->id ); act_count = 0; while( act_count < total ){ UInt32 block = blockiter_curr(&iter); int max = blksize, size; if( volume_readinbuf( vol, buf2, block ) ) break; size = (total-act_count > max)? max : total-act_count; memcpy( (char *)buf + act_count, &buf2, size ); act_count += size; if( blockiter_next( &iter ) ) break; } RET ( act_count ); }