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

1.1       root        1: /*
                      2:  *   Creation Date: <2001/05/05 23:33:49 samuel>
                      3:  *   Time-stamp: <2004/01/12 10:25:39 samuel>
                      4:  *
                      5:  *     /package/hfsplus-files
                      6:  *
                      7:  *     HFS+ file system interface (and ROM lookup support)
                      8:  *
                      9:  *   Copyright (C) 2001, 2002, 2003, 2004 Samuel Rydh ([email protected])
                     10:  *   Copyright (C) 2010 Mark Cave-Ayland ([email protected])
                     11:  *
                     12:  *   This program is free software; you can redistribute it and/or
                     13:  *   modify it under the terms of the GNU General Public License
                     14:  *   as published by the Free Software Foundation
                     15:  *
                     16:  */
                     17: 
                     18: #include "config.h"
                     19: #include "libopenbios/bindings.h"
                     20: #include "fs/fs.h"
                     21: #include "libhfsp.h"
                     22: #include "volume.h"
                     23: #include "record.h"
                     24: #include "unicode.h"
                     25: #include "blockiter.h"
                     26: #include "libc/diskio.h"
                     27: #include "libc/vsprintf.h"
                     28: 
                     29: #define MAC_OS_ROM_CREATOR     0x63687270      /* 'chrp' */
                     30: #define MAC_OS_ROM_TYPE                0x74627869      /* 'tbxi' */
                     31: #define MAC_OS_ROM_NAME                "Mac OS ROM"
                     32: 
                     33: #define FINDER_TYPE            0x464E4452      /* 'FNDR' */
                     34: #define FINDER_CREATOR         0x4D414353      /* 'MACS' */
                     35: #define SYSTEM_TYPE            0x7A737973      /* 'zsys' */
                     36: #define SYSTEM_CREATOR         0x4D414353      /* 'MACS' */
                     37: 
                     38: #define VOLNAME_SIZE   64
                     39: 
                     40: extern void     hfsp_init( void );
                     41: 
                     42: typedef struct {
                     43:        record          rec;
                     44:        char            *path;
                     45:        off_t           pos;
                     46: } hfsp_file_t;
                     47: 
                     48: typedef struct {
                     49:        volume *vol;
                     50:        hfsp_file_t *hfspfile;
                     51: } hfsp_info_t;
                     52: 
                     53: DECLARE_NODE( hfsp, 0, sizeof(hfsp_info_t), "+/packages/hfsplus-files" );
                     54: 
                     55: 
                     56: /************************************************************************/
                     57: /*     Search implementation                                           */
                     58: /************************************************************************/
                     59: 
                     60: typedef int (*match_proc_t)( record *r, record *parent, const void *match_data, hfsp_file_t *pt );
                     61: 
                     62: static int
                     63: search_files( record *par, int recursive, match_proc_t proc, const void *match_data, hfsp_file_t *pt )
                     64: {
                     65:        hfsp_file_t t;
                     66:        record r;
                     67:        int ret = 1;
                     68: 
                     69:        t.path = NULL;
                     70: 
                     71:        record_init_parent( &r, par );
                     72:        do{
                     73:                if( r.record.type == HFSP_FOLDER || r.record.type == HFSP_FILE )
                     74:                        ret = (*proc)( &r, par, match_data, &t );
                     75: 
                     76:                if( ret && r.record.type == HFSP_FOLDER && recursive )
                     77:                        ret = search_files( &r, 1, proc, match_data, &t );
                     78: 
                     79:        } while( ret && !record_next(&r) );
                     80: 
                     81:        if( !ret && pt ) {
                     82:                 char name[256];
                     83:                 const char *s2 = t.path ? t.path : "";
                     84: 
                     85:                unicode_uni2asc( name, &r.key.name, sizeof(name));
                     86: 
                     87:                pt->rec = t.rec;
                     88:                pt->path = malloc( strlen(name) + strlen(s2) + 2 );
                     89:                strcpy( pt->path, name );
                     90:                if( strlen(s2) ) {
                     91:                        strcat( pt->path, "\\" );
                     92:                        strcat( pt->path, s2 );
                     93:                }
                     94:        }
                     95: 
                     96:        if( t.path )
                     97:                free( t.path );
                     98: 
                     99:        return ret;
                    100: }
                    101: 
                    102: static int
                    103: root_search_files( volume *vol, int recursive, match_proc_t proc, const void *match_data, hfsp_file_t *pt )
                    104: {
                    105:        record r;
                    106: 
                    107:        record_init_root( &r, &vol->catalog );
                    108:        return search_files( &r, recursive, proc, match_data, pt );
                    109: }
                    110: 
                    111: static int
                    112: match_file( record *r, record *parent, const void *match_data, hfsp_file_t *pt )
                    113: {
                    114:         const char *p = (const char*)match_data;
                    115:        char name[256];
                    116:        int ret=1;
                    117: 
                    118:        if( r->record.type != HFSP_FILE )
                    119:                return 1;
                    120: 
                    121:        (void) unicode_uni2asc(name, &r->key.name, sizeof(name));
                    122:        if( !(ret=strcasecmp(p, name)) && pt )
                    123:                pt->rec = *r;
                    124: 
                    125:        return ret;
                    126: }
                    127: 
                    128: static int
                    129: match_rom( record *r, record *par, const void *match_data, hfsp_file_t *pt )
                    130: {
                    131:        hfsp_cat_file *file = &r->record.u.file;
                    132:        FInfo *fi = &file->user_info;
                    133:        int ret = 1;
                    134:        char buf[256];
                    135: 
                    136:        if( r->record.type == HFSP_FILE && fi->fdCreator == MAC_OS_ROM_CREATOR && fi->fdType == MAC_OS_ROM_TYPE ) {
                    137:                ret = search_files( par, 0, match_file, "System", NULL )
                    138:                        || search_files( par, 0, match_file, "Finder", NULL );
                    139: 
                    140:                (void) unicode_uni2asc(buf, &r->key.name, sizeof(buf));
                    141:                if( !strcasecmp("BootX", buf) )
                    142:                        return 1;
                    143: 
                    144:                if( !ret && pt )
                    145:                        pt->rec = *r;
                    146:        }
                    147:        return ret;
                    148: }
                    149: 
                    150: static int
                    151: match_path( record *r, record *par, const void *match_data, hfsp_file_t *pt )
                    152: {
                    153:        char name[256], *s, *next, *org;
                    154:        int ret=1;
                    155: 
                    156:        next = org = strdup( (char*)match_data );
                    157:        while( (s=strsep( &next, "\\/" )) && !strlen(s) )
                    158:                ;
                    159:        if( !s ) {
                    160:                free( org );
                    161:                return 1;
                    162:        }
                    163: 
                    164:        if( *s == ':' && strlen(s) == 5 ) {
                    165:                if( r->record.type == HFSP_FILE && !next ) {
                    166:                        /* match type */
                    167:                        hfsp_cat_file *file = &r->record.u.file;
                    168:                        FInfo *fi = &file->user_info;
                    169:                        int i, type=0;
                    170:                        for( i=1; s[i] && i<=4; i++ )
                    171:                                type = (type << 8) | s[i];
                    172:                        /* printk("fi->fdType: %s / %s\n", s+1, b ); */
                    173:                        if( fi->fdType == type ) {
                    174:                                if( pt )
                    175:                                        pt->rec = *r;
                    176:                                ret = 0;
                    177:                        }
                    178:                }
                    179:        } else {
                    180:                (void) unicode_uni2asc(name, &r->key.name, sizeof(name));
                    181: 
                    182:                if( !strcasecmp(s, name) ) {
                    183:                        if( r->record.type == HFSP_FILE && !next ) {
                    184:                                if( pt )
                    185:                                        pt->rec = *r;
                    186:                                ret = 0;
                    187:                        } else /* must be a directory */
                    188:                                ret = search_files( r, 0, match_path, next, pt );
                    189:                }
                    190:        }
                    191:        free( org );
                    192:        return ret;
                    193: }
                    194: 
                    195: 
                    196: /************************************************************************/
                    197: /*     Standard package methods                                                */
                    198: /************************************************************************/
                    199: 
                    200: /* ( -- success? ) */
                    201: static void
                    202: hfsp_files_open( hfsp_info_t *mi )
                    203: {
                    204:        int fd;
                    205:        char *path = my_args_copy();
                    206: 
                    207:        if ( ! path )
                    208:                RET( 0 );
                    209: 
                    210:        fd = open_ih( my_parent() );
                    211:        if ( fd == -1 ) {
                    212:                free( path );
                    213:                RET( 0 );
                    214:        }
                    215: 
                    216:        mi->vol = malloc( sizeof(volume) );
                    217:        if (volume_open(mi->vol, fd)) {
                    218:                free( path );
                    219:                close_io( fd );
                    220:                RET( 0 );
                    221:        }
                    222: 
                    223:        mi->hfspfile = malloc( sizeof(hfsp_file_t) );
                    224:        
                    225:        /* Leading \\ means system folder. The finder info block has
                    226:         * the following meaning.
                    227:         *
                    228:         *  [0] Prefered boot directory ID
                    229:         *  [3] MacOS 9 boot directory ID
                    230:         *  [5] MacOS X boot directory ID
                    231:         */
                    232:        if( !strncmp(path, "\\\\", 2) ) {
                    233:                int *p = (int*)&(mi->vol)->vol.finder_info[0];
                    234:                int cnid = p[0];
                    235:                /* printk(" p[0] = %x, p[3] = %x, p[5] = %x\n", p[0], p[3], p[5] ); */
                    236:                if( p[0] == p[5] && p[3] )
                    237:                        cnid = p[3];
                    238:                if( record_init_cnid(&(mi->hfspfile->rec), &(mi->vol)->catalog, cnid) )
                    239:                        RET ( 0 );
                    240:                path += 2;
                    241:        } else {
                    242:                record_init_root( &(mi->hfspfile->rec), &(mi->vol)->catalog );
                    243:        }
                    244: 
                    245:        if( !search_files(&(mi->hfspfile->rec), 0, match_path, path, mi->hfspfile ) )
                    246:                RET ( -1 );
                    247:        
                    248:        RET ( -1 );
                    249: }
                    250: 
                    251: /* ( -- ) */
                    252: static void
                    253: hfsp_files_close( hfsp_info_t *mi )
                    254: {
                    255:        volume_close(mi->vol);
                    256: 
                    257:        if( mi->hfspfile->path )
                    258:                free( mi->hfspfile->path );
                    259:        free( mi->hfspfile );
                    260: }
                    261: 
                    262: /* ( buf len -- actlen ) */
                    263: static void
                    264: hfsp_files_read( hfsp_info_t *mi )
                    265: {
                    266:        int count = POP();
                    267:        char *buf = (char *)cell2pointer(POP());
                    268: 
                    269:        hfsp_file_t *t = mi->hfspfile;
                    270:        volume *vol = t->rec.tree->vol;
                    271:        UInt32 blksize = vol->blksize;
                    272:        hfsp_cat_file *file = &t->rec.record.u.file;
                    273:        blockiter iter;
                    274:        char buf2[blksize];
                    275:        int act_count, curpos=0;
                    276: 
                    277:        blockiter_init( &iter, vol, &file->data_fork, HFSP_EXTENT_DATA, file->id );
                    278:        while( curpos + blksize < t->pos ) {
                    279:                if( blockiter_next( &iter ) ) {
                    280:                        RET ( -1 );
                    281:                        return;
                    282:                }
                    283:                curpos += blksize;
                    284:        }
                    285:        act_count = 0;
                    286: 
                    287:        while( act_count < count ){
                    288:                UInt32 block = blockiter_curr(&iter);
                    289:                int max = blksize, add = 0, size;
                    290: 
                    291:                if( volume_readinbuf( vol, buf2, block ) )
                    292:                        break;
                    293: 
                    294:                if( curpos < t->pos ){
                    295:                        add += t->pos - curpos;
                    296:                        max -= t->pos - curpos;
                    297:                }
                    298:                size = (count-act_count > max)? max : count-act_count;
                    299:                memcpy( (char *)buf + act_count, &buf2[add], size );
                    300: 
                    301:                curpos += blksize;
                    302:                act_count += size;
                    303: 
                    304:                if( blockiter_next( &iter ) )
                    305:                        break;
                    306:        }
                    307: 
                    308:        t->pos += act_count;
                    309: 
                    310:        RET ( act_count );
                    311: }
                    312: 
                    313: /* ( pos.d -- status ) */
                    314: static void
                    315: hfsp_files_seek( hfsp_info_t *mi )
                    316: {
                    317:        long long pos = DPOP();
                    318:        int offs = (int)pos;
                    319:        int whence = SEEK_SET;
                    320: 
                    321:        hfsp_file_t *t = mi->hfspfile;
                    322:        hfsp_cat_file *file = &t->rec.record.u.file;
                    323:        int total = file->data_fork.total_size;
                    324: 
                    325:        if( offs == -1 ) {
                    326:                offs = 0;
                    327:                whence = SEEK_END;
                    328:        }
                    329: 
                    330:        switch( whence ){
                    331:        case SEEK_END:
                    332:                t->pos = total + offs;
                    333:                break;
                    334:        default:
                    335:        case SEEK_SET:
                    336:                t->pos = offs;
                    337:                break;
                    338:        }
                    339: 
                    340:        if( t->pos < 0 )
                    341:                t->pos = 0;
                    342: 
                    343:        if( t->pos > total )
                    344:                t->pos = total;
                    345: 
                    346:        RET ( 0 );
                    347: }
                    348: 
                    349: /* ( addr -- size ) */
                    350: static void
                    351: hfsp_files_load( hfsp_info_t *mi )
                    352: {
                    353:        char *buf = (char *)cell2pointer(POP());
                    354: 
                    355:        hfsp_file_t *t = mi->hfspfile;
                    356:        volume *vol = t->rec.tree->vol;
                    357:        UInt32 blksize = vol->blksize;
                    358:        hfsp_cat_file *file = &t->rec.record.u.file;
                    359:        int total = file->data_fork.total_size;
                    360:        blockiter iter;
                    361:        char buf2[blksize];
                    362:        int act_count;
                    363: 
                    364:        blockiter_init( &iter, vol, &file->data_fork, HFSP_EXTENT_DATA, file->id );
                    365: 
                    366:        act_count = 0;
                    367: 
                    368:        while( act_count < total ){
                    369:                UInt32 block = blockiter_curr(&iter);
                    370:                int max = blksize, size;
                    371: 
                    372:                if( volume_readinbuf( vol, buf2, block ) )
                    373:                        break;
                    374: 
                    375:                size = (total-act_count > max)? max : total-act_count;
                    376:                memcpy( (char *)buf + act_count, &buf2, size );
                    377: 
                    378:                act_count += size;
                    379: 
                    380:                if( blockiter_next( &iter ) )
                    381:                        break;
                    382:        }
                    383: 
                    384:        RET ( act_count );
                    385: }
                    386: 
                    387: /* ( -- cstr ) */
                    388: static void
                    389: hfsp_files_get_fstype( hfsp_info_t *mi )
                    390: {
                    391:        PUSH( pointer2cell(strdup("HFS+")) );
                    392: }
                    393: 
                    394: /* ( -- cstr ) */
                    395: static void
                    396: hfsp_files_get_path( hfsp_info_t *mi )
                    397: {
                    398:        char *buf;
                    399:        hfsp_file_t *t = mi->hfspfile;
                    400: 
                    401:        if( !t->path )
                    402:                RET ( 0 );
                    403: 
                    404:        buf = malloc(strlen(t->path) + 1);
                    405:        strncpy( buf, t->path, strlen(t->path) );
                    406:        buf[strlen(t->path)] = 0;
                    407: 
                    408:        PUSH(pointer2cell(buf));
                    409: }
                    410: 
                    411: /* ( -- success? ) */
                    412: static void
                    413: hfsp_files_open_nwrom( hfsp_info_t *mi )
                    414: {
                    415:        /* Switch to an existing ROM image file on the fs! */
                    416:        if( !root_search_files(mi->vol, 1, match_rom, NULL, mi->hfspfile) )
                    417:                RET ( -1 );
                    418: 
                    419:        RET ( 0 );
                    420: }
                    421: 
                    422: /* ( -- cstr|0 ) */
                    423: static void
                    424: hfsp_files_volume_name( hfsp_info_t *mi )
                    425: {
                    426:        int fd;
                    427:        char *volname = malloc(VOLNAME_SIZE);
                    428: 
                    429:        fd = open_ih(my_self());
                    430:         if (fd >= 0) {
                    431:                 get_hfs_vol_name(fd, volname, VOLNAME_SIZE);
                    432:                 close_io(fd);
                    433:         } else {
                    434:                 volname[0] = '\0';
                    435:         }
                    436: 
                    437:        PUSH(pointer2cell(volname));
                    438: }
                    439: 
                    440: /* static method, ( pathstr len ihandle -- ) */
                    441: static void
                    442: hfsp_files_dir( hfsp_info_t *dummy )
                    443: {
                    444:        forth_printf("dir method not implemented for HFS+ filesystem\n");
                    445:        POP();
                    446:        POP();
                    447:        POP();
                    448: }
                    449: 
                    450: /* static method, ( pos.d ih -- flag? ) */
                    451: static void
                    452: hfsp_files_probe( hfsp_info_t *dummy )
                    453: {
                    454:        ihandle_t ih = POP_ih();
                    455:        long long offs = DPOP();
                    456:        int fd, ret = 0;
                    457: 
                    458:        fd = open_ih(ih);
                    459:         if (fd >= 0) {
                    460:                 if (volume_probe(fd, offs)) {
                    461:                         ret = -1;
                    462:                 }
                    463:                 close_io(fd);
                    464:         } else {
                    465:                 ret = -1;
                    466:         }
                    467: 
                    468:        RET (ret);
                    469: }
                    470: 
                    471: static void
                    472: hfsp_initializer( hfsp_info_t *dummy )
                    473: {
                    474:        fword("register-fs-package");
                    475: }
                    476: 
                    477: NODE_METHODS( hfsp ) = {
                    478:        { "probe",      hfsp_files_probe        },
                    479:        { "open",       hfsp_files_open         },
                    480:        { "close",      hfsp_files_close        },
                    481:        { "read",       hfsp_files_read         },
                    482:        { "seek",       hfsp_files_seek         },
                    483:        { "load",       hfsp_files_load         },
                    484:        { "dir",        hfsp_files_dir          },
                    485: 
                    486:        /* special */
                    487:        { "open-nwrom",         hfsp_files_open_nwrom   },
                    488:        { "get-path",           hfsp_files_get_path     },
                    489:        { "get-fstype",         hfsp_files_get_fstype   },
                    490:        { "volume-name",        hfsp_files_volume_name  },
                    491: 
                    492:        { NULL,         hfsp_initializer        },
                    493: };
                    494: 
                    495: void
                    496: hfsp_init( void )
                    497: {
                    498:        REGISTER_NODE( hfsp );
                    499: }

unix.superglobalmegacorp.com

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