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