1 /***************************************************************************/
5 /* Embedded resource forks accessor (body). */
7 /* Copyright 2004, 2005, 2006 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_NEW_ARRAY( offsets_internal
, *count
) )
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).
429 FT_Long base_file_len
= ft_strlen( base_file_name
);
434 memory
= library
->memory
;
436 if ( base_file_len
> FT_INT_MAX
)
437 return FT_Err_Array_Too_Large
;
439 if ( FT_ALLOC( newpath
, base_file_len
+ 6 ) )
442 FT_MEM_COPY( newpath
, base_file_name
, base_file_len
);
443 FT_MEM_COPY( newpath
+ base_file_len
, "/rsrc", 6 );
445 *result_file_name
= newpath
;
453 raccess_guess_vfat( FT_Library library
,
455 char * base_file_name
,
456 char **result_file_name
,
457 FT_Long
*result_offset
)
465 memory
= library
->memory
;
467 newpath
= raccess_make_file_name( memory
, base_file_name
,
470 return FT_Err_Out_Of_Memory
;
472 *result_file_name
= newpath
;
480 raccess_guess_linux_cap( FT_Library library
,
482 char * base_file_name
,
483 char **result_file_name
,
484 FT_Long
*result_offset
)
492 memory
= library
->memory
;
494 newpath
= raccess_make_file_name( memory
, base_file_name
, ".resource/" );
496 return FT_Err_Out_Of_Memory
;
498 *result_file_name
= newpath
;
506 raccess_guess_linux_double( FT_Library library
,
508 char * base_file_name
,
509 char **result_file_name
,
510 FT_Long
*result_offset
)
519 memory
= library
->memory
;
521 newpath
= raccess_make_file_name( memory
, base_file_name
, "%" );
523 return FT_Err_Out_Of_Memory
;
525 error
= raccess_guess_linux_double_from_file_name( library
, newpath
,
528 *result_file_name
= newpath
;
537 raccess_guess_linux_netatalk( FT_Library library
,
539 char * base_file_name
,
540 char **result_file_name
,
541 FT_Long
*result_offset
)
550 memory
= library
->memory
;
552 newpath
= raccess_make_file_name( memory
, base_file_name
,
555 return FT_Err_Out_Of_Memory
;
557 error
= raccess_guess_linux_double_from_file_name( library
, newpath
,
560 *result_file_name
= newpath
;
569 raccess_guess_apple_generic( FT_Library library
,
571 char * base_file_name
,
573 FT_Long
*result_offset
)
575 FT_Int32 magic_from_stream
;
577 FT_Int32 version_number
= 0;
578 FT_UShort n_of_entries
;
581 FT_UInt32 entry_id
, entry_offset
, entry_length
= 0;
583 const FT_UInt32 resource_fork_entry_id
= 0x2;
585 FT_UNUSED( library
);
586 FT_UNUSED( base_file_name
);
587 FT_UNUSED( version_number
);
588 FT_UNUSED( entry_length
);
591 if ( FT_READ_LONG( magic_from_stream
) )
593 if ( magic_from_stream
!= magic
)
594 return FT_Err_Unknown_File_Format
;
596 if ( FT_READ_LONG( version_number
) )
600 error
= FT_Stream_Skip( stream
, 16 );
604 if ( FT_READ_USHORT( n_of_entries
) )
606 if ( n_of_entries
== 0 )
607 return FT_Err_Unknown_File_Format
;
609 for ( i
= 0; i
< n_of_entries
; i
++ )
611 if ( FT_READ_LONG( entry_id
) )
613 if ( entry_id
== resource_fork_entry_id
)
615 if ( FT_READ_LONG( entry_offset
) ||
616 FT_READ_LONG( entry_length
) )
618 *result_offset
= entry_offset
;
623 FT_Stream_Skip( stream
, 4 + 4 ); /* offset + length */
626 return FT_Err_Unknown_File_Format
;
631 raccess_guess_linux_double_from_file_name( FT_Library library
,
633 FT_Long
*result_offset
)
641 args2
.flags
= FT_OPEN_PATHNAME
;
642 args2
.pathname
= file_name
;
643 error
= FT_Stream_New( library
, &args2
, &stream2
);
647 error
= raccess_guess_apple_double( library
, stream2
, file_name
,
648 &nouse
, result_offset
);
650 FT_Stream_Free( stream2
, 0 );
657 raccess_make_file_name( FT_Memory memory
,
658 const char *original_name
,
659 const char *insertion
)
665 FT_Error error
= FT_Err_Ok
;
670 new_length
= ft_strlen( original_name
) + ft_strlen( insertion
);
671 if ( FT_ALLOC( new_name
, new_length
+ 1 ) )
674 tmp
= ft_strrchr( original_name
, '/' );
677 ft_strncpy( new_name
, original_name
, tmp
- original_name
+ 1 );
678 new_name
[tmp
- original_name
+ 1] = '\0';
683 slash
= original_name
;
687 ft_strcat( new_name
, insertion
);
688 ft_strcat( new_name
, slash
);
694 #else /* !FT_CONFIG_OPTION_GUESSING_EMBEDDED_RFORK */
697 /*************************************************************************/
698 /* Dummy function; just sets errors */
699 /*************************************************************************/
702 FT_Raccess_Guess( FT_Library library
,
711 FT_UNUSED( library
);
713 FT_UNUSED( base_name
);
716 for ( i
= 0; i
< FT_RACCESS_N_RULES
; i
++ )
720 errors
[i
] = FT_Err_Unimplemented_Feature
;
725 #endif /* !FT_CONFIG_OPTION_GUESSING_EMBEDDED_RFORK */