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