misc/libfreetype/builds/unix/ftsystem.c
changeset 9372 915436ff64ab
parent 9371 f3840de881bd
child 9373 b769a8e38cbd
equal deleted inserted replaced
9371:f3840de881bd 9372:915436ff64ab
     1 /***************************************************************************/
       
     2 /*                                                                         */
       
     3 /*  ftsystem.c                                                             */
       
     4 /*                                                                         */
       
     5 /*    Unix-specific FreeType low-level system interface (body).            */
       
     6 /*                                                                         */
       
     7 /*  Copyright 1996-2001, 2002, 2004, 2005, 2006, 2007, 2008 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_Err_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_Err_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_Err_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 */