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 #include "basepic.h"
     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   static FT_Error
    257   raccess_guess_apple_double( FT_Library  library,
    258                               FT_Stream   stream,
    259                               char       *base_file_name,
    260                               char      **result_file_name,
    261                               FT_Long    *result_offset );
    262 
    263   static FT_Error
    264   raccess_guess_apple_single( FT_Library  library,
    265                               FT_Stream   stream,
    266                               char       *base_file_name,
    267                               char      **result_file_name,
    268                               FT_Long    *result_offset );
    269 
    270   static FT_Error
    271   raccess_guess_darwin_ufs_export( FT_Library  library,
    272                                    FT_Stream   stream,
    273                                    char       *base_file_name,
    274                                    char      **result_file_name,
    275                                    FT_Long    *result_offset );
    276 
    277   static FT_Error
    278   raccess_guess_darwin_newvfs( FT_Library  library,
    279                                FT_Stream   stream,
    280                                char       *base_file_name,
    281                                char      **result_file_name,
    282                                FT_Long    *result_offset );
    283 
    284   static FT_Error
    285   raccess_guess_darwin_hfsplus( FT_Library  library,
    286                                 FT_Stream   stream,
    287                                 char       *base_file_name,
    288                                 char      **result_file_name,
    289                                 FT_Long    *result_offset );
    290 
    291   static FT_Error
    292   raccess_guess_vfat( FT_Library  library,
    293                       FT_Stream   stream,
    294                       char       *base_file_name,
    295                       char      **result_file_name,
    296                       FT_Long    *result_offset );
    297 
    298   static FT_Error
    299   raccess_guess_linux_cap( FT_Library  library,
    300                            FT_Stream   stream,
    301                            char       *base_file_name,
    302                            char      **result_file_name,
    303                            FT_Long    *result_offset );
    304 
    305   static FT_Error
    306   raccess_guess_linux_double( FT_Library  library,
    307                               FT_Stream   stream,
    308                               char       *base_file_name,
    309                               char      **result_file_name,
    310                               FT_Long    *result_offset );
    311 
    312   static FT_Error
    313   raccess_guess_linux_netatalk( FT_Library  library,
    314                                 FT_Stream   stream,
    315                                 char       *base_file_name,
    316                                 char      **result_file_name,
    317                                 FT_Long    *result_offset );
    318 
    319 
    320   CONST_FT_RFORK_RULE_ARRAY_BEGIN(ft_raccess_guess_table,
    321                                   ft_raccess_guess_rec)
    322   CONST_FT_RFORK_RULE_ARRAY_ENTRY(apple_double,      apple_double)
    323   CONST_FT_RFORK_RULE_ARRAY_ENTRY(apple_single,      apple_single)
    324   CONST_FT_RFORK_RULE_ARRAY_ENTRY(darwin_ufs_export, darwin_ufs_export)
    325   CONST_FT_RFORK_RULE_ARRAY_ENTRY(darwin_newvfs,     darwin_newvfs)
    326   CONST_FT_RFORK_RULE_ARRAY_ENTRY(darwin_hfsplus,    darwin_hfsplus)
    327   CONST_FT_RFORK_RULE_ARRAY_ENTRY(vfat,              vfat)
    328   CONST_FT_RFORK_RULE_ARRAY_ENTRY(linux_cap,         linux_cap)
    329   CONST_FT_RFORK_RULE_ARRAY_ENTRY(linux_double,      linux_double)
    330   CONST_FT_RFORK_RULE_ARRAY_ENTRY(linux_netatalk,    linux_netatalk)
    331   CONST_FT_RFORK_RULE_ARRAY_END
    332 
    333 
    334   /*************************************************************************/
    335   /****                                                                 ****/
    336   /****                       Helper functions                          ****/
    337   /****                                                                 ****/
    338   /*************************************************************************/
    339 
    340   static FT_Error
    341   raccess_guess_apple_generic( FT_Library  library,
    342                                FT_Stream   stream,
    343                                char       *base_file_name,
    344                                FT_Int32    magic,
    345                                FT_Long    *result_offset );
    346 
    347   static FT_Error
    348   raccess_guess_linux_double_from_file_name( FT_Library  library,
    349                                              char *      file_name,
    350                                              FT_Long    *result_offset );
    351 
    352   static char *
    353   raccess_make_file_name( FT_Memory    memory,
    354                           const char  *original_name,
    355                           const char  *insertion );
    356 
    357   FT_BASE_DEF( void )
    358   FT_Raccess_Guess( FT_Library  library,
    359                     FT_Stream   stream,
    360                     char*       base_name,
    361                     char      **new_names,
    362                     FT_Long    *offsets,
    363                     FT_Error   *errors )
    364   {
    365     FT_Long  i;
    366 
    367 
    368     for ( i = 0; i < FT_RACCESS_N_RULES; i++ )
    369     {
    370       new_names[i] = NULL;
    371       if ( NULL != stream )
    372         errors[i] = FT_Stream_Seek( stream, 0 );
    373       else
    374         errors[i] = FT_Err_Ok;
    375 
    376       if ( errors[i] )
    377         continue ;
    378 
    379       errors[i] = (FT_RACCESS_GUESS_TABLE_GET[i].func)( library,
    380                                                  stream, base_name,
    381                                                  &(new_names[i]),
    382                                                  &(offsets[i]) );
    383     }
    384 
    385     return;
    386   }
    387 
    388 
    389 #ifndef FT_MACINTOSH
    390   static FT_RFork_Rule
    391   raccess_get_rule_type_from_rule_index( FT_Library  library,
    392                                          FT_UInt     rule_index )
    393   {
    394     FT_UNUSED( library );
    395 
    396     if ( rule_index >= FT_RACCESS_N_RULES )
    397       return FT_RFork_Rule_invalid;
    398 
    399     return FT_RACCESS_GUESS_TABLE_GET[rule_index].type;
    400   }
    401 
    402 
    403   /*
    404    * For this function, refer ftbase.h.
    405    */
    406   FT_LOCAL_DEF( FT_Bool )
    407   ft_raccess_rule_by_darwin_vfs( FT_Library  library,
    408                                  FT_UInt     rule_index )
    409   {
    410     switch( raccess_get_rule_type_from_rule_index( library, rule_index ) )
    411     {
    412       case FT_RFork_Rule_darwin_newvfs:
    413       case FT_RFork_Rule_darwin_hfsplus:
    414         return TRUE;
    415 
    416       default:
    417         return FALSE;
    418     }
    419   }
    420 #endif
    421 
    422 
    423   static FT_Error
    424   raccess_guess_apple_double( FT_Library  library,
    425                               FT_Stream   stream,
    426                               char       *base_file_name,
    427                               char      **result_file_name,
    428                               FT_Long    *result_offset )
    429   {
    430     FT_Int32  magic = ( 0x00 << 24 ) |
    431                       ( 0x05 << 16 ) |
    432                       ( 0x16 <<  8 ) |
    433                         0x07;
    434 
    435 
    436     *result_file_name = NULL;
    437     if ( NULL == stream )
    438       return FT_Err_Cannot_Open_Stream;
    439 
    440     return raccess_guess_apple_generic( library, stream, base_file_name,
    441                                         magic, result_offset );
    442   }
    443 
    444 
    445   static FT_Error
    446   raccess_guess_apple_single( 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                         0x00;
    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_darwin_ufs_export( FT_Library  library,
    469                                    FT_Stream   stream,
    470                                    char       *base_file_name,
    471                                    char      **result_file_name,
    472                                    FT_Long    *result_offset )
    473   {
    474     char*      newpath;
    475     FT_Error   error;
    476     FT_Memory  memory;
    477 
    478     FT_UNUSED( stream );
    479 
    480 
    481     memory  = library->memory;
    482     newpath = raccess_make_file_name( memory, base_file_name, "._" );
    483     if ( !newpath )
    484       return FT_Err_Out_Of_Memory;
    485 
    486     error = raccess_guess_linux_double_from_file_name( library, newpath,
    487                                                        result_offset );
    488     if ( !error )
    489       *result_file_name = newpath;
    490     else
    491       FT_FREE( newpath );
    492 
    493     return error;
    494   }
    495 
    496 
    497   static FT_Error
    498   raccess_guess_darwin_hfsplus( FT_Library  library,
    499                                 FT_Stream   stream,
    500                                 char       *base_file_name,
    501                                 char      **result_file_name,
    502                                 FT_Long    *result_offset )
    503   {
    504     /*
    505       Only meaningful on systems with hfs+ drivers (or Macs).
    506      */
    507     FT_Error   error;
    508     char*      newpath = NULL;
    509     FT_Memory  memory;
    510     FT_Long    base_file_len = ft_strlen( base_file_name );
    511 
    512     FT_UNUSED( stream );
    513 
    514 
    515     memory = library->memory;
    516 
    517     if ( base_file_len + 6 > FT_INT_MAX )
    518       return FT_Err_Array_Too_Large;
    519 
    520     if ( FT_ALLOC( newpath, base_file_len + 6 ) )
    521       return error;
    522 
    523     FT_MEM_COPY( newpath, base_file_name, base_file_len );
    524     FT_MEM_COPY( newpath + base_file_len, "/rsrc", 6 );
    525 
    526     *result_file_name = newpath;
    527     *result_offset    = 0;
    528 
    529     return FT_Err_Ok;
    530   }
    531 
    532 
    533   static FT_Error
    534   raccess_guess_darwin_newvfs( FT_Library  library,
    535                                FT_Stream   stream,
    536                                char       *base_file_name,
    537                                char      **result_file_name,
    538                                FT_Long    *result_offset )
    539   {
    540     /*
    541       Only meaningful on systems with Mac OS X (> 10.1).
    542      */
    543     FT_Error   error;
    544     char*      newpath = NULL;
    545     FT_Memory  memory;
    546     FT_Long    base_file_len = ft_strlen( base_file_name );
    547 
    548     FT_UNUSED( stream );
    549 
    550 
    551     memory = library->memory;
    552 
    553     if ( base_file_len + 18 > FT_INT_MAX )
    554       return FT_Err_Array_Too_Large;
    555 
    556     if ( FT_ALLOC( newpath, base_file_len + 18 ) )
    557       return error;
    558 
    559     FT_MEM_COPY( newpath, base_file_name, base_file_len );
    560     FT_MEM_COPY( newpath + base_file_len, "/..namedfork/rsrc", 18 );
    561 
    562     *result_file_name = newpath;
    563     *result_offset    = 0;
    564 
    565     return FT_Err_Ok;
    566   }
    567 
    568 
    569   static FT_Error
    570   raccess_guess_vfat( FT_Library  library,
    571                       FT_Stream   stream,
    572                       char       *base_file_name,
    573                       char      **result_file_name,
    574                       FT_Long    *result_offset )
    575   {
    576     char*      newpath;
    577     FT_Memory  memory;
    578 
    579     FT_UNUSED( stream );
    580 
    581 
    582     memory = library->memory;
    583 
    584     newpath = raccess_make_file_name( memory, base_file_name,
    585                                       "resource.frk/" );
    586     if ( !newpath )
    587       return FT_Err_Out_Of_Memory;
    588 
    589     *result_file_name = newpath;
    590     *result_offset    = 0;
    591 
    592     return FT_Err_Ok;
    593   }
    594 
    595 
    596   static FT_Error
    597   raccess_guess_linux_cap( FT_Library  library,
    598                            FT_Stream   stream,
    599                            char       *base_file_name,
    600                            char      **result_file_name,
    601                            FT_Long    *result_offset )
    602   {
    603     char*      newpath;
    604     FT_Memory  memory;
    605 
    606     FT_UNUSED( stream );
    607 
    608 
    609     memory = library->memory;
    610 
    611     newpath = raccess_make_file_name( memory, base_file_name, ".resource/" );
    612     if ( !newpath )
    613       return FT_Err_Out_Of_Memory;
    614 
    615     *result_file_name = newpath;
    616     *result_offset    = 0;
    617 
    618     return FT_Err_Ok;
    619   }
    620 
    621 
    622   static FT_Error
    623   raccess_guess_linux_double( FT_Library  library,
    624                               FT_Stream   stream,
    625                               char       *base_file_name,
    626                               char      **result_file_name,
    627                               FT_Long    *result_offset )
    628   {
    629     char*      newpath;
    630     FT_Error   error;
    631     FT_Memory  memory;
    632 
    633     FT_UNUSED( stream );
    634 
    635 
    636     memory = library->memory;
    637 
    638     newpath = raccess_make_file_name( memory, base_file_name, "%" );
    639     if ( !newpath )
    640       return FT_Err_Out_Of_Memory;
    641 
    642     error = raccess_guess_linux_double_from_file_name( library, newpath,
    643                                                        result_offset );
    644     if ( !error )
    645       *result_file_name = newpath;
    646     else
    647       FT_FREE( newpath );
    648 
    649     return error;
    650   }
    651 
    652 
    653   static FT_Error
    654   raccess_guess_linux_netatalk( FT_Library  library,
    655                                 FT_Stream   stream,
    656                                 char       *base_file_name,
    657                                 char      **result_file_name,
    658                                 FT_Long    *result_offset )
    659   {
    660     char*      newpath;
    661     FT_Error   error;
    662     FT_Memory  memory;
    663 
    664     FT_UNUSED( stream );
    665 
    666 
    667     memory = library->memory;
    668 
    669     newpath = raccess_make_file_name( memory, base_file_name,
    670                                       ".AppleDouble/" );
    671     if ( !newpath )
    672       return FT_Err_Out_Of_Memory;
    673 
    674     error = raccess_guess_linux_double_from_file_name( library, newpath,
    675                                                        result_offset );
    676     if ( !error )
    677       *result_file_name = newpath;
    678     else
    679       FT_FREE( newpath );
    680 
    681     return error;
    682   }
    683 
    684 
    685   static FT_Error
    686   raccess_guess_apple_generic( FT_Library  library,
    687                                FT_Stream   stream,
    688                                char       *base_file_name,
    689                                FT_Int32    magic,
    690                                FT_Long    *result_offset )
    691   {
    692     FT_Int32   magic_from_stream;
    693     FT_Error   error;
    694     FT_Int32   version_number = 0;
    695     FT_UShort  n_of_entries;
    696 
    697     int        i;
    698     FT_UInt32  entry_id, entry_offset, entry_length = 0;
    699 
    700     const FT_UInt32  resource_fork_entry_id = 0x2;
    701 
    702     FT_UNUSED( library );
    703     FT_UNUSED( base_file_name );
    704     FT_UNUSED( version_number );
    705     FT_UNUSED( entry_length   );
    706 
    707 
    708     if ( FT_READ_LONG( magic_from_stream ) )
    709       return error;
    710     if ( magic_from_stream != magic )
    711       return FT_Err_Unknown_File_Format;
    712 
    713     if ( FT_READ_LONG( version_number ) )
    714       return error;
    715 
    716     /* filler */
    717     error = FT_Stream_Skip( stream, 16 );
    718     if ( error )
    719       return error;
    720 
    721     if ( FT_READ_USHORT( n_of_entries ) )
    722       return error;
    723     if ( n_of_entries == 0 )
    724       return FT_Err_Unknown_File_Format;
    725 
    726     for ( i = 0; i < n_of_entries; i++ )
    727     {
    728       if ( FT_READ_LONG( entry_id ) )
    729         return error;
    730       if ( entry_id == resource_fork_entry_id )
    731       {
    732         if ( FT_READ_LONG( entry_offset ) ||
    733              FT_READ_LONG( entry_length ) )
    734           continue;
    735         *result_offset = entry_offset;
    736 
    737         return FT_Err_Ok;
    738       }
    739       else
    740       {
    741         error = FT_Stream_Skip( stream, 4 + 4 );    /* offset + length */
    742         if ( error )
    743           return error;
    744       }
    745     }
    746 
    747     return FT_Err_Unknown_File_Format;
    748   }
    749 
    750 
    751   static FT_Error
    752   raccess_guess_linux_double_from_file_name( FT_Library  library,
    753                                              char       *file_name,
    754                                              FT_Long    *result_offset )
    755   {
    756     FT_Open_Args  args2;
    757     FT_Stream     stream2;
    758     char *        nouse = NULL;
    759     FT_Error      error;
    760 
    761 
    762     args2.flags    = FT_OPEN_PATHNAME;
    763     args2.pathname = file_name;
    764     error = FT_Stream_New( library, &args2, &stream2 );
    765     if ( error )
    766       return error;
    767 
    768     error = raccess_guess_apple_double( library, stream2, file_name,
    769                                         &nouse, result_offset );
    770 
    771     FT_Stream_Free( stream2, 0 );
    772 
    773     return error;
    774   }
    775 
    776 
    777   static char*
    778   raccess_make_file_name( FT_Memory    memory,
    779                           const char  *original_name,
    780                           const char  *insertion )
    781   {
    782     char*        new_name = NULL;
    783     const char*  tmp;
    784     const char*  slash;
    785     size_t       new_length;
    786     FT_Error     error = FT_Err_Ok;
    787 
    788     FT_UNUSED( error );
    789 
    790 
    791     new_length = ft_strlen( original_name ) + ft_strlen( insertion );
    792     if ( FT_ALLOC( new_name, new_length + 1 ) )
    793       return NULL;
    794 
    795     tmp = ft_strrchr( original_name, '/' );
    796     if ( tmp )
    797     {
    798       ft_strncpy( new_name, original_name, tmp - original_name + 1 );
    799       new_name[tmp - original_name + 1] = '\0';
    800       slash = tmp + 1;
    801     }
    802     else
    803     {
    804       slash       = original_name;
    805       new_name[0] = '\0';
    806     }
    807 
    808     ft_strcat( new_name, insertion );
    809     ft_strcat( new_name, slash );
    810 
    811     return new_name;
    812   }
    813 
    814 
    815 #else   /* !FT_CONFIG_OPTION_GUESSING_EMBEDDED_RFORK */
    816 
    817 
    818   /*************************************************************************/
    819   /*                  Dummy function; just sets errors                     */
    820   /*************************************************************************/
    821 
    822   FT_BASE_DEF( void )
    823   FT_Raccess_Guess( FT_Library  library,
    824                     FT_Stream   stream,
    825                     char       *base_name,
    826                     char      **new_names,
    827                     FT_Long    *offsets,
    828                     FT_Error   *errors )
    829   {
    830     int  i;
    831 
    832     FT_UNUSED( library );
    833     FT_UNUSED( stream );
    834     FT_UNUSED( base_name );
    835 
    836 
    837     for ( i = 0; i < FT_RACCESS_N_RULES; i++ )
    838     {
    839       new_names[i] = NULL;
    840       offsets[i]   = 0;
    841       errors[i]    = FT_Err_Unimplemented_Feature;
    842     }
    843   }
    844 
    845 
    846 #endif  /* !FT_CONFIG_OPTION_GUESSING_EMBEDDED_RFORK */
    847 
    848 
    849 /* END */
    850