1
/***************************************************************************/
5
/* Embedded resource forks accessor (body). */
7
/* Copyright 2004, 2005, 2006, 2007, 2008, 2009, 2010 by */
8
/* Masatake YAMATO and Redhat K.K. */
10
/* FT_Raccess_Get_HeaderInfo() and raccess_guess_darwin_hfsplus() are */
11
/* derived from ftobjs.c. */
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. */
19
/***************************************************************************/
21
/***************************************************************************/
22
/* Development of the code in this file is support of */
23
/* Information-technology Promotion Agency, Japan. */
24
/***************************************************************************/
28
#include FT_INTERNAL_DEBUG_H
29
#include FT_INTERNAL_STREAM_H
30
#include FT_INTERNAL_RFORK_H
34
#define FT_COMPONENT trace_raccess
37
/*************************************************************************/
38
/*************************************************************************/
39
/*************************************************************************/
42
/**** Resource fork directory access ****/
45
/*************************************************************************/
46
/*************************************************************************/
47
/*************************************************************************/
49
FT_BASE_DEF( FT_Error )
50
FT_Raccess_Get_HeaderInfo( FT_Library library,
57
unsigned char head[16], head2[16];
58
FT_Long map_pos, rdata_len;
59
int allzeros, allmatch, i;
65
error = FT_Stream_Seek( stream, rfork_offset );
69
error = FT_Stream_Read( stream, (FT_Byte *)head, 16 );
73
*rdata_pos = rfork_offset + ( ( head[0] << 24 ) |
77
map_pos = rfork_offset + ( ( head[4] << 24 ) |
81
rdata_len = ( head[ 8] << 24 ) |
86
/* map_len = head[12] .. head[15] */
88
if ( *rdata_pos + rdata_len != map_pos || map_pos == rfork_offset )
89
return FT_Err_Unknown_File_Format;
91
error = FT_Stream_Seek( stream, map_pos );
95
head2[15] = (FT_Byte)( head[15] + 1 ); /* make it be different */
97
error = FT_Stream_Read( stream, (FT_Byte*)head2, 16 );
103
for ( i = 0; i < 16; ++i )
107
if ( head2[i] != head[i] )
110
if ( !allzeros && !allmatch )
111
return FT_Err_Unknown_File_Format;
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 */
117
(void)FT_STREAM_SKIP( 4 /* skip handle to next resource map */
118
+ 2 /* skip file resource number */
119
+ 2 ); /* skip attributes */
121
if ( FT_READ_USHORT( type_list ) )
123
if ( type_list == -1 )
124
return FT_Err_Unknown_File_Format;
126
error = FT_Stream_Seek( stream, map_pos + type_list );
130
*map_offset = map_pos + type_list;
136
ft_raccess_sort_ref_by_id( FT_RFork_Ref* a,
139
if ( a->res_id < b->res_id )
141
else if ( a->res_id > b->res_id )
148
FT_BASE_DEF( FT_Error )
149
FT_Raccess_Get_DataOffsets( FT_Library library,
158
int i, j, cnt, subcnt;
159
FT_Long tag_internal, rpos;
160
FT_Memory memory = library->memory;
162
FT_Long *offsets_internal;
166
error = FT_Stream_Seek( stream, map_offset );
170
if ( FT_READ_USHORT( cnt ) )
174
for ( i = 0; i < cnt; ++i )
176
if ( FT_READ_LONG( tag_internal ) ||
177
FT_READ_USHORT( subcnt ) ||
178
FT_READ_USHORT( rpos ) )
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 ) ) ));
187
if ( tag_internal == tag )
192
error = FT_Stream_Seek( stream, rpos );
196
if ( FT_NEW_ARRAY( ref, *count ) )
199
for ( j = 0; j < *count; ++j )
201
if ( FT_READ_USHORT( ref[j].res_id ) )
203
if ( FT_STREAM_SKIP( 2 ) ) /* resource name */
205
if ( FT_READ_LONG( temp ) )
207
if ( FT_STREAM_SKIP( 4 ) ) /* mbz */
210
ref[j].offset = temp & 0xFFFFFFL;
213
ft_qsort( ref, *count, sizeof ( FT_RFork_Ref ),
214
( int(*)(const void*, const void*) )
215
ft_raccess_sort_ref_by_id );
217
if ( FT_NEW_ARRAY( offsets_internal, *count ) )
220
/* XXX: duplicated reference ID,
221
* gap between reference IDs are acceptable?
222
* further investigation on Apple implementation is needed.
224
for ( j = 0; j < *count; ++j )
225
offsets_internal[j] = rdata_pos + ref[j].offset;
227
*offsets = offsets_internal;
236
return FT_Err_Cannot_Open_Resource;
240
#ifdef FT_CONFIG_OPTION_GUESSING_EMBEDDED_RFORK
242
/*************************************************************************/
243
/*************************************************************************/
244
/*************************************************************************/
247
/**** Guessing functions ****/
249
/**** When you add a new guessing function, ****/
250
/**** update FT_RACCESS_N_RULES in ftrfork.h. ****/
252
/*************************************************************************/
253
/*************************************************************************/
254
/*************************************************************************/
257
(*raccess_guess_func)( FT_Library library,
259
char *base_file_name,
260
char **result_file_name,
261
FT_Long *result_offset );
265
raccess_guess_apple_double( FT_Library library,
267
char *base_file_name,
268
char **result_file_name,
269
FT_Long *result_offset );
272
raccess_guess_apple_single( FT_Library library,
274
char *base_file_name,
275
char **result_file_name,
276
FT_Long *result_offset );
279
raccess_guess_darwin_ufs_export( FT_Library library,
281
char *base_file_name,
282
char **result_file_name,
283
FT_Long *result_offset );
286
raccess_guess_darwin_newvfs( FT_Library library,
288
char *base_file_name,
289
char **result_file_name,
290
FT_Long *result_offset );
293
raccess_guess_darwin_hfsplus( FT_Library library,
295
char *base_file_name,
296
char **result_file_name,
297
FT_Long *result_offset );
300
raccess_guess_vfat( FT_Library library,
302
char *base_file_name,
303
char **result_file_name,
304
FT_Long *result_offset );
307
raccess_guess_linux_cap( FT_Library library,
309
char *base_file_name,
310
char **result_file_name,
311
FT_Long *result_offset );
314
raccess_guess_linux_double( FT_Library library,
316
char *base_file_name,
317
char **result_file_name,
318
FT_Long *result_offset );
321
raccess_guess_linux_netatalk( FT_Library library,
323
char *base_file_name,
324
char **result_file_name,
325
FT_Long *result_offset );
328
/*************************************************************************/
330
/**** Helper functions ****/
332
/*************************************************************************/
335
raccess_guess_apple_generic( FT_Library library,
337
char *base_file_name,
339
FT_Long *result_offset );
342
raccess_guess_linux_double_from_file_name( FT_Library library,
344
FT_Long *result_offset );
347
raccess_make_file_name( FT_Memory memory,
348
const char *original_name,
349
const char *insertion );
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,
361
FT_RFork_Rule_linux_cap,
362
FT_RFork_Rule_linux_double,
363
FT_RFork_Rule_linux_netatalk
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
370
typedef struct raccess_guess_rec_ {
371
raccess_guess_func func;
375
static raccess_guess_rec raccess_guess_table[FT_RACCESS_N_RULES] =
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, },
389
FT_Raccess_Guess( FT_Library library,
399
for ( i = 0; i < FT_RACCESS_N_RULES; i++ )
402
if ( NULL != stream )
403
errors[i] = FT_Stream_Seek( stream, 0 );
405
errors[i] = FT_Err_Ok;
410
errors[i] = (raccess_guess_table[i].func)( library,
421
raccess_get_rule_type_from_rule_index( FT_UInt rule_index )
423
if ( rule_index >= FT_RACCESS_N_RULES )
424
return FT_RFork_Rule_invalid;
426
return raccess_guess_table[rule_index].type;
430
FT_LOCAL_DEF( FT_Bool )
431
raccess_rule_by_darwin_vfs( FT_UInt rule_index )
433
switch( raccess_get_rule_type_from_rule_index( rule_index ) )
435
case FT_RFork_Rule_darwin_newvfs:
436
case FT_RFork_Rule_darwin_hfsplus:
446
raccess_guess_apple_double( FT_Library library,
448
char *base_file_name,
449
char **result_file_name,
450
FT_Long *result_offset )
452
FT_Int32 magic = ( 0x00 << 24 ) |
458
*result_file_name = NULL;
459
if ( NULL == stream )
460
return FT_Err_Cannot_Open_Stream;
462
return raccess_guess_apple_generic( library, stream, base_file_name,
463
magic, result_offset );
468
raccess_guess_apple_single( FT_Library library,
470
char *base_file_name,
471
char **result_file_name,
472
FT_Long *result_offset )
474
FT_Int32 magic = ( 0x00 << 24 ) |
480
*result_file_name = NULL;
481
if ( NULL == stream )
482
return FT_Err_Cannot_Open_Stream;
484
return raccess_guess_apple_generic( library, stream, base_file_name,
485
magic, result_offset );
490
raccess_guess_darwin_ufs_export( FT_Library library,
492
char *base_file_name,
493
char **result_file_name,
494
FT_Long *result_offset )
503
memory = library->memory;
504
newpath = raccess_make_file_name( memory, base_file_name, "._" );
506
return FT_Err_Out_Of_Memory;
508
error = raccess_guess_linux_double_from_file_name( library, newpath,
511
*result_file_name = newpath;
520
raccess_guess_darwin_hfsplus( FT_Library library,
522
char *base_file_name,
523
char **result_file_name,
524
FT_Long *result_offset )
527
Only meaningful on systems with hfs+ drivers (or Macs).
532
FT_Long base_file_len = ft_strlen( base_file_name );
537
memory = library->memory;
539
if ( base_file_len + 6 > FT_INT_MAX )
540
return FT_Err_Array_Too_Large;
542
if ( FT_ALLOC( newpath, base_file_len + 6 ) )
545
FT_MEM_COPY( newpath, base_file_name, base_file_len );
546
FT_MEM_COPY( newpath + base_file_len, "/rsrc", 6 );
548
*result_file_name = newpath;
556
raccess_guess_darwin_newvfs( FT_Library library,
558
char *base_file_name,
559
char **result_file_name,
560
FT_Long *result_offset )
563
Only meaningful on systems with Mac OS X (> 10.1).
568
FT_Long base_file_len = ft_strlen( base_file_name );
573
memory = library->memory;
575
if ( base_file_len + 18 > FT_INT_MAX )
576
return FT_Err_Array_Too_Large;
578
if ( FT_ALLOC( newpath, base_file_len + 18 ) )
581
FT_MEM_COPY( newpath, base_file_name, base_file_len );
582
FT_MEM_COPY( newpath + base_file_len, "/..namedfork/rsrc", 18 );
584
*result_file_name = newpath;
592
raccess_guess_vfat( FT_Library library,
594
char *base_file_name,
595
char **result_file_name,
596
FT_Long *result_offset )
604
memory = library->memory;
606
newpath = raccess_make_file_name( memory, base_file_name,
609
return FT_Err_Out_Of_Memory;
611
*result_file_name = newpath;
619
raccess_guess_linux_cap( FT_Library library,
621
char *base_file_name,
622
char **result_file_name,
623
FT_Long *result_offset )
631
memory = library->memory;
633
newpath = raccess_make_file_name( memory, base_file_name, ".resource/" );
635
return FT_Err_Out_Of_Memory;
637
*result_file_name = newpath;
645
raccess_guess_linux_double( FT_Library library,
647
char *base_file_name,
648
char **result_file_name,
649
FT_Long *result_offset )
658
memory = library->memory;
660
newpath = raccess_make_file_name( memory, base_file_name, "%" );
662
return FT_Err_Out_Of_Memory;
664
error = raccess_guess_linux_double_from_file_name( library, newpath,
667
*result_file_name = newpath;
676
raccess_guess_linux_netatalk( FT_Library library,
678
char *base_file_name,
679
char **result_file_name,
680
FT_Long *result_offset )
689
memory = library->memory;
691
newpath = raccess_make_file_name( memory, base_file_name,
694
return FT_Err_Out_Of_Memory;
696
error = raccess_guess_linux_double_from_file_name( library, newpath,
699
*result_file_name = newpath;
708
raccess_guess_apple_generic( FT_Library library,
710
char *base_file_name,
712
FT_Long *result_offset )
714
FT_Int32 magic_from_stream;
716
FT_Int32 version_number = 0;
717
FT_UShort n_of_entries;
720
FT_UInt32 entry_id, entry_offset, entry_length = 0;
722
const FT_UInt32 resource_fork_entry_id = 0x2;
724
FT_UNUSED( library );
725
FT_UNUSED( base_file_name );
726
FT_UNUSED( version_number );
727
FT_UNUSED( entry_length );
730
if ( FT_READ_LONG( magic_from_stream ) )
732
if ( magic_from_stream != magic )
733
return FT_Err_Unknown_File_Format;
735
if ( FT_READ_LONG( version_number ) )
739
error = FT_Stream_Skip( stream, 16 );
743
if ( FT_READ_USHORT( n_of_entries ) )
745
if ( n_of_entries == 0 )
746
return FT_Err_Unknown_File_Format;
748
for ( i = 0; i < n_of_entries; i++ )
750
if ( FT_READ_LONG( entry_id ) )
752
if ( entry_id == resource_fork_entry_id )
754
if ( FT_READ_LONG( entry_offset ) ||
755
FT_READ_LONG( entry_length ) )
757
*result_offset = entry_offset;
763
error = FT_Stream_Skip( stream, 4 + 4 ); /* offset + length */
769
return FT_Err_Unknown_File_Format;
774
raccess_guess_linux_double_from_file_name( FT_Library library,
776
FT_Long *result_offset )
784
args2.flags = FT_OPEN_PATHNAME;
785
args2.pathname = file_name;
786
error = FT_Stream_New( library, &args2, &stream2 );
790
error = raccess_guess_apple_double( library, stream2, file_name,
791
&nouse, result_offset );
793
FT_Stream_Free( stream2, 0 );
800
raccess_make_file_name( FT_Memory memory,
801
const char *original_name,
802
const char *insertion )
804
char* new_name = NULL;
808
FT_Error error = FT_Err_Ok;
813
new_length = ft_strlen( original_name ) + ft_strlen( insertion );
814
if ( FT_ALLOC( new_name, new_length + 1 ) )
817
tmp = ft_strrchr( original_name, '/' );
820
ft_strncpy( new_name, original_name, tmp - original_name + 1 );
821
new_name[tmp - original_name + 1] = '\0';
826
slash = original_name;
830
ft_strcat( new_name, insertion );
831
ft_strcat( new_name, slash );
837
#else /* !FT_CONFIG_OPTION_GUESSING_EMBEDDED_RFORK */
840
/*************************************************************************/
841
/* Dummy function; just sets errors */
842
/*************************************************************************/
845
FT_Raccess_Guess( FT_Library library,
854
FT_UNUSED( library );
856
FT_UNUSED( base_name );
859
for ( i = 0; i < FT_RACCESS_N_RULES; i++ )
863
errors[i] = FT_Err_Unimplemented_Feature;
868
#endif /* !FT_CONFIG_OPTION_GUESSING_EMBEDDED_RFORK */