1 /***************************************************************************/
5 /* Embedded resource forks accessor (body). */
7 /* Copyright 2004, 2005, 2006, 2007, 2008, 2009 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
);
353 FT_Raccess_Guess( FT_Library library
,
363 raccess_guess_func funcs
[FT_RACCESS_N_RULES
] =
365 raccess_guess_apple_double
,
366 raccess_guess_apple_single
,
367 raccess_guess_darwin_ufs_export
,
368 raccess_guess_darwin_newvfs
,
369 raccess_guess_darwin_hfsplus
,
371 raccess_guess_linux_cap
,
372 raccess_guess_linux_double
,
373 raccess_guess_linux_netatalk
,
376 for ( i
= 0; i
< FT_RACCESS_N_RULES
; i
++ )
379 if ( NULL
!= stream
)
380 errors
[i
] = FT_Stream_Seek( stream
, 0 );
382 errors
[i
] = FT_Err_Ok
;
387 errors
[i
] = (funcs
[i
])( library
, stream
, base_name
,
388 &(new_names
[i
]), &(offsets
[i
]) );
396 raccess_guess_apple_double( FT_Library library
,
398 char *base_file_name
,
399 char **result_file_name
,
400 FT_Long
*result_offset
)
402 FT_Int32 magic
= ( 0x00 << 24 ) |
408 *result_file_name
= NULL
;
409 if ( NULL
== stream
)
410 return FT_Err_Cannot_Open_Stream
;
412 return raccess_guess_apple_generic( library
, stream
, base_file_name
,
413 magic
, result_offset
);
418 raccess_guess_apple_single( FT_Library library
,
420 char *base_file_name
,
421 char **result_file_name
,
422 FT_Long
*result_offset
)
424 FT_Int32 magic
= ( 0x00 << 24 ) |
430 *result_file_name
= NULL
;
431 if ( NULL
== stream
)
432 return FT_Err_Cannot_Open_Stream
;
434 return raccess_guess_apple_generic( library
, stream
, base_file_name
,
435 magic
, result_offset
);
440 raccess_guess_darwin_ufs_export( FT_Library library
,
442 char *base_file_name
,
443 char **result_file_name
,
444 FT_Long
*result_offset
)
453 memory
= library
->memory
;
454 newpath
= raccess_make_file_name( memory
, base_file_name
, "._" );
456 return FT_Err_Out_Of_Memory
;
458 error
= raccess_guess_linux_double_from_file_name( library
, newpath
,
461 *result_file_name
= newpath
;
470 raccess_guess_darwin_hfsplus( FT_Library library
,
472 char *base_file_name
,
473 char **result_file_name
,
474 FT_Long
*result_offset
)
477 Only meaningful on systems with hfs+ drivers (or Macs).
482 FT_Long base_file_len
= ft_strlen( base_file_name
);
487 memory
= library
->memory
;
489 if ( base_file_len
+ 6 > FT_INT_MAX
)
490 return FT_Err_Array_Too_Large
;
492 if ( FT_ALLOC( newpath
, base_file_len
+ 6 ) )
495 FT_MEM_COPY( newpath
, base_file_name
, base_file_len
);
496 FT_MEM_COPY( newpath
+ base_file_len
, "/rsrc", 6 );
498 *result_file_name
= newpath
;
506 raccess_guess_darwin_newvfs( FT_Library library
,
508 char *base_file_name
,
509 char **result_file_name
,
510 FT_Long
*result_offset
)
513 Only meaningful on systems with Mac OS X (> 10.1).
518 FT_Long base_file_len
= ft_strlen( base_file_name
);
523 memory
= library
->memory
;
525 if ( base_file_len
+ 18 > FT_INT_MAX
)
526 return FT_Err_Array_Too_Large
;
528 if ( FT_ALLOC( newpath
, base_file_len
+ 18 ) )
531 FT_MEM_COPY( newpath
, base_file_name
, base_file_len
);
532 FT_MEM_COPY( newpath
+ base_file_len
, "/..namedfork/rsrc", 18 );
534 *result_file_name
= newpath
;
542 raccess_guess_vfat( FT_Library library
,
544 char *base_file_name
,
545 char **result_file_name
,
546 FT_Long
*result_offset
)
554 memory
= library
->memory
;
556 newpath
= raccess_make_file_name( memory
, base_file_name
,
559 return FT_Err_Out_Of_Memory
;
561 *result_file_name
= newpath
;
569 raccess_guess_linux_cap( FT_Library library
,
571 char *base_file_name
,
572 char **result_file_name
,
573 FT_Long
*result_offset
)
581 memory
= library
->memory
;
583 newpath
= raccess_make_file_name( memory
, base_file_name
, ".resource/" );
585 return FT_Err_Out_Of_Memory
;
587 *result_file_name
= newpath
;
595 raccess_guess_linux_double( FT_Library library
,
597 char *base_file_name
,
598 char **result_file_name
,
599 FT_Long
*result_offset
)
608 memory
= library
->memory
;
610 newpath
= raccess_make_file_name( memory
, base_file_name
, "%" );
612 return FT_Err_Out_Of_Memory
;
614 error
= raccess_guess_linux_double_from_file_name( library
, newpath
,
617 *result_file_name
= newpath
;
626 raccess_guess_linux_netatalk( FT_Library library
,
628 char *base_file_name
,
629 char **result_file_name
,
630 FT_Long
*result_offset
)
639 memory
= library
->memory
;
641 newpath
= raccess_make_file_name( memory
, base_file_name
,
644 return FT_Err_Out_Of_Memory
;
646 error
= raccess_guess_linux_double_from_file_name( library
, newpath
,
649 *result_file_name
= newpath
;
658 raccess_guess_apple_generic( FT_Library library
,
660 char *base_file_name
,
662 FT_Long
*result_offset
)
664 FT_Int32 magic_from_stream
;
666 FT_Int32 version_number
= 0;
667 FT_UShort n_of_entries
;
670 FT_UInt32 entry_id
, entry_offset
, entry_length
= 0;
672 const FT_UInt32 resource_fork_entry_id
= 0x2;
674 FT_UNUSED( library
);
675 FT_UNUSED( base_file_name
);
676 FT_UNUSED( version_number
);
677 FT_UNUSED( entry_length
);
680 if ( FT_READ_LONG( magic_from_stream
) )
682 if ( magic_from_stream
!= magic
)
683 return FT_Err_Unknown_File_Format
;
685 if ( FT_READ_LONG( version_number
) )
689 error
= FT_Stream_Skip( stream
, 16 );
693 if ( FT_READ_USHORT( n_of_entries
) )
695 if ( n_of_entries
== 0 )
696 return FT_Err_Unknown_File_Format
;
698 for ( i
= 0; i
< n_of_entries
; i
++ )
700 if ( FT_READ_LONG( entry_id
) )
702 if ( entry_id
== resource_fork_entry_id
)
704 if ( FT_READ_LONG( entry_offset
) ||
705 FT_READ_LONG( entry_length
) )
707 *result_offset
= entry_offset
;
713 error
= FT_Stream_Skip( stream
, 4 + 4 ); /* offset + length */
719 return FT_Err_Unknown_File_Format
;
724 raccess_guess_linux_double_from_file_name( FT_Library library
,
726 FT_Long
*result_offset
)
734 args2
.flags
= FT_OPEN_PATHNAME
;
735 args2
.pathname
= file_name
;
736 error
= FT_Stream_New( library
, &args2
, &stream2
);
740 error
= raccess_guess_apple_double( library
, stream2
, file_name
,
741 &nouse
, result_offset
);
743 FT_Stream_Free( stream2
, 0 );
750 raccess_make_file_name( FT_Memory memory
,
751 const char *original_name
,
752 const char *insertion
)
758 FT_Error error
= FT_Err_Ok
;
763 new_length
= ft_strlen( original_name
) + ft_strlen( insertion
);
764 if ( FT_ALLOC( new_name
, new_length
+ 1 ) )
767 tmp
= ft_strrchr( original_name
, '/' );
770 ft_strncpy( new_name
, original_name
, tmp
- original_name
+ 1 );
771 new_name
[tmp
- original_name
+ 1] = '\0';
776 slash
= original_name
;
780 ft_strcat( new_name
, insertion
);
781 ft_strcat( new_name
, slash
);
787 #else /* !FT_CONFIG_OPTION_GUESSING_EMBEDDED_RFORK */
790 /*************************************************************************/
791 /* Dummy function; just sets errors */
792 /*************************************************************************/
795 FT_Raccess_Guess( FT_Library library
,
804 FT_UNUSED( library
);
806 FT_UNUSED( base_name
);
809 for ( i
= 0; i
< FT_RACCESS_N_RULES
; i
++ )
813 errors
[i
] = FT_Err_Unimplemented_Feature
;
818 #endif /* !FT_CONFIG_OPTION_GUESSING_EMBEDDED_RFORK */