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

1.1       root        1: /*
                      2:  * libhfs - library for reading and writing Macintosh HFS volumes
                      3:  * The fucntions are used to handle the various forms of btrees
                      4:  * found on HFS+ volumes.
                      5:  *
                      6:  * The fucntions are used to handle the various forms of btrees
                      7:  * found on HFS+ volumes.
                      8:  *
                      9:  * Copyright (C) 2000 Klaus Halfmann <[email protected]>
                     10:  * Original 1996-1998 Robert Leslie <[email protected]>
                     11:  * Additional work by  Brad Boyer ([email protected])
                     12:  *
                     13:  * This program is free software; you can redistribute it and/or modify
                     14:  * it under the terms of the GNU General Public License as published by
                     15:  * the Free Software Foundation; either version 2 of the License, or
                     16:  * (at your option) any later version.
                     17:  *
                     18:  * This program is distributed in the hope that it will be useful,
                     19:  * but WITHOUT ANY WARRANTY; without even the implied warranty of
                     20:  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     21:  * GNU General Public License for more details.
                     22:  *
                     23:  * You should have received a copy of the GNU General Public License
                     24:  * along with this program; if not, write to the Free Software
                     25:  * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
                     26:  * MA 02110-1301, USA.
                     27:  *
                     28:  * $Id: btree.c,v 1.14 2000/10/25 05:43:04 hasi Exp $
                     29:  */
                     30: 
                     31: #include "config.h"
                     32: #include "libhfsp.h"
                     33: #include "volume.h"
                     34: #include "btree.h"
                     35: #include "record.h"
                     36: #include "swab.h"
                     37: 
                     38: /* Read the node from the given buffer and swap the bytes.
                     39:  *
                     40:  * return pointer after reading the structure
                     41:  */
                     42: static void* btree_readnode(btree_node_desc* node, void *p)
                     43: {
                     44:     node->next     = bswabU32_inc(p);
                     45:     node->prev     = bswabU32_inc(p);
                     46:     node->kind     = bswabU8_inc(p);
                     47:     node->height    = bswabU8_inc(p);
                     48:     node->num_rec   = bswabU16_inc(p);
                     49:     node->reserved  = bswabU16_inc(p);
                     50:     return p;
                     51: }
                     52: 
                     53: /* read a btree header from the given buffer and swap the bytes.
                     54:  *
                     55:  * return pointer after reading the structure
                     56:  */
                     57: static void* btree_readhead(btree_head* head, void *p)
                     58: {
                     59:        UInt32 *q;
                     60:         head->depth        = bswabU16_inc(p);
                     61:         head->root         = bswabU32_inc(p);
                     62:         head->leaf_count    = bswabU32_inc(p);
                     63:         head->leaf_head            = bswabU32_inc(p);
                     64:         head->leaf_tail            = bswabU32_inc(p);
                     65:         head->node_size            = bswabU16_inc(p);
                     66:         head->max_key_len   = bswabU16_inc(p);
                     67:         head->node_count    = bswabU32_inc(p);
                     68:         head->free_nodes    = bswabU32_inc(p);
                     69:         head->reserved1            = bswabU16_inc(p);
                     70:         head->clump_size    = bswabU32_inc(p);
                     71:         head->btree_type    = bswabU8_inc(p);
                     72:         head->reserved2            = bswabU8_inc(p);
                     73:         head->attributes    = bswabU32_inc(p);
                     74:            // skip reserved bytes
                     75:        q=((UInt32*) p);
                     76:        // ((UInt32*) p) += 16;
                     77:        q+=16;
                     78:        return q;
                     79: }
                     80: 
                     81: /* Priority of the depth of the node compared to LRU value.
                     82:  * Should be the average number of keys per node but these vary. */
                     83: #define DEPTH_FACTOR   1000
                     84: 
                     85: /* Cache size is height of tree + this value
                     86:  * Really big numbers wont help in case of ls -R
                     87:  */
                     88: #define EXTRA_CACHESIZE        3
                     89: 
                     90: /* Not in use by now ... */
                     91: #define CACHE_DIRTY 0x0001
                     92: 
                     93: /* Intialize cache with default cache Size,
                     94:  * must call node_cache_close to deallocate memory */
                     95: static int node_cache_init(node_cache* cache, btree* tree, int size)
                     96: {
                     97:     int nodebufsize;
                     98:     char * buf;
                     99: 
                    100:     cache->size                = size;
                    101:     cache->currindex   = 0;
                    102:     nodebufsize = tree->head.node_size + sizeof(node_buf);
                    103:     buf = malloc(size *(sizeof(node_entry) + nodebufsize));
                    104:     if (!buf)
                    105:        return -1;
                    106:     cache -> nodebufsize = nodebufsize;
                    107:     cache -> entries = (node_entry*) buf;
                    108:     cache -> buffers = (char*) &cache->entries[size];
                    109:     bzero(cache->entries, size*sizeof(node_entry));
                    110:     return 0;
                    111: }
                    112: 
                    113: /* Like cache->buffers[i], since size of node_buf is variable */
                    114: static inline node_buf* node_buf_get(node_cache* cache, int i)
                    115: {
                    116:     return (node_buf*) (cache->buffers + (i * cache->nodebufsize));
                    117: }
                    118: 
                    119: /* flush the node at index */
                    120: static void node_cache_flush_node(node_cache* cache, int index)
                    121: {
                    122:     // NYI
                    123:     cache -> entries[index].index = 0; // invalidate entry
                    124: }
                    125: 
                    126: static void node_cache_close(node_cache* cache)
                    127: {
                    128:     if (!cache->entries) // not (fully) intialized ?
                    129:        return;
                    130:     free(cache->entries);
                    131: }
                    132: 
                    133: /* Load the cach node indentified by index with
                    134:  * the node identified by node_index */
                    135: 
                    136: static node_buf* node_cache_load_buf
                    137:     (btree* bt, node_cache* cache, int index, UInt16 node_index)
                    138: {
                    139:     node_buf   *result     = node_buf_get(cache ,index);
                    140:     UInt32     blkpernode  = bt->blkpernode;
                    141:     UInt32     block       = node_index * blkpernode;
                    142:     void*      p           = volume_readfromfork(bt->vol, result->node, bt->fork,
                    143:                             block, blkpernode, HFSP_EXTENT_DATA, bt->cnid);
                    144:     node_entry *e          = &cache->entries[index];
                    145: 
                    146:     if (!p)
                    147:        return NULL;    // evil ...
                    148: 
                    149:     result->index   = node_index;
                    150:     btree_readnode(&result->desc, p);
                    151: 
                    152:     e -> priority   = result->desc.height * DEPTH_FACTOR;
                    153:     e -> index     = node_index;
                    154:     return result;
                    155: }
                    156: 
                    157: /* Read node at given index, using cache.
                    158:  */
                    159: node_buf* btree_node_by_index(btree* bt, UInt16 index)
                    160: {
                    161:     node_cache*        cache = &bt->cache;
                    162:     int                oldindex, lruindex;
                    163:     int                currindex = cache->currindex;
                    164:     UInt32     prio;
                    165:     node_entry *e;
                    166: 
                    167:     // Shortcut acces to current node, will not change priorities
                    168:     if (cache->entries[currindex].index == index)
                    169:        return node_buf_get(cache ,currindex);
                    170:     oldindex = currindex;
                    171:     if (currindex == 0)
                    172:        currindex = cache->size;
                    173:     currindex--;
                    174:     lruindex = oldindex;           // entry to be flushed when needed
                    175:     prio     = 0;                  // current priority
                    176:     while (currindex != oldindex)   // round robin
                    177:     {
                    178:        e = &cache->entries[currindex];
                    179:        if (e->index == index)      // got it
                    180:        {
                    181:            if (e->priority != 0)   // already top, uuh
                    182:                e->priority--;
                    183:            cache->currindex = currindex;
                    184:            return node_buf_get(cache ,currindex);
                    185:        }
                    186:        else
                    187:        {
                    188:            if (!e->index)
                    189:            {
                    190:                lruindex = currindex;
                    191:                break;  // empty entry, load it
                    192:            }
                    193:            if (e->priority != UINT_MAX) // already least, uuh
                    194:                e->priority++;
                    195:        }
                    196:        if (prio < e->priority)
                    197:        {
                    198:            lruindex = currindex;
                    199:            prio = e->priority;
                    200:        }
                    201:        if (currindex == 0)
                    202:            currindex = cache->size;
                    203:        currindex--;
                    204:     }
                    205:     e = &cache->entries[lruindex];
                    206:     cache->currindex = lruindex;
                    207:     if (e->flags & CACHE_DIRTY)
                    208:            node_cache_flush_node(    cache, lruindex);
                    209:     return node_cache_load_buf  (bt, cache, lruindex, index);
                    210: }
                    211: 
                    212: /** intialize the btree with the first entry in the fork */
                    213: static int btree_init(btree* bt, volume* vol, hfsp_fork_raw* fork)
                    214: {
                    215:     void           *p;
                    216:     char           buf[vol->blksize];
                    217:     UInt16         node_size;
                    218:     btree_node_desc node;
                    219: 
                    220:     bt->vol    = vol;
                    221:     bt->fork   = fork;
                    222:     p  = volume_readfromfork(vol, buf, fork, 0, 1,
                    223:                 HFSP_EXTENT_DATA, bt->cnid);
                    224:     if (!p)
                    225:        return -1;
                    226:     p = btree_readnode(&node, p);
                    227:     if (node.kind != HFSP_NODE_HEAD)
                    228:        return -1;   // should not happen ?
                    229:     btree_readhead(&bt->head, p);
                    230: 
                    231:     node_size = bt->head.node_size;
                    232:     bt->blkpernode = node_size / vol->blksize;
                    233: 
                    234:     if (bt->blkpernode == 0 || vol->blksize *
                    235:            bt->blkpernode != node_size)
                    236:        return -1;  // should never happen ...
                    237: 
                    238:     node_cache_init(&bt->cache, bt, bt->head.depth + EXTRA_CACHESIZE);
                    239: 
                    240:     // Allocate buffer
                    241:     // bt->buf = malloc(node_size);
                    242:     // if (!bt->buf)
                    243:     // return ENOMEM;
                    244: 
                    245:     return 0;
                    246: }
                    247: 
                    248: /** Intialize catalog btree, so that btree_close can safely be called. */
                    249: void btree_reset(btree* bt)
                    250: {
                    251:     bt->cache.entries = NULL;
                    252: }
                    253: 
                    254: /** Intialize catalog btree */
                    255: int btree_init_cat(btree* bt, volume* vol, hfsp_fork_raw* fork)
                    256: {
                    257:     int result = btree_init(bt,vol,fork);      // super (...)
                    258:     bt->cnid  = HFSP_CAT_CNID;
                    259:     bt->kcomp = record_key_compare;
                    260:     bt->kread = record_readkey;
                    261:     return result;
                    262: }
                    263: 
                    264: /** Intialize catalog btree */
                    265: int btree_init_extent(btree* bt, volume* vol, hfsp_fork_raw* fork)
                    266: {
                    267:     int result = btree_init(bt,vol,fork);      // super (...)
                    268:     bt->cnid  = HFSP_EXT_CNID;
                    269:     bt->kcomp = record_extent_key_compare;
                    270:     bt->kread = record_extent_readkey;
                    271:     return result;
                    272: }
                    273: 
                    274: /** close the btree and free any resources */
                    275: void btree_close(btree* bt)
                    276: {
                    277:     node_cache_close(&bt->cache);
                    278:     // free(bt->buf);
                    279: }
                    280: 
                    281: /* returns pointer to key given by index in current node.
                    282:  *
                    283:  * Assumes that current node is not NODE_HEAD ...
                    284:  */
                    285: void* btree_key_by_index(btree* bt, node_buf* buf, UInt16 index)
                    286: {
                    287:     UInt16  node_size      = bt->head.node_size;
                    288:        // The offsets are found at the end of the node ...
                    289:     UInt16  off_pos        = node_size - (index +1) * sizeof(btree_record_offset);
                    290:        // position of offset at end of node
                    291:     btree_record_offset* offset =
                    292:        (btree_record_offset*) (buf->node + off_pos);
                    293: 
                    294:     // now we have the offset and can read the key ...
                    295: #ifdef CONFIG_LITTLE_ENDIAN
                    296:     return buf->node + bswabU16(*offset);
                    297: #else
                    298:     return buf->node + *offset;
                    299: #endif
                    300: }
                    301: 
                    302: 
                    303: #ifdef DEBUG
                    304: 
                    305: /* print btree header node information */
                    306: void btree_printhead(btree_head* head)
                    307: {
                    308:     UInt32 attr;
                    309:     printf("  depth       : %#X\n",  head->depth);
                    310:     printf("  root        : %#lX\n", head->root);
                    311:     printf("  leaf_count  : %#lX\n", head->leaf_count);
                    312:     printf("  leaf_head   : %#lX\n", head->leaf_head);
                    313:     printf("  leaf_tail   : %#lX\n", head->leaf_tail);
                    314:     printf("  node_size   : %#X\n",  head->node_size);
                    315:     printf("  max_key_len : %#X\n",  head->max_key_len);
                    316:     printf("  node_count  : %#lX\n", head->node_count);
                    317:     printf("  free_nodes  : %#lX\n", head->free_nodes);
                    318:     printf("  reserved1   : %#X\n",  head->reserved1);
                    319:     printf("  clump_size  : %#lX\n", head->clump_size);
                    320:     printf("  btree_type  : %#X\n",  head->btree_type);
                    321:     attr = head->attributes;
                    322:     printf("  reserved2   : %#X\n",  head->reserved2);
                    323:     if (attr & HFSPLUS_BAD_CLOSE)
                    324:         printf(" HFSPLUS_BAD_CLOSE *** ");
                    325:     else
                    326:         printf(" !HFSPLUS_BAD_CLOSE");
                    327:     if (attr & HFSPLUS_TREE_BIGKEYS)
                    328:         printf(" HFSPLUS_TREE_BIGKEYS ");
                    329:     else
                    330:         printf("  !HFSPLUS_TREE_BIGKEYS");
                    331:     if (attr & HFSPLUS_TREE_VAR_NDXKEY_SIZE)
                    332:         printf(" HFSPLUS_TREE_VAR_NDXKEY_SIZE");
                    333:     else
                    334:         printf(" !HFSPLUS_TREE_VAR_NDXKEY_SIZE");
                    335:     if (attr & HFSPLUS_TREE_UNUSED)
                    336:         printf(" HFSPLUS_TREE_UNUSED ***\n");
                    337:     printf("\n");
                    338: }
                    339: 
                    340: /* Dump all the node information to stdout */
                    341: void btree_print(btree* bt)
                    342: {
                    343:     btree_node_desc* node;
                    344: 
                    345:     btree_printhead(&bt->head);
                    346: 
                    347:     node = &bt->node;
                    348:     printf("next     : %#lX\n", node->next);
                    349:     printf("prev     : %#lX\n", node->prev);
                    350:     printf("height   : %#X\n",  node->height);
                    351:     printf("num_rec  : %#X\n",  node->num_rec);
                    352:     printf("reserved : %#X\n",  node->reserved);
                    353:     printf("height   : %#X\n",  node->height);                                      switch(node->kind)
                    354:     {
                    355:        case HFSP_NODE_NDX  :
                    356:            printf("HFSP_NODE_NDX\n");
                    357:            break;
                    358:        case HFSP_NODE_HEAD :
                    359:            printf("HFSP_NODE_HEAD\n");
                    360:            break;
                    361:        case HFSP_NODE_MAP  :
                    362:            printf("HFSP_NODE_MAP\n");
                    363:            break;
                    364:        case HFSP_NODE_LEAF :
                    365:            printf("HFSP_NODE_LEAF\n");
                    366:            break;
                    367:        default:
                    368:            printf("*** Unknown Node type ***\n");
                    369:     }
                    370: }
                    371: 
                    372: #endif

unix.superglobalmegacorp.com

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