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