1/****************************************************************************
2 *
3 * ftrfork.c
4 *
5 * Embedded resource forks accessor (body).
6 *
7 * Copyright (C) 2004-2019 by
8 * Masatake YAMATO and Redhat K.K.
9 *
10 * FT_Raccess_Get_HeaderInfo() and raccess_guess_darwin_hfsplus() are
11 * derived from ftobjs.c.
12 *
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.
18 *
19 */
20
21/****************************************************************************
22 * Development of the code in this file is support of
23 * Information-technology Promotion Agency, Japan.
24 */
25
26
27#include <ft2build.h>
28#include FT_INTERNAL_DEBUG_H
29#include FT_INTERNAL_STREAM_H
30#include FT_INTERNAL_RFORK_H
31
32#include "ftbase.h"
33
34#undef FT_COMPONENT
35#define FT_COMPONENT raccess
36
37
38 /*************************************************************************/
39 /*************************************************************************/
40 /*************************************************************************/
41 /**** ****/
42 /**** ****/
43 /**** Resource fork directory access ****/
44 /**** ****/
45 /**** ****/
46 /*************************************************************************/
47 /*************************************************************************/
48 /*************************************************************************/
49
50 FT_BASE_DEF( FT_Error )
51 FT_Raccess_Get_HeaderInfo( FT_Library library,
52 FT_Stream stream,
53 FT_Long rfork_offset,
54 FT_Long *map_offset,
55 FT_Long *rdata_pos )
56 {
57 FT_Error error;
58 unsigned char head[16], head2[16];
59 FT_Long map_pos, map_len, rdata_len;
60 int allzeros, allmatch, i;
61 FT_Long type_list;
62
63 FT_UNUSED( library );
64
65
66 error = FT_Stream_Seek( stream, (FT_ULong)rfork_offset );
67 if ( error )
68 return error;
69
70 error = FT_Stream_Read( stream, (FT_Byte*)head, 16 );
71 if ( error )
72 return error;
73
74 /* ensure positive values */
75 if ( head[0] >= 0x80 ||
76 head[4] >= 0x80 ||
77 head[8] >= 0x80 ||
78 head[12] >= 0x80 )
79 return FT_THROW( Unknown_File_Format );
80
81 *rdata_pos = ( head[ 0] << 24 ) |
82 ( head[ 1] << 16 ) |
83 ( head[ 2] << 8 ) |
84 head[ 3];
85 map_pos = ( head[ 4] << 24 ) |
86 ( head[ 5] << 16 ) |
87 ( head[ 6] << 8 ) |
88 head[ 7];
89 rdata_len = ( head[ 8] << 24 ) |
90 ( head[ 9] << 16 ) |
91 ( head[10] << 8 ) |
92 head[11];
93 map_len = ( head[12] << 24 ) |
94 ( head[13] << 16 ) |
95 ( head[14] << 8 ) |
96 head[15];
97
98 /* the map must not be empty */
99 if ( !map_pos )
100 return FT_THROW( Unknown_File_Format );
101
102 /* check whether rdata and map overlap */
103 if ( *rdata_pos < map_pos )
104 {
105 if ( *rdata_pos > map_pos - rdata_len )
106 return FT_THROW( Unknown_File_Format );
107 }
108 else
109 {
110 if ( map_pos > *rdata_pos - map_len )
111 return FT_THROW( Unknown_File_Format );
112 }
113
114 /* check whether end of rdata or map exceeds stream size */
115 if ( FT_LONG_MAX - rdata_len < *rdata_pos ||
116 FT_LONG_MAX - map_len < map_pos ||
117
118 FT_LONG_MAX - ( *rdata_pos + rdata_len ) < rfork_offset ||
119 FT_LONG_MAX - ( map_pos + map_len ) < rfork_offset ||
120
121 (FT_ULong)( rfork_offset + *rdata_pos + rdata_len ) > stream->size ||
122 (FT_ULong)( rfork_offset + map_pos + map_len ) > stream->size )
123 return FT_THROW( Unknown_File_Format );
124
125 *rdata_pos += rfork_offset;
126 map_pos += rfork_offset;
127
128 error = FT_Stream_Seek( stream, (FT_ULong)map_pos );
129 if ( error )
130 return error;
131
132 head2[15] = (FT_Byte)( head[15] + 1 ); /* make it be different */
133
134 error = FT_Stream_Read( stream, (FT_Byte*)head2, 16 );
135 if ( error )
136 return error;
137
138 allzeros = 1;
139 allmatch = 1;
140 for ( i = 0; i < 16; i++ )
141 {
142 if ( head2[i] != 0 )
143 allzeros = 0;
144 if ( head2[i] != head[i] )
145 allmatch = 0;
146 }
147 if ( !allzeros && !allmatch )
148 return FT_THROW( Unknown_File_Format );
149
150 /* If we have reached this point then it is probably a mac resource */
151 /* file. Now, does it contain any interesting resources? */
152
153 (void)FT_STREAM_SKIP( 4 /* skip handle to next resource map */
154 + 2 /* skip file resource number */
155 + 2 ); /* skip attributes */
156
157 if ( FT_READ_SHORT( type_list ) )
158 return error;
159 if ( type_list < 0 )
160 return FT_THROW( Unknown_File_Format );
161
162 error = FT_Stream_Seek( stream, (FT_ULong)( map_pos + type_list ) );
163 if ( error )
164 return error;
165
166 *map_offset = map_pos + type_list;
167 return FT_Err_Ok;
168 }
169
170
171 static int
172 ft_raccess_sort_ref_by_id( FT_RFork_Ref* a,
173 FT_RFork_Ref* b )
174 {
175 if ( a->res_id < b->res_id )
176 return -1;
177 else if ( a->res_id > b->res_id )
178 return 1;
179 else
180 return 0;
181 }
182
183
184 FT_BASE_DEF( FT_Error )
185 FT_Raccess_Get_DataOffsets( FT_Library library,
186 FT_Stream stream,
187 FT_Long map_offset,
188 FT_Long rdata_pos,
189 FT_Long tag,
190 FT_Bool sort_by_res_id,
191 FT_Long **offsets,
192 FT_Long *count )
193 {
194 FT_Error error;
195 int i, j, cnt, subcnt;
196 FT_Long tag_internal, rpos;
197 FT_Memory memory = library->memory;
198 FT_Long temp;
199 FT_Long *offsets_internal = NULL;
200 FT_RFork_Ref *ref = NULL;
201
202
203 FT_TRACE3(( "\n" ));
204 error = FT_Stream_Seek( stream, (FT_ULong)map_offset );
205 if ( error )
206 return error;
207
208 if ( FT_READ_SHORT( cnt ) )
209 return error;
210 cnt++;
211
212 /* `rpos' is a signed 16bit integer offset to resource records; the */
213 /* size of a resource record is 12 bytes. The map header is 28 bytes, */
214 /* and a type list needs 10 bytes or more. If we assume that the name */
215 /* list is empty and we have only a single entry in the type list, */
216 /* there can be at most */
217 /* */
218 /* (32768 - 28 - 10) / 12 = 2727 */
219 /* */
220 /* resources. */
221 /* */
222 /* A type list starts with a two-byte counter, followed by 10-byte */
223 /* type records. Assuming that there are no resources, the number of */
224 /* type records can be at most */
225 /* */
226 /* (32768 - 28 - 2) / 8 = 4079 */
227 /* */
228 if ( cnt > 4079 )
229 return FT_THROW( Invalid_Table );
230
231 for ( i = 0; i < cnt; i++ )
232 {
233 if ( FT_READ_LONG( tag_internal ) ||
234 FT_READ_SHORT( subcnt ) ||
235 FT_READ_SHORT( rpos ) )
236 return error;
237
238 FT_TRACE2(( "Resource tags: %c%c%c%c\n",
239 (char)( 0xFF & ( tag_internal >> 24 ) ),
240 (char)( 0xFF & ( tag_internal >> 16 ) ),
241 (char)( 0xFF & ( tag_internal >> 8 ) ),
242 (char)( 0xFF & ( tag_internal >> 0 ) ) ));
243 FT_TRACE3(( " : subcount=%d, suboffset=0x%04x\n",
244 subcnt, rpos ));
245
246 if ( tag_internal == tag )
247 {
248 *count = subcnt + 1;
249 rpos += map_offset;
250
251 /* a zero count might be valid in the resource specification, */
252 /* however, it is completely useless to us */
253 if ( *count < 1 || *count > 2727 )
254 return FT_THROW( Invalid_Table );
255
256 error = FT_Stream_Seek( stream, (FT_ULong)rpos );
257 if ( error )
258 return error;
259
260 if ( FT_NEW_ARRAY( ref, *count ) )
261 return error;
262
263 for ( j = 0; j < *count; j++ )
264 {
265 if ( FT_READ_SHORT( ref[j].res_id ) )
266 goto Exit;
267 if ( FT_STREAM_SKIP( 2 ) ) /* resource name offset */
268 goto Exit;
269 if ( FT_READ_LONG( temp ) ) /* attributes (8bit), offset (24bit) */
270 goto Exit;
271 if ( FT_STREAM_SKIP( 4 ) ) /* mbz */
272 goto Exit;
273
274 /*
275 * According to Inside Macintosh: More Macintosh Toolbox,
276 * "Resource IDs" (1-46), there are some reserved IDs.
277 * However, FreeType2 is not a font synthesizer, no need
278 * to check the acceptable resource ID.
279 */
280 if ( temp < 0 )
281 {
282 error = FT_THROW( Invalid_Table );
283 goto Exit;
284 }
285
286 ref[j].offset = temp & 0xFFFFFFL;
287
288 FT_TRACE3(( " [%d]:"
289 " resource_id=0x%04x, offset=0x%08x\n",
290 j, (FT_UShort)ref[j].res_id, ref[j].offset ));
291 }
292
293 if ( sort_by_res_id )
294 {
295 ft_qsort( ref,
296 (size_t)*count,
297 sizeof ( FT_RFork_Ref ),
298 ( int(*)(const void*,
299 const void*) )ft_raccess_sort_ref_by_id );
300
301 FT_TRACE3(( " -- sort resources by their ids --\n" ));
302
303 for ( j = 0; j < *count; j++ )
304 FT_TRACE3(( " [%d]:"
305 " resource_id=0x%04x, offset=0x%08x\n",
306 j, ref[j].res_id, ref[j].offset ));
307 }
308
309 if ( FT_NEW_ARRAY( offsets_internal, *count ) )
310 goto Exit;
311
312 /* XXX: duplicated reference ID,
313 * gap between reference IDs are acceptable?
314 * further investigation on Apple implementation is needed.
315 */
316 for ( j = 0; j < *count; j++ )
317 offsets_internal[j] = rdata_pos + ref[j].offset;
318
319 *offsets = offsets_internal;
320 error = FT_Err_Ok;
321
322 Exit:
323 FT_FREE( ref );
324 return error;
325 }
326 }
327
328 return FT_THROW( Cannot_Open_Resource );
329 }
330
331
332#ifdef FT_CONFIG_OPTION_GUESSING_EMBEDDED_RFORK
333
334 /*************************************************************************/
335 /*************************************************************************/
336 /*************************************************************************/
337 /**** ****/
338 /**** ****/
339 /**** Guessing functions ****/
340 /**** ****/
341 /**** When you add a new guessing function, ****/
342 /**** update FT_RACCESS_N_RULES in ftrfork.h. ****/
343 /**** ****/
344 /*************************************************************************/
345 /*************************************************************************/
346 /*************************************************************************/
347
348 static FT_Error
349 raccess_guess_apple_double( FT_Library library,
350 FT_Stream stream,
351 char *base_file_name,
352 char **result_file_name,
353 FT_Long *result_offset );
354
355 static FT_Error
356 raccess_guess_apple_single( FT_Library library,
357 FT_Stream stream,
358 char *base_file_name,
359 char **result_file_name,
360 FT_Long *result_offset );
361
362 static FT_Error
363 raccess_guess_darwin_ufs_export( FT_Library library,
364 FT_Stream stream,
365 char *base_file_name,
366 char **result_file_name,
367 FT_Long *result_offset );
368
369 static FT_Error
370 raccess_guess_darwin_newvfs( FT_Library library,
371 FT_Stream stream,
372 char *base_file_name,
373 char **result_file_name,
374 FT_Long *result_offset );
375
376 static FT_Error
377 raccess_guess_darwin_hfsplus( FT_Library library,
378 FT_Stream stream,
379 char *base_file_name,
380 char **result_file_name,
381 FT_Long *result_offset );
382
383 static FT_Error
384 raccess_guess_vfat( FT_Library library,
385 FT_Stream stream,
386 char *base_file_name,
387 char **result_file_name,
388 FT_Long *result_offset );
389
390 static FT_Error
391 raccess_guess_linux_cap( FT_Library library,
392 FT_Stream stream,
393 char *base_file_name,
394 char **result_file_name,
395 FT_Long *result_offset );
396
397 static FT_Error
398 raccess_guess_linux_double( FT_Library library,
399 FT_Stream stream,
400 char *base_file_name,
401 char **result_file_name,
402 FT_Long *result_offset );
403
404 static FT_Error
405 raccess_guess_linux_netatalk( FT_Library library,
406 FT_Stream stream,
407 char *base_file_name,
408 char **result_file_name,
409 FT_Long *result_offset );
410
411
412 CONST_FT_RFORK_RULE_ARRAY_BEGIN(ft_raccess_guess_table,
413 ft_raccess_guess_rec)
414 CONST_FT_RFORK_RULE_ARRAY_ENTRY(apple_double, apple_double)
415 CONST_FT_RFORK_RULE_ARRAY_ENTRY(apple_single, apple_single)
416 CONST_FT_RFORK_RULE_ARRAY_ENTRY(darwin_ufs_export, darwin_ufs_export)
417 CONST_FT_RFORK_RULE_ARRAY_ENTRY(darwin_newvfs, darwin_newvfs)
418 CONST_FT_RFORK_RULE_ARRAY_ENTRY(darwin_hfsplus, darwin_hfsplus)
419 CONST_FT_RFORK_RULE_ARRAY_ENTRY(vfat, vfat)
420 CONST_FT_RFORK_RULE_ARRAY_ENTRY(linux_cap, linux_cap)
421 CONST_FT_RFORK_RULE_ARRAY_ENTRY(linux_double, linux_double)
422 CONST_FT_RFORK_RULE_ARRAY_ENTRY(linux_netatalk, linux_netatalk)
423 CONST_FT_RFORK_RULE_ARRAY_END
424
425
426 /*************************************************************************/
427 /**** ****/
428 /**** Helper functions ****/
429 /**** ****/
430 /*************************************************************************/
431
432 static FT_Error
433 raccess_guess_apple_generic( FT_Library library,
434 FT_Stream stream,
435 char *base_file_name,
436 FT_Int32 magic,
437 FT_Long *result_offset );
438
439 static FT_Error
440 raccess_guess_linux_double_from_file_name( FT_Library library,
441 char* file_name,
442 FT_Long *result_offset );
443
444 static char *
445 raccess_make_file_name( FT_Memory memory,
446 const char *original_name,
447 const char *insertion );
448
449 FT_BASE_DEF( void )
450 FT_Raccess_Guess( FT_Library library,
451 FT_Stream stream,
452 char* base_name,
453 char **new_names,
454 FT_Long *offsets,
455 FT_Error *errors )
456 {
457 FT_Int i;
458
459
460 for ( i = 0; i < FT_RACCESS_N_RULES; i++ )
461 {
462 new_names[i] = NULL;
463 if ( NULL != stream )
464 errors[i] = FT_Stream_Seek( stream, 0 );
465 else
466 errors[i] = FT_Err_Ok;
467
468 if ( errors[i] )
469 continue;
470
471 errors[i] = ft_raccess_guess_table[i].func( library,
472 stream, base_name,
473 &(new_names[i]),
474 &(offsets[i]) );
475 }
476
477 return;
478 }
479
480
481#if defined( FT_CONFIG_OPTION_MAC_FONTS ) && !defined( FT_MACINTOSH )
482 static FT_RFork_Rule
483 raccess_get_rule_type_from_rule_index( FT_Library library,
484 FT_UInt rule_index )
485 {
486 FT_UNUSED( library );
487
488 if ( rule_index >= FT_RACCESS_N_RULES )
489 return FT_RFork_Rule_invalid;
490
491 return ft_raccess_guess_table[rule_index].type;
492 }
493
494
495 /*
496 * For this function, refer ftbase.h.
497 */
498 FT_LOCAL_DEF( FT_Bool )
499 ft_raccess_rule_by_darwin_vfs( FT_Library library,
500 FT_UInt rule_index )
501 {
502 switch( raccess_get_rule_type_from_rule_index( library, rule_index ) )
503 {
504 case FT_RFork_Rule_darwin_newvfs:
505 case FT_RFork_Rule_darwin_hfsplus:
506 return TRUE;
507
508 default:
509 return FALSE;
510 }
511 }
512#endif
513
514
515 static FT_Error
516 raccess_guess_apple_double( FT_Library library,
517 FT_Stream stream,
518 char *base_file_name,
519 char **result_file_name,
520 FT_Long *result_offset )
521 {
522 FT_Int32 magic = ( 0x00 << 24 ) |
523 ( 0x05 << 16 ) |
524 ( 0x16 << 8 ) |
525 0x07;
526
527
528 *result_file_name = NULL;
529 if ( NULL == stream )
530 return FT_THROW( Cannot_Open_Stream );
531
532 return raccess_guess_apple_generic( library, stream, base_file_name,
533 magic, result_offset );
534 }
535
536
537 static FT_Error
538 raccess_guess_apple_single( FT_Library library,
539 FT_Stream stream,
540 char *base_file_name,
541 char **result_file_name,
542 FT_Long *result_offset )
543 {
544 FT_Int32 magic = ( 0x00 << 24 ) |
545 ( 0x05 << 16 ) |
546 ( 0x16 << 8 ) |
547 0x00;
548
549
550 *result_file_name = NULL;
551 if ( NULL == stream )
552 return FT_THROW( Cannot_Open_Stream );
553
554 return raccess_guess_apple_generic( library, stream, base_file_name,
555 magic, result_offset );
556 }
557
558
559 static FT_Error
560 raccess_guess_darwin_ufs_export( FT_Library library,
561 FT_Stream stream,
562 char *base_file_name,
563 char **result_file_name,
564 FT_Long *result_offset )
565 {
566 char* newpath;
567 FT_Error error;
568 FT_Memory memory;
569
570 FT_UNUSED( stream );
571
572
573 memory = library->memory;
574 newpath = raccess_make_file_name( memory, base_file_name, "._" );
575 if ( !newpath )
576 return FT_THROW( Out_Of_Memory );
577
578 error = raccess_guess_linux_double_from_file_name( library, newpath,
579 result_offset );
580 if ( !error )
581 *result_file_name = newpath;
582 else
583 FT_FREE( newpath );
584
585 return error;
586 }
587
588
589 static FT_Error
590 raccess_guess_darwin_hfsplus( FT_Library library,
591 FT_Stream stream,
592 char *base_file_name,
593 char **result_file_name,
594 FT_Long *result_offset )
595 {
596 /*
597 Only meaningful on systems with hfs+ drivers (or Macs).
598 */
599 FT_Error error;
600 char* newpath = NULL;
601 FT_Memory memory;
602 FT_Long base_file_len = (FT_Long)ft_strlen( base_file_name );
603
604 FT_UNUSED( stream );
605
606
607 memory = library->memory;
608
609 if ( base_file_len + 6 > FT_INT_MAX )
610 return FT_THROW( Array_Too_Large );
611
612 if ( FT_ALLOC( newpath, base_file_len + 6 ) )
613 return error;
614
615 FT_MEM_COPY( newpath, base_file_name, base_file_len );
616 FT_MEM_COPY( newpath + base_file_len, "/rsrc", 6 );
617
618 *result_file_name = newpath;
619 *result_offset = 0;
620
621 return FT_Err_Ok;
622 }
623
624
625 static FT_Error
626 raccess_guess_darwin_newvfs( FT_Library library,
627 FT_Stream stream,
628 char *base_file_name,
629 char **result_file_name,
630 FT_Long *result_offset )
631 {
632 /*
633 Only meaningful on systems with Mac OS X (> 10.1).
634 */
635 FT_Error error;
636 char* newpath = NULL;
637 FT_Memory memory;
638 FT_Long base_file_len = (FT_Long)ft_strlen( base_file_name );
639
640 FT_UNUSED( stream );
641
642
643 memory = library->memory;
644
645 if ( base_file_len + 18 > FT_INT_MAX )
646 return FT_THROW( Array_Too_Large );
647
648 if ( FT_ALLOC( newpath, base_file_len + 18 ) )
649 return error;
650
651 FT_MEM_COPY( newpath, base_file_name, base_file_len );
652 FT_MEM_COPY( newpath + base_file_len, "/..namedfork/rsrc", 18 );
653
654 *result_file_name = newpath;
655 *result_offset = 0;
656
657 return FT_Err_Ok;
658 }
659
660
661 static FT_Error
662 raccess_guess_vfat( FT_Library library,
663 FT_Stream stream,
664 char *base_file_name,
665 char **result_file_name,
666 FT_Long *result_offset )
667 {
668 char* newpath;
669 FT_Memory memory;
670
671 FT_UNUSED( stream );
672
673
674 memory = library->memory;
675
676 newpath = raccess_make_file_name( memory, base_file_name,
677 "resource.frk/" );
678 if ( !newpath )
679 return FT_THROW( Out_Of_Memory );
680
681 *result_file_name = newpath;
682 *result_offset = 0;
683
684 return FT_Err_Ok;
685 }
686
687
688 static FT_Error
689 raccess_guess_linux_cap( FT_Library library,
690 FT_Stream stream,
691 char *base_file_name,
692 char **result_file_name,
693 FT_Long *result_offset )
694 {
695 char* newpath;
696 FT_Memory memory;
697
698 FT_UNUSED( stream );
699
700
701 memory = library->memory;
702
703 newpath = raccess_make_file_name( memory, base_file_name, ".resource/" );
704 if ( !newpath )
705 return FT_THROW( Out_Of_Memory );
706
707 *result_file_name = newpath;
708 *result_offset = 0;
709
710 return FT_Err_Ok;
711 }
712
713
714 static FT_Error
715 raccess_guess_linux_double( FT_Library library,
716 FT_Stream stream,
717 char *base_file_name,
718 char **result_file_name,
719 FT_Long *result_offset )
720 {
721 char* newpath;
722 FT_Error error;
723 FT_Memory memory;
724
725 FT_UNUSED( stream );
726
727
728 memory = library->memory;
729
730 newpath = raccess_make_file_name( memory, base_file_name, "%" );
731 if ( !newpath )
732 return FT_THROW( Out_Of_Memory );
733
734 error = raccess_guess_linux_double_from_file_name( library, newpath,
735 result_offset );
736 if ( !error )
737 *result_file_name = newpath;
738 else
739 FT_FREE( newpath );
740
741 return error;
742 }
743
744
745 static FT_Error
746 raccess_guess_linux_netatalk( FT_Library library,
747 FT_Stream stream,
748 char *base_file_name,
749 char **result_file_name,
750 FT_Long *result_offset )
751 {
752 char* newpath;
753 FT_Error error;
754 FT_Memory memory;
755
756 FT_UNUSED( stream );
757
758
759 memory = library->memory;
760
761 newpath = raccess_make_file_name( memory, base_file_name,
762 ".AppleDouble/" );
763 if ( !newpath )
764 return FT_THROW( Out_Of_Memory );
765
766 error = raccess_guess_linux_double_from_file_name( library, newpath,
767 result_offset );
768 if ( !error )
769 *result_file_name = newpath;
770 else
771 FT_FREE( newpath );
772
773 return error;
774 }
775
776
777 static FT_Error
778 raccess_guess_apple_generic( FT_Library library,
779 FT_Stream stream,
780 char *base_file_name,
781 FT_Int32 magic,
782 FT_Long *result_offset )
783 {
784 FT_Int32 magic_from_stream;
785 FT_Error error;
786 FT_Int32 version_number = 0;
787 FT_UShort n_of_entries;
788
789 int i;
790 FT_Int32 entry_id, entry_offset, entry_length = 0;
791
792 const FT_Int32 resource_fork_entry_id = 0x2;
793
794 FT_UNUSED( library );
795 FT_UNUSED( base_file_name );
796 FT_UNUSED( version_number );
797 FT_UNUSED( entry_length );
798
799
800 if ( FT_READ_LONG( magic_from_stream ) )
801 return error;
802 if ( magic_from_stream != magic )
803 return FT_THROW( Unknown_File_Format );
804
805 if ( FT_READ_LONG( version_number ) )
806 return error;
807
808 /* filler */
809 error = FT_Stream_Skip( stream, 16 );
810 if ( error )
811 return error;
812
813 if ( FT_READ_USHORT( n_of_entries ) )
814 return error;
815 if ( n_of_entries == 0 )
816 return FT_THROW( Unknown_File_Format );
817
818 for ( i = 0; i < n_of_entries; i++ )
819 {
820 if ( FT_READ_LONG( entry_id ) )
821 return error;
822 if ( entry_id == resource_fork_entry_id )
823 {
824 if ( FT_READ_LONG( entry_offset ) ||
825 FT_READ_LONG( entry_length ) )
826 continue;
827 *result_offset = entry_offset;
828
829 return FT_Err_Ok;
830 }
831 else
832 {
833 error = FT_Stream_Skip( stream, 4 + 4 ); /* offset + length */
834 if ( error )
835 return error;
836 }
837 }
838
839 return FT_THROW( Unknown_File_Format );
840 }
841
842
843 static FT_Error
844 raccess_guess_linux_double_from_file_name( FT_Library library,
845 char *file_name,
846 FT_Long *result_offset )
847 {
848 FT_Open_Args args2;
849 FT_Stream stream2;
850 char* nouse = NULL;
851 FT_Error error;
852
853
854 args2.flags = FT_OPEN_PATHNAME;
855 args2.pathname = file_name;
856 error = FT_Stream_New( library, &args2, &stream2 );
857 if ( error )
858 return error;
859
860 error = raccess_guess_apple_double( library, stream2, file_name,
861 &nouse, result_offset );
862
863 FT_Stream_Free( stream2, 0 );
864
865 return error;
866 }
867
868
869 static char*
870 raccess_make_file_name( FT_Memory memory,
871 const char *original_name,
872 const char *insertion )
873 {
874 char* new_name = NULL;
875 const char* tmp;
876 const char* slash;
877 size_t new_length;
878 FT_Error error = FT_Err_Ok;
879
880 FT_UNUSED( error );
881
882
883 new_length = ft_strlen( original_name ) + ft_strlen( insertion );
884 if ( FT_ALLOC( new_name, new_length + 1 ) )
885 return NULL;
886
887 tmp = ft_strrchr( original_name, '/' );
888 if ( tmp )
889 {
890 ft_strncpy( new_name,
891 original_name,
892 (size_t)( tmp - original_name + 1 ) );
893 new_name[tmp - original_name + 1] = '\0';
894 slash = tmp + 1;
895 }
896 else
897 {
898 slash = original_name;
899 new_name[0] = '\0';
900 }
901
902 ft_strcat( new_name, insertion );
903 ft_strcat( new_name, slash );
904
905 return new_name;
906 }
907
908
909#else /* !FT_CONFIG_OPTION_GUESSING_EMBEDDED_RFORK */
910
911
912 /**************************************************************************
913 * Dummy function; just sets errors
914 */
915
916 FT_BASE_DEF( void )
917 FT_Raccess_Guess( FT_Library library,
918 FT_Stream stream,
919 char *base_name,
920 char **new_names,
921 FT_Long *offsets,
922 FT_Error *errors )
923 {
924 FT_Int i;
925
926 FT_UNUSED( library );
927 FT_UNUSED( stream );
928 FT_UNUSED( base_name );
929
930
931 for ( i = 0; i < FT_RACCESS_N_RULES; i++ )
932 {
933 new_names[i] = NULL;
934 offsets[i] = 0;
935 errors[i] = FT_ERR( Unimplemented_Feature );
936 }
937 }
938
939
940#endif /* !FT_CONFIG_OPTION_GUESSING_EMBEDDED_RFORK */
941
942
943/* END */
944