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 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 ) 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 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 ) 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 typedef FT_Error 257 (*raccess_guess_func)( FT_Library library, 258 FT_Stream stream, 259 char *base_file_name, 260 char **result_file_name, 261 FT_Long *result_offset ); 262 263 264 static FT_Error 265 raccess_guess_apple_double( FT_Library library, 266 FT_Stream stream, 267 char *base_file_name, 268 char **result_file_name, 269 FT_Long *result_offset ); 270 271 static FT_Error 272 raccess_guess_apple_single( FT_Library library, 273 FT_Stream stream, 274 char *base_file_name, 275 char **result_file_name, 276 FT_Long *result_offset ); 277 278 static FT_Error 279 raccess_guess_darwin_ufs_export( FT_Library library, 280 FT_Stream stream, 281 char *base_file_name, 282 char **result_file_name, 283 FT_Long *result_offset ); 284 285 static FT_Error 286 raccess_guess_darwin_newvfs( 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_darwin_hfsplus( 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_vfat( 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_linux_cap( 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_linux_double( 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_linux_netatalk( FT_Library library, 322 FT_Stream stream, 323 char *base_file_name, 324 char **result_file_name, 325 FT_Long *result_offset ); 326 327 328 /*************************************************************************/ 329 /**** ****/ 330 /**** Helper functions ****/ 331 /**** ****/ 332 /*************************************************************************/ 333 334 static FT_Error 335 raccess_guess_apple_generic( FT_Library library, 336 FT_Stream stream, 337 char *base_file_name, 338 FT_Int32 magic, 339 FT_Long *result_offset ); 340 341 static FT_Error 342 raccess_guess_linux_double_from_file_name( FT_Library library, 343 char * file_name, 344 FT_Long *result_offset ); 345 346 static char * 347 raccess_make_file_name( FT_Memory memory, 348 const char *original_name, 349 const char *insertion ); 350 351 352 typedef enum FT_RFork_Rule_ { 353 FT_RFork_Rule_invalid = -2, 354 FT_RFork_Rule_uknown, /* -1 */ 355 FT_RFork_Rule_apple_double, 356 FT_RFork_Rule_apple_single, 357 FT_RFork_Rule_darwin_ufs_export, 358 FT_RFork_Rule_darwin_newvfs, 359 FT_RFork_Rule_darwin_hfsplus, 360 FT_RFork_Rule_vfat, 361 FT_RFork_Rule_linux_cap, 362 FT_RFork_Rule_linux_double, 363 FT_RFork_Rule_linux_netatalk 364 } FT_RFork_Rule; 365 366 /* For fast translation between rule index and rule type, 367 * the macros FT_RFORK_xxx should be kept consistent with 368 * the raccess_guess_funcs table 369 */ 370 typedef struct raccess_guess_rec_ { 371 raccess_guess_func func; 372 FT_RFork_Rule type; 373 } raccess_guess_rec; 374 375 static raccess_guess_rec raccess_guess_table[FT_RACCESS_N_RULES] = 376 { 377 { raccess_guess_apple_double, FT_RFork_Rule_apple_double, }, 378 { raccess_guess_apple_single, FT_RFork_Rule_apple_single, }, 379 { raccess_guess_darwin_ufs_export, FT_RFork_Rule_darwin_ufs_export, }, 380 { raccess_guess_darwin_newvfs, FT_RFork_Rule_darwin_newvfs, }, 381 { raccess_guess_darwin_hfsplus, FT_RFork_Rule_darwin_hfsplus, }, 382 { raccess_guess_vfat, FT_RFork_Rule_vfat, }, 383 { raccess_guess_linux_cap, FT_RFork_Rule_linux_cap, }, 384 { raccess_guess_linux_double, FT_RFork_Rule_linux_double, }, 385 { raccess_guess_linux_netatalk, FT_RFork_Rule_linux_netatalk, }, 386 }; 387 388 FT_BASE_DEF( void ) 389 FT_Raccess_Guess( FT_Library library, 390 FT_Stream stream, 391 char* base_name, 392 char **new_names, 393 FT_Long *offsets, 394 FT_Error *errors ) 395 { 396 FT_Long i; 397 398 399 for ( i = 0; i < FT_RACCESS_N_RULES; i++ ) 400 { 401 new_names[i] = NULL; 402 if ( NULL != stream ) 403 errors[i] = FT_Stream_Seek( stream, 0 ); 404 else 405 errors[i] = FT_Err_Ok; 406 407 if ( errors[i] ) 408 continue ; 409 410 errors[i] = (raccess_guess_table[i].func)( library, 411 stream, base_name, 412 &(new_names[i]), 413 &(offsets[i]) ); 414 } 415 416 return; 417 } 418 419 420 static FT_RFork_Rule 421 raccess_get_rule_type_from_rule_index( FT_UInt rule_index ) 422 { 423 if ( rule_index >= FT_RACCESS_N_RULES ) 424 return FT_RFork_Rule_invalid; 425 426 return raccess_guess_table[rule_index].type; 427 } 428 429 430 FT_LOCAL_DEF( FT_Bool ) 431 raccess_rule_by_darwin_vfs( FT_UInt rule_index ) 432 { 433 switch( raccess_get_rule_type_from_rule_index( rule_index ) ) 434 { 435 case FT_RFork_Rule_darwin_newvfs: 436 case FT_RFork_Rule_darwin_hfsplus: 437 return TRUE; 438 439 default: 440 return FALSE; 441 } 442 } 443 444 445 static FT_Error 446 raccess_guess_apple_double( 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 0x07; 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 468 raccess_guess_apple_single( FT_Library library, 469 FT_Stream stream, 470 char *base_file_name, 471 char **result_file_name, 472 FT_Long *result_offset ) 473 { 474 FT_Int32 magic = ( 0x00 << 24 ) | 475 ( 0x05 << 16 ) | 476 ( 0x16 << 8 ) | 477 0x00; 478 479 480 *result_file_name = NULL; 481 if ( NULL == stream ) 482 return FT_Err_Cannot_Open_Stream; 483 484 return raccess_guess_apple_generic( library, stream, base_file_name, 485 magic, result_offset ); 486 } 487 488 489 static FT_Error 490 raccess_guess_darwin_ufs_export( FT_Library library, 491 FT_Stream stream, 492 char *base_file_name, 493 char **result_file_name, 494 FT_Long *result_offset ) 495 { 496 char* newpath; 497 FT_Error error; 498 FT_Memory memory; 499 500 FT_UNUSED( stream ); 501 502 503 memory = library->memory; 504 newpath = raccess_make_file_name( memory, base_file_name, "._" ); 505 if ( !newpath ) 506 return FT_Err_Out_Of_Memory; 507 508 error = raccess_guess_linux_double_from_file_name( library, newpath, 509 result_offset ); 510 if ( !error ) 511 *result_file_name = newpath; 512 else 513 FT_FREE( newpath ); 514 515 return error; 516 } 517 518 519 static FT_Error 520 raccess_guess_darwin_hfsplus( FT_Library library, 521 FT_Stream stream, 522 char *base_file_name, 523 char **result_file_name, 524 FT_Long *result_offset ) 525 { 526 /* 527 Only meaningful on systems with hfs+ drivers (or Macs). 528 */ 529 FT_Error error; 530 char* newpath = NULL; 531 FT_Memory memory; 532 FT_Long base_file_len = ft_strlen( base_file_name ); 533 534 FT_UNUSED( stream ); 535 536 537 memory = library->memory; 538 539 if ( base_file_len + 6 > FT_INT_MAX ) 540 return FT_Err_Array_Too_Large; 541 542 if ( FT_ALLOC( newpath, base_file_len + 6 ) ) 543 return error; 544 545 FT_MEM_COPY( newpath, base_file_name, base_file_len ); 546 FT_MEM_COPY( newpath + base_file_len, "/rsrc", 6 ); 547 548 *result_file_name = newpath; 549 *result_offset = 0; 550 551 return FT_Err_Ok; 552 } 553 554 555 static FT_Error 556 raccess_guess_darwin_newvfs( FT_Library library, 557 FT_Stream stream, 558 char *base_file_name, 559 char **result_file_name, 560 FT_Long *result_offset ) 561 { 562 /* 563 Only meaningful on systems with Mac OS X (> 10.1). 564 */ 565 FT_Error error; 566 char* newpath = NULL; 567 FT_Memory memory; 568 FT_Long base_file_len = ft_strlen( base_file_name ); 569 570 FT_UNUSED( stream ); 571 572 573 memory = library->memory; 574 575 if ( base_file_len + 18 > FT_INT_MAX ) 576 return FT_Err_Array_Too_Large; 577 578 if ( FT_ALLOC( newpath, base_file_len + 18 ) ) 579 return error; 580 581 FT_MEM_COPY( newpath, base_file_name, base_file_len ); 582 FT_MEM_COPY( newpath + base_file_len, "/..namedfork/rsrc", 18 ); 583 584 *result_file_name = newpath; 585 *result_offset = 0; 586 587 return FT_Err_Ok; 588 } 589 590 591 static FT_Error 592 raccess_guess_vfat( FT_Library library, 593 FT_Stream stream, 594 char *base_file_name, 595 char **result_file_name, 596 FT_Long *result_offset ) 597 { 598 char* newpath; 599 FT_Memory memory; 600 601 FT_UNUSED( stream ); 602 603 604 memory = library->memory; 605 606 newpath = raccess_make_file_name( memory, base_file_name, 607 "resource.frk/" ); 608 if ( !newpath ) 609 return FT_Err_Out_Of_Memory; 610 611 *result_file_name = newpath; 612 *result_offset = 0; 613 614 return FT_Err_Ok; 615 } 616 617 618 static FT_Error 619 raccess_guess_linux_cap( FT_Library library, 620 FT_Stream stream, 621 char *base_file_name, 622 char **result_file_name, 623 FT_Long *result_offset ) 624 { 625 char* newpath; 626 FT_Memory memory; 627 628 FT_UNUSED( stream ); 629 630 631 memory = library->memory; 632 633 newpath = raccess_make_file_name( memory, base_file_name, ".resource/" ); 634 if ( !newpath ) 635 return FT_Err_Out_Of_Memory; 636 637 *result_file_name = newpath; 638 *result_offset = 0; 639 640 return FT_Err_Ok; 641 } 642 643 644 static FT_Error 645 raccess_guess_linux_double( FT_Library library, 646 FT_Stream stream, 647 char *base_file_name, 648 char **result_file_name, 649 FT_Long *result_offset ) 650 { 651 char* newpath; 652 FT_Error error; 653 FT_Memory memory; 654 655 FT_UNUSED( stream ); 656 657 658 memory = library->memory; 659 660 newpath = raccess_make_file_name( memory, base_file_name, "%" ); 661 if ( !newpath ) 662 return FT_Err_Out_Of_Memory; 663 664 error = raccess_guess_linux_double_from_file_name( library, newpath, 665 result_offset ); 666 if ( !error ) 667 *result_file_name = newpath; 668 else 669 FT_FREE( newpath ); 670 671 return error; 672 } 673 674 675 static FT_Error 676 raccess_guess_linux_netatalk( FT_Library library, 677 FT_Stream stream, 678 char *base_file_name, 679 char **result_file_name, 680 FT_Long *result_offset ) 681 { 682 char* newpath; 683 FT_Error error; 684 FT_Memory memory; 685 686 FT_UNUSED( stream ); 687 688 689 memory = library->memory; 690 691 newpath = raccess_make_file_name( memory, base_file_name, 692 ".AppleDouble/" ); 693 if ( !newpath ) 694 return FT_Err_Out_Of_Memory; 695 696 error = raccess_guess_linux_double_from_file_name( library, newpath, 697 result_offset ); 698 if ( !error ) 699 *result_file_name = newpath; 700 else 701 FT_FREE( newpath ); 702 703 return error; 704 } 705 706 707 static FT_Error 708 raccess_guess_apple_generic( FT_Library library, 709 FT_Stream stream, 710 char *base_file_name, 711 FT_Int32 magic, 712 FT_Long *result_offset ) 713 { 714 FT_Int32 magic_from_stream; 715 FT_Error error; 716 FT_Int32 version_number = 0; 717 FT_UShort n_of_entries; 718 719 int i; 720 FT_UInt32 entry_id, entry_offset, entry_length = 0; 721 722 const FT_UInt32 resource_fork_entry_id = 0x2; 723 724 FT_UNUSED( library ); 725 FT_UNUSED( base_file_name ); 726 FT_UNUSED( version_number ); 727 FT_UNUSED( entry_length ); 728 729 730 if ( FT_READ_LONG( magic_from_stream ) ) 731 return error; 732 if ( magic_from_stream != magic ) 733 return FT_Err_Unknown_File_Format; 734 735 if ( FT_READ_LONG( version_number ) ) 736 return error; 737 738 /* filler */ 739 error = FT_Stream_Skip( stream, 16 ); 740 if ( error ) 741 return error; 742 743 if ( FT_READ_USHORT( n_of_entries ) ) 744 return error; 745 if ( n_of_entries == 0 ) 746 return FT_Err_Unknown_File_Format; 747 748 for ( i = 0; i < n_of_entries; i++ ) 749 { 750 if ( FT_READ_LONG( entry_id ) ) 751 return error; 752 if ( entry_id == resource_fork_entry_id ) 753 { 754 if ( FT_READ_LONG( entry_offset ) || 755 FT_READ_LONG( entry_length ) ) 756 continue; 757 *result_offset = entry_offset; 758 759 return FT_Err_Ok; 760 } 761 else 762 { 763 error = FT_Stream_Skip( stream, 4 + 4 ); /* offset + length */ 764 if ( error ) 765 return error; 766 } 767 } 768 769 return FT_Err_Unknown_File_Format; 770 } 771 772 773 static FT_Error 774 raccess_guess_linux_double_from_file_name( FT_Library library, 775 char *file_name, 776 FT_Long *result_offset ) 777 { 778 FT_Open_Args args2; 779 FT_Stream stream2; 780 char * nouse = NULL; 781 FT_Error error; 782 783 784 args2.flags = FT_OPEN_PATHNAME; 785 args2.pathname = file_name; 786 error = FT_Stream_New( library, &args2, &stream2 ); 787 if ( error ) 788 return error; 789 790 error = raccess_guess_apple_double( library, stream2, file_name, 791 &nouse, result_offset ); 792 793 FT_Stream_Free( stream2, 0 ); 794 795 return error; 796 } 797 798 799 static char* 800 raccess_make_file_name( FT_Memory memory, 801 const char *original_name, 802 const char *insertion ) 803 { 804 char* new_name = NULL; 805 const char* tmp; 806 const char* slash; 807 size_t new_length; 808 FT_Error error = FT_Err_Ok; 809 810 FT_UNUSED( error ); 811 812 813 new_length = ft_strlen( original_name ) + ft_strlen( insertion ); 814 if ( FT_ALLOC( new_name, new_length + 1 ) ) 815 return NULL; 816 817 tmp = ft_strrchr( original_name, '/' ); 818 if ( tmp ) 819 { 820 ft_strncpy( new_name, original_name, tmp - original_name + 1 ); 821 new_name[tmp - original_name + 1] = '\0'; 822 slash = tmp + 1; 823 } 824 else 825 { 826 slash = original_name; 827 new_name[0] = '\0'; 828 } 829 830 ft_strcat( new_name, insertion ); 831 ft_strcat( new_name, slash ); 832 833 return new_name; 834 } 835 836 837 #else /* !FT_CONFIG_OPTION_GUESSING_EMBEDDED_RFORK */ 838 839 840 /*************************************************************************/ 841 /* Dummy function; just sets errors */ 842 /*************************************************************************/ 843 844 FT_BASE_DEF( void ) 845 FT_Raccess_Guess( FT_Library library, 846 FT_Stream stream, 847 char *base_name, 848 char **new_names, 849 FT_Long *offsets, 850 FT_Error *errors ) 851 { 852 int i; 853 854 FT_UNUSED( library ); 855 FT_UNUSED( stream ); 856 FT_UNUSED( base_name ); 857 858 859 for ( i = 0; i < FT_RACCESS_N_RULES; i++ ) 860 { 861 new_names[i] = NULL; 862 offsets[i] = 0; 863 errors[i] = FT_Err_Unimplemented_Feature; 864 } 865 } 866 867 868 #endif /* !FT_CONFIG_OPTION_GUESSING_EMBEDDED_RFORK */ 869 870 871 /* END */ 872