00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 #include <ft2build.h>
00028 #include FT_INTERNAL_DEBUG_H
00029 #include FT_INTERNAL_STREAM_H
00030 #include FT_INTERNAL_RFORK_H
00031
00032
00033 #undef FT_COMPONENT
00034 #define FT_COMPONENT trace_raccess
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049 FT_BASE_DEF( FT_Error )
00050 FT_Raccess_Get_HeaderInfo( FT_Library library,
00051 FT_Stream stream,
00052 FT_Long rfork_offset,
00053 FT_Long *map_offset,
00054 FT_Long *rdata_pos )
00055 {
00056 FT_Error error;
00057 unsigned char head[16], head2[16];
00058 FT_Long map_pos, rdata_len;
00059 int allzeros, allmatch, i;
00060 FT_Long type_list;
00061
00062 FT_UNUSED( library );
00063
00064
00065 error = FT_Stream_Seek( stream, rfork_offset );
00066 if ( error )
00067 return error;
00068
00069 error = FT_Stream_Read( stream, (FT_Byte *)head, 16 );
00070 if ( error )
00071 return error;
00072
00073 *rdata_pos = rfork_offset + ( ( head[0] << 24 ) |
00074 ( head[1] << 16 ) |
00075 ( head[2] << 8 ) |
00076 head[3] );
00077 map_pos = rfork_offset + ( ( head[4] << 24 ) |
00078 ( head[5] << 16 ) |
00079 ( head[6] << 8 ) |
00080 head[7] );
00081 rdata_len = ( head[ 8] << 24 ) |
00082 ( head[ 9] << 16 ) |
00083 ( head[10] << 8 ) |
00084 head[11];
00085
00086
00087
00088 if ( *rdata_pos + rdata_len != map_pos || map_pos == rfork_offset )
00089 return FT_Err_Unknown_File_Format;
00090
00091 error = FT_Stream_Seek( stream, map_pos );
00092 if ( error )
00093 return error;
00094
00095 head2[15] = (FT_Byte)( head[15] + 1 );
00096
00097 error = FT_Stream_Read( stream, (FT_Byte*)head2, 16 );
00098 if ( error )
00099 return error;
00100
00101 allzeros = 1;
00102 allmatch = 1;
00103 for ( i = 0; i < 16; ++i )
00104 {
00105 if ( head2[i] != 0 )
00106 allzeros = 0;
00107 if ( head2[i] != head[i] )
00108 allmatch = 0;
00109 }
00110 if ( !allzeros && !allmatch )
00111 return FT_Err_Unknown_File_Format;
00112
00113
00114
00115
00116
00117 (void)FT_STREAM_SKIP( 4
00118 + 2
00119 + 2 );
00120
00121 if ( FT_READ_USHORT( type_list ) )
00122 return error;
00123 if ( type_list == -1 )
00124 return FT_Err_Unknown_File_Format;
00125
00126 error = FT_Stream_Seek( stream, map_pos + type_list );
00127 if ( error )
00128 return error;
00129
00130 *map_offset = map_pos + type_list;
00131 return FT_Err_Ok;
00132 }
00133
00134
00135 static int
00136 ft_raccess_sort_ref_by_id( FT_RFork_Ref* a,
00137 FT_RFork_Ref* b )
00138 {
00139 if ( a->res_id < b->res_id )
00140 return -1;
00141 else if ( a->res_id > b->res_id )
00142 return 1;
00143 else
00144 return 0;
00145 }
00146
00147
00148 FT_BASE_DEF( FT_Error )
00149 FT_Raccess_Get_DataOffsets( FT_Library library,
00150 FT_Stream stream,
00151 FT_Long map_offset,
00152 FT_Long rdata_pos,
00153 FT_Long tag,
00154 FT_Long **offsets,
00155 FT_Long *count )
00156 {
00157 FT_Error error;
00158 int i, j, cnt, subcnt;
00159 FT_Long tag_internal, rpos;
00160 FT_Memory memory = library->memory;
00161 FT_Long temp;
00162 FT_Long *offsets_internal;
00163 FT_RFork_Ref *ref;
00164
00165
00166 error = FT_Stream_Seek( stream, map_offset );
00167 if ( error )
00168 return error;
00169
00170 if ( FT_READ_USHORT( cnt ) )
00171 return error;
00172 cnt++;
00173
00174 for ( i = 0; i < cnt; ++i )
00175 {
00176 if ( FT_READ_LONG( tag_internal ) ||
00177 FT_READ_USHORT( subcnt ) ||
00178 FT_READ_USHORT( rpos ) )
00179 return error;
00180
00181 FT_TRACE2(( "Resource tags: %c%c%c%c\n",
00182 (char)( 0xff & ( tag_internal >> 24 ) ),
00183 (char)( 0xff & ( tag_internal >> 16 ) ),
00184 (char)( 0xff & ( tag_internal >> 8 ) ),
00185 (char)( 0xff & ( tag_internal >> 0 ) ) ));
00186
00187 if ( tag_internal == tag )
00188 {
00189 *count = subcnt + 1;
00190 rpos += map_offset;
00191
00192 error = FT_Stream_Seek( stream, rpos );
00193 if ( error )
00194 return error;
00195
00196 if ( FT_NEW_ARRAY( ref, *count ) )
00197 return error;
00198
00199 for ( j = 0; j < *count; ++j )
00200 {
00201 if ( FT_READ_USHORT( ref[j].res_id ) )
00202 goto Exit;
00203 if ( FT_STREAM_SKIP( 2 ) )
00204 goto Exit;
00205 if ( FT_READ_LONG( temp ) )
00206 goto Exit;
00207 if ( FT_STREAM_SKIP( 4 ) )
00208 goto Exit;
00209
00210 ref[j].offset = temp & 0xFFFFFFL;
00211 }
00212
00213 ft_qsort( ref, *count, sizeof ( FT_RFork_Ref ),
00214 ( int(*)(const void*, const void*) )
00215 ft_raccess_sort_ref_by_id );
00216
00217 if ( FT_NEW_ARRAY( offsets_internal, *count ) )
00218 goto Exit;
00219
00220
00221
00222
00223
00224 for ( j = 0; j < *count; ++j )
00225 offsets_internal[j] = rdata_pos + ref[j].offset;
00226
00227 *offsets = offsets_internal;
00228 error = FT_Err_Ok;
00229
00230 Exit:
00231 FT_FREE( ref );
00232 return error;
00233 }
00234 }
00235
00236 return FT_Err_Cannot_Open_Resource;
00237 }
00238
00239
00240 #ifdef FT_CONFIG_OPTION_GUESSING_EMBEDDED_RFORK
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256 typedef FT_Error
00257 (*raccess_guess_func)( FT_Library library,
00258 FT_Stream stream,
00259 char *base_file_name,
00260 char **result_file_name,
00261 FT_Long *result_offset );
00262
00263
00264 static FT_Error
00265 raccess_guess_apple_double( FT_Library library,
00266 FT_Stream stream,
00267 char *base_file_name,
00268 char **result_file_name,
00269 FT_Long *result_offset );
00270
00271 static FT_Error
00272 raccess_guess_apple_single( FT_Library library,
00273 FT_Stream stream,
00274 char *base_file_name,
00275 char **result_file_name,
00276 FT_Long *result_offset );
00277
00278 static FT_Error
00279 raccess_guess_darwin_ufs_export( FT_Library library,
00280 FT_Stream stream,
00281 char *base_file_name,
00282 char **result_file_name,
00283 FT_Long *result_offset );
00284
00285 static FT_Error
00286 raccess_guess_darwin_newvfs( FT_Library library,
00287 FT_Stream stream,
00288 char *base_file_name,
00289 char **result_file_name,
00290 FT_Long *result_offset );
00291
00292 static FT_Error
00293 raccess_guess_darwin_hfsplus( FT_Library library,
00294 FT_Stream stream,
00295 char *base_file_name,
00296 char **result_file_name,
00297 FT_Long *result_offset );
00298
00299 static FT_Error
00300 raccess_guess_vfat( FT_Library library,
00301 FT_Stream stream,
00302 char *base_file_name,
00303 char **result_file_name,
00304 FT_Long *result_offset );
00305
00306 static FT_Error
00307 raccess_guess_linux_cap( FT_Library library,
00308 FT_Stream stream,
00309 char *base_file_name,
00310 char **result_file_name,
00311 FT_Long *result_offset );
00312
00313 static FT_Error
00314 raccess_guess_linux_double( FT_Library library,
00315 FT_Stream stream,
00316 char *base_file_name,
00317 char **result_file_name,
00318 FT_Long *result_offset );
00319
00320 static FT_Error
00321 raccess_guess_linux_netatalk( FT_Library library,
00322 FT_Stream stream,
00323 char *base_file_name,
00324 char **result_file_name,
00325 FT_Long *result_offset );
00326
00327
00328
00329
00330
00331
00332
00333
00334 static FT_Error
00335 raccess_guess_apple_generic( FT_Library library,
00336 FT_Stream stream,
00337 char *base_file_name,
00338 FT_Int32 magic,
00339 FT_Long *result_offset );
00340
00341 static FT_Error
00342 raccess_guess_linux_double_from_file_name( FT_Library library,
00343 char * file_name,
00344 FT_Long *result_offset );
00345
00346 static char *
00347 raccess_make_file_name( FT_Memory memory,
00348 const char *original_name,
00349 const char *insertion );
00350
00351
00352 FT_BASE_DEF( void )
00353 FT_Raccess_Guess( FT_Library library,
00354 FT_Stream stream,
00355 char* base_name,
00356 char **new_names,
00357 FT_Long *offsets,
00358 FT_Error *errors )
00359 {
00360 FT_Long i;
00361
00362
00363 raccess_guess_func funcs[FT_RACCESS_N_RULES] =
00364 {
00365 raccess_guess_apple_double,
00366 raccess_guess_apple_single,
00367 raccess_guess_darwin_ufs_export,
00368 raccess_guess_darwin_newvfs,
00369 raccess_guess_darwin_hfsplus,
00370 raccess_guess_vfat,
00371 raccess_guess_linux_cap,
00372 raccess_guess_linux_double,
00373 raccess_guess_linux_netatalk,
00374 };
00375
00376 for ( i = 0; i < FT_RACCESS_N_RULES; i++ )
00377 {
00378 new_names[i] = NULL;
00379 if ( NULL != stream )
00380 errors[i] = FT_Stream_Seek( stream, 0 );
00381 else
00382 errors[i] = FT_Err_Ok;
00383
00384 if ( errors[i] )
00385 continue ;
00386
00387 errors[i] = (funcs[i])( library, stream, base_name,
00388 &(new_names[i]), &(offsets[i]) );
00389 }
00390
00391 return;
00392 }
00393
00394
00395 static FT_Error
00396 raccess_guess_apple_double( FT_Library library,
00397 FT_Stream stream,
00398 char *base_file_name,
00399 char **result_file_name,
00400 FT_Long *result_offset )
00401 {
00402 FT_Int32 magic = ( 0x00 << 24 ) |
00403 ( 0x05 << 16 ) |
00404 ( 0x16 << 8 ) |
00405 0x07;
00406
00407
00408 *result_file_name = NULL;
00409 if ( NULL == stream )
00410 return FT_Err_Cannot_Open_Stream;
00411
00412 return raccess_guess_apple_generic( library, stream, base_file_name,
00413 magic, result_offset );
00414 }
00415
00416
00417 static FT_Error
00418 raccess_guess_apple_single( FT_Library library,
00419 FT_Stream stream,
00420 char *base_file_name,
00421 char **result_file_name,
00422 FT_Long *result_offset )
00423 {
00424 FT_Int32 magic = ( 0x00 << 24 ) |
00425 ( 0x05 << 16 ) |
00426 ( 0x16 << 8 ) |
00427 0x00;
00428
00429
00430 *result_file_name = NULL;
00431 if ( NULL == stream )
00432 return FT_Err_Cannot_Open_Stream;
00433
00434 return raccess_guess_apple_generic( library, stream, base_file_name,
00435 magic, result_offset );
00436 }
00437
00438
00439 static FT_Error
00440 raccess_guess_darwin_ufs_export( FT_Library library,
00441 FT_Stream stream,
00442 char *base_file_name,
00443 char **result_file_name,
00444 FT_Long *result_offset )
00445 {
00446 char* newpath;
00447 FT_Error error;
00448 FT_Memory memory;
00449
00450 FT_UNUSED( stream );
00451
00452
00453 memory = library->memory;
00454 newpath = raccess_make_file_name( memory, base_file_name, "._" );
00455 if ( !newpath )
00456 return FT_Err_Out_Of_Memory;
00457
00458 error = raccess_guess_linux_double_from_file_name( library, newpath,
00459 result_offset );
00460 if ( !error )
00461 *result_file_name = newpath;
00462 else
00463 FT_FREE( newpath );
00464
00465 return error;
00466 }
00467
00468
00469 static FT_Error
00470 raccess_guess_darwin_hfsplus( FT_Library library,
00471 FT_Stream stream,
00472 char *base_file_name,
00473 char **result_file_name,
00474 FT_Long *result_offset )
00475 {
00476
00477
00478
00479 FT_Error error;
00480 char* newpath;
00481 FT_Memory memory;
00482 FT_Long base_file_len = ft_strlen( base_file_name );
00483
00484 FT_UNUSED( stream );
00485
00486
00487 memory = library->memory;
00488
00489 if ( base_file_len + 6 > FT_INT_MAX )
00490 return FT_Err_Array_Too_Large;
00491
00492 if ( FT_ALLOC( newpath, base_file_len + 6 ) )
00493 return error;
00494
00495 FT_MEM_COPY( newpath, base_file_name, base_file_len );
00496 FT_MEM_COPY( newpath + base_file_len, "/rsrc", 6 );
00497
00498 *result_file_name = newpath;
00499 *result_offset = 0;
00500
00501 return FT_Err_Ok;
00502 }
00503
00504
00505 static FT_Error
00506 raccess_guess_darwin_newvfs( FT_Library library,
00507 FT_Stream stream,
00508 char *base_file_name,
00509 char **result_file_name,
00510 FT_Long *result_offset )
00511 {
00512
00513
00514
00515 FT_Error error;
00516 char* newpath;
00517 FT_Memory memory;
00518 FT_Long base_file_len = ft_strlen( base_file_name );
00519
00520 FT_UNUSED( stream );
00521
00522
00523 memory = library->memory;
00524
00525 if ( base_file_len + 18 > FT_INT_MAX )
00526 return FT_Err_Array_Too_Large;
00527
00528 if ( FT_ALLOC( newpath, base_file_len + 18 ) )
00529 return error;
00530
00531 FT_MEM_COPY( newpath, base_file_name, base_file_len );
00532 FT_MEM_COPY( newpath + base_file_len, "/..namedfork/rsrc", 18 );
00533
00534 *result_file_name = newpath;
00535 *result_offset = 0;
00536
00537 return FT_Err_Ok;
00538 }
00539
00540
00541 static FT_Error
00542 raccess_guess_vfat( FT_Library library,
00543 FT_Stream stream,
00544 char *base_file_name,
00545 char **result_file_name,
00546 FT_Long *result_offset )
00547 {
00548 char* newpath;
00549 FT_Memory memory;
00550
00551 FT_UNUSED( stream );
00552
00553
00554 memory = library->memory;
00555
00556 newpath = raccess_make_file_name( memory, base_file_name,
00557 "resource.frk/" );
00558 if ( !newpath )
00559 return FT_Err_Out_Of_Memory;
00560
00561 *result_file_name = newpath;
00562 *result_offset = 0;
00563
00564 return FT_Err_Ok;
00565 }
00566
00567
00568 static FT_Error
00569 raccess_guess_linux_cap( FT_Library library,
00570 FT_Stream stream,
00571 char *base_file_name,
00572 char **result_file_name,
00573 FT_Long *result_offset )
00574 {
00575 char* newpath;
00576 FT_Memory memory;
00577
00578 FT_UNUSED( stream );
00579
00580
00581 memory = library->memory;
00582
00583 newpath = raccess_make_file_name( memory, base_file_name, ".resource/" );
00584 if ( !newpath )
00585 return FT_Err_Out_Of_Memory;
00586
00587 *result_file_name = newpath;
00588 *result_offset = 0;
00589
00590 return FT_Err_Ok;
00591 }
00592
00593
00594 static FT_Error
00595 raccess_guess_linux_double( FT_Library library,
00596 FT_Stream stream,
00597 char *base_file_name,
00598 char **result_file_name,
00599 FT_Long *result_offset )
00600 {
00601 char* newpath;
00602 FT_Error error;
00603 FT_Memory memory;
00604
00605 FT_UNUSED( stream );
00606
00607
00608 memory = library->memory;
00609
00610 newpath = raccess_make_file_name( memory, base_file_name, "%" );
00611 if ( !newpath )
00612 return FT_Err_Out_Of_Memory;
00613
00614 error = raccess_guess_linux_double_from_file_name( library, newpath,
00615 result_offset );
00616 if ( !error )
00617 *result_file_name = newpath;
00618 else
00619 FT_FREE( newpath );
00620
00621 return error;
00622 }
00623
00624
00625 static FT_Error
00626 raccess_guess_linux_netatalk( FT_Library library,
00627 FT_Stream stream,
00628 char *base_file_name,
00629 char **result_file_name,
00630 FT_Long *result_offset )
00631 {
00632 char* newpath;
00633 FT_Error error;
00634 FT_Memory memory;
00635
00636 FT_UNUSED( stream );
00637
00638
00639 memory = library->memory;
00640
00641 newpath = raccess_make_file_name( memory, base_file_name,
00642 ".AppleDouble/" );
00643 if ( !newpath )
00644 return FT_Err_Out_Of_Memory;
00645
00646 error = raccess_guess_linux_double_from_file_name( library, newpath,
00647 result_offset );
00648 if ( !error )
00649 *result_file_name = newpath;
00650 else
00651 FT_FREE( newpath );
00652
00653 return error;
00654 }
00655
00656
00657 static FT_Error
00658 raccess_guess_apple_generic( FT_Library library,
00659 FT_Stream stream,
00660 char *base_file_name,
00661 FT_Int32 magic,
00662 FT_Long *result_offset )
00663 {
00664 FT_Int32 magic_from_stream;
00665 FT_Error error;
00666 FT_Int32 version_number = 0;
00667 FT_UShort n_of_entries;
00668
00669 int i;
00670 FT_UInt32 entry_id, entry_offset, entry_length = 0;
00671
00672 const FT_UInt32 resource_fork_entry_id = 0x2;
00673
00674 FT_UNUSED( library );
00675 FT_UNUSED( base_file_name );
00676 FT_UNUSED( version_number );
00677 FT_UNUSED( entry_length );
00678
00679
00680 if ( FT_READ_LONG( magic_from_stream ) )
00681 return error;
00682 if ( magic_from_stream != magic )
00683 return FT_Err_Unknown_File_Format;
00684
00685 if ( FT_READ_LONG( version_number ) )
00686 return error;
00687
00688
00689 error = FT_Stream_Skip( stream, 16 );
00690 if ( error )
00691 return error;
00692
00693 if ( FT_READ_USHORT( n_of_entries ) )
00694 return error;
00695 if ( n_of_entries == 0 )
00696 return FT_Err_Unknown_File_Format;
00697
00698 for ( i = 0; i < n_of_entries; i++ )
00699 {
00700 if ( FT_READ_LONG( entry_id ) )
00701 return error;
00702 if ( entry_id == resource_fork_entry_id )
00703 {
00704 if ( FT_READ_LONG( entry_offset ) ||
00705 FT_READ_LONG( entry_length ) )
00706 continue;
00707 *result_offset = entry_offset;
00708
00709 return FT_Err_Ok;
00710 }
00711 else
00712 {
00713 error = FT_Stream_Skip( stream, 4 + 4 );
00714 if ( error )
00715 return error;
00716 }
00717 }
00718
00719 return FT_Err_Unknown_File_Format;
00720 }
00721
00722
00723 static FT_Error
00724 raccess_guess_linux_double_from_file_name( FT_Library library,
00725 char *file_name,
00726 FT_Long *result_offset )
00727 {
00728 FT_Open_Args args2;
00729 FT_Stream stream2;
00730 char * nouse = NULL;
00731 FT_Error error;
00732
00733
00734 args2.flags = FT_OPEN_PATHNAME;
00735 args2.pathname = file_name;
00736 error = FT_Stream_New( library, &args2, &stream2 );
00737 if ( error )
00738 return error;
00739
00740 error = raccess_guess_apple_double( library, stream2, file_name,
00741 &nouse, result_offset );
00742
00743 FT_Stream_Free( stream2, 0 );
00744
00745 return error;
00746 }
00747
00748
00749 static char*
00750 raccess_make_file_name( FT_Memory memory,
00751 const char *original_name,
00752 const char *insertion )
00753 {
00754 char* new_name;
00755 const char* tmp;
00756 const char* slash;
00757 size_t new_length;
00758 FT_Error error = FT_Err_Ok;
00759
00760 FT_UNUSED( error );
00761
00762
00763 new_length = ft_strlen( original_name ) + ft_strlen( insertion );
00764 if ( FT_ALLOC( new_name, new_length + 1 ) )
00765 return NULL;
00766
00767 tmp = ft_strrchr( original_name, '/' );
00768 if ( tmp )
00769 {
00770 ft_strncpy( new_name, original_name, tmp - original_name + 1 );
00771 new_name[tmp - original_name + 1] = '\0';
00772 slash = tmp + 1;
00773 }
00774 else
00775 {
00776 slash = original_name;
00777 new_name[0] = '\0';
00778 }
00779
00780 ft_strcat( new_name, insertion );
00781 ft_strcat( new_name, slash );
00782
00783 return new_name;
00784 }
00785
00786
00787 #else
00788
00789
00790
00791
00792
00793
00794 FT_BASE_DEF( void )
00795 FT_Raccess_Guess( FT_Library library,
00796 FT_Stream stream,
00797 char *base_name,
00798 char **new_names,
00799 FT_Long *offsets,
00800 FT_Error *errors )
00801 {
00802 int i;
00803
00804 FT_UNUSED( library );
00805 FT_UNUSED( stream );
00806 FT_UNUSED( base_name );
00807
00808
00809 for ( i = 0; i < FT_RACCESS_N_RULES; i++ )
00810 {
00811 new_names[i] = NULL;
00812 offsets[i] = 0;
00813 errors[i] = FT_Err_Unimplemented_Feature;
00814 }
00815 }
00816
00817
00818 #endif
00819
00820
00821