Home | History | Annotate | Download | only in base
      1 /***************************************************************************/
      2 /*                                                                         */
      3 /*  ftrfork.c                                                              */
      4 /*                                                                         */
      5 /*    Embedded resource forks accessor (body).                             */
      6 /*                                                                         */
      7 /*  Copyright 2004, 2005, 2006, 2007, 2008, 2009, 2010 by                  */
      8 /*  Masatake YAMATO and Redhat K.K.                                        */
      9 /*                                                                         */
     10 /*  FT_Raccess_Get_HeaderInfo() and raccess_guess_darwin_hfsplus() are     */
     11 /*  derived from ftobjs.c.                                                 */
     12 /*                                                                         */
     13 /*  This file is part of the FreeType project, and may only be used,       */
     14 /*  modified, and distributed under the terms of the FreeType project      */
     15 /*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
     16 /*  this file you indicate that you have read the license and              */
     17 /*  understand and accept it fully.                                        */
     18 /*                                                                         */
     19 /***************************************************************************/
     20 
     21 /***************************************************************************/
     22 /* Development of the code in this file is support of                      */
     23 /* Information-technology Promotion Agency, Japan.                         */
     24 /***************************************************************************/
     25 
     26 
     27 #include <ft2build.h>
     28 #include FT_INTERNAL_DEBUG_H
     29 #include FT_INTERNAL_STREAM_H
     30 #include FT_INTERNAL_RFORK_H
     31 
     32 
     33 #undef  FT_COMPONENT
     34 #define FT_COMPONENT  trace_raccess
     35 
     36 
     37   /*************************************************************************/
     38   /*************************************************************************/
     39   /*************************************************************************/
     40   /****                                                                 ****/
     41   /****                                                                 ****/
     42   /****               Resource fork directory access                    ****/
     43   /****                                                                 ****/
     44   /****                                                                 ****/
     45   /*************************************************************************/
     46   /*************************************************************************/
     47   /*************************************************************************/
     48 
     49   FT_BASE_DEF( FT_Error )
     50   FT_Raccess_Get_HeaderInfo( FT_Library  library,
     51                              FT_Stream   stream,
     52                              FT_Long     rfork_offset,
     53                              FT_Long    *map_offset,
     54                              FT_Long    *rdata_pos )
     55   {
     56     FT_Error       error;
     57     unsigned char  head[16], head2[16];
     58     FT_Long        map_pos, rdata_len;
     59     int            allzeros, allmatch, i;
     60     FT_Long        type_list;
     61 
     62     FT_UNUSED( library );
     63 
     64 
     65     error = FT_Stream_Seek( stream, rfork_offset );
     66     if ( error )
     67       return error;
     68 
     69     error = FT_Stream_Read( stream, (FT_Byte *)head, 16 );
     70     if ( error )
     71       return error;
     72 
     73     *rdata_pos = rfork_offset + ( ( head[0] << 24 ) |
     74                                   ( head[1] << 16 ) |
     75                                   ( head[2] <<  8 ) |
     76                                     head[3]         );
     77     map_pos    = rfork_offset + ( ( head[4] << 24 ) |
     78                                   ( head[5] << 16 ) |
     79                                   ( head[6] <<  8 ) |
     80                                     head[7]         );
     81     rdata_len = ( head[ 8] << 24 ) |
     82                 ( head[ 9] << 16 ) |
     83                 ( head[10] <<  8 ) |
     84                   head[11];
     85 
     86     /* map_len = head[12] .. head[15] */
     87 
     88     if ( *rdata_pos + rdata_len != map_pos || map_pos == rfork_offset )
     89       return FT_Err_Unknown_File_Format;
     90 
     91     error = FT_Stream_Seek( stream, map_pos );
     92     if ( error )
     93       return error;
     94 
     95     head2[15] = (FT_Byte)( head[15] + 1 );       /* make it be different */
     96 
     97     error = FT_Stream_Read( stream, (FT_Byte*)head2, 16 );
     98     if ( error )
     99       return error;
    100 
    101     allzeros = 1;
    102     allmatch = 1;
    103     for ( i = 0; i < 16; ++i )
    104     {
    105       if ( head2[i] != 0 )
    106         allzeros = 0;
    107       if ( head2[i] != head[i] )
    108         allmatch = 0;
    109     }
    110     if ( !allzeros && !allmatch )
    111       return FT_Err_Unknown_File_Format;
    112 
    113     /* If we have reached this point then it is probably a mac resource */
    114     /* file.  Now, does it contain any interesting resources?           */
    115     /* Skip handle to next resource map, the file resource number, and  */
    116     /* attributes.                                                      */
    117     (void)FT_STREAM_SKIP( 4        /* skip handle to next resource map */
    118                           + 2      /* skip file resource number */
    119                           + 2 );   /* skip attributes */
    120 
    121     if ( FT_READ_USHORT( type_list ) )
    122       return error;
    123     if ( type_list == -1 )
    124       return FT_Err_Unknown_File_Format;
    125 
    126     error = FT_Stream_Seek( stream, map_pos + type_list );
    127     if ( error )
    128       return error;
    129 
    130     *map_offset = map_pos + type_list;
    131     return FT_Err_Ok;
    132   }
    133 
    134 
    135   static int
    136   ft_raccess_sort_ref_by_id( FT_RFork_Ref*  a,
    137                              FT_RFork_Ref*  b )
    138   {
    139     if ( a->res_id < b->res_id )
    140       return -1;
    141     else if ( a->res_id > b->res_id )
    142       return 1;
    143     else
    144       return 0;
    145   }
    146 
    147 
    148   FT_BASE_DEF( FT_Error )
    149   FT_Raccess_Get_DataOffsets( FT_Library  library,
    150                               FT_Stream   stream,
    151                               FT_Long     map_offset,
    152                               FT_Long     rdata_pos,
    153                               FT_Long     tag,
    154                               FT_Long   **offsets,
    155                               FT_Long    *count )
    156   {
    157     FT_Error      error;
    158     int           i, j, cnt, subcnt;
    159     FT_Long       tag_internal, rpos;
    160     FT_Memory     memory = library->memory;
    161     FT_Long       temp;
    162     FT_Long       *offsets_internal = NULL;
    163     FT_RFork_Ref  *ref = NULL;
    164 
    165 
    166     error = FT_Stream_Seek( stream, map_offset );
    167     if ( error )
    168       return error;
    169 
    170     if ( FT_READ_USHORT( cnt ) )
    171       return error;
    172     cnt++;
    173 
    174     for ( i = 0; i < cnt; ++i )
    175     {
    176       if ( FT_READ_LONG( tag_internal ) ||
    177            FT_READ_USHORT( subcnt )     ||
    178            FT_READ_USHORT( rpos )       )
    179         return error;
    180 
    181       FT_TRACE2(( "Resource tags: %c%c%c%c\n",
    182                   (char)( 0xff & ( tag_internal >> 24 ) ),
    183                   (char)( 0xff & ( tag_internal >> 16 ) ),
    184                   (char)( 0xff & ( tag_internal >>  8 ) ),
    185                   (char)( 0xff & ( tag_internal >>  0 ) ) ));
    186 
    187       if ( tag_internal == tag )
    188       {
    189         *count = subcnt + 1;
    190         rpos  += map_offset;
    191 
    192         error = FT_Stream_Seek( stream, rpos );
    193         if ( error )
    194           return error;
    195 
    196         if ( FT_NEW_ARRAY( ref, *count ) )
    197           return error;
    198 
    199         for ( j = 0; j < *count; ++j )
    200         {
    201           if ( FT_READ_USHORT( ref[j].res_id ) )
    202             goto Exit;
    203           if ( FT_STREAM_SKIP( 2 ) ) /* resource name */
    204             goto Exit;
    205           if ( FT_READ_LONG( temp ) )
    206             goto Exit;
    207           if ( FT_STREAM_SKIP( 4 ) ) /* mbz */
    208             goto Exit;
    209 
    210           ref[j].offset = temp & 0xFFFFFFL;
    211         }
    212 
    213         ft_qsort( ref, *count, sizeof ( FT_RFork_Ref ),
    214                   ( int(*)(const void*, const void*) )
    215                   ft_raccess_sort_ref_by_id );
    216 
    217         if ( FT_NEW_ARRAY( offsets_internal, *count ) )
    218           goto Exit;
    219 
    220         /* XXX: duplicated reference ID,
    221          *      gap between reference IDs are acceptable?
    222          *      further investigation on Apple implementation is needed.
    223          */
    224         for ( j = 0; j < *count; ++j )
    225           offsets_internal[j] = rdata_pos + ref[j].offset;
    226 
    227         *offsets = offsets_internal;
    228         error    = FT_Err_Ok;
    229 
    230       Exit:
    231         FT_FREE( ref );
    232         return error;
    233       }
    234     }
    235 
    236     return FT_Err_Cannot_Open_Resource;
    237   }
    238 
    239 
    240 #ifdef FT_CONFIG_OPTION_GUESSING_EMBEDDED_RFORK
    241 
    242   /*************************************************************************/
    243   /*************************************************************************/
    244   /*************************************************************************/
    245   /****                                                                 ****/
    246   /****                                                                 ****/
    247   /****                     Guessing functions                          ****/
    248   /****                                                                 ****/
    249   /****            When you add a new guessing function,                ****/
    250   /****           update FT_RACCESS_N_RULES in ftrfork.h.               ****/
    251   /****                                                                 ****/
    252   /*************************************************************************/
    253   /*************************************************************************/
    254   /*************************************************************************/
    255 
    256   typedef FT_Error
    257   (*raccess_guess_func)( FT_Library  library,
    258                          FT_Stream   stream,
    259                          char       *base_file_name,
    260                          char      **result_file_name,
    261                          FT_Long    *result_offset );
    262 
    263 
    264   static FT_Error
    265   raccess_guess_apple_double( FT_Library  library,
    266                               FT_Stream   stream,
    267                               char       *base_file_name,
    268                               char      **result_file_name,
    269                               FT_Long    *result_offset );
    270 
    271   static FT_Error
    272   raccess_guess_apple_single( FT_Library  library,
    273                               FT_Stream   stream,
    274                               char       *base_file_name,
    275                               char      **result_file_name,
    276                               FT_Long    *result_offset );
    277 
    278   static FT_Error
    279   raccess_guess_darwin_ufs_export( FT_Library  library,
    280                                    FT_Stream   stream,
    281                                    char       *base_file_name,
    282                                    char      **result_file_name,
    283                                    FT_Long    *result_offset );
    284 
    285   static FT_Error
    286   raccess_guess_darwin_newvfs( FT_Library  library,
    287                                FT_Stream   stream,
    288                                char       *base_file_name,
    289                                char      **result_file_name,
    290                                FT_Long    *result_offset );
    291 
    292   static FT_Error
    293   raccess_guess_darwin_hfsplus( FT_Library  library,
    294                                 FT_Stream   stream,
    295                                 char       *base_file_name,
    296                                 char      **result_file_name,
    297                                 FT_Long    *result_offset );
    298 
    299   static FT_Error
    300   raccess_guess_vfat( FT_Library  library,
    301                       FT_Stream   stream,
    302                       char       *base_file_name,
    303                       char      **result_file_name,
    304                       FT_Long    *result_offset );
    305 
    306   static FT_Error
    307   raccess_guess_linux_cap( FT_Library  library,
    308                            FT_Stream   stream,
    309                            char       *base_file_name,
    310                            char      **result_file_name,
    311                            FT_Long    *result_offset );
    312 
    313   static FT_Error
    314   raccess_guess_linux_double( FT_Library  library,
    315                               FT_Stream   stream,
    316                               char       *base_file_name,
    317                               char      **result_file_name,
    318                               FT_Long    *result_offset );
    319 
    320   static FT_Error
    321   raccess_guess_linux_netatalk( FT_Library  library,
    322                                 FT_Stream   stream,
    323                                 char       *base_file_name,
    324                                 char      **result_file_name,
    325                                 FT_Long    *result_offset );
    326 
    327 
    328   /*************************************************************************/
    329   /****                                                                 ****/
    330   /****                       Helper functions                          ****/
    331   /****                                                                 ****/
    332   /*************************************************************************/
    333 
    334   static FT_Error
    335   raccess_guess_apple_generic( FT_Library  library,
    336                                FT_Stream   stream,
    337                                char       *base_file_name,
    338                                FT_Int32    magic,
    339                                FT_Long    *result_offset );
    340 
    341   static FT_Error
    342   raccess_guess_linux_double_from_file_name( FT_Library  library,
    343                                              char *      file_name,
    344                                              FT_Long    *result_offset );
    345 
    346   static char *
    347   raccess_make_file_name( FT_Memory    memory,
    348                           const char  *original_name,
    349                           const char  *insertion );
    350 
    351 
    352   typedef enum  FT_RFork_Rule_ {
    353     FT_RFork_Rule_invalid = -2,
    354     FT_RFork_Rule_uknown, /* -1 */
    355     FT_RFork_Rule_apple_double,
    356     FT_RFork_Rule_apple_single,
    357     FT_RFork_Rule_darwin_ufs_export,
    358     FT_RFork_Rule_darwin_newvfs,
    359     FT_RFork_Rule_darwin_hfsplus,
    360     FT_RFork_Rule_vfat,
    361     FT_RFork_Rule_linux_cap,
    362     FT_RFork_Rule_linux_double,
    363     FT_RFork_Rule_linux_netatalk
    364   } FT_RFork_Rule;
    365 
    366   /* For fast translation between rule index and rule type,
    367    * the macros FT_RFORK_xxx should be kept consistent with
    368    * the raccess_guess_funcs table
    369    */
    370   typedef struct raccess_guess_rec_ {
    371     raccess_guess_func  func;
    372     FT_RFork_Rule       type;
    373   } raccess_guess_rec;
    374 
    375   static raccess_guess_rec  raccess_guess_table[FT_RACCESS_N_RULES] =
    376   {
    377     { raccess_guess_apple_double,	FT_RFork_Rule_apple_double, },
    378     { raccess_guess_apple_single,	FT_RFork_Rule_apple_single, },
    379     { raccess_guess_darwin_ufs_export,	FT_RFork_Rule_darwin_ufs_export, },
    380     { raccess_guess_darwin_newvfs,	FT_RFork_Rule_darwin_newvfs, },
    381     { raccess_guess_darwin_hfsplus,	FT_RFork_Rule_darwin_hfsplus, },
    382     { raccess_guess_vfat,		FT_RFork_Rule_vfat, },
    383     { raccess_guess_linux_cap,		FT_RFork_Rule_linux_cap, },
    384     { raccess_guess_linux_double,	FT_RFork_Rule_linux_double, },
    385     { raccess_guess_linux_netatalk,	FT_RFork_Rule_linux_netatalk, },
    386   };
    387 
    388   FT_BASE_DEF( void )
    389   FT_Raccess_Guess( FT_Library  library,
    390                     FT_Stream   stream,
    391                     char*       base_name,
    392                     char      **new_names,
    393                     FT_Long    *offsets,
    394                     FT_Error   *errors )
    395   {
    396     FT_Long  i;
    397 
    398 
    399     for ( i = 0; i < FT_RACCESS_N_RULES; i++ )
    400     {
    401       new_names[i] = NULL;
    402       if ( NULL != stream )
    403         errors[i] = FT_Stream_Seek( stream, 0 );
    404       else
    405         errors[i] = FT_Err_Ok;
    406 
    407       if ( errors[i] )
    408         continue ;
    409 
    410       errors[i] = (raccess_guess_table[i].func)( library,
    411                                                  stream, base_name,
    412                                                  &(new_names[i]),
    413                                                  &(offsets[i]) );
    414     }
    415 
    416     return;
    417   }
    418 
    419 
    420   static FT_RFork_Rule
    421   raccess_get_rule_type_from_rule_index( FT_UInt  rule_index )
    422   {
    423     if ( rule_index >= FT_RACCESS_N_RULES )
    424       return FT_RFork_Rule_invalid;
    425 
    426     return raccess_guess_table[rule_index].type;
    427   }
    428 
    429 
    430   FT_LOCAL_DEF( FT_Bool )
    431   raccess_rule_by_darwin_vfs( FT_UInt  rule_index )
    432   {
    433     switch( raccess_get_rule_type_from_rule_index( rule_index ) )
    434     {
    435       case FT_RFork_Rule_darwin_newvfs:
    436       case FT_RFork_Rule_darwin_hfsplus:
    437         return TRUE;
    438 
    439       default:
    440         return FALSE;
    441     }
    442   }
    443 
    444 
    445   static FT_Error
    446   raccess_guess_apple_double( FT_Library  library,
    447                               FT_Stream   stream,
    448                               char       *base_file_name,
    449                               char      **result_file_name,
    450                               FT_Long    *result_offset )
    451   {
    452     FT_Int32  magic = ( 0x00 << 24 ) |
    453                       ( 0x05 << 16 ) |
    454                       ( 0x16 <<  8 ) |
    455                         0x07;
    456 
    457 
    458     *result_file_name = NULL;
    459     if ( NULL == stream )
    460       return FT_Err_Cannot_Open_Stream;
    461 
    462     return raccess_guess_apple_generic( library, stream, base_file_name,
    463                                         magic, result_offset );
    464   }
    465 
    466 
    467   static FT_Error
    468   raccess_guess_apple_single( FT_Library  library,
    469                               FT_Stream   stream,
    470                               char       *base_file_name,
    471                               char      **result_file_name,
    472                               FT_Long    *result_offset )
    473   {
    474     FT_Int32  magic = ( 0x00 << 24 ) |
    475                       ( 0x05 << 16 ) |
    476                       ( 0x16 <<  8 ) |
    477                         0x00;
    478 
    479 
    480     *result_file_name = NULL;
    481     if ( NULL == stream )
    482       return FT_Err_Cannot_Open_Stream;
    483 
    484     return raccess_guess_apple_generic( library, stream, base_file_name,
    485                                         magic, result_offset );
    486   }
    487 
    488 
    489   static FT_Error
    490   raccess_guess_darwin_ufs_export( FT_Library  library,
    491                                    FT_Stream   stream,
    492                                    char       *base_file_name,
    493                                    char      **result_file_name,
    494                                    FT_Long    *result_offset )
    495   {
    496     char*      newpath;
    497     FT_Error   error;
    498     FT_Memory  memory;
    499 
    500     FT_UNUSED( stream );
    501 
    502 
    503     memory  = library->memory;
    504     newpath = raccess_make_file_name( memory, base_file_name, "._" );
    505     if ( !newpath )
    506       return FT_Err_Out_Of_Memory;
    507 
    508     error = raccess_guess_linux_double_from_file_name( library, newpath,
    509                                                        result_offset );
    510     if ( !error )
    511       *result_file_name = newpath;
    512     else
    513       FT_FREE( newpath );
    514 
    515     return error;
    516   }
    517 
    518 
    519   static FT_Error
    520   raccess_guess_darwin_hfsplus( FT_Library  library,
    521                                 FT_Stream   stream,
    522                                 char       *base_file_name,
    523                                 char      **result_file_name,
    524                                 FT_Long    *result_offset )
    525   {
    526     /*
    527       Only meaningful on systems with hfs+ drivers (or Macs).
    528      */
    529     FT_Error   error;
    530     char*      newpath = NULL;
    531     FT_Memory  memory;
    532     FT_Long    base_file_len = ft_strlen( base_file_name );
    533 
    534     FT_UNUSED( stream );
    535 
    536 
    537     memory = library->memory;
    538 
    539     if ( base_file_len + 6 > FT_INT_MAX )
    540       return FT_Err_Array_Too_Large;
    541 
    542     if ( FT_ALLOC( newpath, base_file_len + 6 ) )
    543       return error;
    544 
    545     FT_MEM_COPY( newpath, base_file_name, base_file_len );
    546     FT_MEM_COPY( newpath + base_file_len, "/rsrc", 6 );
    547 
    548     *result_file_name = newpath;
    549     *result_offset    = 0;
    550 
    551     return FT_Err_Ok;
    552   }
    553 
    554 
    555   static FT_Error
    556   raccess_guess_darwin_newvfs( FT_Library  library,
    557                                FT_Stream   stream,
    558                                char       *base_file_name,
    559                                char      **result_file_name,
    560                                FT_Long    *result_offset )
    561   {
    562     /*
    563       Only meaningful on systems with Mac OS X (> 10.1).
    564      */
    565     FT_Error   error;
    566     char*      newpath = NULL;
    567     FT_Memory  memory;
    568     FT_Long    base_file_len = ft_strlen( base_file_name );
    569 
    570     FT_UNUSED( stream );
    571 
    572 
    573     memory = library->memory;
    574 
    575     if ( base_file_len + 18 > FT_INT_MAX )
    576       return FT_Err_Array_Too_Large;
    577 
    578     if ( FT_ALLOC( newpath, base_file_len + 18 ) )
    579       return error;
    580 
    581     FT_MEM_COPY( newpath, base_file_name, base_file_len );
    582     FT_MEM_COPY( newpath + base_file_len, "/..namedfork/rsrc", 18 );
    583 
    584     *result_file_name = newpath;
    585     *result_offset    = 0;
    586 
    587     return FT_Err_Ok;
    588   }
    589 
    590 
    591   static FT_Error
    592   raccess_guess_vfat( FT_Library  library,
    593                       FT_Stream   stream,
    594                       char       *base_file_name,
    595                       char      **result_file_name,
    596                       FT_Long    *result_offset )
    597   {
    598     char*      newpath;
    599     FT_Memory  memory;
    600 
    601     FT_UNUSED( stream );
    602 
    603 
    604     memory = library->memory;
    605 
    606     newpath = raccess_make_file_name( memory, base_file_name,
    607                                       "resource.frk/" );
    608     if ( !newpath )
    609       return FT_Err_Out_Of_Memory;
    610 
    611     *result_file_name = newpath;
    612     *result_offset    = 0;
    613 
    614     return FT_Err_Ok;
    615   }
    616 
    617 
    618   static FT_Error
    619   raccess_guess_linux_cap( FT_Library  library,
    620                            FT_Stream   stream,
    621                            char       *base_file_name,
    622                            char      **result_file_name,
    623                            FT_Long    *result_offset )
    624   {
    625     char*      newpath;
    626     FT_Memory  memory;
    627 
    628     FT_UNUSED( stream );
    629 
    630 
    631     memory = library->memory;
    632 
    633     newpath = raccess_make_file_name( memory, base_file_name, ".resource/" );
    634     if ( !newpath )
    635       return FT_Err_Out_Of_Memory;
    636 
    637     *result_file_name = newpath;
    638     *result_offset    = 0;
    639 
    640     return FT_Err_Ok;
    641   }
    642 
    643 
    644   static FT_Error
    645   raccess_guess_linux_double( FT_Library  library,
    646                               FT_Stream   stream,
    647                               char       *base_file_name,
    648                               char      **result_file_name,
    649                               FT_Long    *result_offset )
    650   {
    651     char*      newpath;
    652     FT_Error   error;
    653     FT_Memory  memory;
    654 
    655     FT_UNUSED( stream );
    656 
    657 
    658     memory = library->memory;
    659 
    660     newpath = raccess_make_file_name( memory, base_file_name, "%" );
    661     if ( !newpath )
    662       return FT_Err_Out_Of_Memory;
    663 
    664     error = raccess_guess_linux_double_from_file_name( library, newpath,
    665                                                        result_offset );
    666     if ( !error )
    667       *result_file_name = newpath;
    668     else
    669       FT_FREE( newpath );
    670 
    671     return error;
    672   }
    673 
    674 
    675   static FT_Error
    676   raccess_guess_linux_netatalk( FT_Library  library,
    677                                 FT_Stream   stream,
    678                                 char       *base_file_name,
    679                                 char      **result_file_name,
    680                                 FT_Long    *result_offset )
    681   {
    682     char*      newpath;
    683     FT_Error   error;
    684     FT_Memory  memory;
    685 
    686     FT_UNUSED( stream );
    687 
    688 
    689     memory = library->memory;
    690 
    691     newpath = raccess_make_file_name( memory, base_file_name,
    692                                       ".AppleDouble/" );
    693     if ( !newpath )
    694       return FT_Err_Out_Of_Memory;
    695 
    696     error = raccess_guess_linux_double_from_file_name( library, newpath,
    697                                                        result_offset );
    698     if ( !error )
    699       *result_file_name = newpath;
    700     else
    701       FT_FREE( newpath );
    702 
    703     return error;
    704   }
    705 
    706 
    707   static FT_Error
    708   raccess_guess_apple_generic( FT_Library  library,
    709                                FT_Stream   stream,
    710                                char       *base_file_name,
    711                                FT_Int32    magic,
    712                                FT_Long    *result_offset )
    713   {
    714     FT_Int32   magic_from_stream;
    715     FT_Error   error;
    716     FT_Int32   version_number = 0;
    717     FT_UShort  n_of_entries;
    718 
    719     int        i;
    720     FT_UInt32  entry_id, entry_offset, entry_length = 0;
    721 
    722     const FT_UInt32  resource_fork_entry_id = 0x2;
    723 
    724     FT_UNUSED( library );
    725     FT_UNUSED( base_file_name );
    726     FT_UNUSED( version_number );
    727     FT_UNUSED( entry_length   );
    728 
    729 
    730     if ( FT_READ_LONG( magic_from_stream ) )
    731       return error;
    732     if ( magic_from_stream != magic )
    733       return FT_Err_Unknown_File_Format;
    734 
    735     if ( FT_READ_LONG( version_number ) )
    736       return error;
    737 
    738     /* filler */
    739     error = FT_Stream_Skip( stream, 16 );
    740     if ( error )
    741       return error;
    742 
    743     if ( FT_READ_USHORT( n_of_entries ) )
    744       return error;
    745     if ( n_of_entries == 0 )
    746       return FT_Err_Unknown_File_Format;
    747 
    748     for ( i = 0; i < n_of_entries; i++ )
    749     {
    750       if ( FT_READ_LONG( entry_id ) )
    751         return error;
    752       if ( entry_id == resource_fork_entry_id )
    753       {
    754         if ( FT_READ_LONG( entry_offset ) ||
    755              FT_READ_LONG( entry_length ) )
    756           continue;
    757         *result_offset = entry_offset;
    758 
    759         return FT_Err_Ok;
    760       }
    761       else
    762       {
    763         error = FT_Stream_Skip( stream, 4 + 4 );    /* offset + length */
    764         if ( error )
    765           return error;
    766       }
    767     }
    768 
    769     return FT_Err_Unknown_File_Format;
    770   }
    771 
    772 
    773   static FT_Error
    774   raccess_guess_linux_double_from_file_name( FT_Library  library,
    775                                              char       *file_name,
    776                                              FT_Long    *result_offset )
    777   {
    778     FT_Open_Args  args2;
    779     FT_Stream     stream2;
    780     char *        nouse = NULL;
    781     FT_Error      error;
    782 
    783 
    784     args2.flags    = FT_OPEN_PATHNAME;
    785     args2.pathname = file_name;
    786     error = FT_Stream_New( library, &args2, &stream2 );
    787     if ( error )
    788       return error;
    789 
    790     error = raccess_guess_apple_double( library, stream2, file_name,
    791                                         &nouse, result_offset );
    792 
    793     FT_Stream_Free( stream2, 0 );
    794 
    795     return error;
    796   }
    797 
    798 
    799   static char*
    800   raccess_make_file_name( FT_Memory    memory,
    801                           const char  *original_name,
    802                           const char  *insertion )
    803   {
    804     char*        new_name = NULL;
    805     const char*  tmp;
    806     const char*  slash;
    807     size_t       new_length;
    808     FT_Error     error = FT_Err_Ok;
    809 
    810     FT_UNUSED( error );
    811 
    812 
    813     new_length = ft_strlen( original_name ) + ft_strlen( insertion );
    814     if ( FT_ALLOC( new_name, new_length + 1 ) )
    815       return NULL;
    816 
    817     tmp = ft_strrchr( original_name, '/' );
    818     if ( tmp )
    819     {
    820       ft_strncpy( new_name, original_name, tmp - original_name + 1 );
    821       new_name[tmp - original_name + 1] = '\0';
    822       slash = tmp + 1;
    823     }
    824     else
    825     {
    826       slash       = original_name;
    827       new_name[0] = '\0';
    828     }
    829 
    830     ft_strcat( new_name, insertion );
    831     ft_strcat( new_name, slash );
    832 
    833     return new_name;
    834   }
    835 
    836 
    837 #else   /* !FT_CONFIG_OPTION_GUESSING_EMBEDDED_RFORK */
    838 
    839 
    840   /*************************************************************************/
    841   /*                  Dummy function; just sets errors                     */
    842   /*************************************************************************/
    843 
    844   FT_BASE_DEF( void )
    845   FT_Raccess_Guess( FT_Library  library,
    846                     FT_Stream   stream,
    847                     char       *base_name,
    848                     char      **new_names,
    849                     FT_Long    *offsets,
    850                     FT_Error   *errors )
    851   {
    852     int  i;
    853 
    854     FT_UNUSED( library );
    855     FT_UNUSED( stream );
    856     FT_UNUSED( base_name );
    857 
    858 
    859     for ( i = 0; i < FT_RACCESS_N_RULES; i++ )
    860     {
    861       new_names[i] = NULL;
    862       offsets[i]   = 0;
    863       errors[i]    = FT_Err_Unimplemented_Feature;
    864     }
    865   }
    866 
    867 
    868 #endif  /* !FT_CONFIG_OPTION_GUESSING_EMBEDDED_RFORK */
    869 
    870 
    871 /* END */
    872