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