tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

ftsystem.c (10581B)


      1 /****************************************************************************
      2 *
      3 * ftsystem.c
      4 *
      5 *   Unix-specific FreeType low-level system interface (body).
      6 *
      7 * Copyright (C) 1996-2025 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 FT_CONFIG_CONFIG_H
     22 #include <freetype/internal/ftdebug.h>
     23 #include <freetype/ftsystem.h>
     24 #include <freetype/fterrors.h>
     25 #include <freetype/fttypes.h>
     26 #include <freetype/internal/ftstream.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   * It is not necessary to do any error checking for the
     83   * allocation-related functions.  This will be done by the higher level
     84   * routines like ft_mem_alloc() or ft_mem_realloc().
     85   *
     86   */
     87 
     88 
     89  /**************************************************************************
     90   *
     91   * @Function:
     92   *   ft_alloc
     93   *
     94   * @Description:
     95   *   The memory allocation function.
     96   *
     97   * @Input:
     98   *   memory ::
     99   *     A pointer to the memory object.
    100   *
    101   *   size ::
    102   *     The requested size in bytes.
    103   *
    104   * @Return:
    105   *   The address of newly allocated block.
    106   */
    107  FT_CALLBACK_DEF( void* )
    108  ft_alloc( FT_Memory  memory,
    109            long       size )
    110  {
    111    FT_UNUSED( memory );
    112 
    113    return malloc( size );
    114  }
    115 
    116 
    117  /**************************************************************************
    118   *
    119   * @Function:
    120   *   ft_realloc
    121   *
    122   * @Description:
    123   *   The memory reallocation function.
    124   *
    125   * @Input:
    126   *   memory ::
    127   *     A pointer to the memory object.
    128   *
    129   *   cur_size ::
    130   *     The current size of the allocated memory block.
    131   *
    132   *   new_size ::
    133   *     The newly requested size in bytes.
    134   *
    135   *   block ::
    136   *     The current address of the block in memory.
    137   *
    138   * @Return:
    139   *   The address of the reallocated memory block.
    140   */
    141  FT_CALLBACK_DEF( void* )
    142  ft_realloc( FT_Memory  memory,
    143              long       cur_size,
    144              long       new_size,
    145              void*      block )
    146  {
    147    FT_UNUSED( memory );
    148    FT_UNUSED( cur_size );
    149 
    150    return realloc( block, new_size );
    151  }
    152 
    153 
    154  /**************************************************************************
    155   *
    156   * @Function:
    157   *   ft_free
    158   *
    159   * @Description:
    160   *   The memory release function.
    161   *
    162   * @Input:
    163   *   memory ::
    164   *     A pointer to the memory object.
    165   *
    166   *   block ::
    167   *     The address of block in memory to be freed.
    168   */
    169  FT_CALLBACK_DEF( void )
    170  ft_free( FT_Memory  memory,
    171           void*      block )
    172  {
    173    FT_UNUSED( memory );
    174 
    175    free( block );
    176  }
    177 
    178 
    179  /**************************************************************************
    180   *
    181   *                    RESOURCE MANAGEMENT INTERFACE
    182   *
    183   */
    184 
    185 
    186  /**************************************************************************
    187   *
    188   * The macro FT_COMPONENT is used in trace mode.  It is an implicit
    189   * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log
    190   * messages during execution.
    191   */
    192 #undef  FT_COMPONENT
    193 #define FT_COMPONENT  io
    194 
    195  /* We use the macro STREAM_FILE for convenience to extract the       */
    196  /* system-specific stream handle from a given FreeType stream object */
    197 #define STREAM_FILE( stream )  ( (FILE*)stream->descriptor.pointer )
    198 
    199 
    200  /**************************************************************************
    201   *
    202   * @Function:
    203   *   ft_close_stream_by_munmap
    204   *
    205   * @Description:
    206   *   The function to close a stream which is opened by mmap.
    207   *
    208   * @Input:
    209   *   stream :: A pointer to the stream object.
    210   */
    211  FT_CALLBACK_DEF( void )
    212  ft_close_stream_by_munmap( FT_Stream  stream )
    213  {
    214    munmap( (MUNMAP_ARG_CAST)stream->descriptor.pointer, stream->size );
    215 
    216    stream->descriptor.pointer = NULL;
    217    stream->size               = 0;
    218    stream->base               = NULL;
    219  }
    220 
    221 
    222  /**************************************************************************
    223   *
    224   * @Function:
    225   *   ft_close_stream_by_free
    226   *
    227   * @Description:
    228   *   The function to close a stream which is created by ft_alloc.
    229   *
    230   * @Input:
    231   *   stream :: A pointer to the stream object.
    232   */
    233  FT_CALLBACK_DEF( void )
    234  ft_close_stream_by_free( FT_Stream  stream )
    235  {
    236    ft_free( stream->memory, stream->descriptor.pointer );
    237 
    238    stream->descriptor.pointer = NULL;
    239    stream->size               = 0;
    240    stream->base               = NULL;
    241  }
    242 
    243 
    244  /* documentation is in ftobjs.h */
    245 
    246  FT_BASE_DEF( FT_Error )
    247  FT_Stream_Open( FT_Stream    stream,
    248                  const char*  filepathname )
    249  {
    250    int          file;
    251    struct stat  stat_buf;
    252 
    253 
    254    if ( !stream )
    255      return FT_THROW( Invalid_Stream_Handle );
    256 
    257    /* open the file */
    258    file = open( filepathname, O_RDONLY );
    259    if ( file < 0 )
    260    {
    261      FT_ERROR(( "FT_Stream_Open:" ));
    262      FT_ERROR(( " could not open `%s'\n", filepathname ));
    263      return FT_THROW( Cannot_Open_Resource );
    264    }
    265 
    266    /* Here we ensure that a "fork" will _not_ duplicate   */
    267    /* our opened input streams on Unix.  This is critical */
    268    /* since it avoids some (possible) access control      */
    269    /* issues and cleans up the kernel file table a bit.   */
    270    /*                                                     */
    271 #ifdef F_SETFD
    272 #ifdef FD_CLOEXEC
    273    (void)fcntl( file, F_SETFD, FD_CLOEXEC );
    274 #else
    275    (void)fcntl( file, F_SETFD, 1 );
    276 #endif /* FD_CLOEXEC */
    277 #endif /* F_SETFD */
    278 
    279    if ( fstat( file, &stat_buf ) < 0 )
    280    {
    281      FT_ERROR(( "FT_Stream_Open:" ));
    282      FT_ERROR(( " could not `fstat' file `%s'\n", filepathname ));
    283      goto Fail_Map;
    284    }
    285 
    286    /* XXX: TODO -- real 64bit platform support                        */
    287    /*                                                                 */
    288    /* `stream->size' is typedef'd to unsigned long (in `ftsystem.h'); */
    289    /* `stat_buf.st_size', however, is usually typedef'd to off_t      */
    290    /* (in sys/stat.h).                                                */
    291    /* On some platforms, the former is 32bit and the latter is 64bit. */
    292    /* To avoid overflow caused by fonts in huge files larger than     */
    293    /* 2GB, do a test.  Temporary fix proposed by Sean McBride.        */
    294    /*                                                                 */
    295    if ( stat_buf.st_size > LONG_MAX )
    296    {
    297      FT_ERROR(( "FT_Stream_Open: file is too big\n" ));
    298      goto Fail_Map;
    299    }
    300    else if ( stat_buf.st_size == 0 )
    301    {
    302      FT_ERROR(( "FT_Stream_Open: zero-length file\n" ));
    303      goto Fail_Map;
    304    }
    305 
    306    /* This cast potentially truncates a 64bit to 32bit! */
    307    stream->size = (unsigned long)stat_buf.st_size;
    308    stream->pos  = 0;
    309    stream->base = (unsigned char *)mmap( NULL,
    310                                          stream->size,
    311                                          PROT_READ,
    312                                          MAP_FILE | MAP_PRIVATE,
    313                                          file,
    314                                          0 );
    315 
    316    if ( stream->base != MAP_FAILED )
    317      stream->close = ft_close_stream_by_munmap;
    318    else
    319    {
    320      ssize_t  total_read_count;
    321 
    322 
    323      FT_ERROR(( "FT_Stream_Open:" ));
    324      FT_ERROR(( " could not `mmap' file `%s'\n", filepathname ));
    325 
    326      stream->base = (unsigned char*)ft_alloc( stream->memory, stream->size );
    327 
    328      if ( !stream->base )
    329      {
    330        FT_ERROR(( "FT_Stream_Open:" ));
    331        FT_ERROR(( " could not `alloc' memory\n" ));
    332        goto Fail_Map;
    333      }
    334 
    335      total_read_count = 0;
    336      do
    337      {
    338        ssize_t  read_count;
    339 
    340 
    341        read_count = read( file,
    342                           stream->base + total_read_count,
    343                           stream->size - total_read_count );
    344 
    345        if ( read_count <= 0 )
    346        {
    347          if ( read_count == -1 && errno == EINTR )
    348            continue;
    349 
    350          FT_ERROR(( "FT_Stream_Open:" ));
    351          FT_ERROR(( " error while `read'ing file `%s'\n", filepathname ));
    352          goto Fail_Read;
    353        }
    354 
    355        total_read_count += read_count;
    356 
    357      } while ( (unsigned long)total_read_count != stream->size );
    358 
    359      stream->close = ft_close_stream_by_free;
    360    }
    361 
    362    close( file );
    363 
    364    stream->descriptor.pointer = stream->base;
    365    stream->pathname.pointer   = (char*)filepathname;
    366 
    367    stream->read = NULL;
    368 
    369    FT_TRACE1(( "FT_Stream_Open:" ));
    370    FT_TRACE1(( " opened `%s' (%ld bytes) successfully\n",
    371                filepathname, stream->size ));
    372 
    373    return FT_Err_Ok;
    374 
    375  Fail_Read:
    376    ft_free( stream->memory, stream->base );
    377 
    378  Fail_Map:
    379    close( file );
    380 
    381    stream->base = NULL;
    382    stream->size = 0;
    383    stream->pos  = 0;
    384 
    385    return FT_THROW( Cannot_Open_Stream );
    386  }
    387 
    388 
    389 #ifdef FT_DEBUG_MEMORY
    390 
    391  extern FT_Int
    392  ft_mem_debug_init( FT_Memory  memory );
    393 
    394  extern void
    395  ft_mem_debug_done( FT_Memory  memory );
    396 
    397 #endif
    398 
    399 
    400  /* documentation is in ftobjs.h */
    401 
    402  FT_BASE_DEF( FT_Memory )
    403  FT_New_Memory( void )
    404  {
    405    FT_Memory  memory;
    406 
    407 
    408    memory = (FT_Memory)malloc( sizeof ( *memory ) );
    409    if ( memory )
    410    {
    411      memory->user    = NULL;
    412      memory->alloc   = ft_alloc;
    413      memory->realloc = ft_realloc;
    414      memory->free    = ft_free;
    415 #ifdef FT_DEBUG_MEMORY
    416      ft_mem_debug_init( memory );
    417 #endif
    418    }
    419 
    420    return memory;
    421  }
    422 
    423 
    424  /* documentation is in ftobjs.h */
    425 
    426  FT_BASE_DEF( void )
    427  FT_Done_Memory( FT_Memory  memory )
    428  {
    429 #ifdef FT_DEBUG_MEMORY
    430    ft_mem_debug_done( memory );
    431 #endif
    432    memory->free( memory, memory );
    433  }
    434 
    435 
    436 /* END */