Annotation of qemu/roms/openbios/fs/hfsplus/hfsp_volume.c, revision 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.