ftrfork.c
上传用户:yisoukefu
上传日期:2020-08-09
资源大小:39506k
文件大小:23k
源码类别:

其他游戏

开发平台:

Visual C++

  1. /***************************************************************************/
  2. /*                                                                         */
  3. /*  ftrfork.c                                                              */
  4. /*                                                                         */
  5. /*    Embedded resource forks accessor (body).                             */
  6. /*                                                                         */
  7. /*  Copyright 2004, 2005, 2006 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. /* Development of the code in this file is support of                      */
  22. /* Information-technology Promotion Agency, Japan.                         */
  23. /***************************************************************************/
  24. #include <ft2build.h>
  25. #include FT_INTERNAL_DEBUG_H
  26. #include FT_INTERNAL_STREAM_H
  27. #include FT_INTERNAL_RFORK_H
  28. #undef  FT_COMPONENT
  29. #define FT_COMPONENT  trace_raccess
  30.   /*************************************************************************/
  31.   /*************************************************************************/
  32.   /*************************************************************************/
  33.   /****                                                                 ****/
  34.   /****                                                                 ****/
  35.   /****               Resource fork directory access                    ****/
  36.   /****                                                                 ****/
  37.   /****                                                                 ****/
  38.   /*************************************************************************/
  39.   /*************************************************************************/
  40.   /*************************************************************************/
  41.   FT_BASE_DEF( FT_Error )
  42.   FT_Raccess_Get_HeaderInfo( FT_Library  library,
  43.                              FT_Stream   stream,
  44.                              FT_Long     rfork_offset,
  45.                              FT_Long    *map_offset,
  46.                              FT_Long    *rdata_pos )
  47.   {
  48.     FT_Error       error;
  49.     unsigned char  head[16], head2[16];
  50.     FT_Long        map_pos, rdata_len;
  51.     int            allzeros, allmatch, i;
  52.     FT_Long        type_list;
  53.     FT_UNUSED( library );
  54.     error = FT_Stream_Seek( stream, rfork_offset );
  55.     if ( error )
  56.       return error;
  57.     error = FT_Stream_Read( stream, (FT_Byte *)head, 16 );
  58.     if ( error )
  59.       return error;
  60.     *rdata_pos = rfork_offset + ( ( head[0] << 24 ) |
  61.                                   ( head[1] << 16 ) |
  62.                                   ( head[2] <<  8 ) |
  63.                                     head[3]         );
  64.     map_pos    = rfork_offset + ( ( head[4] << 24 ) |
  65.                                   ( head[5] << 16 ) |
  66.                                   ( head[6] <<  8 ) |
  67.                                     head[7]         );
  68.     rdata_len = ( head[ 8] << 24 ) |
  69.                 ( head[ 9] << 16 ) |
  70.                 ( head[10] <<  8 ) |
  71.                   head[11];
  72.     /* map_len = head[12] .. head[15] */
  73.     if ( *rdata_pos + rdata_len != map_pos || map_pos == rfork_offset )
  74.       return FT_Err_Unknown_File_Format;
  75.     error = FT_Stream_Seek( stream, map_pos );
  76.     if ( error )
  77.       return error;
  78.     head2[15] = (FT_Byte)( head[15] + 1 );       /* make it be different */
  79.     error = FT_Stream_Read( stream, (FT_Byte*)head2, 16 );
  80.     if ( error )
  81.       return error;
  82.     allzeros = 1;
  83.     allmatch = 1;
  84.     for ( i = 0; i < 16; ++i )
  85.     {
  86.       if ( head2[i] != 0 )
  87.         allzeros = 0;
  88.       if ( head2[i] != head[i] )
  89.         allmatch = 0;
  90.     }
  91.     if ( !allzeros && !allmatch )
  92.       return FT_Err_Unknown_File_Format;
  93.     /* If we have reached this point then it is probably a mac resource */
  94.     /* file.  Now, does it contain any interesting resources?           */
  95.     /* Skip handle to next resource map, the file resource number, and  */
  96.     /* attributes.                                                      */
  97.     (void)FT_STREAM_SKIP( 4        /* skip handle to next resource map */
  98.                           + 2      /* skip file resource number */
  99.                           + 2 );   /* skip attributes */
  100.     if ( FT_READ_USHORT( type_list ) )
  101.       return error;
  102.     if ( type_list == -1 )
  103.       return FT_Err_Unknown_File_Format;
  104.     error = FT_Stream_Seek( stream, map_pos + type_list );
  105.     if ( error )
  106.       return error;
  107.     *map_offset = map_pos + type_list;
  108.     return FT_Err_Ok;
  109.   }
  110.   FT_BASE_DEF( FT_Error )
  111.   FT_Raccess_Get_DataOffsets( FT_Library  library,
  112.                               FT_Stream   stream,
  113.                               FT_Long     map_offset,
  114.                               FT_Long     rdata_pos,
  115.                               FT_Long     tag,
  116.                               FT_Long   **offsets,
  117.                               FT_Long    *count )
  118.   {
  119.     FT_Error   error;
  120.     int        i, j, cnt, subcnt;
  121.     FT_Long    tag_internal, rpos;
  122.     FT_Memory  memory = library->memory;
  123.     FT_Long    temp;
  124.     FT_Long    *offsets_internal;
  125.     error = FT_Stream_Seek( stream, map_offset );
  126.     if ( error )
  127.       return error;
  128.     if ( FT_READ_USHORT( cnt ) )
  129.       return error;
  130.     cnt++;
  131.     for ( i = 0; i < cnt; ++i )
  132.     {
  133.       if ( FT_READ_LONG( tag_internal ) ||
  134.            FT_READ_USHORT( subcnt )     ||
  135.            FT_READ_USHORT( rpos )       )
  136.         return error;
  137.       FT_TRACE2(( "Resource tags: %c%c%c%cn",
  138.                   (char)( 0xff & ( tag_internal >> 24 ) ),
  139.                   (char)( 0xff & ( tag_internal >> 16 ) ),
  140.                   (char)( 0xff & ( tag_internal >>  8 ) ),
  141.                   (char)( 0xff & ( tag_internal >>  0 ) ) ));
  142.       if ( tag_internal == tag )
  143.       {
  144.         *count = subcnt + 1;
  145.         rpos  += map_offset;
  146.         error = FT_Stream_Seek( stream, rpos );
  147.         if ( error )
  148.           return error;
  149.         if ( FT_NEW_ARRAY( offsets_internal, *count ) )
  150.           return error;
  151.         for ( j = 0; j < *count; ++j )
  152.         {
  153.           (void)FT_STREAM_SKIP( 2 ); /* resource id */
  154.           (void)FT_STREAM_SKIP( 2 ); /* rsource name */
  155.           if ( FT_READ_LONG( temp ) )
  156.           {
  157.             FT_FREE( offsets_internal );
  158.             return error;
  159.           }
  160.           offsets_internal[j] = rdata_pos + ( temp & 0xFFFFFFL );
  161.           (void)FT_STREAM_SKIP( 4 ); /* mbz */
  162.         }
  163.         *offsets = offsets_internal;
  164.         return FT_Err_Ok;
  165.       }
  166.     }
  167.     return FT_Err_Cannot_Open_Resource;
  168.   }
  169. #ifdef FT_CONFIG_OPTION_GUESSING_EMBEDDED_RFORK
  170.   /*************************************************************************/
  171.   /*************************************************************************/
  172.   /*************************************************************************/
  173.   /****                                                                 ****/
  174.   /****                                                                 ****/
  175.   /****                     Guessing functions                          ****/
  176.   /****                                                                 ****/
  177.   /****            When you add a new guessing function,                ****/
  178.   /****           update FT_RACCESS_N_RULES in ftrfork.h.               ****/
  179.   /****                                                                 ****/
  180.   /*************************************************************************/
  181.   /*************************************************************************/
  182.   /*************************************************************************/
  183.   typedef FT_Error
  184.   (*raccess_guess_func)( FT_Library  library,
  185.                          FT_Stream   stream,
  186.                          char *      base_file_name,
  187.                          char      **result_file_name,
  188.                          FT_Long    *result_offset );
  189.   static FT_Error
  190.   raccess_guess_apple_double( FT_Library  library,
  191.                               FT_Stream   stream,
  192.                               char *      base_file_name,
  193.                               char      **result_file_name,
  194.                               FT_Long    *result_offset );
  195.   static FT_Error
  196.   raccess_guess_apple_single( FT_Library  library,
  197.                               FT_Stream   stream,
  198.                               char *      base_file_name,
  199.                               char      **result_file_name,
  200.                               FT_Long    *result_offset );
  201.   static FT_Error
  202.   raccess_guess_darwin_ufs_export( FT_Library  library,
  203.                                    FT_Stream   stream,
  204.                                    char *      base_file_name,
  205.                                    char      **result_file_name,
  206.                                    FT_Long    *result_offset );
  207.   static FT_Error
  208.   raccess_guess_darwin_hfsplus( FT_Library  library,
  209.                                 FT_Stream   stream,
  210.                                 char *      base_file_name,
  211.                                 char      **result_file_name,
  212.                                 FT_Long    *result_offset );
  213.   static FT_Error
  214.   raccess_guess_vfat( FT_Library  library,
  215.                       FT_Stream   stream,
  216.                       char *      base_file_name,
  217.                       char      **result_file_name,
  218.                       FT_Long    *result_offset );
  219.   static FT_Error
  220.   raccess_guess_linux_cap( FT_Library  library,
  221.                            FT_Stream   stream,
  222.                            char *      base_file_name,
  223.                            char      **result_file_name,
  224.                            FT_Long    *result_offset );
  225.   static FT_Error
  226.   raccess_guess_linux_double( FT_Library  library,
  227.                               FT_Stream   stream,
  228.                               char *      base_file_name,
  229.                               char      **result_file_name,
  230.                               FT_Long    *result_offset );
  231.   static FT_Error
  232.   raccess_guess_linux_netatalk( FT_Library  library,
  233.                                 FT_Stream   stream,
  234.                                 char *      base_file_name,
  235.                                 char      **result_file_name,
  236.                                 FT_Long    *result_offset );
  237.   /*************************************************************************/
  238.   /****                                                                 ****/
  239.   /****                       Helper functions                          ****/
  240.   /****                                                                 ****/
  241.   /*************************************************************************/
  242.   static FT_Error
  243.   raccess_guess_apple_generic( FT_Library  library,
  244.                                FT_Stream   stream,
  245.                                char *      base_file_name,
  246.                                FT_Int32    magic,
  247.                                FT_Long    *result_offset );
  248.   static FT_Error
  249.   raccess_guess_linux_double_from_file_name( FT_Library  library,
  250.                                              char *      file_name,
  251.                                              FT_Long    *result_offset );
  252.   static char *
  253.   raccess_make_file_name( FT_Memory    memory,
  254.                           const char  *original_name,
  255.                           const char  *insertion );
  256.   FT_BASE_DEF( void )
  257.   FT_Raccess_Guess( FT_Library  library,
  258.                     FT_Stream   stream,
  259.                     char*       base_name,
  260.                     char      **new_names,
  261.                     FT_Long    *offsets,
  262.                     FT_Error   *errors )
  263.   {
  264.     FT_Long  i;
  265.     raccess_guess_func  funcs[FT_RACCESS_N_RULES] =
  266.     {
  267.       raccess_guess_apple_double,
  268.       raccess_guess_apple_single,
  269.       raccess_guess_darwin_ufs_export,
  270.       raccess_guess_darwin_hfsplus,
  271.       raccess_guess_vfat,
  272.       raccess_guess_linux_cap,
  273.       raccess_guess_linux_double,
  274.       raccess_guess_linux_netatalk,
  275.     };
  276.     for ( i = 0; i < FT_RACCESS_N_RULES; i++ )
  277.     {
  278.       new_names[i] = NULL;
  279.       errors[i] = FT_Stream_Seek( stream, 0 );
  280.       if ( errors[i] )
  281.         continue ;
  282.       errors[i] = (funcs[i])( library, stream, base_name,
  283.                               &(new_names[i]), &(offsets[i]) );
  284.     }
  285.     return;
  286.   }
  287.   static FT_Error
  288.   raccess_guess_apple_double( FT_Library  library,
  289.                               FT_Stream   stream,
  290.                               char *      base_file_name,
  291.                               char      **result_file_name,
  292.                               FT_Long    *result_offset )
  293.   {
  294.     FT_Int32  magic = ( 0x00 << 24 | 0x05 << 16 | 0x16 << 8 | 0x07 );
  295.     *result_file_name = NULL;
  296.     return raccess_guess_apple_generic( library, stream, base_file_name,
  297.                                         magic, result_offset );
  298.   }
  299.   static FT_Error
  300.   raccess_guess_apple_single( FT_Library  library,
  301.                               FT_Stream   stream,
  302.                               char *      base_file_name,
  303.                               char      **result_file_name,
  304.                               FT_Long    *result_offset )
  305.   {
  306.     FT_Int32  magic = (0x00 << 24 | 0x05 << 16 | 0x16 << 8 | 0x00);
  307.     *result_file_name = NULL;
  308.     return raccess_guess_apple_generic( library, stream, base_file_name,
  309.                                         magic, result_offset );
  310.   }
  311.   static FT_Error
  312.   raccess_guess_darwin_ufs_export( FT_Library  library,
  313.                                    FT_Stream   stream,
  314.                                    char *      base_file_name,
  315.                                    char      **result_file_name,
  316.                                    FT_Long    *result_offset )
  317.   {
  318.     char*      newpath;
  319.     FT_Error   error;
  320.     FT_Memory  memory;
  321.     FT_UNUSED( stream );
  322.     memory  = library->memory;
  323.     newpath = raccess_make_file_name( memory, base_file_name, "._" );
  324.     if ( !newpath )
  325.       return FT_Err_Out_Of_Memory;
  326.     error = raccess_guess_linux_double_from_file_name( library, newpath,
  327.                                                        result_offset );
  328.     if ( !error )
  329.       *result_file_name = newpath;
  330.     else
  331.       FT_FREE( newpath );
  332.     return error;
  333.   }
  334.   static FT_Error
  335.   raccess_guess_darwin_hfsplus( FT_Library  library,
  336.                                 FT_Stream   stream,
  337.                                 char *      base_file_name,
  338.                                 char      **result_file_name,
  339.                                 FT_Long    *result_offset )
  340.   {
  341.     /*
  342.       Only meaningful on systems with hfs+ drivers (or Macs).
  343.      */
  344.     FT_Error   error;
  345.     char*      newpath;
  346.     FT_Memory  memory;
  347.     FT_Long    base_file_len = ft_strlen( base_file_name );
  348.     FT_UNUSED( stream );
  349.     memory = library->memory;
  350.     if ( base_file_len > FT_INT_MAX )
  351.       return FT_Err_Array_Too_Large;
  352.     if ( FT_ALLOC( newpath, base_file_len + 6 ) )
  353.       return error;
  354.     FT_MEM_COPY( newpath, base_file_name, base_file_len );
  355.     FT_MEM_COPY( newpath + base_file_len, "/rsrc", 6 );
  356.     *result_file_name = newpath;
  357.     *result_offset    = 0;
  358.     return FT_Err_Ok;
  359.   }
  360.   static FT_Error
  361.   raccess_guess_vfat( FT_Library  library,
  362.                       FT_Stream   stream,
  363.                       char *      base_file_name,
  364.                       char      **result_file_name,
  365.                       FT_Long    *result_offset )
  366.   {
  367.     char*      newpath;
  368.     FT_Memory  memory;
  369.     FT_UNUSED( stream );
  370.     memory = library->memory;
  371.     newpath = raccess_make_file_name( memory, base_file_name,
  372.                                       "resource.frk/" );
  373.     if ( !newpath )
  374.       return FT_Err_Out_Of_Memory;
  375.     *result_file_name = newpath;
  376.     *result_offset    = 0;
  377.     return FT_Err_Ok;
  378.   }
  379.   static FT_Error
  380.   raccess_guess_linux_cap( FT_Library  library,
  381.                            FT_Stream   stream,
  382.                            char *      base_file_name,
  383.                            char      **result_file_name,
  384.                            FT_Long    *result_offset )
  385.   {
  386.     char*      newpath;
  387.     FT_Memory  memory;
  388.     FT_UNUSED( stream );
  389.     memory = library->memory;
  390.     newpath = raccess_make_file_name( memory, base_file_name, ".resource/" );
  391.     if ( !newpath )
  392.       return FT_Err_Out_Of_Memory;
  393.     *result_file_name = newpath;
  394.     *result_offset    = 0;
  395.     return FT_Err_Ok;
  396.   }
  397.   static FT_Error
  398.   raccess_guess_linux_double( FT_Library  library,
  399.                               FT_Stream   stream,
  400.                               char *      base_file_name,
  401.                               char      **result_file_name,
  402.                               FT_Long    *result_offset )
  403.   {
  404.     char*      newpath;
  405.     FT_Error   error;
  406.     FT_Memory  memory;
  407.     FT_UNUSED( stream );
  408.     memory = library->memory;
  409.     newpath = raccess_make_file_name( memory, base_file_name, "%" );
  410.     if ( !newpath )
  411.       return FT_Err_Out_Of_Memory;
  412.     error = raccess_guess_linux_double_from_file_name( library, newpath,
  413.                                                        result_offset );
  414.     if ( !error )
  415.       *result_file_name = newpath;
  416.     else
  417.       FT_FREE( newpath );
  418.     return error;
  419.   }
  420.   static FT_Error
  421.   raccess_guess_linux_netatalk( FT_Library  library,
  422.                                 FT_Stream   stream,
  423.                                 char *      base_file_name,
  424.                                 char      **result_file_name,
  425.                                 FT_Long    *result_offset )
  426.   {
  427.     char*      newpath;
  428.     FT_Error   error;
  429.     FT_Memory  memory;
  430.     FT_UNUSED( stream );
  431.     memory = library->memory;
  432.     newpath = raccess_make_file_name( memory, base_file_name,
  433.                                       ".AppleDouble/" );
  434.     if ( !newpath )
  435.       return FT_Err_Out_Of_Memory;
  436.     error = raccess_guess_linux_double_from_file_name( library, newpath,
  437.                                                        result_offset );
  438.     if ( !error )
  439.       *result_file_name = newpath;
  440.     else
  441.       FT_FREE( newpath );
  442.     return error;
  443.   }
  444.   static FT_Error
  445.   raccess_guess_apple_generic( FT_Library  library,
  446.                                FT_Stream   stream,
  447.                                char *      base_file_name,
  448.                                FT_Int32    magic,
  449.                                FT_Long    *result_offset )
  450.   {
  451.     FT_Int32   magic_from_stream;
  452.     FT_Error   error;
  453.     FT_Int32   version_number = 0;
  454.     FT_UShort  n_of_entries;
  455.     int        i;
  456.     FT_UInt32  entry_id, entry_offset, entry_length = 0;
  457.     const FT_UInt32  resource_fork_entry_id = 0x2;
  458.     FT_UNUSED( library );
  459.     FT_UNUSED( base_file_name );
  460.     FT_UNUSED( version_number );
  461.     FT_UNUSED( entry_length   );
  462.     if ( FT_READ_LONG( magic_from_stream ) )
  463.       return error;
  464.     if ( magic_from_stream != magic )
  465.       return FT_Err_Unknown_File_Format;
  466.     if ( FT_READ_LONG( version_number ) )
  467.       return error;
  468.     /* filler */
  469.     error = FT_Stream_Skip( stream, 16 );
  470.     if ( error )
  471.       return error;
  472.     if ( FT_READ_USHORT( n_of_entries ) )
  473.       return error;
  474.     if ( n_of_entries == 0 )
  475.       return FT_Err_Unknown_File_Format;
  476.     for ( i = 0; i < n_of_entries; i++ )
  477.     {
  478.       if ( FT_READ_LONG( entry_id ) )
  479.         return error;
  480.       if ( entry_id == resource_fork_entry_id )
  481.       {
  482.         if ( FT_READ_LONG( entry_offset ) ||
  483.              FT_READ_LONG( entry_length ) )
  484.           continue;
  485.         *result_offset = entry_offset;
  486.         return FT_Err_Ok;
  487.       }
  488.       else
  489.         FT_Stream_Skip( stream, 4 + 4 );    /* offset + length */
  490.       }
  491.     return FT_Err_Unknown_File_Format;
  492.   }
  493.   static FT_Error
  494.   raccess_guess_linux_double_from_file_name( FT_Library  library,
  495.                                              char *      file_name,
  496.                                              FT_Long    *result_offset )
  497.   {
  498.     FT_Open_Args  args2;
  499.     FT_Stream     stream2;
  500.     char *        nouse = NULL;
  501.     FT_Error      error;
  502.     args2.flags    = FT_OPEN_PATHNAME;
  503.     args2.pathname = file_name;
  504.     error = FT_Stream_New( library, &args2, &stream2 );
  505.     if ( error )
  506.       return error;
  507.     error = raccess_guess_apple_double( library, stream2, file_name,
  508.                                         &nouse, result_offset );
  509.     FT_Stream_Free( stream2, 0 );
  510.     return error;
  511.   }
  512.   static char*
  513.   raccess_make_file_name( FT_Memory    memory,
  514.                           const char  *original_name,
  515.                           const char  *insertion )
  516.   {
  517.     char*        new_name;
  518.     char*        tmp;
  519.     const char*  slash;
  520.     unsigned     new_length;
  521.     FT_Error     error = FT_Err_Ok;
  522.     FT_UNUSED( error );
  523.     new_length = ft_strlen( original_name ) + ft_strlen( insertion );
  524.     if ( FT_ALLOC( new_name, new_length + 1 ) )
  525.       return NULL;
  526.     tmp = ft_strrchr( original_name, '/' );
  527.     if ( tmp )
  528.     {
  529.       ft_strncpy( new_name, original_name, tmp - original_name + 1 );
  530.       new_name[tmp - original_name + 1] = '';
  531.       slash = tmp + 1;
  532.     }
  533.     else
  534.     {
  535.       slash       = original_name;
  536.       new_name[0] = '';
  537.     }
  538.     ft_strcat( new_name, insertion );
  539.     ft_strcat( new_name, slash );
  540.     return new_name;
  541.   }
  542. #else   /* !FT_CONFIG_OPTION_GUESSING_EMBEDDED_RFORK */
  543.   /*************************************************************************/
  544.   /*                  Dummy function; just sets errors                     */
  545.   /*************************************************************************/
  546.   FT_BASE_DEF( void )
  547.   FT_Raccess_Guess( FT_Library  library,
  548.                     FT_Stream   stream,
  549.                     char*       base_name,
  550.                     char      **new_names,
  551.                     FT_Long    *offsets,
  552.                     FT_Error   *errors )
  553.   {
  554.     int  i;
  555.     FT_UNUSED( library );
  556.     FT_UNUSED( stream );
  557.     FT_UNUSED( base_name );
  558.     for ( i = 0; i < FT_RACCESS_N_RULES; i++ )
  559.     {
  560.       new_names[i] = NULL;
  561.       offsets[i]   = 0;
  562.       errors[i]    = FT_Err_Unimplemented_Feature;
  563.     }
  564.   }
  565. #endif  /* !FT_CONFIG_OPTION_GUESSING_EMBEDDED_RFORK */
  566. /* END */