Annotation of qemu/roms/openbios/fs/hfsplus/hfsp_volume.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * libhfs - library for reading and writing Macintosh HFS volumes
                      3:  *
                      4:  * Code to acces the basic volume information of a HFS+ volume.
                      5:  *
                      6:  * Copyright (C) 2000 Klaus Halfmann <[email protected]>
                      7:  * Original work by 1996-1998 Robert Leslie <[email protected]>
                      8:  * other work 2000 from Brad Boyer ([email protected])
                      9:  *
                     10:  * This program is free software; you can redistribute it and/or modify
                     11:  * it under the terms of the GNU General Public License as published by
                     12:  * the Free Software Foundation; either version 2 of the License, or
                     13:  * (at your option) any later version.
                     14:  *
                     15:  * This program is distributed in the hope that it will be useful,
                     16:  * but WITHOUT ANY WARRANTY; without even the implied warranty of
                     17:  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     18:  * GNU General Public License for more details.
                     19:  *
                     20:  * You should have received a copy of the GNU General Public License
                     21:  * along with this program; if not, write to the Free Software
                     22:  * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
                     23:  * MA 02110-1301, USA.
                     24:  *
                     25:  * $Id: volume.c,v 1.21 2000/10/25 05:43:04 hasi Exp $
                     26:  */
                     27: 
                     28: #include "config.h"
                     29: #include "libhfsp.h"
                     30: #include "volume.h"
                     31: #include "record.h"
                     32: #include "btree.h"
                     33: #include "blockiter.h"
                     34: #include "os.h"
                     35: #include "swab.h"
                     36: #include "hfstime.h"
                     37: 
                     38: 
                     39: /* Fill a given buffer with the given block in volume.
                     40:  */
                     41: int
                     42: volume_readinbuf(volume * vol,void* buf, long block)
                     43: {
                     44:        UInt16 blksize_bits;
                     45:        ASSERT( block < vol->maxblocks);
                     46: 
                     47:        blksize_bits = vol->blksize_bits;
                     48:        block   += vol->startblock;
                     49:        if( os_seek(vol->os_fd, block, blksize_bits) == block)
                     50:                if( 1 == os_read(vol->os_fd, buf, 1, blksize_bits))
                     51:                        return 0;
                     52:        return -1;
                     53: }
                     54: 
                     55: /* read multiple blocks into given memory.
                     56:  *
                     57:  * returns given pinter or NULL on failure.
                     58:  */
                     59: void*
                     60: volume_readfromfork(volume* vol, void* buf,
                     61:                hfsp_fork_raw* f, UInt32 block,
                     62:                UInt32 count, UInt8 forktype, UInt32 fileId)
                     63: {
                     64:        blockiter iter;
                     65:        char *cbuf = buf;
                     66: 
                     67:        blockiter_init(&iter, vol, f, forktype, fileId);
                     68:        if( blockiter_skip(&iter, block))
                     69:                return NULL;
                     70: 
                     71:        while( count > 0) {
                     72:                --count;
                     73:                if( volume_readinbuf(vol, cbuf, blockiter_curr(&iter)))
                     74:                        return NULL;
                     75:                cbuf += vol->blksize;
                     76:                if( count > 0 && blockiter_next(&iter))
                     77:                        return NULL;
                     78:        }
                     79:        return buf;
                     80: }
                     81: 
                     82: 
                     83: /* Read a raw hfsp_extent_rec from memory.
                     84:  *
                     85:  * return pointer right after the structure.
                     86:  */
                     87: void*
                     88: volume_readextent(void *p, hfsp_extent_rec er)
                     89: {
                     90:        int             i;
                     91:        hfsp_extent     *e;
                     92: 
                     93:        for( i=0; i < 8; i++) {
                     94:                e = &er[i];
                     95:                e->start_block = bswabU32_inc(p);
                     96:                e->block_count = bswabU32_inc(p);
                     97:        }
                     98:        return p;
                     99: }
                    100: 
                    101: /* Read a raw hfsp_fork from memory.
                    102:  *
                    103:  * return pointer right after the structure.
                    104:  */
                    105: void*
                    106: volume_readfork(void *p, hfsp_fork_raw* f)
                    107: {
                    108:        f->total_size   = bswabU64_inc(p);
                    109:        f->clump_size   = bswabU32_inc(p);
                    110:        f->total_blocks = bswabU32_inc(p);
                    111: 
                    112:        return volume_readextent(p, f->extents);
                    113: }
                    114: 
                    115: /* Read the volume from the given buffer and swap the bytes.
                    116:  *
                    117:  * ToDo: add more consitency checks.
                    118:  */
                    119: static int
                    120: volume_readbuf(hfsp_vh* vh, char * p)
                    121: {
                    122:        if(  (vh->signature = bswabU16_inc(p)) != HFSP_VOLHEAD_SIG)
                    123:                HFSP_ERROR(-1, "This is not a HFS+ volume");
                    124: 
                    125:        vh->version             = bswabU16_inc(p);
                    126:        vh->attributes          = bswabU32_inc(p);
                    127:        vh->last_mount_vers     = bswabU32_inc(p);
                    128:        vh->reserved            = bswabU32_inc(p);
                    129:        vh->create_date         = bswabU32_inc(p);
                    130:        vh->modify_date         = bswabU32_inc(p);
                    131:        vh->backup_date         = bswabU32_inc(p);
                    132:        vh->checked_date        = bswabU32_inc(p);
                    133:        vh->file_count          = bswabU32_inc(p);
                    134:        vh->folder_count        = bswabU32_inc(p);
                    135:        vh->blocksize           = bswabU32_inc(p);
                    136:        vh->total_blocks        = bswabU32_inc(p);
                    137:        vh->free_blocks         = bswabU32_inc(p);
                    138:        vh->next_alloc          = bswabU32_inc(p);
                    139:        vh->rsrc_clump_sz       = bswabU32_inc(p);
                    140:        vh->data_clump_sz       = bswabU32_inc(p);
                    141:        vh->next_cnid           = bswabU32_inc(p);
                    142:        vh->write_count         = bswabU32_inc(p);
                    143:        vh->encodings_bmp       = bswabU64_inc(p);
                    144:        memcpy(vh->finder_info, p, 32);
                    145:        p += 32; // So finderinfo must be swapped later, ***
                    146:        p = volume_readfork(p, &vh->alloc_file );
                    147:        p = volume_readfork(p, &vh->ext_file   );
                    148:        p = volume_readfork(p, &vh->cat_file   );
                    149:        p = volume_readfork(p, &vh->attr_file  );
                    150:         volume_readfork(p, &vh->start_file );
                    151:        return 0;
                    152:   fail:
                    153:        return -1;
                    154: }
                    155: 
                    156: /* Read the volume from the given block */
                    157: static int
                    158: volume_read(volume * vol, hfsp_vh* vh, UInt32 block)
                    159: {
                    160:        char buf[vol->blksize];
                    161: 
                    162:        if( volume_readinbuf(vol, buf, block))
                    163:                return -1;
                    164:         return volume_readbuf(vh, buf);
                    165: }
                    166: 
                    167: /* Find out wether the volume is wrapped and unwrap it eventually */
                    168: static int
                    169: volume_read_wrapper(volume * vol, hfsp_vh* vh)
                    170: {
                    171:        UInt16  signature;
                    172:        char    buf[vol->blksize];
                    173:         char    *p = buf;
                    174: 
                    175:        if( volume_readinbuf(vol, buf, 2) ) // Wrapper or volume header starts here
                    176:                return -1;
                    177: 
                    178:        signature = bswabU16_inc(p);
                    179:        if( signature == HFS_VOLHEAD_SIG) {             /* Wrapper */
                    180:                UInt32  drAlBlkSiz;                     /* size (in bytes) of allocation blocks */
                    181:                UInt32  sect_per_block;                 /* how may block build an hfs sector */
                    182:                UInt16  drAlBlSt;                       /* first allocation block in volume */
                    183:                UInt16  embeds, embedl;                 /* Start/lenght of embedded area in blocks */
                    184: 
                    185:                p += 0x12;                      /* skip unneded HFS vol fields */
                    186:                drAlBlkSiz = bswabU32_inc(p);           /* offset 0x14 */
                    187:                p += 0x4;                       /* skip unneded HFS vol fields */
                    188:                drAlBlSt = bswabU16_inc(p);             /* offset 0x1C */
                    189: 
                    190:                p += 0x5E;                      /* skip unneded HFS vol fields */
                    191:                signature = bswabU16_inc(p);            /* offset 0x7C, drEmbedSigWord */
                    192:                if( signature != HFSP_VOLHEAD_SIG)
                    193:                        HFSP_ERROR(-1, "This looks like a normal HFS volume");
                    194:                embeds = bswabU16_inc(p);
                    195:                embedl = bswabU16_inc(p);
                    196:                sect_per_block =  (drAlBlkSiz / HFSP_BLOCKSZ);
                    197:                // end is absolute (not relative to HFS+ start)
                    198:                vol->maxblocks = embedl * sect_per_block;
                    199:                vol->startblock = drAlBlSt + embeds * sect_per_block;
                    200:                /* Now we can try to read the embedded HFS+ volume header */
                    201:                return volume_read(vol,vh,2);
                    202:        }
                    203:        else if( signature == HFSP_VOLHEAD_SIG) { /* Native HFS+ volume */
                    204:                p = buf; // Restore to begin of block
                    205:                 return volume_readbuf(vh, p);
                    206:        } else
                    207:                 HFSP_ERROR(-1, "Neither Wrapper nor native HFS+ volume header found");
                    208: fail:
                    209:        return -1;
                    210: }
                    211: 
                    212: 
                    213: /* Open the device, read and verify the volume header
                    214:    (and its backup) */
                    215: int
                    216: volume_open( volume* vol, int os_fd )
                    217: {
                    218:        hfsp_vh backup; /* backup volume found at second to last block */
                    219:        long    sect_per_block;
                    220:        int     shift;
                    221: 
                    222:        vol->blksize_bits       = HFSP_BLOCKSZ_BITS;
                    223:        vol->blksize            = HFSP_BLOCKSZ;
                    224:        vol->startblock         = 0;
                    225:        vol->maxblocks          = 3;
                    226:                /* this should be enough until we find the volume descriptor */
                    227:        vol->extents            = NULL; /* Thanks to Jeremias Sauceda */
                    228: 
                    229:        btree_reset(&vol->catalog);
                    230:        vol->os_fd = os_fd;
                    231: 
                    232:        // vol->maxblocks = os_seek(vol->os_fd, -1, HFSP_BLOCKSZ_BITS);
                    233:        // This wont work for /dev/... but we do not really need it
                    234: 
                    235:        if( volume_read_wrapper(vol, &vol->vol))
                    236:                return -1;
                    237:        if( volume_read(vol, &backup, vol->maxblocks - 2))
                    238:                return -1;
                    239: 
                    240:        /* Now switch blksize from HFSP_BLOCKSZ (512) to value given in header
                    241:           and adjust depend values accordingly, after that a block always
                    242:           means a HFS+ allocation size */
                    243: 
                    244:        /* Usually 4096 / 512  == 8 */
                    245:        sect_per_block = vol->vol.blocksize / HFSP_BLOCKSZ;
                    246:        shift = 0;
                    247:        if( sect_per_block > 1) {
                    248:                shift = 1;
                    249:                while( sect_per_block > 2) {
                    250:                        sect_per_block >>=1;
                    251:                        shift++;
                    252:                }               /* shift = 3 */
                    253:        }
                    254:        vol -> blksize_bits += shift;
                    255:        vol -> blksize = 1 << vol->blksize_bits;
                    256:        vol -> startblock >>= shift;
                    257:        vol -> maxblocks = vol->vol.total_blocks;       /* cant calculate via shift ? */
                    258: 
                    259:        if( btree_init_cat(&vol->catalog, vol, &vol->vol.cat_file))
                    260:                return -1;
                    261: 
                    262:        return 0;
                    263: }
                    264: 
                    265: /* Write back all data eventually cached and close the device */
                    266: int
                    267: volume_close(volume* vol)
                    268: {
                    269:        btree_close(&vol->catalog);
                    270:        if( vol->extents) {
                    271:                btree_close(vol->extents);
                    272:                FREE(vol->extents);
                    273:        }
                    274:        return 0;
                    275: }
                    276: 
                    277: /* internal fucntion used to create the extents btree,
                    278:    is called by inline function when needed */
                    279: void
                    280: volume_create_extents_tree(volume* vol)
                    281: {
                    282:        btree* result = (btree*) ALLOC(btree*, sizeof(btree));
                    283:        if( !result)
                    284:                HFSP_ERROR(ENOMEM, "No memory for extents btree");
                    285:        if( !btree_init_extent(result, vol, &vol->vol.ext_file)) {
                    286:                vol->extents = result;
                    287:                return;
                    288:        }
                    289:   fail:
                    290:        vol->extents = NULL;
                    291: }
                    292: 
                    293: /* Determine whether the volume is a HFS-plus volume */
                    294: int
                    295: volume_probe(int fd, long long offset)
                    296: {
                    297:        UInt16 *vol;
                    298:        int ret = 0;
                    299: 
                    300:        vol = (UInt16 *)malloc(2 * 1 << HFSP_BLOCKSZ_BITS);
                    301:        os_seek_offset( fd, 2 * (1 << HFSP_BLOCKSZ_BITS) + offset );
                    302:        os_read(fd, vol, 2, HFSP_BLOCKSZ_BITS);
                    303: 
                    304:        if (__be16_to_cpu(vol[0]) == HFS_VOLHEAD_SIG &&
                    305:                __be16_to_cpu(vol[0x7c]) == HFSP_VOLHEAD_SIG) {
                    306:                ret = -1;
                    307:        } else if (__be16_to_cpu(vol[0]) == HFSP_VOLHEAD_SIG) {
                    308:                ret = -1;
                    309:        }
                    310: 
                    311:        free(vol);
                    312:        return ret;
                    313: }
                    314: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.