1 /***************************************************************************/ 2 /* */ 3 /* ftrfork.c */ 4 /* */ 5 /* Embedded resource forks accessor (body). */ 6 /* */ 7 /* Copyright 2004, 2005, 2006, 2007, 2008, 2009, 2010 by */ 8 /* Masatake YAMATO and Redhat K.K. */ 9 /* */ 10 /* FT_Raccess_Get_HeaderInfo() and raccess_guess_darwin_hfsplus() are */ 11 /* derived from ftobjs.c. */ 12 /* */ 13 /* This file is part of the FreeType project, and may only be used, */ 14 /* modified, and distributed under the terms of the FreeType project */ 15 /* license, LICENSE.TXT. By continuing to use, modify, or distribute */ 16 /* this file you indicate that you have read the license and */ 17 /* understand and accept it fully. */ 18 /* */ 19 /***************************************************************************/ 20 21 /***************************************************************************/ 22 /* Development of the code in this file is support of */ 23 /* Information-technology Promotion Agency, Japan. */ 24 /***************************************************************************/ 25 26 27 #include <ft2build.h> 28 #include FT_INTERNAL_DEBUG_H 29 #include FT_INTERNAL_STREAM_H 30 #include FT_INTERNAL_RFORK_H 31 #include "basepic.h" 32 33 #undef FT_COMPONENT 34 #define FT_COMPONENT trace_raccess 35 36 37 /*************************************************************************/ 38 /*************************************************************************/ 39 /*************************************************************************/ 40 /**** ****/ 41 /**** ****/ 42 /**** Resource fork directory access ****/ 43 /**** ****/ 44 /**** ****/ 45 /*************************************************************************/ 46 /*************************************************************************/ 47 /*************************************************************************/ 48 49 FT_BASE_DEF( FT_Error ) FT_Raccess_Get_HeaderInfo(FT_Library library,FT_Stream stream,FT_Long rfork_offset,FT_Long * map_offset,FT_Long * rdata_pos)50 FT_Raccess_Get_HeaderInfo( FT_Library library, 51 FT_Stream stream, 52 FT_Long rfork_offset, 53 FT_Long *map_offset, 54 FT_Long *rdata_pos ) 55 { 56 FT_Error error; 57 unsigned char head[16], head2[16]; 58 FT_Long map_pos, rdata_len; 59 int allzeros, allmatch, i; 60 FT_Long type_list; 61 62 FT_UNUSED( library ); 63 64 65 error = FT_Stream_Seek( stream, rfork_offset ); 66 if ( error ) 67 return error; 68 69 error = FT_Stream_Read( stream, (FT_Byte *)head, 16 ); 70 if ( error ) 71 return error; 72 73 *rdata_pos = rfork_offset + ( ( head[0] << 24 ) | 74 ( head[1] << 16 ) | 75 ( head[2] << 8 ) | 76 head[3] ); 77 map_pos = rfork_offset + ( ( head[4] << 24 ) | 78 ( head[5] << 16 ) | 79 ( head[6] << 8 ) | 80 head[7] ); 81 rdata_len = ( head[ 8] << 24 ) | 82 ( head[ 9] << 16 ) | 83 ( head[10] << 8 ) | 84 head[11]; 85 86 /* map_len = head[12] .. head[15] */ 87 88 if ( *rdata_pos + rdata_len != map_pos || map_pos == rfork_offset ) 89 return FT_Err_Unknown_File_Format; 90 91 error = FT_Stream_Seek( stream, map_pos ); 92 if ( error ) 93 return error; 94 95 head2[15] = (FT_Byte)( head[15] + 1 ); /* make it be different */ 96 97 error = FT_Stream_Read( stream, (FT_Byte*)head2, 16 ); 98 if ( error ) 99 return error; 100 101 allzeros = 1; 102 allmatch = 1; 103 for ( i = 0; i < 16; ++i ) 104 { 105 if ( head2[i] != 0 ) 106 allzeros = 0; 107 if ( head2[i] != head[i] ) 108 allmatch = 0; 109 } 110 if ( !allzeros && !allmatch ) 111 return FT_Err_Unknown_File_Format; 112 113 /* If we have reached this point then it is probably a mac resource */ 114 /* file. Now, does it contain any interesting resources? */ 115 /* Skip handle to next resource map, the file resource number, and */ 116 /* attributes. */ 117 (void)FT_STREAM_SKIP( 4 /* skip handle to next resource map */ 118 + 2 /* skip file resource number */ 119 + 2 ); /* skip attributes */ 120 121 if ( FT_READ_USHORT( type_list ) ) 122 return error; 123 if ( type_list == -1 ) 124 return FT_Err_Unknown_File_Format; 125 126 error = FT_Stream_Seek( stream, map_pos + type_list ); 127 if ( error ) 128 return error; 129 130 *map_offset = map_pos + type_list; 131 return FT_Err_Ok; 132 } 133 134 135 static int ft_raccess_sort_ref_by_id(FT_RFork_Ref * a,FT_RFork_Ref * b)136 ft_raccess_sort_ref_by_id( FT_RFork_Ref* a, 137 FT_RFork_Ref* b ) 138 { 139 if ( a->res_id < b->res_id ) 140 return -1; 141 else if ( a->res_id > b->res_id ) 142 return 1; 143 else 144 return 0; 145 } 146 147 148 FT_BASE_DEF( FT_Error ) FT_Raccess_Get_DataOffsets(FT_Library library,FT_Stream stream,FT_Long map_offset,FT_Long rdata_pos,FT_Long tag,FT_Long ** offsets,FT_Long * count)149 FT_Raccess_Get_DataOffsets( FT_Library library, 150 FT_Stream stream, 151 FT_Long map_offset, 152 FT_Long rdata_pos, 153 FT_Long tag, 154 FT_Long **offsets, 155 FT_Long *count ) 156 { 157 FT_Error error; 158 int i, j, cnt, subcnt; 159 FT_Long tag_internal, rpos; 160 FT_Memory memory = library->memory; 161 FT_Long temp; 162 FT_Long *offsets_internal = NULL; 163 FT_RFork_Ref *ref = NULL; 164 165 166 error = FT_Stream_Seek( stream, map_offset ); 167 if ( error ) 168 return error; 169 170 if ( FT_READ_USHORT( cnt ) ) 171 return error; 172 cnt++; 173 174 for ( i = 0; i < cnt; ++i ) 175 { 176 if ( FT_READ_LONG( tag_internal ) || 177 FT_READ_USHORT( subcnt ) || 178 FT_READ_USHORT( rpos ) ) 179 return error; 180 181 FT_TRACE2(( "Resource tags: %c%c%c%c\n", 182 (char)( 0xff & ( tag_internal >> 24 ) ), 183 (char)( 0xff & ( tag_internal >> 16 ) ), 184 (char)( 0xff & ( tag_internal >> 8 ) ), 185 (char)( 0xff & ( tag_internal >> 0 ) ) )); 186 187 if ( tag_internal == tag ) 188 { 189 *count = subcnt + 1; 190 rpos += map_offset; 191 192 error = FT_Stream_Seek( stream, rpos ); 193 if ( error ) 194 return error; 195 196 if ( FT_NEW_ARRAY( ref, *count ) ) 197 return error; 198 199 for ( j = 0; j < *count; ++j ) 200 { 201 if ( FT_READ_USHORT( ref[j].res_id ) ) 202 goto Exit; 203 if ( FT_STREAM_SKIP( 2 ) ) /* resource name */ 204 goto Exit; 205 if ( FT_READ_LONG( temp ) ) 206 goto Exit; 207 if ( FT_STREAM_SKIP( 4 ) ) /* mbz */ 208 goto Exit; 209 210 ref[j].offset = temp & 0xFFFFFFL; 211 } 212 213 ft_qsort( ref, *count, sizeof ( FT_RFork_Ref ), 214 ( int(*)(const void*, const void*) ) 215 ft_raccess_sort_ref_by_id ); 216 217 if ( FT_NEW_ARRAY( offsets_internal, *count ) ) 218 goto Exit; 219 220 /* XXX: duplicated reference ID, 221 * gap between reference IDs are acceptable? 222 * further investigation on Apple implementation is needed. 223 */ 224 for ( j = 0; j < *count; ++j ) 225 offsets_internal[j] = rdata_pos + ref[j].offset; 226 227 *offsets = offsets_internal; 228 error = FT_Err_Ok; 229 230 Exit: 231 FT_FREE( ref ); 232 return error; 233 } 234 } 235 236 return FT_Err_Cannot_Open_Resource; 237 } 238 239 240 #ifdef FT_CONFIG_OPTION_GUESSING_EMBEDDED_RFORK 241 242 /*************************************************************************/ 243 /*************************************************************************/ 244 /*************************************************************************/ 245 /**** ****/ 246 /**** ****/ 247 /**** Guessing functions ****/ 248 /**** ****/ 249 /**** When you add a new guessing function, ****/ 250 /**** update FT_RACCESS_N_RULES in ftrfork.h. ****/ 251 /**** ****/ 252 /*************************************************************************/ 253 /*************************************************************************/ 254 /*************************************************************************/ 255 256 static FT_Error 257 raccess_guess_apple_double( FT_Library library, 258 FT_Stream stream, 259 char *base_file_name, 260 char **result_file_name, 261 FT_Long *result_offset ); 262 263 static FT_Error 264 raccess_guess_apple_single( FT_Library library, 265 FT_Stream stream, 266 char *base_file_name, 267 char **result_file_name, 268 FT_Long *result_offset ); 269 270 static FT_Error 271 raccess_guess_darwin_ufs_export( FT_Library library, 272 FT_Stream stream, 273 char *base_file_name, 274 char **result_file_name, 275 FT_Long *result_offset ); 276 277 static FT_Error 278 raccess_guess_darwin_newvfs( FT_Library library, 279 FT_Stream stream, 280 char *base_file_name, 281 char **result_file_name, 282 FT_Long *result_offset ); 283 284 static FT_Error 285 raccess_guess_darwin_hfsplus( FT_Library library, 286 FT_Stream stream, 287 char *base_file_name, 288 char **result_file_name, 289 FT_Long *result_offset ); 290 291 static FT_Error 292 raccess_guess_vfat( FT_Library library, 293 FT_Stream stream, 294 char *base_file_name, 295 char **result_file_name, 296 FT_Long *result_offset ); 297 298 static FT_Error 299 raccess_guess_linux_cap( FT_Library library, 300 FT_Stream stream, 301 char *base_file_name, 302 char **result_file_name, 303 FT_Long *result_offset ); 304 305 static FT_Error 306 raccess_guess_linux_double( FT_Library library, 307 FT_Stream stream, 308 char *base_file_name, 309 char **result_file_name, 310 FT_Long *result_offset ); 311 312 static FT_Error 313 raccess_guess_linux_netatalk( FT_Library library, 314 FT_Stream stream, 315 char *base_file_name, 316 char **result_file_name, 317 FT_Long *result_offset ); 318 319 320 CONST_FT_RFORK_RULE_ARRAY_BEGIN(ft_raccess_guess_table, 321 ft_raccess_guess_rec) 322 CONST_FT_RFORK_RULE_ARRAY_ENTRY(apple_double, apple_double) 323 CONST_FT_RFORK_RULE_ARRAY_ENTRY(apple_single, apple_single) 324 CONST_FT_RFORK_RULE_ARRAY_ENTRY(darwin_ufs_export, darwin_ufs_export) 325 CONST_FT_RFORK_RULE_ARRAY_ENTRY(darwin_newvfs, darwin_newvfs) 326 CONST_FT_RFORK_RULE_ARRAY_ENTRY(darwin_hfsplus, darwin_hfsplus) 327 CONST_FT_RFORK_RULE_ARRAY_ENTRY(vfat, vfat) 328 CONST_FT_RFORK_RULE_ARRAY_ENTRY(linux_cap, linux_cap) 329 CONST_FT_RFORK_RULE_ARRAY_ENTRY(linux_double, linux_double) 330 CONST_FT_RFORK_RULE_ARRAY_ENTRY(linux_netatalk, linux_netatalk) 331 CONST_FT_RFORK_RULE_ARRAY_END 332 333 334 /*************************************************************************/ 335 /**** ****/ 336 /**** Helper functions ****/ 337 /**** ****/ 338 /*************************************************************************/ 339 340 static FT_Error 341 raccess_guess_apple_generic( FT_Library library, 342 FT_Stream stream, 343 char *base_file_name, 344 FT_Int32 magic, 345 FT_Long *result_offset ); 346 347 static FT_Error 348 raccess_guess_linux_double_from_file_name( FT_Library library, 349 char * file_name, 350 FT_Long *result_offset ); 351 352 static char * 353 raccess_make_file_name( FT_Memory memory, 354 const char *original_name, 355 const char *insertion ); 356 357 FT_BASE_DEF( void ) FT_Raccess_Guess(FT_Library library,FT_Stream stream,char * base_name,char ** new_names,FT_Long * offsets,FT_Error * errors)358 FT_Raccess_Guess( FT_Library library, 359 FT_Stream stream, 360 char* base_name, 361 char **new_names, 362 FT_Long *offsets, 363 FT_Error *errors ) 364 { 365 FT_Long i; 366 367 368 for ( i = 0; i < FT_RACCESS_N_RULES; i++ ) 369 { 370 new_names[i] = NULL; 371 if ( NULL != stream ) 372 errors[i] = FT_Stream_Seek( stream, 0 ); 373 else 374 errors[i] = FT_Err_Ok; 375 376 if ( errors[i] ) 377 continue ; 378 379 errors[i] = (FT_RACCESS_GUESS_TABLE_GET[i].func)( library, 380 stream, base_name, 381 &(new_names[i]), 382 &(offsets[i]) ); 383 } 384 385 return; 386 } 387 388 389 #ifndef FT_MACINTOSH 390 static FT_RFork_Rule raccess_get_rule_type_from_rule_index(FT_Library library,FT_UInt rule_index)391 raccess_get_rule_type_from_rule_index( FT_Library library, 392 FT_UInt rule_index ) 393 { 394 FT_UNUSED( library ); 395 396 if ( rule_index >= FT_RACCESS_N_RULES ) 397 return FT_RFork_Rule_invalid; 398 399 return FT_RACCESS_GUESS_TABLE_GET[rule_index].type; 400 } 401 402 403 /* 404 * For this function, refer ftbase.h. 405 */ 406 FT_LOCAL_DEF( FT_Bool ) ft_raccess_rule_by_darwin_vfs(FT_Library library,FT_UInt rule_index)407 ft_raccess_rule_by_darwin_vfs( FT_Library library, 408 FT_UInt rule_index ) 409 { 410 switch( raccess_get_rule_type_from_rule_index( library, rule_index ) ) 411 { 412 case FT_RFork_Rule_darwin_newvfs: 413 case FT_RFork_Rule_darwin_hfsplus: 414 return TRUE; 415 416 default: 417 return FALSE; 418 } 419 } 420 #endif 421 422 423 static FT_Error raccess_guess_apple_double(FT_Library library,FT_Stream stream,char * base_file_name,char ** result_file_name,FT_Long * result_offset)424 raccess_guess_apple_double( FT_Library library, 425 FT_Stream stream, 426 char *base_file_name, 427 char **result_file_name, 428 FT_Long *result_offset ) 429 { 430 FT_Int32 magic = ( 0x00 << 24 ) | 431 ( 0x05 << 16 ) | 432 ( 0x16 << 8 ) | 433 0x07; 434 435 436 *result_file_name = NULL; 437 if ( NULL == stream ) 438 return FT_Err_Cannot_Open_Stream; 439 440 return raccess_guess_apple_generic( library, stream, base_file_name, 441 magic, result_offset ); 442 } 443 444 445 static FT_Error raccess_guess_apple_single(FT_Library library,FT_Stream stream,char * base_file_name,char ** result_file_name,FT_Long * result_offset)446 raccess_guess_apple_single( FT_Library library, 447 FT_Stream stream, 448 char *base_file_name, 449 char **result_file_name, 450 FT_Long *result_offset ) 451 { 452 FT_Int32 magic = ( 0x00 << 24 ) | 453 ( 0x05 << 16 ) | 454 ( 0x16 << 8 ) | 455 0x00; 456 457 458 *result_file_name = NULL; 459 if ( NULL == stream ) 460 return FT_Err_Cannot_Open_Stream; 461 462 return raccess_guess_apple_generic( library, stream, base_file_name, 463 magic, result_offset ); 464 } 465 466 467 static FT_Error raccess_guess_darwin_ufs_export(FT_Library library,FT_Stream stream,char * base_file_name,char ** result_file_name,FT_Long * result_offset)468 raccess_guess_darwin_ufs_export( FT_Library library, 469 FT_Stream stream, 470 char *base_file_name, 471 char **result_file_name, 472 FT_Long *result_offset ) 473 { 474 char* newpath; 475 FT_Error error; 476 FT_Memory memory; 477 478 FT_UNUSED( stream ); 479 480 481 memory = library->memory; 482 newpath = raccess_make_file_name( memory, base_file_name, "._" ); 483 if ( !newpath ) 484 return FT_Err_Out_Of_Memory; 485 486 error = raccess_guess_linux_double_from_file_name( library, newpath, 487 result_offset ); 488 if ( !error ) 489 *result_file_name = newpath; 490 else 491 FT_FREE( newpath ); 492 493 return error; 494 } 495 496 497 static FT_Error raccess_guess_darwin_hfsplus(FT_Library library,FT_Stream stream,char * base_file_name,char ** result_file_name,FT_Long * result_offset)498 raccess_guess_darwin_hfsplus( FT_Library library, 499 FT_Stream stream, 500 char *base_file_name, 501 char **result_file_name, 502 FT_Long *result_offset ) 503 { 504 /* 505 Only meaningful on systems with hfs+ drivers (or Macs). 506 */ 507 FT_Error error; 508 char* newpath = NULL; 509 FT_Memory memory; 510 FT_Long base_file_len = ft_strlen( base_file_name ); 511 512 FT_UNUSED( stream ); 513 514 515 memory = library->memory; 516 517 if ( base_file_len + 6 > FT_INT_MAX ) 518 return FT_Err_Array_Too_Large; 519 520 if ( FT_ALLOC( newpath, base_file_len + 6 ) ) 521 return error; 522 523 FT_MEM_COPY( newpath, base_file_name, base_file_len ); 524 FT_MEM_COPY( newpath + base_file_len, "/rsrc", 6 ); 525 526 *result_file_name = newpath; 527 *result_offset = 0; 528 529 return FT_Err_Ok; 530 } 531 532 533 static FT_Error raccess_guess_darwin_newvfs(FT_Library library,FT_Stream stream,char * base_file_name,char ** result_file_name,FT_Long * result_offset)534 raccess_guess_darwin_newvfs( FT_Library library, 535 FT_Stream stream, 536 char *base_file_name, 537 char **result_file_name, 538 FT_Long *result_offset ) 539 { 540 /* 541 Only meaningful on systems with Mac OS X (> 10.1). 542 */ 543 FT_Error error; 544 char* newpath = NULL; 545 FT_Memory memory; 546 FT_Long base_file_len = ft_strlen( base_file_name ); 547 548 FT_UNUSED( stream ); 549 550 551 memory = library->memory; 552 553 if ( base_file_len + 18 > FT_INT_MAX ) 554 return FT_Err_Array_Too_Large; 555 556 if ( FT_ALLOC( newpath, base_file_len + 18 ) ) 557 return error; 558 559 FT_MEM_COPY( newpath, base_file_name, base_file_len ); 560 FT_MEM_COPY( newpath + base_file_len, "/..namedfork/rsrc", 18 ); 561 562 *result_file_name = newpath; 563 *result_offset = 0; 564 565 return FT_Err_Ok; 566 } 567 568 569 static FT_Error raccess_guess_vfat(FT_Library library,FT_Stream stream,char * base_file_name,char ** result_file_name,FT_Long * result_offset)570 raccess_guess_vfat( FT_Library library, 571 FT_Stream stream, 572 char *base_file_name, 573 char **result_file_name, 574 FT_Long *result_offset ) 575 { 576 char* newpath; 577 FT_Memory memory; 578 579 FT_UNUSED( stream ); 580 581 582 memory = library->memory; 583 584 newpath = raccess_make_file_name( memory, base_file_name, 585 "resource.frk/" ); 586 if ( !newpath ) 587 return FT_Err_Out_Of_Memory; 588 589 *result_file_name = newpath; 590 *result_offset = 0; 591 592 return FT_Err_Ok; 593 } 594 595 596 static FT_Error raccess_guess_linux_cap(FT_Library library,FT_Stream stream,char * base_file_name,char ** result_file_name,FT_Long * result_offset)597 raccess_guess_linux_cap( FT_Library library, 598 FT_Stream stream, 599 char *base_file_name, 600 char **result_file_name, 601 FT_Long *result_offset ) 602 { 603 char* newpath; 604 FT_Memory memory; 605 606 FT_UNUSED( stream ); 607 608 609 memory = library->memory; 610 611 newpath = raccess_make_file_name( memory, base_file_name, ".resource/" ); 612 if ( !newpath ) 613 return FT_Err_Out_Of_Memory; 614 615 *result_file_name = newpath; 616 *result_offset = 0; 617 618 return FT_Err_Ok; 619 } 620 621 622 static FT_Error raccess_guess_linux_double(FT_Library library,FT_Stream stream,char * base_file_name,char ** result_file_name,FT_Long * result_offset)623 raccess_guess_linux_double( FT_Library library, 624 FT_Stream stream, 625 char *base_file_name, 626 char **result_file_name, 627 FT_Long *result_offset ) 628 { 629 char* newpath; 630 FT_Error error; 631 FT_Memory memory; 632 633 FT_UNUSED( stream ); 634 635 636 memory = library->memory; 637 638 newpath = raccess_make_file_name( memory, base_file_name, "%" ); 639 if ( !newpath ) 640 return FT_Err_Out_Of_Memory; 641 642 error = raccess_guess_linux_double_from_file_name( library, newpath, 643 result_offset ); 644 if ( !error ) 645 *result_file_name = newpath; 646 else 647 FT_FREE( newpath ); 648 649 return error; 650 } 651 652 653 static FT_Error raccess_guess_linux_netatalk(FT_Library library,FT_Stream stream,char * base_file_name,char ** result_file_name,FT_Long * result_offset)654 raccess_guess_linux_netatalk( FT_Library library, 655 FT_Stream stream, 656 char *base_file_name, 657 char **result_file_name, 658 FT_Long *result_offset ) 659 { 660 char* newpath; 661 FT_Error error; 662 FT_Memory memory; 663 664 FT_UNUSED( stream ); 665 666 667 memory = library->memory; 668 669 newpath = raccess_make_file_name( memory, base_file_name, 670 ".AppleDouble/" ); 671 if ( !newpath ) 672 return FT_Err_Out_Of_Memory; 673 674 error = raccess_guess_linux_double_from_file_name( library, newpath, 675 result_offset ); 676 if ( !error ) 677 *result_file_name = newpath; 678 else 679 FT_FREE( newpath ); 680 681 return error; 682 } 683 684 685 static FT_Error raccess_guess_apple_generic(FT_Library library,FT_Stream stream,char * base_file_name,FT_Int32 magic,FT_Long * result_offset)686 raccess_guess_apple_generic( FT_Library library, 687 FT_Stream stream, 688 char *base_file_name, 689 FT_Int32 magic, 690 FT_Long *result_offset ) 691 { 692 FT_Int32 magic_from_stream; 693 FT_Error error; 694 FT_Int32 version_number = 0; 695 FT_UShort n_of_entries; 696 697 int i; 698 FT_UInt32 entry_id, entry_offset, entry_length = 0; 699 700 const FT_UInt32 resource_fork_entry_id = 0x2; 701 702 FT_UNUSED( library ); 703 FT_UNUSED( base_file_name ); 704 FT_UNUSED( version_number ); 705 FT_UNUSED( entry_length ); 706 707 708 if ( FT_READ_LONG( magic_from_stream ) ) 709 return error; 710 if ( magic_from_stream != magic ) 711 return FT_Err_Unknown_File_Format; 712 713 if ( FT_READ_LONG( version_number ) ) 714 return error; 715 716 /* filler */ 717 error = FT_Stream_Skip( stream, 16 ); 718 if ( error ) 719 return error; 720 721 if ( FT_READ_USHORT( n_of_entries ) ) 722 return error; 723 if ( n_of_entries == 0 ) 724 return FT_Err_Unknown_File_Format; 725 726 for ( i = 0; i < n_of_entries; i++ ) 727 { 728 if ( FT_READ_LONG( entry_id ) ) 729 return error; 730 if ( entry_id == resource_fork_entry_id ) 731 { 732 if ( FT_READ_LONG( entry_offset ) || 733 FT_READ_LONG( entry_length ) ) 734 continue; 735 *result_offset = entry_offset; 736 737 return FT_Err_Ok; 738 } 739 else 740 { 741 error = FT_Stream_Skip( stream, 4 + 4 ); /* offset + length */ 742 if ( error ) 743 return error; 744 } 745 } 746 747 return FT_Err_Unknown_File_Format; 748 } 749 750 751 static FT_Error raccess_guess_linux_double_from_file_name(FT_Library library,char * file_name,FT_Long * result_offset)752 raccess_guess_linux_double_from_file_name( FT_Library library, 753 char *file_name, 754 FT_Long *result_offset ) 755 { 756 FT_Open_Args args2; 757 FT_Stream stream2; 758 char * nouse = NULL; 759 FT_Error error; 760 761 762 args2.flags = FT_OPEN_PATHNAME; 763 args2.pathname = file_name; 764 error = FT_Stream_New( library, &args2, &stream2 ); 765 if ( error ) 766 return error; 767 768 error = raccess_guess_apple_double( library, stream2, file_name, 769 &nouse, result_offset ); 770 771 FT_Stream_Free( stream2, 0 ); 772 773 return error; 774 } 775 776 777 static char* raccess_make_file_name(FT_Memory memory,const char * original_name,const char * insertion)778 raccess_make_file_name( FT_Memory memory, 779 const char *original_name, 780 const char *insertion ) 781 { 782 char* new_name = NULL; 783 const char* tmp; 784 const char* slash; 785 size_t new_length; 786 FT_Error error = FT_Err_Ok; 787 788 FT_UNUSED( error ); 789 790 791 new_length = ft_strlen( original_name ) + ft_strlen( insertion ); 792 if ( FT_ALLOC( new_name, new_length + 1 ) ) 793 return NULL; 794 795 tmp = ft_strrchr( original_name, '/' ); 796 if ( tmp ) 797 { 798 ft_strncpy( new_name, original_name, tmp - original_name + 1 ); 799 new_name[tmp - original_name + 1] = '\0'; 800 slash = tmp + 1; 801 } 802 else 803 { 804 slash = original_name; 805 new_name[0] = '\0'; 806 } 807 808 ft_strcat( new_name, insertion ); 809 ft_strcat( new_name, slash ); 810 811 return new_name; 812 } 813 814 815 #else /* !FT_CONFIG_OPTION_GUESSING_EMBEDDED_RFORK */ 816 817 818 /*************************************************************************/ 819 /* Dummy function; just sets errors */ 820 /*************************************************************************/ 821 822 FT_BASE_DEF( void ) FT_Raccess_Guess(FT_Library library,FT_Stream stream,char * base_name,char ** new_names,FT_Long * offsets,FT_Error * errors)823 FT_Raccess_Guess( FT_Library library, 824 FT_Stream stream, 825 char *base_name, 826 char **new_names, 827 FT_Long *offsets, 828 FT_Error *errors ) 829 { 830 int i; 831 832 FT_UNUSED( library ); 833 FT_UNUSED( stream ); 834 FT_UNUSED( base_name ); 835 836 837 for ( i = 0; i < FT_RACCESS_N_RULES; i++ ) 838 { 839 new_names[i] = NULL; 840 offsets[i] = 0; 841 errors[i] = FT_Err_Unimplemented_Feature; 842 } 843 } 844 845 846 #endif /* !FT_CONFIG_OPTION_GUESSING_EMBEDDED_RFORK */ 847 848 849 /* END */ 850