1/****************************************************************************
2 *
3 * ftrfork.c
4 *
5 * Embedded resource forks accessor (body).
6 *
7 * Copyright (C) 2004-2023 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 <freetype/internal/ftdebug.h>
28#include <freetype/internal/ftstream.h>
29#include <freetype/internal/ftrfork.h>
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.
273 */
274 if ( temp < 0 )
275 {
276 error = FT_THROW( Invalid_Table );
277 goto Exit;
278 }
279
280 ref[j].offset = temp & 0xFFFFFFL;
281
282 FT_TRACE3(( " [%d]:"
283 " resource_id=0x%04x, offset=0x%08lx\n",
284 j, (FT_UShort)ref[j].res_id, ref[j].offset ));
285 }
286
287 if ( sort_by_res_id )
288 {
289 ft_qsort( ref,
290 (size_t)*count,
291 sizeof ( FT_RFork_Ref ),
292 ft_raccess_sort_ref_by_id );
293
294 FT_TRACE3(( " -- sort resources by their ids --\n" ));
295
296 for ( j = 0; j < *count; j++ )
297 FT_TRACE3(( " [%d]:"
298 " resource_id=0x%04x, offset=0x%08lx\n",
299 j, ref[j].res_id, ref[j].offset ));
300 }
301
302 if ( FT_QNEW_ARRAY( offsets_internal, *count ) )
303 goto Exit;
304
305 /* XXX: duplicated reference ID,
306 * gap between reference IDs are acceptable?
307 * further investigation on Apple implementation is needed.
308 */
309 for ( j = 0; j < *count; j++ )
310 offsets_internal[j] = rdata_pos + ref[j].offset;
311
312 *offsets = offsets_internal;
313 error = FT_Err_Ok;
314
315 Exit:
316 FT_FREE( ref );
317 return error;
318 }
319 }
320
321 return FT_THROW( Cannot_Open_Resource );
322 }
323
324
325#ifdef FT_CONFIG_OPTION_GUESSING_EMBEDDED_RFORK
326
327 /*************************************************************************/
328 /*************************************************************************/
329 /*************************************************************************/
330 /**** ****/
331 /**** ****/
332 /**** Guessing functions ****/
333 /**** ****/
334 /**** When you add a new guessing function, ****/
335 /**** update FT_RACCESS_N_RULES in ftrfork.h. ****/
336 /**** ****/
337 /*************************************************************************/
338 /*************************************************************************/
339 /*************************************************************************/
340
341 static FT_Error
342 raccess_guess_apple_double( FT_Library library,
343 FT_Stream stream,
344 char *base_file_name,
345 char **result_file_name,
346 FT_Long *result_offset );
347
348 static FT_Error
349 raccess_guess_apple_single( 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_darwin_ufs_export( 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_newvfs( 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_hfsplus( 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_vfat( 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_linux_cap( 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_double( 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_netatalk( FT_Library library,
399 FT_Stream stream,
400 char *base_file_name,
401 char **result_file_name,
402 FT_Long *result_offset );
403
404
405 CONST_FT_RFORK_RULE_ARRAY_BEGIN( ft_raccess_guess_table,
406 ft_raccess_guess_rec )
407 CONST_FT_RFORK_RULE_ARRAY_ENTRY( apple_double, apple_double )
408 CONST_FT_RFORK_RULE_ARRAY_ENTRY( apple_single, apple_single )
409 CONST_FT_RFORK_RULE_ARRAY_ENTRY( darwin_ufs_export, darwin_ufs_export )
410 CONST_FT_RFORK_RULE_ARRAY_ENTRY( darwin_newvfs, darwin_newvfs )
411 CONST_FT_RFORK_RULE_ARRAY_ENTRY( darwin_hfsplus, darwin_hfsplus )
412 CONST_FT_RFORK_RULE_ARRAY_ENTRY( vfat, vfat )
413 CONST_FT_RFORK_RULE_ARRAY_ENTRY( linux_cap, linux_cap )
414 CONST_FT_RFORK_RULE_ARRAY_ENTRY( linux_double, linux_double )
415 CONST_FT_RFORK_RULE_ARRAY_ENTRY( linux_netatalk, linux_netatalk )
416 CONST_FT_RFORK_RULE_ARRAY_END
417
418
419 /*************************************************************************/
420 /**** ****/
421 /**** Helper functions ****/
422 /**** ****/
423 /*************************************************************************/
424
425 static FT_Error
426 raccess_guess_apple_generic( FT_Library library,
427 FT_Stream stream,
428 char *base_file_name,
429 FT_Int32 magic,
430 FT_Long *result_offset );
431
432 static FT_Error
433 raccess_guess_linux_double_from_file_name( FT_Library library,
434 char* file_name,
435 FT_Long *result_offset );
436
437 static char *
438 raccess_make_file_name( FT_Memory memory,
439 const char *original_name,
440 const char *insertion );
441
442 FT_BASE_DEF( void )
443 FT_Raccess_Guess( FT_Library library,
444 FT_Stream stream,
445 char* base_name,
446 char **new_names,
447 FT_Long *offsets,
448 FT_Error *errors )
449 {
450 FT_Int i;
451
452
453 for ( i = 0; i < FT_RACCESS_N_RULES; i++ )
454 {
455 new_names[i] = NULL;
456 if ( NULL != stream )
457 errors[i] = FT_Stream_Seek( stream, 0 );
458 else
459 errors[i] = FT_Err_Ok;
460
461 if ( errors[i] )
462 continue;
463
464 errors[i] = ft_raccess_guess_table[i].func( library,
465 stream, base_name,
466 &(new_names[i]),
467 &(offsets[i]) );
468 }
469
470 return;
471 }
472
473
474#if defined( FT_CONFIG_OPTION_MAC_FONTS ) && !defined( FT_MACINTOSH )
475 static FT_RFork_Rule
476 raccess_get_rule_type_from_rule_index( FT_Library library,
477 FT_UInt rule_index )
478 {
479 FT_UNUSED( library );
480
481 if ( rule_index >= FT_RACCESS_N_RULES )
482 return FT_RFork_Rule_invalid;
483
484 return ft_raccess_guess_table[rule_index].type;
485 }
486
487
488 /*
489 * For this function, refer ftbase.h.
490 */
491 FT_LOCAL_DEF( FT_Bool )
492 ft_raccess_rule_by_darwin_vfs( FT_Library library,
493 FT_UInt rule_index )
494 {
495 switch( raccess_get_rule_type_from_rule_index( library, rule_index ) )
496 {
497 case FT_RFork_Rule_darwin_newvfs:
498 case FT_RFork_Rule_darwin_hfsplus:
499 return TRUE;
500
501 default:
502 return FALSE;
503 }
504 }
505#endif
506
507
508 static FT_Error
509 raccess_guess_apple_double( FT_Library library,
510 FT_Stream stream,
511 char *base_file_name,
512 char **result_file_name,
513 FT_Long *result_offset )
514 {
515 FT_Int32 magic = ( 0x00 << 24 ) |
516 ( 0x05 << 16 ) |
517 ( 0x16 << 8 ) |
518 0x07;
519
520
521 *result_file_name = NULL;
522 if ( NULL == stream )
523 return FT_THROW( Cannot_Open_Stream );
524
525 return raccess_guess_apple_generic( library, stream, base_file_name,
526 magic, result_offset );
527 }
528
529
530 static FT_Error
531 raccess_guess_apple_single( FT_Library library,
532 FT_Stream stream,
533 char *base_file_name,
534 char **result_file_name,
535 FT_Long *result_offset )
536 {
537 FT_Int32 magic = ( 0x00 << 24 ) |
538 ( 0x05 << 16 ) |
539 ( 0x16 << 8 ) |
540 0x00;
541
542
543 *result_file_name = NULL;
544 if ( NULL == stream )
545 return FT_THROW( Cannot_Open_Stream );
546
547 return raccess_guess_apple_generic( library, stream, base_file_name,
548 magic, result_offset );
549 }
550
551
552 static FT_Error
553 raccess_guess_darwin_ufs_export( FT_Library library,
554 FT_Stream stream,
555 char *base_file_name,
556 char **result_file_name,
557 FT_Long *result_offset )
558 {
559 char* newpath;
560 FT_Error error;
561 FT_Memory memory;
562
563 FT_UNUSED( stream );
564
565
566 memory = library->memory;
567 newpath = raccess_make_file_name( memory, base_file_name, "._" );
568 if ( !newpath )
569 return FT_THROW( Out_Of_Memory );
570
571 error = raccess_guess_linux_double_from_file_name( library, newpath,
572 result_offset );
573 if ( !error )
574 *result_file_name = newpath;
575 else
576 FT_FREE( newpath );
577
578 return error;
579 }
580
581
582 static FT_Error
583 raccess_guess_darwin_hfsplus( FT_Library library,
584 FT_Stream stream,
585 char *base_file_name,
586 char **result_file_name,
587 FT_Long *result_offset )
588 {
589 /*
590 Only meaningful on systems with hfs+ drivers (or Macs).
591 */
592 FT_Error error;
593 char* newpath = NULL;
594 FT_Memory memory;
595 FT_Long base_file_len = (FT_Long)ft_strlen( base_file_name );
596
597 FT_UNUSED( stream );
598
599
600 memory = library->memory;
601
602 if ( base_file_len + 6 > FT_INT_MAX )
603 return FT_THROW( Array_Too_Large );
604
605 if ( FT_QALLOC( newpath, base_file_len + 6 ) )
606 return error;
607
608 FT_MEM_COPY( newpath, base_file_name, base_file_len );
609 FT_MEM_COPY( newpath + base_file_len, "/rsrc", 6 );
610
611 *result_file_name = newpath;
612 *result_offset = 0;
613
614 return FT_Err_Ok;
615 }
616
617
618 static FT_Error
619 raccess_guess_darwin_newvfs( FT_Library library,
620 FT_Stream stream,
621 char *base_file_name,
622 char **result_file_name,
623 FT_Long *result_offset )
624 {
625 /*
626 Only meaningful on systems with Mac OS X (> 10.1).
627 */
628 FT_Error error;
629 char* newpath = NULL;
630 FT_Memory memory;
631 FT_Long base_file_len = (FT_Long)ft_strlen( base_file_name );
632
633 FT_UNUSED( stream );
634
635
636 memory = library->memory;
637
638 if ( base_file_len + 18 > FT_INT_MAX )
639 return FT_THROW( Array_Too_Large );
640
641 if ( FT_QALLOC( newpath, base_file_len + 18 ) )
642 return error;
643
644 FT_MEM_COPY( newpath, base_file_name, base_file_len );
645 FT_MEM_COPY( newpath + base_file_len, "/..namedfork/rsrc", 18 );
646
647 *result_file_name = newpath;
648 *result_offset = 0;
649
650 return FT_Err_Ok;
651 }
652
653
654 static FT_Error
655 raccess_guess_vfat( FT_Library library,
656 FT_Stream stream,
657 char *base_file_name,
658 char **result_file_name,
659 FT_Long *result_offset )
660 {
661 char* newpath;
662 FT_Memory memory;
663
664 FT_UNUSED( stream );
665
666
667 memory = library->memory;
668
669 newpath = raccess_make_file_name( memory, base_file_name,
670 "resource.frk/" );
671 if ( !newpath )
672 return FT_THROW( Out_Of_Memory );
673
674 *result_file_name = newpath;
675 *result_offset = 0;
676
677 return FT_Err_Ok;
678 }
679
680
681 static FT_Error
682 raccess_guess_linux_cap( FT_Library library,
683 FT_Stream stream,
684 char *base_file_name,
685 char **result_file_name,
686 FT_Long *result_offset )
687 {
688 char* newpath;
689 FT_Memory memory;
690
691 FT_UNUSED( stream );
692
693
694 memory = library->memory;
695
696 newpath = raccess_make_file_name( memory, base_file_name, ".resource/" );
697 if ( !newpath )
698 return FT_THROW( Out_Of_Memory );
699
700 *result_file_name = newpath;
701 *result_offset = 0;
702
703 return FT_Err_Ok;
704 }
705
706
707 static FT_Error
708 raccess_guess_linux_double( FT_Library library,
709 FT_Stream stream,
710 char *base_file_name,
711 char **result_file_name,
712 FT_Long *result_offset )
713 {
714 char* newpath;
715 FT_Error error;
716 FT_Memory memory;
717
718 FT_UNUSED( stream );
719
720
721 memory = library->memory;
722
723 newpath = raccess_make_file_name( memory, base_file_name, "%" );
724 if ( !newpath )
725 return FT_THROW( Out_Of_Memory );
726
727 error = raccess_guess_linux_double_from_file_name( library, newpath,
728 result_offset );
729 if ( !error )
730 *result_file_name = newpath;
731 else
732 FT_FREE( newpath );
733
734 return error;
735 }
736
737
738 static FT_Error
739 raccess_guess_linux_netatalk( FT_Library library,
740 FT_Stream stream,
741 char *base_file_name,
742 char **result_file_name,
743 FT_Long *result_offset )
744 {
745 char* newpath;
746 FT_Error error;
747 FT_Memory memory;
748
749 FT_UNUSED( stream );
750
751
752 memory = library->memory;
753
754 newpath = raccess_make_file_name( memory, base_file_name,
755 ".AppleDouble/" );
756 if ( !newpath )
757 return FT_THROW( Out_Of_Memory );
758
759 error = raccess_guess_linux_double_from_file_name( library, newpath,
760 result_offset );
761 if ( !error )
762 *result_file_name = newpath;
763 else
764 FT_FREE( newpath );
765
766 return error;
767 }
768
769
770 static FT_Error
771 raccess_guess_apple_generic( FT_Library library,
772 FT_Stream stream,
773 char *base_file_name,
774 FT_Int32 magic,
775 FT_Long *result_offset )
776 {
777 FT_Int32 magic_from_stream;
778 FT_Error error;
779 FT_Int32 version_number = 0;
780 FT_UShort n_of_entries;
781
782 int i;
783 FT_Int32 entry_id, entry_offset, entry_length = 0;
784
785 const FT_Int32 resource_fork_entry_id = 0x2;
786
787 FT_UNUSED( library );
788 FT_UNUSED( base_file_name );
789 FT_UNUSED( version_number );
790 FT_UNUSED( entry_length );
791
792
793 if ( FT_READ_LONG( magic_from_stream ) )
794 return error;
795 if ( magic_from_stream != magic )
796 return FT_THROW( Unknown_File_Format );
797
798 if ( FT_READ_LONG( version_number ) )
799 return error;
800
801 /* filler */
802 error = FT_Stream_Skip( stream, 16 );
803 if ( error )
804 return error;
805
806 if ( FT_READ_USHORT( n_of_entries ) )
807 return error;
808 if ( n_of_entries == 0 )
809 return FT_THROW( Unknown_File_Format );
810
811 for ( i = 0; i < n_of_entries; i++ )
812 {
813 if ( FT_READ_LONG( entry_id ) )
814 return error;
815 if ( entry_id == resource_fork_entry_id )
816 {
817 if ( FT_READ_LONG( entry_offset ) ||
818 FT_READ_LONG( entry_length ) )
819 continue;
820 *result_offset = entry_offset;
821
822 return FT_Err_Ok;
823 }
824 else
825 {
826 error = FT_Stream_Skip( stream, 4 + 4 ); /* offset + length */
827 if ( error )
828 return error;
829 }
830 }
831
832 return FT_THROW( Unknown_File_Format );
833 }
834
835
836 static FT_Error
837 raccess_guess_linux_double_from_file_name( FT_Library library,
838 char *file_name,
839 FT_Long *result_offset )
840 {
841 FT_Open_Args args2;
842 FT_Stream stream2;
843 char* nouse = NULL;
844 FT_Error error;
845
846
847 args2.flags = FT_OPEN_PATHNAME;
848 args2.pathname = file_name;
849 error = FT_Stream_New( library, &args2, &stream2 );
850 if ( error )
851 return error;
852
853 error = raccess_guess_apple_double( library, stream2, file_name,
854 &nouse, result_offset );
855
856 FT_Stream_Free( stream2, 0 );
857
858 return error;
859 }
860
861
862 static char*
863 raccess_make_file_name( FT_Memory memory,
864 const char *original_name,
865 const char *insertion )
866 {
867 char* new_name = NULL;
868 const char* tmp;
869 const char* slash;
870 size_t new_length;
871 FT_Error error;
872
873
874 new_length = ft_strlen( original_name ) + ft_strlen( insertion );
875 if ( FT_QALLOC( new_name, new_length + 1 ) )
876 return NULL;
877
878 tmp = ft_strrchr( original_name, '/' );
879 if ( tmp )
880 {
881 ft_strncpy( new_name,
882 original_name,
883 (size_t)( tmp - original_name + 1 ) );
884 new_name[tmp - original_name + 1] = '\0';
885 slash = tmp + 1;
886 }
887 else
888 {
889 slash = original_name;
890 new_name[0] = '\0';
891 }
892
893 ft_strcat( new_name, insertion );
894 ft_strcat( new_name, slash );
895
896 return new_name;
897 }
898
899
900#else /* !FT_CONFIG_OPTION_GUESSING_EMBEDDED_RFORK */
901
902
903 /**************************************************************************
904 * Dummy function; just sets errors
905 */
906
907 FT_BASE_DEF( void )
908 FT_Raccess_Guess( FT_Library library,
909 FT_Stream stream,
910 char *base_name,
911 char **new_names,
912 FT_Long *offsets,
913 FT_Error *errors )
914 {
915 FT_Int i;
916
917 FT_UNUSED( library );
918 FT_UNUSED( stream );
919 FT_UNUSED( base_name );
920
921
922 for ( i = 0; i < FT_RACCESS_N_RULES; i++ )
923 {
924 new_names[i] = NULL;
925 offsets[i] = 0;
926 errors[i] = FT_ERR( Unimplemented_Feature );
927 }
928 }
929
930
931#endif /* !FT_CONFIG_OPTION_GUESSING_EMBEDDED_RFORK */
932
933
934/* END */
935