~pmdj/ubuntu/trusty/qemu/2.9+applesmc+fadtv3

« back to all changes in this revision

Viewing changes to roms/openbios/fs/hfsplus/hfsp_record.c

  • Committer: Phil Dennis-Jordan
  • Date: 2017-07-21 08:03:43 UTC
  • mfrom: (1.1.1)
  • Revision ID: phil@philjordan.eu-20170721080343-2yr2vdj7713czahv
New upstream release 2.9.0.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * libhfsp - library for reading and writing Macintosh HFS+ volumes.
 
3
 *
 
4
 * a record contains a key and a folder or file and is part
 
5
 * of a btree.
 
6
 *
 
7
 * Copyright (C) 2000 Klaus Halfmann <khalfmann@libra.de>
 
8
 * Original 1996-1998 Robert Leslie <rob@mars.org>
 
9
 * Additional work by  Brad Boyer (flar@pants.nu)
 
10
 *
 
11
 * This program is free software; you can redistribute it and/or modify
 
12
 * it under the terms of the GNU General Public License as published by
 
13
 * the Free Software Foundation; either version 2 of the License, or
 
14
 * (at your option) any later version.
 
15
 *
 
16
 * This program is distributed in the hope that it will be useful,
 
17
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
18
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
19
 * GNU General Public License for more details.
 
20
 *
 
21
 * You should have received a copy of the GNU General Public License
 
22
 * along with this program; if not, write to the Free Software
 
23
 * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
 
24
 * MA 02110-1301, USA.
 
25
 *
 
26
 * $Id: record.c,v 1.24 2000/10/17 05:58:46 hasi Exp $
 
27
 */
 
28
 
 
29
#include "config.h"
 
30
#include "libhfsp.h"
 
31
#include "hfstime.h"
 
32
#include "record.h"
 
33
#include "volume.h"
 
34
#include "btree.h"
 
35
#include "unicode.h"
 
36
#include "swab.h"
 
37
 
 
38
/* read a hfsp_cat_key from memory */
 
39
void* record_readkey(void* p, void* buf)
 
40
{
 
41
    hfsp_cat_key*   key = (hfsp_cat_key*) buf;
 
42
    const void*     check;
 
43
    UInt16          key_length, len,i;
 
44
    UInt16*         cp;
 
45
 
 
46
    key->key_length = key_length    = bswabU16_inc(p);
 
47
    check = p;
 
48
    key->parent_cnid                = bswabU32_inc(p);
 
49
    key->name.strlen = len          = bswabU16_inc(p);
 
50
    cp = key->name.name;
 
51
    for (i=0; i < len; i++, cp++)
 
52
        *cp                         = bswabU16_inc(p);
 
53
        /* check if keylenght was correct */
 
54
    if (key_length != ((char*) p) - ((char*) check))
 
55
         HFSP_ERROR(EINVAL, "Invalid key length in record_readkey");
 
56
    return p;
 
57
  fail:
 
58
    return NULL;
 
59
}
 
60
 
 
61
/* read a hfsp_extent_key from memory */
 
62
void* record_extent_readkey(void* p, void* buf)
 
63
{
 
64
    hfsp_extent_key* key = (hfsp_extent_key*) buf;
 
65
    UInt16  key_length;
 
66
 
 
67
    key->key_length = key_length    = bswabU16_inc(p);
 
68
    key->fork_type                  = bswabU8_inc(p);
 
69
    key->filler                     = bswabU8_inc(p);
 
70
    if (key_length != 10)
 
71
        HFSP_ERROR(-1, "Invalid key length in record_extent_readkey");
 
72
    key->file_id                    = bswabU32_inc(p);
 
73
    key->start_block                = bswabU32_inc(p);
 
74
    return p;
 
75
  fail:
 
76
    return NULL;
 
77
}
 
78
 
 
79
 
 
80
/* read posix permission from memory */
 
81
static inline void* record_readperm(void *p, hfsp_perm* perm)
 
82
{
 
83
    perm->owner= bswabU32_inc(p);
 
84
    perm->group= bswabU32_inc(p);
 
85
    perm->mode = bswabU32_inc(p);
 
86
    perm->dev  = bswabU32_inc(p);
 
87
    return p;
 
88
}
 
89
 
 
90
/* read directory info */
 
91
static inline void* record_readDInfo(void *p, DInfo* info)
 
92
{
 
93
    info->frRect.top    = bswabU16_inc(p);
 
94
    info->frRect.left   = bswabU16_inc(p);
 
95
    info->frRect.bottom = bswabU16_inc(p);
 
96
    info->frRect.right  = bswabU16_inc(p);
 
97
    info->frFlags       = bswabU16_inc(p);
 
98
    info->frLocation.v  = bswabU16_inc(p);
 
99
    info->frLocation.h  = bswabU16_inc(p);
 
100
    info->frView        = bswabU16_inc(p);
 
101
    return p;
 
102
}
 
103
 
 
104
/* read extra Directory info */
 
105
static inline void* record_readDXInfo(void *p, DXInfo* xinfo)
 
106
{
 
107
    xinfo->frScroll.v  = bswabU16_inc(p);
 
108
    xinfo->frScroll.h  = bswabU16_inc(p);
 
109
    xinfo->frOpenChain = bswabU32_inc(p);
 
110
    xinfo->frUnused    = bswabU16_inc(p);
 
111
    xinfo->frComment   = bswabU16_inc(p);
 
112
    xinfo->frPutAway   = bswabU32_inc(p);
 
113
    return p;
 
114
}
 
115
 
 
116
/* read a hfsp_cat_folder from memory */
 
117
static void* record_readfolder(void *p, hfsp_cat_folder* folder)
 
118
{
 
119
    folder->flags               = bswabU16_inc(p);
 
120
    folder->valence             = bswabU32_inc(p);
 
121
    folder->id                  = bswabU32_inc(p);
 
122
    folder->create_date         = bswabU32_inc(p);
 
123
    folder->content_mod_date    = bswabU32_inc(p);
 
124
    folder->attribute_mod_date  = bswabU32_inc(p);
 
125
    folder->access_date         = bswabU32_inc(p);
 
126
    folder->backup_date         = bswabU32_inc(p);
 
127
    p = record_readperm     (p, &folder->permissions);
 
128
    p = record_readDInfo    (p, &folder->user_info);
 
129
    p = record_readDXInfo   (p, &folder->finder_info);
 
130
    folder->text_encoding       = bswabU32_inc(p);
 
131
    folder->reserved            = bswabU32_inc(p);
 
132
    return p;
 
133
}
 
134
 
 
135
/* read file info */
 
136
static inline void* record_readFInfo(void *p, FInfo* info)
 
137
{
 
138
    info->fdType        = bswabU32_inc(p);
 
139
    info->fdCreator     = bswabU32_inc(p);
 
140
    info->fdFlags       = bswabU16_inc(p);
 
141
    info->fdLocation.v  = bswabU16_inc(p);
 
142
    info->fdLocation.h  = bswabU16_inc(p);
 
143
    info->fdFldr        = bswabU16_inc(p);
 
144
    return p;
 
145
}
 
146
 
 
147
/* read extra File info */
 
148
static inline void* record_readFXInfo(void *p, FXInfo* xinfo)
 
149
{
 
150
    SInt16 *q;
 
151
    xinfo->fdIconID     = bswabU16_inc(p);
 
152
    q=(SInt16*) p;
 
153
    q+=4; // skip unused
 
154
    p=(void *)q;
 
155
    xinfo->fdComment    = bswabU16_inc(p);
 
156
    xinfo->fdPutAway    = bswabU32_inc(p);
 
157
    return p;
 
158
}
 
159
 
 
160
/* read a hfsp_cat_file from memory */
 
161
static void* record_readfile(void *p, hfsp_cat_file* file)
 
162
{
 
163
    file->flags                 = bswabU16_inc(p);
 
164
    file->reserved1             = bswabU32_inc(p);
 
165
    file->id                    = bswabU32_inc(p);
 
166
    file->create_date           = bswabU32_inc(p);
 
167
    file->content_mod_date      = bswabU32_inc(p);
 
168
    file->attribute_mod_date    = bswabU32_inc(p);
 
169
    file->access_date           = bswabU32_inc(p);
 
170
    file->backup_date           = bswabU32_inc(p);
 
171
    p = record_readperm     (p, &file->permissions);
 
172
    p = record_readFInfo    (p, &file->user_info);
 
173
    p = record_readFXInfo   (p, &file->finder_info);
 
174
    file->text_encoding         = bswabU32_inc(p);
 
175
    file->reserved2             = bswabU32_inc(p);
 
176
    p =     volume_readfork (p, &file->data_fork);
 
177
    return  volume_readfork (p, &file->res_fork);
 
178
}
 
179
 
 
180
/* read a hfsp_cat_thread from memory */
 
181
static void* record_readthread(void *p, hfsp_cat_thread* entry)
 
182
{
 
183
    int     i;
 
184
    UInt16  len;
 
185
    UInt16* cp;
 
186
 
 
187
    entry->         reserved    = bswabU16_inc(p);
 
188
    entry->         parentID    = bswabU32_inc(p);
 
189
    entry->nodeName.strlen = len= bswabU16_inc(p);
 
190
    cp = entry->nodeName.name;
 
191
    if (len > 255)
 
192
        HFSP_ERROR(-1, "Invalid key length in record thread");
 
193
    for (i=0; i < len; i++, cp++)
 
194
        *cp                      = bswabU16_inc(p);
 
195
    return p;
 
196
 fail:
 
197
    return NULL;
 
198
}
 
199
 
 
200
/* read a hfsp_cat_entry from memory */
 
201
static void* record_readentry(void *p, hfsp_cat_entry* entry)
 
202
{
 
203
    UInt16 type = bswabU16_inc(p);
 
204
    entry->type = type;
 
205
    switch (type)
 
206
    {
 
207
        case HFSP_FOLDER:
 
208
            return record_readfolder(p, &entry->u.folder);
 
209
        case HFSP_FILE:
 
210
            return record_readfile  (p, &entry->u.file);
 
211
        case HFSP_FOLDER_THREAD:
 
212
        case HFSP_FILE_THREAD:
 
213
            return record_readthread(p, &entry->u.thread);
 
214
        default:
 
215
            HFSP_ERROR(-1, "Unexpected record type in record_readentry");
 
216
    } ;
 
217
  fail:
 
218
    return NULL;
 
219
}
 
220
 
 
221
 
 
222
/* Most of the functions here will not change the node in the btree,
 
223
   But this must be changed in the future ... */
 
224
 
 
225
 
 
226
/* intialize the record with the given index entry in the btree. */
 
227
static int record_init(record* r, btree* bt, node_buf* buf, UInt16 index)
 
228
{
 
229
    void *p;
 
230
    r-> tree   = bt;
 
231
    p = btree_key_by_index(bt,buf,index);
 
232
    if (!p)
 
233
        return -1;
 
234
    p = record_readkey  (p, &r->key);
 
235
    if (!p)
 
236
        return -1;
 
237
    p = record_readentry(p, &r->record);
 
238
    if (!p)
 
239
        return -1;
 
240
    r->node_index = buf->index;
 
241
    r-> keyind    = index;
 
242
 
 
243
    return 0;
 
244
}
 
245
 
 
246
/* intialize the record with the given index entry in the btree. */
 
247
static int record_init_extent(extent_record* r, btree* bt, node_buf* buf, UInt16 index)
 
248
{
 
249
    void *p;
 
250
    r-> tree   = bt;
 
251
    p = btree_key_by_index(bt, buf,index);
 
252
    if (!p)
 
253
        return -1;
 
254
    p = record_extent_readkey(p, &r->key);
 
255
    if (!p)
 
256
        return -1;
 
257
    p = volume_readextent(p, r->extent);
 
258
    if (!p)
 
259
        return -1;
 
260
    r->node_index = buf->index;
 
261
    r-> keyind    = index;
 
262
 
 
263
    return 0;
 
264
}
 
265
 
 
266
/* intialize the record to the first record of the tree
 
267
 * which is (per design) the root node.
 
268
 */
 
269
int record_init_root(record* r, btree* tree)
 
270
{
 
271
    // Position to first leaf node ...
 
272
    UInt32 leaf_head = tree->head.leaf_head;
 
273
    node_buf* buf = btree_node_by_index(tree, leaf_head);
 
274
    if (!buf)
 
275
        return -1;
 
276
    return record_init(r, tree, buf, 0);
 
277
}
 
278
 
 
279
/* Compare two cat_keys ... */
 
280
int record_key_compare(void* k1, void* k2)
 
281
{
 
282
    hfsp_cat_key* key1 = (hfsp_cat_key*) k1;
 
283
    hfsp_cat_key* key2 = (hfsp_cat_key*) k2;
 
284
    int diff = key2->parent_cnid - key1->parent_cnid;
 
285
    if (!diff) // same parent
 
286
        diff = fast_unicode_compare(&key1->name, &key2->name);
 
287
    return diff;
 
288
}
 
289
 
 
290
/* Compare two extent_keys ... */
 
291
int record_extent_key_compare(void* k1, void* k2)
 
292
{
 
293
    hfsp_extent_key* key1 = (hfsp_extent_key*) k1;
 
294
    hfsp_extent_key* key2 = (hfsp_extent_key*) k2;
 
295
    int diff = key2->fork_type - key1->fork_type;
 
296
    if (!diff) // same type
 
297
    {
 
298
        diff = key2->file_id - key1->file_id;
 
299
        if (!diff) // same file
 
300
            diff = key2->start_block - key1->start_block;
 
301
    }
 
302
    return diff;
 
303
}
 
304
 
 
305
/* Position node in btree so that key might be inside */
 
306
static node_buf* record_find_node(btree* tree, void *key)
 
307
{
 
308
    int                 start, end, mid, comp;  // components of a binary search
 
309
    void                *p = NULL;
 
310
    char                curr_key[tree->head.max_key_len];
 
311
                    // The current key under examination
 
312
    hfsp_key_read       readkey     = tree->kread;
 
313
    hfsp_key_compare    key_compare = tree->kcomp;
 
314
    UInt32              index;
 
315
    node_buf*           node = btree_node_by_index(tree, tree->head.root);
 
316
    if (!node)
 
317
        HFSP_ERROR(-1, "record_find_node: Cant position to root node");
 
318
    while (node->desc.kind == HFSP_NODE_NDX)
 
319
    {
 
320
        mid = start = 0;
 
321
        end  = node->desc.num_rec;
 
322
        comp = -1;
 
323
        while (start < end)
 
324
        {
 
325
            mid = (start + end) >> 1;
 
326
            p = btree_key_by_index(tree, node, mid);
 
327
            if (!p)
 
328
                HFSP_ERROR(-1, "record_find_node: unexpected error");
 
329
            p = readkey  (p, curr_key);
 
330
            if (!p)
 
331
                HFSP_ERROR(-1, "record_find_node: unexpected error");
 
332
            comp = key_compare(curr_key, key);
 
333
            if (comp > 0)
 
334
                start = mid + 1;
 
335
            else if (comp < 0)
 
336
                end = mid;
 
337
            else
 
338
                break;
 
339
        }
 
340
        if (!p) // Empty tree, fascinating ...
 
341
            HFSP_ERROR(-1, "record_find_node: unexpected empty node");
 
342
        if (comp < 0)   // mmh interesting key is before this key ...
 
343
        {
 
344
            if (mid == 0)
 
345
                return NULL;  // nothing before this key ..
 
346
            p = btree_key_by_index(tree, node, mid-1);
 
347
            if (!p)
 
348
                HFSP_ERROR(-1, "record_find_node: unexpected error");
 
349
            p = readkey  (p, curr_key);
 
350
            if (!p)
 
351
                HFSP_ERROR(-1, "record_find_node: unexpected error");
 
352
        }
 
353
 
 
354
        index = bswabU32_inc(p);
 
355
        node = btree_node_by_index(tree, index);
 
356
    }
 
357
    return node;        // go on and use the found node
 
358
  fail:
 
359
    return NULL;
 
360
}
 
361
 
 
362
/* search for the given key in the btree.
 
363
 *
 
364
 * returns pointer to memory just after key or NULL
 
365
 * In any case *keyind recives the index where the
 
366
 * key was found (or could be inserted.)
 
367
 */
 
368
static void *
 
369
record_find_key(btree* tree, void* key, int* keyind, UInt16* node_index)
 
370
{
 
371
    node_buf* buf = record_find_node(tree, key);
 
372
    if (buf)
 
373
    {
 
374
        int                 comp  = -1;
 
375
        int                 start = 0; // components of a binary search
 
376
        int                 end   = buf->desc.num_rec;
 
377
        int                 mid   = -1;
 
378
        void                *p    = NULL;
 
379
        char                curr_key[tree->head.max_key_len];
 
380
        hfsp_key_read       readkey     = tree->kread;
 
381
        hfsp_key_compare    key_compare = tree->kcomp;
 
382
        while (start < end)
 
383
        {
 
384
            mid = (start + end) >> 1;
 
385
            p = btree_key_by_index(tree, buf, mid);
 
386
            if (!p)
 
387
                HFSP_ERROR(-1, "record_init_key: unexpected error");
 
388
            p = readkey  (p, curr_key);
 
389
            if (!p)
 
390
                HFSP_ERROR(-1, "record_init_cat_key: unexpected error");
 
391
            comp = key_compare(curr_key, key);
 
392
            if (comp > 0)
 
393
                start = mid + 1;
 
394
            else if (comp < 0)
 
395
                end = mid;
 
396
            else
 
397
                break;
 
398
        }
 
399
        if (!p) // Empty tree, fascinating ...
 
400
            HFSP_ERROR(ENOENT, "record_init_key: unexpected empty node");
 
401
        *keyind = mid;
 
402
        *node_index = buf->index;
 
403
        if (!comp)      // found something ...
 
404
            return p;
 
405
    }
 
406
    HFSP_ERROR(ENOENT, NULL);
 
407
  fail:
 
408
    return NULL;
 
409
}
 
410
 
 
411
/* intialize the record by searching for the given key in the btree.
 
412
 *
 
413
 * r is umodified on error.
 
414
 */
 
415
static int
 
416
record_init_key(record* r, btree* tree, hfsp_cat_key* key)
 
417
{
 
418
    int     keyind;
 
419
    UInt16  node_index;
 
420
    void    *p = record_find_key(tree, key, &keyind, &node_index);
 
421
 
 
422
    if (p)
 
423
    {
 
424
        r -> tree      = tree;
 
425
        r -> node_index= node_index;
 
426
        r -> keyind    = keyind;
 
427
        r -> key       = *key; // Better use a record_key_copy ...
 
428
        p = record_readentry(p, &r->record);
 
429
        if (!p)
 
430
            HFSP_ERROR(-1, "record_init_key: unexpected error");
 
431
        return 0;
 
432
    }
 
433
  fail:
 
434
    return -1;
 
435
}
 
436
 
 
437
/* intialize the extent_record to the extent identified by the
 
438
 * (first) blockindex.
 
439
 *
 
440
 * forktype: either HFSP_EXTEND_DATA or HFSP_EXTEND_RSRC
 
441
 */
 
442
int record_init_file(extent_record* r, btree* tree,
 
443
                    UInt8 forktype, UInt32 fileId, UInt32 blockindex)
 
444
{
 
445
    int             keyind;
 
446
    UInt16          node_index;
 
447
    hfsp_extent_key key = { 10, forktype, 0, fileId, blockindex };
 
448
    void            *p = record_find_key(tree, &key, &keyind, &node_index);
 
449
 
 
450
    if (p)
 
451
    {
 
452
        r -> tree      = tree;
 
453
        r -> node_index= node_index;
 
454
        r -> keyind    = keyind;
 
455
        r -> key       = key; // Better use a record_key_copy ...
 
456
        p =  volume_readextent(p, r->extent);
 
457
        if (!p)
 
458
            HFSP_ERROR(-1, "record_init_file: unexpected error");
 
459
        return 0;
 
460
    }
 
461
  fail:
 
462
    return -1;
 
463
}
 
464
 
 
465
/* intialize the record to the folder identified by cnid
 
466
 */
 
467
int record_init_cnid(record* r, btree* tree, UInt32 cnid)
 
468
{
 
469
    hfsp_cat_key    thread_key;     // the thread is the first record
 
470
 
 
471
    thread_key.key_length = 6;      // null name (like '.' in unix )
 
472
    thread_key.parent_cnid = cnid;
 
473
    thread_key.name.strlen = 0;
 
474
 
 
475
    return record_init_key(r, tree, &thread_key);
 
476
}
 
477
 
 
478
/* intialize the record to the first record of the parent.
 
479
 */
 
480
int record_init_parent(record* r, record* parent)
 
481
{
 
482
    if (parent->record.type == HFSP_FOLDER)
 
483
        return record_init_cnid(r, parent->tree, parent->record.u.folder.id);
 
484
    else if(parent->record.type == HFSP_FOLDER_THREAD)
 
485
    {
 
486
        if (r != parent)
 
487
            *r = *parent; // The folder thread is in fact the first entry, like '.'
 
488
        return 0;
 
489
    }
 
490
    HFSP_ERROR(EINVAL,
 
491
        "record_init_parent: parent is neither folder nor folder thread.");
 
492
 
 
493
  fail:
 
494
    return EINVAL;
 
495
}
 
496
 
 
497
 
 
498
/* find correct node record for given node and *pindex.
 
499
 *
 
500
 * index of record in this (or next) node
 
501
 * */
 
502
static node_buf* prepare_next(btree* tree, UInt16 node_index, UInt16* pindex)
 
503
{
 
504
    node_buf*        buf    = btree_node_by_index(tree, node_index);
 
505
    btree_node_desc* desc   = &buf->desc;
 
506
    UInt32           numrec = desc->num_rec;
 
507
    if (*pindex >= numrec) // move on to next node
 
508
    {
 
509
        UInt16 next = desc->next;
 
510
        *pindex = 0;
 
511
        if (!next   /* is there a next node ? */
 
512
        ||  !( buf = btree_node_by_index(tree, next)))
 
513
            return NULL;
 
514
    }
 
515
    return buf;
 
516
}
 
517
/* move record foreward to next entry.
 
518
 *
 
519
 * In case of an error the value of *r is undefined !
 
520
 */
 
521
int record_next(record* r)
 
522
{
 
523
    btree*      tree    = r->tree;
 
524
    UInt16      index   = r->keyind +1;
 
525
    UInt32      parent;
 
526
    node_buf*   buf     = prepare_next(tree, r->node_index, &index);
 
527
 
 
528
    if (!buf)
 
529
        return ENOENT;  // No (more) such file or directory
 
530
 
 
531
    parent = r->key.parent_cnid;
 
532
 
 
533
    if (record_init(r, tree, buf, index))
 
534
        return -1;
 
535
 
 
536
    if (r->key.parent_cnid != parent || // end of current directory
 
537
        index != r->keyind)             // internal error ?
 
538
        return ENOENT;  // No (more) such file or directory
 
539
 
 
540
    return 0;
 
541
}
 
542
 
 
543
/* move record foreward to next extent record.
 
544
 *
 
545
 * In case of an error the value of *r is undefined !
 
546
 */
 
547
int record_next_extent(extent_record* r)
 
548
{
 
549
    btree*      tree   = r->tree;
 
550
    UInt16      index  = r->keyind +1;
 
551
    UInt32      file_id;
 
552
    UInt8       fork_type;
 
553
    node_buf*   buf     = prepare_next(tree, r->node_index, &index);
 
554
 
 
555
    if (!buf)
 
556
        return ENOENT;  // No (more) such file or directory
 
557
 
 
558
    file_id     = r->key.file_id;
 
559
    fork_type   = r->key.fork_type;
 
560
 
 
561
    if (record_init_extent(r, tree, buf, index))
 
562
        return -1;
 
563
 
 
564
    if (r->key.file_id   != file_id ||      // end of current file
 
565
        r->key.fork_type != fork_type ||    // end of current fork
 
566
        index != r->keyind)                 // internal error ?
 
567
        return ENOENT;  // No (more) such file or directory
 
568
 
 
569
    return 0;
 
570
}
 
571
 
 
572
/* intialize the record by searching for the given string in the given folder.
 
573
 *
 
574
 * parent and r may be the same.
 
575
 */
 
576
int record_init_string_parent(record* r, record* parent, char* name)
 
577
{
 
578
    hfsp_cat_key key;
 
579
 
 
580
    if (parent->record.type == HFSP_FOLDER)
 
581
        key.parent_cnid = parent->record.u.folder.id;
 
582
    else if(parent->record.type == HFSP_FOLDER_THREAD)
 
583
        key.parent_cnid = parent->key.parent_cnid;
 
584
    else
 
585
        HFSP_ERROR(-1, "record_init_string_parent: parent is not a folder.");
 
586
 
 
587
    key.key_length = 6 + unicode_asc2uni(&key.name,name); // 6 for minumum size
 
588
    return record_init_key(r, parent->tree, &key);
 
589
 
 
590
  fail:
 
591
    return -1;
 
592
}
 
593
 
 
594
/* move record up in folder hierarchy (if possible) */
 
595
int record_up(record* r)
 
596
{
 
597
    if (r->record.type == HFSP_FOLDER)
 
598
    {
 
599
        // locate folder thread
 
600
        if (record_init_cnid(r, r->tree, r->record.u.folder.id))
 
601
            return -1;
 
602
    }
 
603
    else if(r->record.type == HFSP_FOLDER_THREAD)
 
604
    {
 
605
        // do nothing were are already where we want to be
 
606
    }
 
607
    else
 
608
        HFSP_ERROR(-1, "record_up: record is neither folder nor folder thread.");
 
609
 
 
610
    if(r->record.type != HFSP_FOLDER_THREAD)
 
611
        HFSP_ERROR(-1, "record_up: unable to locate parent");
 
612
    return record_init_cnid(r, r->tree, r->record.u.thread.parentID);
 
613
 
 
614
  fail:
 
615
    return -1;
 
616
}
 
617
 
 
618
#ifdef DEBUG
 
619
 
 
620
/* print Quickdraw Point */
 
621
static void record_print_Point(Point* p)
 
622
{
 
623
    printf("[ v=%d, h=%d ]", p->v, p->h);
 
624
}
 
625
 
 
626
/* print Quickdraw Rect */
 
627
static void record_print_Rect(Rect* r)
 
628
{
 
629
    printf("[ top=%d, left=%d, bottom=%d, right=%d  ]",
 
630
             r->top, r->left, r->bottom, r->right);
 
631
}
 
632
 
 
633
/* print the key of a record */
 
634
static void record_print_key(hfsp_cat_key* key)
 
635
{
 
636
    char buf[255]; // mh this _might_ overflow
 
637
    unicode_uni2asc(buf, &key->name, 255);
 
638
    printf("parent cnid :    %ld\n",   key->parent_cnid);
 
639
    printf("name        :    %s\n", buf);
 
640
}
 
641
 
 
642
/* print permissions */
 
643
static void record_print_perm(hfsp_perm* perm)
 
644
{
 
645
    printf("owner               :\t%ld\n",  perm->owner);
 
646
    printf("group               :\t%ld\n",  perm->group);
 
647
    printf("perm                :\t0x%lX\n",perm->mode);
 
648
    printf("dev                 :\t%ld\n",  perm->dev);
 
649
}
 
650
 
 
651
/* print Directory info */
 
652
static void record_print_DInfo(DInfo* dinfo)
 
653
{
 
654
    printf(  "frRect              :\t");    record_print_Rect(&dinfo->frRect);
 
655
    printf("\nfrFlags             :\t0X%X\n",    dinfo->frFlags);
 
656
    printf(  "frLocation          :\t");    record_print_Point(&dinfo->frLocation);
 
657
    printf("\nfrView              :\t0X%X\n",    dinfo->frView);
 
658
}
 
659
 
 
660
/* print extended Directory info */
 
661
static void record_print_DXInfo(DXInfo* xinfo)
 
662
{
 
663
    printf(  "frScroll            :\t");    record_print_Point(&xinfo->frScroll);
 
664
    printf("\nfrOpenChain         :\t%ld\n",  xinfo->frOpenChain);
 
665
    printf(  "frUnused            :\t%d\n",   xinfo->frUnused);
 
666
    printf(  "frComment           :\t%d\n",   xinfo->frComment);
 
667
    printf(  "frPutAway           :\t%ld\n",  xinfo->frPutAway);
 
668
}
 
669
 
 
670
static void record_print_folder(hfsp_cat_folder* folder)
 
671
{
 
672
    printf("flags               :\t0x%X\n",     folder->flags);
 
673
    printf("valence             :\t0x%lX\n",    folder->valence);
 
674
    printf("id                  :\t%ld\n",      folder->id);
 
675
    record_print_perm   (&folder->permissions);
 
676
    record_print_DInfo  (&folder->user_info);
 
677
    record_print_DXInfo (&folder->finder_info);
 
678
    printf("text_encoding       :\t0x%lX\n",    folder->text_encoding);
 
679
    printf("reserved            :\t0x%lX\n",    folder->reserved);
 
680
}
 
681
 
 
682
/* print File info */
 
683
static void record_print_FInfo(FInfo* finfo)
 
684
{
 
685
    printf(  "fdType              :\t%4.4s\n", (char*) &finfo->fdType);
 
686
    printf(  "fdCreator           :\t%4.4s\n", (char*) &finfo->fdCreator);
 
687
    printf(  "fdFlags             :\t0X%X\n", finfo->fdFlags);
 
688
    printf(  "fdLocation          :\t");     record_print_Point(&finfo->fdLocation);
 
689
    printf("\nfdFldr              :\t%d\n",  finfo->fdFldr);
 
690
}
 
691
 
 
692
/* print extended File info */
 
693
static void record_print_FXInfo(FXInfo* xinfo)
 
694
{
 
695
    printf(  "fdIconID            :\t%d\n",   xinfo->fdIconID);
 
696
    // xinfo -> fdUnused;
 
697
    printf(  "fdComment           :\t%d\n",   xinfo->fdComment);
 
698
    printf(  "fdPutAway           :\t%ld\n",  xinfo->fdPutAway);
 
699
}
 
700
 
 
701
/* print folder entry */
 
702
 
 
703
/* print file entry */
 
704
static void record_print_file(hfsp_cat_file* file)
 
705
{
 
706
    printf("flags               :\t0x%X\n",     file->flags);
 
707
    printf("reserved1           :\t0x%lX\n",    file->reserved1);
 
708
    printf("id                  :\t%ld\n",      file->id);
 
709
    record_print_perm   (&file->permissions);
 
710
    record_print_FInfo  (&file->user_info);
 
711
    record_print_FXInfo (&file->finder_info);
 
712
    printf("text_encoding       :\t0x%lX\n",    file->text_encoding);
 
713
    printf("reserved            :\t0x%lX\n",    file->reserved2);
 
714
    printf("Datafork:\n");
 
715
    volume_print_fork (&file->data_fork);
 
716
    printf("Rsrcfork:\n");
 
717
    volume_print_fork (&file->res_fork);
 
718
}
 
719
 
 
720
/* print info for a file or folder thread */
 
721
static void record_print_thread(hfsp_cat_thread* entry)
 
722
{
 
723
    char buf[255]; // mh this _might_ overflow
 
724
    unicode_uni2asc(buf, &entry->nodeName, 255);
 
725
    printf("parent cnid :\t%ld\n", entry->parentID);
 
726
    printf("name        :\t%s\n" , buf);
 
727
}
 
728
 
 
729
/* print the information for a record */
 
730
static void record_print_entry(hfsp_cat_entry* entry)
 
731
{
 
732
    switch (entry->type)
 
733
    {
 
734
        case HFSP_FOLDER:
 
735
            printf("=== Folder ===\n");
 
736
            return record_print_folder(&entry->u.folder);
 
737
        case HFSP_FILE:
 
738
            printf("=== File ===\n");
 
739
            return record_print_file  (&entry->u.file);
 
740
        case HFSP_FOLDER_THREAD:
 
741
            printf("=== Folder Thread ===\n");
 
742
            return record_print_thread(&entry->u.thread);
 
743
        case HFSP_FILE_THREAD:
 
744
            printf("=== File Thread ==\n");
 
745
            return record_print_thread(&entry->u.thread);
 
746
        default:
 
747
            printf("=== Unknown Record Type ===\n");
 
748
    } ;
 
749
}
 
750
 
 
751
    /* Dump all the record information to stdout */
 
752
void record_print(record* r)
 
753
{
 
754
    printf ("keyind      :    %u\n", r->keyind);
 
755
    record_print_key  (&r->key);
 
756
    record_print_entry(&r->record);
 
757
}
 
758
 
 
759
#endif