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