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