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;
    163     FT_RFork_Ref  *ref;
    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   FT_BASE_DEF( void )
    353   FT_Raccess_Guess( FT_Library  library,
    354                     FT_Stream   stream,
    355                     char*       base_name,
    356                     char      **new_names,
    357                     FT_Long    *offsets,
    358                     FT_Error   *errors )
    359   {
    360     FT_Long  i;
    361 
    362 
    363     raccess_guess_func  funcs[FT_RACCESS_N_RULES] =
    364     {
    365       raccess_guess_apple_double,
    366       raccess_guess_apple_single,
    367       raccess_guess_darwin_ufs_export,
    368       raccess_guess_darwin_newvfs,
    369       raccess_guess_darwin_hfsplus,
    370       raccess_guess_vfat,
    371       raccess_guess_linux_cap,
    372       raccess_guess_linux_double,
    373       raccess_guess_linux_netatalk,
    374     };
    375 
    376     for ( i = 0; i < FT_RACCESS_N_RULES; i++ )
    377     {
    378       new_names[i] = NULL;
    379       if ( NULL != stream )
    380         errors[i] = FT_Stream_Seek( stream, 0 );
    381       else
    382         errors[i] = FT_Err_Ok;
    383 
    384       if ( errors[i] )
    385         continue ;
    386 
    387       errors[i] = (funcs[i])( library, stream, base_name,
    388                               &(new_names[i]), &(offsets[i]) );
    389     }
    390 
    391     return;
    392   }
    393 
    394 
    395   static FT_Error
    396   raccess_guess_apple_double( FT_Library  library,
    397                               FT_Stream   stream,
    398                               char       *base_file_name,
    399                               char      **result_file_name,
    400                               FT_Long    *result_offset )
    401   {
    402     FT_Int32  magic = ( 0x00 << 24 ) |
    403                       ( 0x05 << 16 ) |
    404                       ( 0x16 <<  8 ) |
    405                         0x07;
    406 
    407 
    408     *result_file_name = NULL;
    409     if ( NULL == stream )
    410       return FT_Err_Cannot_Open_Stream;
    411 
    412     return raccess_guess_apple_generic( library, stream, base_file_name,
    413                                         magic, result_offset );
    414   }
    415 
    416 
    417   static FT_Error
    418   raccess_guess_apple_single( FT_Library  library,
    419                               FT_Stream   stream,
    420                               char       *base_file_name,
    421                               char      **result_file_name,
    422                               FT_Long    *result_offset )
    423   {
    424     FT_Int32  magic = ( 0x00 << 24 ) |
    425                       ( 0x05 << 16 ) |
    426                       ( 0x16 <<  8 ) |
    427                         0x00;
    428 
    429 
    430     *result_file_name = NULL;
    431     if ( NULL == stream )
    432       return FT_Err_Cannot_Open_Stream;
    433 
    434     return raccess_guess_apple_generic( library, stream, base_file_name,
    435                                         magic, result_offset );
    436   }
    437 
    438 
    439   static FT_Error
    440   raccess_guess_darwin_ufs_export( FT_Library  library,
    441                                    FT_Stream   stream,
    442                                    char       *base_file_name,
    443                                    char      **result_file_name,
    444                                    FT_Long    *result_offset )
    445   {
    446     char*      newpath;
    447     FT_Error   error;
    448     FT_Memory  memory;
    449 
    450     FT_UNUSED( stream );
    451 
    452 
    453     memory  = library->memory;
    454     newpath = raccess_make_file_name( memory, base_file_name, "._" );
    455     if ( !newpath )
    456       return FT_Err_Out_Of_Memory;
    457 
    458     error = raccess_guess_linux_double_from_file_name( library, newpath,
    459                                                        result_offset );
    460     if ( !error )
    461       *result_file_name = newpath;
    462     else
    463       FT_FREE( newpath );
    464 
    465     return error;
    466   }
    467 
    468 
    469   static FT_Error
    470   raccess_guess_darwin_hfsplus( FT_Library  library,
    471                                 FT_Stream   stream,
    472                                 char       *base_file_name,
    473                                 char      **result_file_name,
    474                                 FT_Long    *result_offset )
    475   {
    476     /*
    477       Only meaningful on systems with hfs+ drivers (or Macs).
    478      */
    479     FT_Error   error;
    480     char*      newpath;
    481     FT_Memory  memory;
    482     FT_Long    base_file_len = ft_strlen( base_file_name );
    483 
    484     FT_UNUSED( stream );
    485 
    486 
    487     memory = library->memory;
    488 
    489     if ( base_file_len + 6 > FT_INT_MAX )
    490       return FT_Err_Array_Too_Large;
    491 
    492     if ( FT_ALLOC( newpath, base_file_len + 6 ) )
    493       return error;
    494 
    495     FT_MEM_COPY( newpath, base_file_name, base_file_len );
    496     FT_MEM_COPY( newpath + base_file_len, "/rsrc", 6 );
    497 
    498     *result_file_name = newpath;
    499     *result_offset    = 0;
    500 
    501     return FT_Err_Ok;
    502   }
    503 
    504 
    505   static FT_Error
    506   raccess_guess_darwin_newvfs( FT_Library  library,
    507                                FT_Stream   stream,
    508                                char       *base_file_name,
    509                                char      **result_file_name,
    510                                FT_Long    *result_offset )
    511   {
    512     /*
    513       Only meaningful on systems with Mac OS X (> 10.1).
    514      */
    515     FT_Error   error;
    516     char*      newpath;
    517     FT_Memory  memory;
    518     FT_Long    base_file_len = ft_strlen( base_file_name );
    519 
    520     FT_UNUSED( stream );
    521 
    522 
    523     memory = library->memory;
    524 
    525     if ( base_file_len + 18 > FT_INT_MAX )
    526       return FT_Err_Array_Too_Large;
    527 
    528     if ( FT_ALLOC( newpath, base_file_len + 18 ) )
    529       return error;
    530 
    531     FT_MEM_COPY( newpath, base_file_name, base_file_len );
    532     FT_MEM_COPY( newpath + base_file_len, "/..namedfork/rsrc", 18 );
    533 
    534     *result_file_name = newpath;
    535     *result_offset    = 0;
    536 
    537     return FT_Err_Ok;
    538   }
    539 
    540 
    541   static FT_Error
    542   raccess_guess_vfat( FT_Library  library,
    543                       FT_Stream   stream,
    544                       char       *base_file_name,
    545                       char      **result_file_name,
    546                       FT_Long    *result_offset )
    547   {
    548     char*      newpath;
    549     FT_Memory  memory;
    550 
    551     FT_UNUSED( stream );
    552 
    553 
    554     memory = library->memory;
    555 
    556     newpath = raccess_make_file_name( memory, base_file_name,
    557                                       "resource.frk/" );
    558     if ( !newpath )
    559       return FT_Err_Out_Of_Memory;
    560 
    561     *result_file_name = newpath;
    562     *result_offset    = 0;
    563 
    564     return FT_Err_Ok;
    565   }
    566 
    567 
    568   static FT_Error
    569   raccess_guess_linux_cap( FT_Library  library,
    570                            FT_Stream   stream,
    571                            char       *base_file_name,
    572                            char      **result_file_name,
    573                            FT_Long    *result_offset )
    574   {
    575     char*      newpath;
    576     FT_Memory  memory;
    577 
    578     FT_UNUSED( stream );
    579 
    580 
    581     memory = library->memory;
    582 
    583     newpath = raccess_make_file_name( memory, base_file_name, ".resource/" );
    584     if ( !newpath )
    585       return FT_Err_Out_Of_Memory;
    586 
    587     *result_file_name = newpath;
    588     *result_offset    = 0;
    589 
    590     return FT_Err_Ok;
    591   }
    592 
    593 
    594   static FT_Error
    595   raccess_guess_linux_double( FT_Library  library,
    596                               FT_Stream   stream,
    597                               char       *base_file_name,
    598                               char      **result_file_name,
    599                               FT_Long    *result_offset )
    600   {
    601     char*      newpath;
    602     FT_Error   error;
    603     FT_Memory  memory;
    604 
    605     FT_UNUSED( stream );
    606 
    607 
    608     memory = library->memory;
    609 
    610     newpath = raccess_make_file_name( memory, base_file_name, "%" );
    611     if ( !newpath )
    612       return FT_Err_Out_Of_Memory;
    613 
    614     error = raccess_guess_linux_double_from_file_name( library, newpath,
    615                                                        result_offset );
    616     if ( !error )
    617       *result_file_name = newpath;
    618     else
    619       FT_FREE( newpath );
    620 
    621     return error;
    622   }
    623 
    624 
    625   static FT_Error
    626   raccess_guess_linux_netatalk( FT_Library  library,
    627                                 FT_Stream   stream,
    628                                 char       *base_file_name,
    629                                 char      **result_file_name,
    630                                 FT_Long    *result_offset )
    631   {
    632     char*      newpath;
    633     FT_Error   error;
    634     FT_Memory  memory;
    635 
    636     FT_UNUSED( stream );
    637 
    638 
    639     memory = library->memory;
    640 
    641     newpath = raccess_make_file_name( memory, base_file_name,
    642                                       ".AppleDouble/" );
    643     if ( !newpath )
    644       return FT_Err_Out_Of_Memory;
    645 
    646     error = raccess_guess_linux_double_from_file_name( library, newpath,
    647                                                        result_offset );
    648     if ( !error )
    649       *result_file_name = newpath;
    650     else
    651       FT_FREE( newpath );
    652 
    653     return error;
    654   }
    655 
    656 
    657   static FT_Error
    658   raccess_guess_apple_generic( FT_Library  library,
    659                                FT_Stream   stream,
    660                                char       *base_file_name,
    661                                FT_Int32    magic,
    662                                FT_Long    *result_offset )
    663   {
    664     FT_Int32   magic_from_stream;
    665     FT_Error   error;
    666     FT_Int32   version_number = 0;
    667     FT_UShort  n_of_entries;
    668 
    669     int        i;
    670     FT_UInt32  entry_id, entry_offset, entry_length = 0;
    671 
    672     const FT_UInt32  resource_fork_entry_id = 0x2;
    673 
    674     FT_UNUSED( library );
    675     FT_UNUSED( base_file_name );
    676     FT_UNUSED( version_number );
    677     FT_UNUSED( entry_length   );
    678 
    679 
    680     if ( FT_READ_LONG( magic_from_stream ) )
    681       return error;
    682     if ( magic_from_stream != magic )
    683       return FT_Err_Unknown_File_Format;
    684 
    685     if ( FT_READ_LONG( version_number ) )
    686       return error;
    687 
    688     /* filler */
    689     error = FT_Stream_Skip( stream, 16 );
    690     if ( error )
    691       return error;
    692 
    693     if ( FT_READ_USHORT( n_of_entries ) )
    694       return error;
    695     if ( n_of_entries == 0 )
    696       return FT_Err_Unknown_File_Format;
    697 
    698     for ( i = 0; i < n_of_entries; i++ )
    699     {
    700       if ( FT_READ_LONG( entry_id ) )
    701         return error;
    702       if ( entry_id == resource_fork_entry_id )
    703       {
    704         if ( FT_READ_LONG( entry_offset ) ||
    705              FT_READ_LONG( entry_length ) )
    706           continue;
    707         *result_offset = entry_offset;
    708 
    709         return FT_Err_Ok;
    710       }
    711       else
    712       {
    713         error = FT_Stream_Skip( stream, 4 + 4 );    /* offset + length */
    714         if ( error )
    715           return error;
    716       }
    717     }
    718 
    719     return FT_Err_Unknown_File_Format;
    720   }
    721 
    722 
    723   static FT_Error
    724   raccess_guess_linux_double_from_file_name( FT_Library  library,
    725                                              char       *file_name,
    726                                              FT_Long    *result_offset )
    727   {
    728     FT_Open_Args  args2;
    729     FT_Stream     stream2;
    730     char *        nouse = NULL;
    731     FT_Error      error;
    732 
    733 
    734     args2.flags    = FT_OPEN_PATHNAME;
    735     args2.pathname = file_name;
    736     error = FT_Stream_New( library, &args2, &stream2 );
    737     if ( error )
    738       return error;
    739 
    740     error = raccess_guess_apple_double( library, stream2, file_name,
    741                                         &nouse, result_offset );
    742 
    743     FT_Stream_Free( stream2, 0 );
    744 
    745     return error;
    746   }
    747 
    748 
    749   static char*
    750   raccess_make_file_name( FT_Memory    memory,
    751                           const char  *original_name,
    752                           const char  *insertion )
    753   {
    754     char*        new_name = NULL;
    755     const char*  tmp;
    756     const char*  slash;
    757     size_t       new_length;
    758     FT_Error     error = FT_Err_Ok;
    759 
    760     FT_UNUSED( error );
    761 
    762 
    763     new_length = ft_strlen( original_name ) + ft_strlen( insertion );
    764     if ( FT_ALLOC( new_name, new_length + 1 ) )
    765       return NULL;
    766 
    767     tmp = ft_strrchr( original_name, '/' );
    768     if ( tmp )
    769     {
    770       ft_strncpy( new_name, original_name, tmp - original_name + 1 );
    771       new_name[tmp - original_name + 1] = '\0';
    772       slash = tmp + 1;
    773     }
    774     else
    775     {
    776       slash       = original_name;
    777       new_name[0] = '\0';
    778     }
    779 
    780     ft_strcat( new_name, insertion );
    781     ft_strcat( new_name, slash );
    782 
    783     return new_name;
    784   }
    785 
    786 
    787 #else   /* !FT_CONFIG_OPTION_GUESSING_EMBEDDED_RFORK */
    788 
    789 
    790   /*************************************************************************/
    791   /*                  Dummy function; just sets errors                     */
    792   /*************************************************************************/
    793 
    794   FT_BASE_DEF( void )
    795   FT_Raccess_Guess( FT_Library  library,
    796                     FT_Stream   stream,
    797                     char       *base_name,
    798                     char      **new_names,
    799                     FT_Long    *offsets,
    800                     FT_Error   *errors )
    801   {
    802     int  i;
    803 
    804     FT_UNUSED( library );
    805     FT_UNUSED( stream );
    806     FT_UNUSED( base_name );
    807 
    808 
    809     for ( i = 0; i < FT_RACCESS_N_RULES; i++ )
    810     {
    811       new_names[i] = NULL;
    812       offsets[i]   = 0;
    813       errors[i]    = FT_Err_Unimplemented_Feature;
    814     }
    815   }
    816 
    817 
    818 #endif  /* !FT_CONFIG_OPTION_GUESSING_EMBEDDED_RFORK */
    819 
    820 
    821 /* END */
    822