ftsystem.c

Go to the documentation of this file.
00001 /***************************************************************************/
00002 /*                                                                         */
00003 /*  ftsystem.c                                                             */
00004 /*                                                                         */
00005 /*    Unix-specific FreeType low-level system interface (body).            */
00006 /*                                                                         */
00007 /*  Copyright 1996-2001, 2002, 2004, 2005, 2006, 2007, 2008 by             */
00008 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
00009 /*                                                                         */
00010 /*  This file is part of the FreeType project, and may only be used,       */
00011 /*  modified, and distributed under the terms of the FreeType project      */
00012 /*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
00013 /*  this file you indicate that you have read the license and              */
00014 /*  understand and accept it fully.                                        */
00015 /*                                                                         */
00016 /***************************************************************************/
00017 
00018 
00019 #include <ft2build.h>
00020   /* we use our special ftconfig.h file, not the standard one */
00021 #include <ftconfig.h>
00022 #include FT_INTERNAL_DEBUG_H
00023 #include FT_SYSTEM_H
00024 #include FT_ERRORS_H
00025 #include FT_TYPES_H
00026 #include FT_INTERNAL_STREAM_H
00027 
00028   /* memory-mapping includes and definitions */
00029 #ifdef HAVE_UNISTD_H
00030 #include <unistd.h>
00031 #endif
00032 
00033 #include <sys/mman.h>
00034 #ifndef MAP_FILE
00035 #define MAP_FILE  0x00
00036 #endif
00037 
00038 #ifdef MUNMAP_USES_VOIDP
00039 #define MUNMAP_ARG_CAST  void *
00040 #else
00041 #define MUNMAP_ARG_CAST  char *
00042 #endif
00043 
00044 #ifdef NEED_MUNMAP_DECL
00045 
00046 #ifdef __cplusplus
00047   extern "C"
00048 #else
00049   extern
00050 #endif
00051   int
00052   munmap( char*  addr,
00053           int    len );
00054 
00055 #define MUNMAP_ARG_CAST  char *
00056 
00057 #endif /* NEED_DECLARATION_MUNMAP */
00058 
00059 
00060 #include <sys/types.h>
00061 #include <sys/stat.h>
00062 
00063 #ifdef HAVE_FCNTL_H
00064 #include <fcntl.h>
00065 #endif
00066 
00067 #include <stdio.h>
00068 #include <stdlib.h>
00069 #include <string.h>
00070 #include <errno.h>
00071 
00072 
00073   /*************************************************************************/
00074   /*                                                                       */
00075   /*                       MEMORY MANAGEMENT INTERFACE                     */
00076   /*                                                                       */
00077   /*************************************************************************/
00078 
00079 
00080   /*************************************************************************/
00081   /*                                                                       */
00082   /* <Function>                                                            */
00083   /*    ft_alloc                                                           */
00084   /*                                                                       */
00085   /* <Description>                                                         */
00086   /*    The memory allocation function.                                    */
00087   /*                                                                       */
00088   /* <Input>                                                               */
00089   /*    memory :: A pointer to the memory object.                          */
00090   /*                                                                       */
00091   /*    size   :: The requested size in bytes.                             */
00092   /*                                                                       */
00093   /* <Return>                                                              */
00094   /*    The address of newly allocated block.                              */
00095   /*                                                                       */
00096   FT_CALLBACK_DEF( void* )
00097   ft_alloc( FT_Memory  memory,
00098             long       size )
00099   {
00100     FT_UNUSED( memory );
00101 
00102     return malloc( size );
00103   }
00104 
00105 
00106   /*************************************************************************/
00107   /*                                                                       */
00108   /* <Function>                                                            */
00109   /*    ft_realloc                                                         */
00110   /*                                                                       */
00111   /* <Description>                                                         */
00112   /*    The memory reallocation function.                                  */
00113   /*                                                                       */
00114   /* <Input>                                                               */
00115   /*    memory   :: A pointer to the memory object.                        */
00116   /*                                                                       */
00117   /*    cur_size :: The current size of the allocated memory block.        */
00118   /*                                                                       */
00119   /*    new_size :: The newly requested size in bytes.                     */
00120   /*                                                                       */
00121   /*    block    :: The current address of the block in memory.            */
00122   /*                                                                       */
00123   /* <Return>                                                              */
00124   /*    The address of the reallocated memory block.                       */
00125   /*                                                                       */
00126   FT_CALLBACK_DEF( void* )
00127   ft_realloc( FT_Memory  memory,
00128               long       cur_size,
00129               long       new_size,
00130               void*      block )
00131   {
00132     FT_UNUSED( memory );
00133     FT_UNUSED( cur_size );
00134 
00135     return realloc( block, new_size );
00136   }
00137 
00138 
00139   /*************************************************************************/
00140   /*                                                                       */
00141   /* <Function>                                                            */
00142   /*    ft_free                                                            */
00143   /*                                                                       */
00144   /* <Description>                                                         */
00145   /*    The memory release function.                                       */
00146   /*                                                                       */
00147   /* <Input>                                                               */
00148   /*    memory :: A pointer to the memory object.                          */
00149   /*                                                                       */
00150   /*    block  :: The address of block in memory to be freed.              */
00151   /*                                                                       */
00152   FT_CALLBACK_DEF( void )
00153   ft_free( FT_Memory  memory,
00154            void*      block )
00155   {
00156     FT_UNUSED( memory );
00157 
00158     free( block );
00159   }
00160 
00161 
00162   /*************************************************************************/
00163   /*                                                                       */
00164   /*                     RESOURCE MANAGEMENT INTERFACE                     */
00165   /*                                                                       */
00166   /*************************************************************************/
00167 
00168 
00169   /*************************************************************************/
00170   /*                                                                       */
00171   /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
00172   /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
00173   /* messages during execution.                                            */
00174   /*                                                                       */
00175 #undef  FT_COMPONENT
00176 #define FT_COMPONENT  trace_io
00177 
00178   /* We use the macro STREAM_FILE for convenience to extract the       */
00179   /* system-specific stream handle from a given FreeType stream object */
00180 #define STREAM_FILE( stream )  ( (FILE*)stream->descriptor.pointer )
00181 
00182 
00183   /*************************************************************************/
00184   /*                                                                       */
00185   /* <Function>                                                            */
00186   /*    ft_close_stream_by_munmap                                          */
00187   /*                                                                       */
00188   /* <Description>                                                         */
00189   /*    The function to close a stream which is opened by mmap.            */
00190   /*                                                                       */
00191   /* <Input>                                                               */
00192   /*    stream :: A pointer to the stream object.                          */
00193   /*                                                                       */
00194   FT_CALLBACK_DEF( void )
00195   ft_close_stream_by_munmap( FT_Stream  stream )
00196   {
00197     munmap( (MUNMAP_ARG_CAST)stream->descriptor.pointer, stream->size );
00198 
00199     stream->descriptor.pointer = NULL;
00200     stream->size               = 0;
00201     stream->base               = 0;
00202   }
00203 
00204 
00205   /*************************************************************************/
00206   /*                                                                       */
00207   /* <Function>                                                            */
00208   /*    ft_close_stream_by_free                                            */
00209   /*                                                                       */
00210   /* <Description>                                                         */
00211   /*    The function to close a stream which is created by ft_alloc.       */
00212   /*                                                                       */
00213   /* <Input>                                                               */
00214   /*    stream :: A pointer to the stream object.                          */
00215   /*                                                                       */
00216   FT_CALLBACK_DEF( void )
00217   ft_close_stream_by_free( FT_Stream  stream )
00218   {
00219     ft_free( NULL, stream->descriptor.pointer );
00220 
00221     stream->descriptor.pointer = NULL;
00222     stream->size               = 0;
00223     stream->base               = 0;
00224   }
00225 
00226 
00227   /* documentation is in ftobjs.h */
00228 
00229   FT_BASE_DEF( FT_Error )
00230   FT_Stream_Open( FT_Stream    stream,
00231                   const char*  filepathname )
00232   {
00233     int          file;
00234     struct stat  stat_buf;
00235 
00236 
00237     if ( !stream )
00238       return FT_Err_Invalid_Stream_Handle;
00239 
00240     /* open the file */
00241     file = open( filepathname, O_RDONLY );
00242     if ( file < 0 )
00243     {
00244       FT_ERROR(( "FT_Stream_Open:" ));
00245       FT_ERROR(( " could not open `%s'\n", filepathname ));
00246       return FT_Err_Cannot_Open_Resource;
00247     }
00248 
00249     /* Here we ensure that a "fork" will _not_ duplicate   */
00250     /* our opened input streams on Unix.  This is critical */
00251     /* since it avoids some (possible) access control      */
00252     /* issues and cleans up the kernel file table a bit.   */
00253     /*                                                     */
00254 #ifdef F_SETFD
00255 #ifdef FD_CLOEXEC
00256     (void)fcntl( file, F_SETFD, FD_CLOEXEC );
00257 #else
00258     (void)fcntl( file, F_SETFD, 1 );
00259 #endif /* FD_CLOEXEC */
00260 #endif /* F_SETFD */
00261 
00262     if ( fstat( file, &stat_buf ) < 0 )
00263     {
00264       FT_ERROR(( "FT_Stream_Open:" ));
00265       FT_ERROR(( " could not `fstat' file `%s'\n", filepathname ));
00266       goto Fail_Map;
00267     }
00268 
00269     /* XXX: TODO -- real 64bit platform support                        */
00270     /*                                                                 */
00271     /* `stream->size' is typedef'd to unsigned long (in                */
00272     /* freetype/ftsystem.h); `stat_buf.st_size', however, is usually   */
00273     /* typedef'd to off_t (in sys/stat.h).                             */
00274     /* On some platforms, the former is 32bit and the latter is 64bit. */
00275     /* To avoid overflow caused by fonts in huge files larger than     */
00276     /* 2GB, do a test.  Temporary fix proposed by Sean McBride.        */
00277     /*                                                                 */
00278     if ( stat_buf.st_size > LONG_MAX )
00279     {
00280       FT_ERROR(( "FT_Stream_Open: file is too big\n" ));
00281       goto Fail_Map;
00282     }
00283     else if ( stat_buf.st_size == 0 )
00284     {
00285       FT_ERROR(( "FT_Stream_Open: zero-length file\n" ));
00286       goto Fail_Map;
00287     }
00288 
00289     /* This cast potentially truncates a 64bit to 32bit! */
00290     stream->size = (unsigned long)stat_buf.st_size;
00291     stream->pos  = 0;
00292     stream->base = (unsigned char *)mmap( NULL,
00293                                           stream->size,
00294                                           PROT_READ,
00295                                           MAP_FILE | MAP_PRIVATE,
00296                                           file,
00297                                           0 );
00298 
00299     /* on some RTOS, mmap might return 0 */
00300     if ( (long)stream->base != -1 && stream->base != NULL )
00301       stream->close = ft_close_stream_by_munmap;
00302     else
00303     {
00304       ssize_t  total_read_count;
00305 
00306 
00307       FT_ERROR(( "FT_Stream_Open:" ));
00308       FT_ERROR(( " could not `mmap' file `%s'\n", filepathname ));
00309 
00310       stream->base = (unsigned char*)ft_alloc( NULL, stream->size );
00311 
00312       if ( !stream->base )
00313       {
00314         FT_ERROR(( "FT_Stream_Open:" ));
00315         FT_ERROR(( " could not `alloc' memory\n" ));
00316         goto Fail_Map;
00317       }
00318 
00319       total_read_count = 0;
00320       do {
00321         ssize_t  read_count;
00322 
00323 
00324         read_count = read( file,
00325                            stream->base + total_read_count,
00326                            stream->size - total_read_count );
00327 
00328         if ( read_count <= 0 )
00329         {
00330           if ( read_count == -1 && errno == EINTR )
00331             continue;
00332 
00333           FT_ERROR(( "FT_Stream_Open:" ));
00334           FT_ERROR(( " error while `read'ing file `%s'\n", filepathname ));
00335           goto Fail_Read;
00336         }
00337 
00338         total_read_count += read_count;
00339 
00340       } while ( (unsigned long)total_read_count != stream->size );
00341 
00342       stream->close = ft_close_stream_by_free;
00343     }
00344 
00345     close( file );
00346 
00347     stream->descriptor.pointer = stream->base;
00348     stream->pathname.pointer   = (char*)filepathname;
00349 
00350     stream->read = 0;
00351 
00352     FT_TRACE1(( "FT_Stream_Open:" ));
00353     FT_TRACE1(( " opened `%s' (%d bytes) successfully\n",
00354                 filepathname, stream->size ));
00355 
00356     return FT_Err_Ok;
00357 
00358   Fail_Read:
00359     ft_free( NULL, stream->base );
00360 
00361   Fail_Map:
00362     close( file );
00363 
00364     stream->base = NULL;
00365     stream->size = 0;
00366     stream->pos  = 0;
00367 
00368     return FT_Err_Cannot_Open_Stream;
00369   }
00370 
00371 
00372 #ifdef FT_DEBUG_MEMORY
00373 
00374   extern FT_Int
00375   ft_mem_debug_init( FT_Memory  memory );
00376 
00377   extern void
00378   ft_mem_debug_done( FT_Memory  memory );
00379 
00380 #endif
00381 
00382 
00383   /* documentation is in ftobjs.h */
00384 
00385   FT_BASE_DEF( FT_Memory )
00386   FT_New_Memory( void )
00387   {
00388     FT_Memory  memory;
00389 
00390 
00391     memory = (FT_Memory)malloc( sizeof ( *memory ) );
00392     if ( memory )
00393     {
00394       memory->user    = 0;
00395       memory->alloc   = ft_alloc;
00396       memory->realloc = ft_realloc;
00397       memory->free    = ft_free;
00398 #ifdef FT_DEBUG_MEMORY
00399       ft_mem_debug_init( memory );
00400 #endif
00401     }
00402 
00403     return memory;
00404   }
00405 
00406 
00407   /* documentation is in ftobjs.h */
00408 
00409   FT_BASE_DEF( void )
00410   FT_Done_Memory( FT_Memory  memory )
00411   {
00412 #ifdef FT_DEBUG_MEMORY
00413     ft_mem_debug_done( memory );
00414 #endif
00415     memory->free( memory, memory );
00416   }
00417 
00418 
00419 /* END */

Generated on Tue Jul 5 14:13:34 2011 for ROOT_528-00b_version by  doxygen 1.5.1