1 /**************************************************************************** 2 * 3 * ftsystem.c 4 * 5 * Unix-specific FreeType low-level system interface (body). 6 * 7 * Copyright (C) 1996-2021 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 <vtkfreetype/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* ) ft_alloc(FT_Memory memory,long size)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* ) ft_realloc(FT_Memory memory,long cur_size,long new_size,void * block)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 ) ft_free(FT_Memory memory,void * block)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 ) ft_close_stream_by_munmap(FT_Stream stream)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 = 0; 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 ) ft_close_stream_by_free(FT_Stream stream)234 ft_close_stream_by_free( FT_Stream stream ) 235 { 236 ft_free( NULL, stream->descriptor.pointer ); 237 238 stream->descriptor.pointer = NULL; 239 stream->size = 0; 240 stream->base = 0; 241 } 242 243 244 /* documentation is in ftobjs.h */ 245 246 FT_BASE_DEF( FT_Error ) FT_Stream_Open(FT_Stream stream,const char * filepathname)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 /* on some RTOS, mmap might return 0 */ 317 if ( (long)stream->base != -1 && stream->base != NULL ) 318 stream->close = ft_close_stream_by_munmap; 319 else 320 { 321 ssize_t total_read_count; 322 323 324 FT_ERROR(( "FT_Stream_Open:" )); 325 FT_ERROR(( " could not `mmap' file `%s'\n", filepathname )); 326 327 stream->base = (unsigned char*)ft_alloc( NULL, stream->size ); 328 329 if ( !stream->base ) 330 { 331 FT_ERROR(( "FT_Stream_Open:" )); 332 FT_ERROR(( " could not `alloc' memory\n" )); 333 goto Fail_Map; 334 } 335 336 total_read_count = 0; 337 do 338 { 339 ssize_t read_count; 340 341 342 read_count = read( file, 343 stream->base + total_read_count, 344 stream->size - total_read_count ); 345 346 if ( read_count <= 0 ) 347 { 348 if ( read_count == -1 && errno == EINTR ) 349 continue; 350 351 FT_ERROR(( "FT_Stream_Open:" )); 352 FT_ERROR(( " error while `read'ing file `%s'\n", filepathname )); 353 goto Fail_Read; 354 } 355 356 total_read_count += read_count; 357 358 } while ( (unsigned long)total_read_count != stream->size ); 359 360 stream->close = ft_close_stream_by_free; 361 } 362 363 close( file ); 364 365 stream->descriptor.pointer = stream->base; 366 stream->pathname.pointer = (char*)filepathname; 367 368 stream->read = 0; 369 370 FT_TRACE1(( "FT_Stream_Open:" )); 371 FT_TRACE1(( " opened `%s' (%ld bytes) successfully\n", 372 filepathname, stream->size )); 373 374 return FT_Err_Ok; 375 376 Fail_Read: 377 ft_free( NULL, stream->base ); 378 379 Fail_Map: 380 close( file ); 381 382 stream->base = NULL; 383 stream->size = 0; 384 stream->pos = 0; 385 386 return FT_THROW( Cannot_Open_Stream ); 387 } 388 389 390 #ifdef FT_DEBUG_MEMORY 391 392 extern FT_Int 393 ft_mem_debug_init( FT_Memory memory ); 394 395 extern void 396 ft_mem_debug_done( FT_Memory memory ); 397 398 #endif 399 400 401 /* documentation is in ftobjs.h */ 402 403 FT_BASE_DEF( FT_Memory ) FT_New_Memory(void)404 FT_New_Memory( void ) 405 { 406 FT_Memory memory; 407 408 409 memory = (FT_Memory)malloc( sizeof ( *memory ) ); 410 if ( memory ) 411 { 412 memory->user = 0; 413 memory->alloc = ft_alloc; 414 memory->realloc = ft_realloc; 415 memory->free = ft_free; 416 #ifdef FT_DEBUG_MEMORY 417 ft_mem_debug_init( memory ); 418 #endif 419 } 420 421 return memory; 422 } 423 424 425 /* documentation is in ftobjs.h */ 426 427 FT_BASE_DEF( void ) FT_Done_Memory(FT_Memory memory)428 FT_Done_Memory( FT_Memory memory ) 429 { 430 #ifdef FT_DEBUG_MEMORY 431 ft_mem_debug_done( memory ); 432 #endif 433 memory->free( memory, memory ); 434 } 435 436 437 /* END */ 438