1
/***************************************************************************/
5
/* Embedded resource forks accessor (body). */
7
/* Copyright 2004 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;
135
FT_BASE_DEF( FT_Error )
136
FT_Raccess_Get_DataOffsets( FT_Library library,
145
int i, j, cnt, subcnt;
146
FT_Long tag_internal, rpos;
147
FT_Memory memory = library->memory;
149
FT_Long *offsets_internal;
152
error = FT_Stream_Seek( stream, map_offset );
156
if ( FT_READ_USHORT( cnt ) )
160
for ( i = 0; i < cnt; ++i )
162
if ( FT_READ_LONG( tag_internal ) ||
163
FT_READ_USHORT( subcnt ) ||
164
FT_READ_USHORT( rpos ) )
167
FT_TRACE2(( "Resource tags: %c%c%c%c\n",
168
(char)( 0xff & ( tag_internal >> 24 ) ),
169
(char)( 0xff & ( tag_internal >> 16 ) ),
170
(char)( 0xff & ( tag_internal >> 8 ) ),
171
(char)( 0xff & ( tag_internal >> 0 ) ) ));
173
if ( tag_internal == tag )
178
error = FT_Stream_Seek( stream, rpos );
182
if ( FT_ALLOC( offsets_internal, *count * sizeof( FT_Long ) ) )
185
for ( j = 0; j < *count; ++j )
187
(void)FT_STREAM_SKIP( 2 ); /* resource id */
188
(void)FT_STREAM_SKIP( 2 ); /* rsource name */
190
if ( FT_READ_LONG( temp ) )
192
FT_FREE( offsets_internal );
196
offsets_internal[j] = rdata_pos + ( temp & 0xFFFFFFL );
198
(void)FT_STREAM_SKIP( 4 ); /* mbz */
201
*offsets = offsets_internal;
207
return FT_Err_Cannot_Open_Resource;
211
#ifdef FT_CONFIG_OPTION_GUESSING_EMBEDDED_RFORK
213
/*************************************************************************/
214
/*************************************************************************/
215
/*************************************************************************/
218
/**** Guessing functions ****/
220
/**** When you add a new guessing function, ****/
221
/**** update FT_RACCESS_N_RULES in ftrfork.h. ****/
223
/*************************************************************************/
224
/*************************************************************************/
225
/*************************************************************************/
228
(*raccess_guess_func)( FT_Library library,
230
char * base_file_name,
231
char **result_file_name,
232
FT_Long *result_offset );
236
raccess_guess_apple_double( FT_Library library,
238
char * base_file_name,
239
char **result_file_name,
240
FT_Long *result_offset );
243
raccess_guess_apple_single( FT_Library library,
245
char * base_file_name,
246
char **result_file_name,
247
FT_Long *result_offset );
250
raccess_guess_darwin_ufs_export( FT_Library library,
252
char * base_file_name,
253
char **result_file_name,
254
FT_Long *result_offset );
257
raccess_guess_darwin_hfsplus( FT_Library library,
259
char * base_file_name,
260
char **result_file_name,
261
FT_Long *result_offset );
264
raccess_guess_vfat( FT_Library library,
266
char * base_file_name,
267
char **result_file_name,
268
FT_Long *result_offset );
271
raccess_guess_linux_cap( FT_Library library,
273
char * base_file_name,
274
char **result_file_name,
275
FT_Long *result_offset );
278
raccess_guess_linux_double( FT_Library library,
280
char * base_file_name,
281
char **result_file_name,
282
FT_Long *result_offset );
285
raccess_guess_linux_netatalk( FT_Library library,
287
char * base_file_name,
288
char **result_file_name,
289
FT_Long *result_offset );
292
/*************************************************************************/
294
/**** Helper functions ****/
296
/*************************************************************************/
299
raccess_guess_apple_generic( FT_Library library,
301
char * base_file_name,
303
FT_Long *result_offset );
306
raccess_guess_linux_double_from_file_name( FT_Library library,
308
FT_Long *result_offset );
311
raccess_make_file_name( FT_Memory memory,
312
const char *original_name,
313
const char *insertion );
317
FT_Raccess_Guess( FT_Library library,
327
raccess_guess_func funcs[FT_RACCESS_N_RULES] =
329
raccess_guess_apple_double,
330
raccess_guess_apple_single,
331
raccess_guess_darwin_ufs_export,
332
raccess_guess_darwin_hfsplus,
334
raccess_guess_linux_cap,
335
raccess_guess_linux_double,
336
raccess_guess_linux_netatalk,
339
for ( i = 0; i < FT_RACCESS_N_RULES; i++ )
342
errors[i] = FT_Stream_Seek( stream, 0 );
346
errors[i] = (funcs[i])( library, stream, base_name,
347
&(new_names[i]), &(offsets[i]) );
355
raccess_guess_apple_double( FT_Library library,
357
char * base_file_name,
358
char **result_file_name,
359
FT_Long *result_offset )
361
FT_Int32 magic = ( 0x00 << 24 | 0x05 << 16 | 0x16 << 8 | 0x07 );
364
*result_file_name = NULL;
365
return raccess_guess_apple_generic( library, stream, base_file_name,
366
magic, result_offset );
371
raccess_guess_apple_single( FT_Library library,
373
char * base_file_name,
374
char **result_file_name,
375
FT_Long *result_offset )
377
FT_Int32 magic = (0x00 << 24 | 0x05 << 16 | 0x16 << 8 | 0x00);
380
*result_file_name = NULL;
381
return raccess_guess_apple_generic( library, stream, base_file_name,
382
magic, result_offset );
387
raccess_guess_darwin_ufs_export( FT_Library library,
389
char * base_file_name,
390
char **result_file_name,
391
FT_Long *result_offset )
400
memory = library->memory;
401
newpath = raccess_make_file_name( memory, base_file_name, "._" );
403
return FT_Err_Out_Of_Memory;
405
error = raccess_guess_linux_double_from_file_name( library, newpath,
408
*result_file_name = newpath;
417
raccess_guess_darwin_hfsplus( FT_Library library,
419
char * base_file_name,
420
char **result_file_name,
421
FT_Long *result_offset )
424
Only meaningful on systems with hfs+ drivers (or Macs).
433
memory = library->memory;
435
if ( FT_ALLOC( newpath,
436
ft_strlen( base_file_name ) + ft_strlen( "/rsrc" ) + 1 ) )
439
ft_strcpy( newpath, base_file_name );
440
ft_strcat( newpath, "/rsrc" );
441
*result_file_name = newpath;
448
raccess_guess_vfat( FT_Library library,
450
char * base_file_name,
451
char **result_file_name,
452
FT_Long *result_offset )
460
memory = library->memory;
462
newpath = raccess_make_file_name( memory, base_file_name,
465
return FT_Err_Out_Of_Memory;
467
*result_file_name = newpath;
475
raccess_guess_linux_cap( FT_Library library,
477
char * base_file_name,
478
char **result_file_name,
479
FT_Long *result_offset )
487
memory = library->memory;
489
newpath = raccess_make_file_name( memory, base_file_name, ".resource/" );
491
return FT_Err_Out_Of_Memory;
493
*result_file_name = newpath;
501
raccess_guess_linux_double( FT_Library library,
503
char * base_file_name,
504
char **result_file_name,
505
FT_Long *result_offset )
514
memory = library->memory;
516
newpath = raccess_make_file_name( memory, base_file_name, "%" );
518
return FT_Err_Out_Of_Memory;
520
error = raccess_guess_linux_double_from_file_name( library, newpath,
523
*result_file_name = newpath;
532
raccess_guess_linux_netatalk( FT_Library library,
534
char * base_file_name,
535
char **result_file_name,
536
FT_Long *result_offset )
545
memory = library->memory;
547
newpath = raccess_make_file_name( memory, base_file_name,
550
return FT_Err_Out_Of_Memory;
552
error = raccess_guess_linux_double_from_file_name( library, newpath,
555
*result_file_name = newpath;
564
raccess_guess_apple_generic( FT_Library library,
566
char * base_file_name,
568
FT_Long *result_offset )
570
FT_Int32 magic_from_stream;
572
FT_Int32 version_number;
573
FT_UShort n_of_entries;
576
FT_UInt32 entry_id, entry_offset, entry_length;
578
const FT_UInt32 resource_fork_entry_id = 0x2;
580
FT_UNUSED( library );
581
FT_UNUSED( base_file_name );
584
if ( FT_READ_LONG ( magic_from_stream ) )
586
if ( magic_from_stream != magic )
587
return FT_Err_Unknown_File_Format;
589
if ( FT_READ_LONG( version_number ) )
593
error = FT_Stream_Skip( stream, 16 );
597
if ( FT_READ_USHORT( n_of_entries ) )
599
if ( n_of_entries == 0 )
600
return FT_Err_Unknown_File_Format;
602
for ( i = 0; i < n_of_entries; i++ )
604
if ( FT_READ_LONG( entry_id ) )
606
if ( entry_id == resource_fork_entry_id )
608
if ( FT_READ_LONG( entry_offset ) ||
609
FT_READ_LONG( entry_length ) )
611
*result_offset = entry_offset;
616
FT_Stream_Skip( stream, 4 + 4 ); /* offset + length */
619
return FT_Err_Unknown_File_Format;
624
raccess_guess_linux_double_from_file_name( FT_Library library,
626
FT_Long *result_offset )
635
memory = library->memory;
637
args2.flags = FT_OPEN_PATHNAME;
638
args2.pathname = file_name;
639
error = FT_Stream_New( library, &args2, &stream2 );
643
error = raccess_guess_apple_double( library, stream2, file_name,
644
&nouse, result_offset );
646
FT_Stream_Close( stream2 );
653
raccess_make_file_name( FT_Memory memory,
654
const char *original_name,
655
const char *insertion )
663
new_length = ft_strlen( original_name ) + ft_strlen( insertion );
664
if ( FT_ALLOC( new_name, new_length + 1 ) )
667
tmp = ft_strrchr( original_name, '/' );
670
ft_strncpy( new_name, original_name, tmp - original_name + 1 );
671
new_name[tmp - original_name + 1] = '\0';
676
slash = original_name;
680
ft_strcat( new_name, insertion );
681
ft_strcat( new_name, slash );
687
#else /* !FT_CONFIG_OPTION_GUESSING_EMBEDDED_RFORK */
690
/*************************************************************************/
691
/* Dummy function; just sets errors */
692
/*************************************************************************/
695
FT_Raccess_Guess( FT_Library library,
705
for ( i = 0; i < FT_RACCESS_N_RULES; i++ )
709
errors[i] = FT_Err_Unimplemented_Feature;
714
#endif /* !FT_CONFIG_OPTION_GUESSING_EMBEDDED_RFORK */