Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | Download | RSS feed

  1. /***************************************************************************/
  2. /*                                                                         */
  3. /*  ftsystem.c                                                             */
  4. /*                                                                         */
  5. /*    Unix-specific FreeType low-level system interface (body).            */
  6. /*                                                                         */
  7. /*  Copyright 1996-2002, 2004-2008, 2013 by                                */
  8. /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
  9. /*                                                                         */
  10. /*  This file is part of the FreeType project, and may only be used,       */
  11. /*  modified, and distributed under the terms of the FreeType project      */
  12. /*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
  13. /*  this file you indicate that you have read the license and              */
  14. /*  understand and accept it fully.                                        */
  15. /*                                                                         */
  16. /***************************************************************************/
  17.  
  18.  
  19. #include <ft2build.h>
  20.   /* we use our special ftconfig.h file, not the standard one */
  21. #include <ftconfig.h>
  22. #include FT_INTERNAL_DEBUG_H
  23. #include FT_SYSTEM_H
  24. #include FT_ERRORS_H
  25. #include FT_TYPES_H
  26. #include FT_INTERNAL_STREAM_H
  27.  
  28.   /* memory-mapping includes and definitions */
  29. #ifdef HAVE_UNISTD_H
  30. #include <unistd.h>
  31. #endif
  32.  
  33. #include <sys/mman.h>
  34. #ifndef MAP_FILE
  35. #define MAP_FILE  0x00
  36. #endif
  37.  
  38. #ifdef MUNMAP_USES_VOIDP
  39. #define MUNMAP_ARG_CAST  void *
  40. #else
  41. #define MUNMAP_ARG_CAST  char *
  42. #endif
  43.  
  44. #ifdef NEED_MUNMAP_DECL
  45.  
  46. #ifdef __cplusplus
  47.   extern "C"
  48. #else
  49.   extern
  50. #endif
  51.   int
  52.   munmap( char*  addr,
  53.           int    len );
  54.  
  55. #define MUNMAP_ARG_CAST  char *
  56.  
  57. #endif /* NEED_DECLARATION_MUNMAP */
  58.  
  59.  
  60. #include <sys/types.h>
  61. #include <sys/stat.h>
  62.  
  63. #ifdef HAVE_FCNTL_H
  64. #include <fcntl.h>
  65. #endif
  66.  
  67. #include <stdio.h>
  68. #include <stdlib.h>
  69. #include <string.h>
  70. #include <errno.h>
  71.  
  72.  
  73.   /*************************************************************************/
  74.   /*                                                                       */
  75.   /*                       MEMORY MANAGEMENT INTERFACE                     */
  76.   /*                                                                       */
  77.   /*************************************************************************/
  78.  
  79.  
  80.   /*************************************************************************/
  81.   /*                                                                       */
  82.   /* <Function>                                                            */
  83.   /*    ft_alloc                                                           */
  84.   /*                                                                       */
  85.   /* <Description>                                                         */
  86.   /*    The memory allocation function.                                    */
  87.   /*                                                                       */
  88.   /* <Input>                                                               */
  89.   /*    memory :: A pointer to the memory object.                          */
  90.   /*                                                                       */
  91.   /*    size   :: The requested size in bytes.                             */
  92.   /*                                                                       */
  93.   /* <Return>                                                              */
  94.   /*    The address of newly allocated block.                              */
  95.   /*                                                                       */
  96.   FT_CALLBACK_DEF( void* )
  97.   ft_alloc( FT_Memory  memory,
  98.             long       size )
  99.   {
  100.     FT_UNUSED( memory );
  101.  
  102.     return malloc( size );
  103.   }
  104.  
  105.  
  106.   /*************************************************************************/
  107.   /*                                                                       */
  108.   /* <Function>                                                            */
  109.   /*    ft_realloc                                                         */
  110.   /*                                                                       */
  111.   /* <Description>                                                         */
  112.   /*    The memory reallocation function.                                  */
  113.   /*                                                                       */
  114.   /* <Input>                                                               */
  115.   /*    memory   :: A pointer to the memory object.                        */
  116.   /*                                                                       */
  117.   /*    cur_size :: The current size of the allocated memory block.        */
  118.   /*                                                                       */
  119.   /*    new_size :: The newly requested size in bytes.                     */
  120.   /*                                                                       */
  121.   /*    block    :: The current address of the block in memory.            */
  122.   /*                                                                       */
  123.   /* <Return>                                                              */
  124.   /*    The address of the reallocated memory block.                       */
  125.   /*                                                                       */
  126.   FT_CALLBACK_DEF( void* )
  127.   ft_realloc( FT_Memory  memory,
  128.               long       cur_size,
  129.               long       new_size,
  130.               void*      block )
  131.   {
  132.     FT_UNUSED( memory );
  133.     FT_UNUSED( cur_size );
  134.  
  135.     return realloc( block, new_size );
  136.   }
  137.  
  138.  
  139.   /*************************************************************************/
  140.   /*                                                                       */
  141.   /* <Function>                                                            */
  142.   /*    ft_free                                                            */
  143.   /*                                                                       */
  144.   /* <Description>                                                         */
  145.   /*    The memory release function.                                       */
  146.   /*                                                                       */
  147.   /* <Input>                                                               */
  148.   /*    memory :: A pointer to the memory object.                          */
  149.   /*                                                                       */
  150.   /*    block  :: The address of block in memory to be freed.              */
  151.   /*                                                                       */
  152.   FT_CALLBACK_DEF( void )
  153.   ft_free( FT_Memory  memory,
  154.            void*      block )
  155.   {
  156.     FT_UNUSED( memory );
  157.  
  158.     free( block );
  159.   }
  160.  
  161.  
  162.   /*************************************************************************/
  163.   /*                                                                       */
  164.   /*                     RESOURCE MANAGEMENT INTERFACE                     */
  165.   /*                                                                       */
  166.   /*************************************************************************/
  167.  
  168.  
  169.   /*************************************************************************/
  170.   /*                                                                       */
  171.   /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
  172.   /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
  173.   /* messages during execution.                                            */
  174.   /*                                                                       */
  175. #undef  FT_COMPONENT
  176. #define FT_COMPONENT  trace_io
  177.  
  178.   /* We use the macro STREAM_FILE for convenience to extract the       */
  179.   /* system-specific stream handle from a given FreeType stream object */
  180. #define STREAM_FILE( stream )  ( (FILE*)stream->descriptor.pointer )
  181.  
  182.  
  183.   /*************************************************************************/
  184.   /*                                                                       */
  185.   /* <Function>                                                            */
  186.   /*    ft_close_stream_by_munmap                                          */
  187.   /*                                                                       */
  188.   /* <Description>                                                         */
  189.   /*    The function to close a stream which is opened by mmap.            */
  190.   /*                                                                       */
  191.   /* <Input>                                                               */
  192.   /*    stream :: A pointer to the stream object.                          */
  193.   /*                                                                       */
  194.   FT_CALLBACK_DEF( void )
  195.   ft_close_stream_by_munmap( FT_Stream  stream )
  196.   {
  197.     munmap( (MUNMAP_ARG_CAST)stream->descriptor.pointer, stream->size );
  198.  
  199.     stream->descriptor.pointer = NULL;
  200.     stream->size               = 0;
  201.     stream->base               = 0;
  202.   }
  203.  
  204.  
  205.   /*************************************************************************/
  206.   /*                                                                       */
  207.   /* <Function>                                                            */
  208.   /*    ft_close_stream_by_free                                            */
  209.   /*                                                                       */
  210.   /* <Description>                                                         */
  211.   /*    The function to close a stream which is created by ft_alloc.       */
  212.   /*                                                                       */
  213.   /* <Input>                                                               */
  214.   /*    stream :: A pointer to the stream object.                          */
  215.   /*                                                                       */
  216.   FT_CALLBACK_DEF( void )
  217.   ft_close_stream_by_free( FT_Stream  stream )
  218.   {
  219.     ft_free( NULL, stream->descriptor.pointer );
  220.  
  221.     stream->descriptor.pointer = NULL;
  222.     stream->size               = 0;
  223.     stream->base               = 0;
  224.   }
  225.  
  226.  
  227.   /* documentation is in ftobjs.h */
  228.  
  229.   FT_BASE_DEF( FT_Error )
  230.   FT_Stream_Open( FT_Stream    stream,
  231.                   const char*  filepathname )
  232.   {
  233.     int          file;
  234.     struct stat  stat_buf;
  235.  
  236.  
  237.     if ( !stream )
  238.       return FT_THROW( Invalid_Stream_Handle );
  239.  
  240.     /* open the file */
  241.     file = open( filepathname, O_RDONLY );
  242.     if ( file < 0 )
  243.     {
  244.       FT_ERROR(( "FT_Stream_Open:" ));
  245.       FT_ERROR(( " could not open `%s'\n", filepathname ));
  246.       return FT_THROW( Cannot_Open_Resource );
  247.     }
  248.  
  249.     /* Here we ensure that a "fork" will _not_ duplicate   */
  250.     /* our opened input streams on Unix.  This is critical */
  251.     /* since it avoids some (possible) access control      */
  252.     /* issues and cleans up the kernel file table a bit.   */
  253.     /*                                                     */
  254. #ifdef F_SETFD
  255. #ifdef FD_CLOEXEC
  256.     (void)fcntl( file, F_SETFD, FD_CLOEXEC );
  257. #else
  258.     (void)fcntl( file, F_SETFD, 1 );
  259. #endif /* FD_CLOEXEC */
  260. #endif /* F_SETFD */
  261.  
  262.     if ( fstat( file, &stat_buf ) < 0 )
  263.     {
  264.       FT_ERROR(( "FT_Stream_Open:" ));
  265.       FT_ERROR(( " could not `fstat' file `%s'\n", filepathname ));
  266.       goto Fail_Map;
  267.     }
  268.  
  269.     /* XXX: TODO -- real 64bit platform support                        */
  270.     /*                                                                 */
  271.     /* `stream->size' is typedef'd to unsigned long (in                */
  272.     /* freetype/ftsystem.h); `stat_buf.st_size', however, is usually   */
  273.     /* typedef'd to off_t (in sys/stat.h).                             */
  274.     /* On some platforms, the former is 32bit and the latter is 64bit. */
  275.     /* To avoid overflow caused by fonts in huge files larger than     */
  276.     /* 2GB, do a test.  Temporary fix proposed by Sean McBride.        */
  277.     /*                                                                 */
  278.     if ( stat_buf.st_size > LONG_MAX )
  279.     {
  280.       FT_ERROR(( "FT_Stream_Open: file is too big\n" ));
  281.       goto Fail_Map;
  282.     }
  283.     else if ( stat_buf.st_size == 0 )
  284.     {
  285.       FT_ERROR(( "FT_Stream_Open: zero-length file\n" ));
  286.       goto Fail_Map;
  287.     }
  288.  
  289.     /* This cast potentially truncates a 64bit to 32bit! */
  290.     stream->size = (unsigned long)stat_buf.st_size;
  291.     stream->pos  = 0;
  292.     stream->base = (unsigned char *)mmap( NULL,
  293.                                           stream->size,
  294.                                           PROT_READ,
  295.                                           MAP_FILE | MAP_PRIVATE,
  296.                                           file,
  297.                                           0 );
  298.  
  299.     /* on some RTOS, mmap might return 0 */
  300.     if ( (long)stream->base != -1 && stream->base != NULL )
  301.       stream->close = ft_close_stream_by_munmap;
  302.     else
  303.     {
  304.       ssize_t  total_read_count;
  305.  
  306.  
  307.       FT_ERROR(( "FT_Stream_Open:" ));
  308.       FT_ERROR(( " could not `mmap' file `%s'\n", filepathname ));
  309.  
  310.       stream->base = (unsigned char*)ft_alloc( NULL, stream->size );
  311.  
  312.       if ( !stream->base )
  313.       {
  314.         FT_ERROR(( "FT_Stream_Open:" ));
  315.         FT_ERROR(( " could not `alloc' memory\n" ));
  316.         goto Fail_Map;
  317.       }
  318.  
  319.       total_read_count = 0;
  320.       do {
  321.         ssize_t  read_count;
  322.  
  323.  
  324.         read_count = read( file,
  325.                            stream->base + total_read_count,
  326.                            stream->size - total_read_count );
  327.  
  328.         if ( read_count <= 0 )
  329.         {
  330.           if ( read_count == -1 && errno == EINTR )
  331.             continue;
  332.  
  333.           FT_ERROR(( "FT_Stream_Open:" ));
  334.           FT_ERROR(( " error while `read'ing file `%s'\n", filepathname ));
  335.           goto Fail_Read;
  336.         }
  337.  
  338.         total_read_count += read_count;
  339.  
  340.       } while ( (unsigned long)total_read_count != stream->size );
  341.  
  342.       stream->close = ft_close_stream_by_free;
  343.     }
  344.  
  345.     close( file );
  346.  
  347.     stream->descriptor.pointer = stream->base;
  348.     stream->pathname.pointer   = (char*)filepathname;
  349.  
  350.     stream->read = 0;
  351.  
  352.     FT_TRACE1(( "FT_Stream_Open:" ));
  353.     FT_TRACE1(( " opened `%s' (%d bytes) successfully\n",
  354.                 filepathname, stream->size ));
  355.  
  356.     return FT_Err_Ok;
  357.  
  358.   Fail_Read:
  359.     ft_free( NULL, stream->base );
  360.  
  361.   Fail_Map:
  362.     close( file );
  363.  
  364.     stream->base = NULL;
  365.     stream->size = 0;
  366.     stream->pos  = 0;
  367.  
  368.     return FT_THROW( Cannot_Open_Stream );
  369.   }
  370.  
  371.  
  372. #ifdef FT_DEBUG_MEMORY
  373.  
  374.   extern FT_Int
  375.   ft_mem_debug_init( FT_Memory  memory );
  376.  
  377.   extern void
  378.   ft_mem_debug_done( FT_Memory  memory );
  379.  
  380. #endif
  381.  
  382.  
  383.   /* documentation is in ftobjs.h */
  384.  
  385.   FT_BASE_DEF( FT_Memory )
  386.   FT_New_Memory( void )
  387.   {
  388.     FT_Memory  memory;
  389.  
  390.  
  391.     memory = (FT_Memory)malloc( sizeof ( *memory ) );
  392.     if ( memory )
  393.     {
  394.       memory->user    = 0;
  395.       memory->alloc   = ft_alloc;
  396.       memory->realloc = ft_realloc;
  397.       memory->free    = ft_free;
  398. #ifdef FT_DEBUG_MEMORY
  399.       ft_mem_debug_init( memory );
  400. #endif
  401.     }
  402.  
  403.     return memory;
  404.   }
  405.  
  406.  
  407.   /* documentation is in ftobjs.h */
  408.  
  409.   FT_BASE_DEF( void )
  410.   FT_Done_Memory( FT_Memory  memory )
  411.   {
  412. #ifdef FT_DEBUG_MEMORY
  413.     ft_mem_debug_done( memory );
  414. #endif
  415.     memory->free( memory, memory );
  416.   }
  417.  
  418.  
  419. /* END */
  420.