misc/libfreetype/src/base/ftrfork.c
branchwebgl
changeset 9521 8054d9d775fd
parent 9282 92af50454cf2
parent 9519 b8b5c82eb61b
child 9950 2759212a27de
equal deleted inserted replaced
9282:92af50454cf2 9521:8054d9d775fd
     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   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;
       
   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;
       
   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 */