XFA: merge patch from CL 817753002
[pdfium.git] / core / src / fxge / fx_freetype / fxft2.5.01 / src / base / ftrfork.c
1 /***************************************************************************/
2 /*                                                                         */
3 /*  ftrfork.c                                                              */
4 /*                                                                         */
5 /*    Embedded resource forks accessor (body).                             */
6 /*                                                                         */
7 /*  Copyright 2004-2010, 2013 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 "../../include/ft2build.h"
28 #include "../../include/freetype/internal/ftdebug.h"
29 #include "../../include/freetype/internal/ftstream.h"
30 #include "../../include/freetype/internal/ftrfork.h"
31 #include "basepic.h"
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 )
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_THROW( 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_THROW( 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_THROW( 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
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 )
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 = NULL;
163     FT_RFork_Ref  *ref = NULL;
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_THROW( 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   static FT_Error
257   raccess_guess_apple_double( FT_Library  library,
258                               FT_Stream   stream,
259                               char       *base_file_name,
260                               char      **result_file_name,
261                               FT_Long    *result_offset );
262
263   static FT_Error
264   raccess_guess_apple_single( FT_Library  library,
265                               FT_Stream   stream,
266                               char       *base_file_name,
267                               char      **result_file_name,
268                               FT_Long    *result_offset );
269
270   static FT_Error
271   raccess_guess_darwin_ufs_export( FT_Library  library,
272                                    FT_Stream   stream,
273                                    char       *base_file_name,
274                                    char      **result_file_name,
275                                    FT_Long    *result_offset );
276
277   static FT_Error
278   raccess_guess_darwin_newvfs( FT_Library  library,
279                                FT_Stream   stream,
280                                char       *base_file_name,
281                                char      **result_file_name,
282                                FT_Long    *result_offset );
283
284   static FT_Error
285   raccess_guess_darwin_hfsplus( FT_Library  library,
286                                 FT_Stream   stream,
287                                 char       *base_file_name,
288                                 char      **result_file_name,
289                                 FT_Long    *result_offset );
290
291   static FT_Error
292   raccess_guess_vfat( FT_Library  library,
293                       FT_Stream   stream,
294                       char       *base_file_name,
295                       char      **result_file_name,
296                       FT_Long    *result_offset );
297
298   static FT_Error
299   raccess_guess_linux_cap( FT_Library  library,
300                            FT_Stream   stream,
301                            char       *base_file_name,
302                            char      **result_file_name,
303                            FT_Long    *result_offset );
304
305   static FT_Error
306   raccess_guess_linux_double( FT_Library  library,
307                               FT_Stream   stream,
308                               char       *base_file_name,
309                               char      **result_file_name,
310                               FT_Long    *result_offset );
311
312   static FT_Error
313   raccess_guess_linux_netatalk( FT_Library  library,
314                                 FT_Stream   stream,
315                                 char       *base_file_name,
316                                 char      **result_file_name,
317                                 FT_Long    *result_offset );
318
319
320   CONST_FT_RFORK_RULE_ARRAY_BEGIN(ft_raccess_guess_table,
321                                   ft_raccess_guess_rec)
322   CONST_FT_RFORK_RULE_ARRAY_ENTRY(apple_double,      apple_double)
323   CONST_FT_RFORK_RULE_ARRAY_ENTRY(apple_single,      apple_single)
324   CONST_FT_RFORK_RULE_ARRAY_ENTRY(darwin_ufs_export, darwin_ufs_export)
325   CONST_FT_RFORK_RULE_ARRAY_ENTRY(darwin_newvfs,     darwin_newvfs)
326   CONST_FT_RFORK_RULE_ARRAY_ENTRY(darwin_hfsplus,    darwin_hfsplus)
327   CONST_FT_RFORK_RULE_ARRAY_ENTRY(vfat,              vfat)
328   CONST_FT_RFORK_RULE_ARRAY_ENTRY(linux_cap,         linux_cap)
329   CONST_FT_RFORK_RULE_ARRAY_ENTRY(linux_double,      linux_double)
330   CONST_FT_RFORK_RULE_ARRAY_ENTRY(linux_netatalk,    linux_netatalk)
331   CONST_FT_RFORK_RULE_ARRAY_END
332
333
334   /*************************************************************************/
335   /****                                                                 ****/
336   /****                       Helper functions                          ****/
337   /****                                                                 ****/
338   /*************************************************************************/
339
340   static FT_Error
341   raccess_guess_apple_generic( FT_Library  library,
342                                FT_Stream   stream,
343                                char       *base_file_name,
344                                FT_Int32    magic,
345                                FT_Long    *result_offset );
346
347   static FT_Error
348   raccess_guess_linux_double_from_file_name( FT_Library  library,
349                                              char *      file_name,
350                                              FT_Long    *result_offset );
351
352   static char *
353   raccess_make_file_name( FT_Memory    memory,
354                           const char  *original_name,
355                           const char  *insertion );
356
357   FT_BASE_DEF( void )
358   FT_Raccess_Guess( FT_Library  library,
359                     FT_Stream   stream,
360                     char*       base_name,
361                     char      **new_names,
362                     FT_Long    *offsets,
363                     FT_Error   *errors )
364   {
365     FT_Int  i;
366
367
368     for ( i = 0; i < FT_RACCESS_N_RULES; i++ )
369     {
370       new_names[i] = NULL;
371       if ( NULL != stream )
372         errors[i] = FT_Stream_Seek( stream, 0 );
373       else
374         errors[i] = FT_Err_Ok;
375
376       if ( errors[i] )
377         continue ;
378
379       errors[i] = (FT_RACCESS_GUESS_TABLE_GET[i].func)( library,
380                                                  stream, base_name,
381                                                  &(new_names[i]),
382                                                  &(offsets[i]) );
383     }
384
385     return;
386   }
387
388
389 #ifndef FT_MACINTOSH
390   static FT_RFork_Rule
391   raccess_get_rule_type_from_rule_index( FT_Library  library,
392                                          FT_UInt     rule_index )
393   {
394     FT_UNUSED( library );
395
396     if ( rule_index >= FT_RACCESS_N_RULES )
397       return FT_RFork_Rule_invalid;
398
399     return FT_RACCESS_GUESS_TABLE_GET[rule_index].type;
400   }
401
402
403   /*
404    * For this function, refer ftbase.h.
405    */
406   FT_LOCAL_DEF( FT_Bool )
407   ft_raccess_rule_by_darwin_vfs( FT_Library  library,
408                                  FT_UInt     rule_index )
409   {
410     switch( raccess_get_rule_type_from_rule_index( library, rule_index ) )
411     {
412       case FT_RFork_Rule_darwin_newvfs:
413       case FT_RFork_Rule_darwin_hfsplus:
414         return TRUE;
415
416       default:
417         return FALSE;
418     }
419   }
420 #endif
421
422
423   static FT_Error
424   raccess_guess_apple_double( FT_Library  library,
425                               FT_Stream   stream,
426                               char       *base_file_name,
427                               char      **result_file_name,
428                               FT_Long    *result_offset )
429   {
430     FT_Int32  magic = ( 0x00 << 24 ) |
431                       ( 0x05 << 16 ) |
432                       ( 0x16 <<  8 ) |
433                         0x07;
434
435
436     *result_file_name = NULL;
437     if ( NULL == stream )
438       return FT_THROW( Cannot_Open_Stream );
439
440     return raccess_guess_apple_generic( library, stream, base_file_name,
441                                         magic, result_offset );
442   }
443
444
445   static FT_Error
446   raccess_guess_apple_single( FT_Library  library,
447                               FT_Stream   stream,
448                               char       *base_file_name,
449                               char      **result_file_name,
450                               FT_Long    *result_offset )
451   {
452     FT_Int32  magic = ( 0x00 << 24 ) |
453                       ( 0x05 << 16 ) |
454                       ( 0x16 <<  8 ) |
455                         0x00;
456
457
458     *result_file_name = NULL;
459     if ( NULL == stream )
460       return FT_THROW( Cannot_Open_Stream );
461
462     return raccess_guess_apple_generic( library, stream, base_file_name,
463                                         magic, result_offset );
464   }
465
466
467   static FT_Error
468   raccess_guess_darwin_ufs_export( FT_Library  library,
469                                    FT_Stream   stream,
470                                    char       *base_file_name,
471                                    char      **result_file_name,
472                                    FT_Long    *result_offset )
473   {
474     char*      newpath;
475     FT_Error   error;
476     FT_Memory  memory;
477
478     FT_UNUSED( stream );
479
480
481     memory  = library->memory;
482     newpath = raccess_make_file_name( memory, base_file_name, "._" );
483     if ( !newpath )
484       return FT_THROW( Out_Of_Memory );
485
486     error = raccess_guess_linux_double_from_file_name( library, newpath,
487                                                        result_offset );
488     if ( !error )
489       *result_file_name = newpath;
490     else
491       FT_FREE( newpath );
492
493     return error;
494   }
495
496
497   static FT_Error
498   raccess_guess_darwin_hfsplus( FT_Library  library,
499                                 FT_Stream   stream,
500                                 char       *base_file_name,
501                                 char      **result_file_name,
502                                 FT_Long    *result_offset )
503   {
504     /*
505       Only meaningful on systems with hfs+ drivers (or Macs).
506      */
507     FT_Error   error;
508     char*      newpath = NULL;
509     FT_Memory  memory;
510     FT_Long    base_file_len = (FT_Long)ft_strlen( base_file_name );
511
512     FT_UNUSED( stream );
513
514
515     memory = library->memory;
516
517     if ( base_file_len + 6 > FT_INT_MAX )
518       return FT_THROW( Array_Too_Large );
519
520     if ( FT_ALLOC( newpath, base_file_len + 6 ) )
521       return error;
522
523     FT_MEM_COPY( newpath, base_file_name, base_file_len );
524     FT_MEM_COPY( newpath + base_file_len, "/rsrc", 6 );
525
526     *result_file_name = newpath;
527     *result_offset    = 0;
528
529     return FT_Err_Ok;
530   }
531
532
533   static FT_Error
534   raccess_guess_darwin_newvfs( FT_Library  library,
535                                FT_Stream   stream,
536                                char       *base_file_name,
537                                char      **result_file_name,
538                                FT_Long    *result_offset )
539   {
540     /*
541       Only meaningful on systems with Mac OS X (> 10.1).
542      */
543     FT_Error   error;
544     char*      newpath = NULL;
545     FT_Memory  memory;
546     FT_Long    base_file_len = (FT_Long)ft_strlen( base_file_name );
547
548     FT_UNUSED( stream );
549
550
551     memory = library->memory;
552
553     if ( base_file_len + 18 > FT_INT_MAX )
554       return FT_THROW( Array_Too_Large );
555
556     if ( FT_ALLOC( newpath, base_file_len + 18 ) )
557       return error;
558
559     FT_MEM_COPY( newpath, base_file_name, base_file_len );
560     FT_MEM_COPY( newpath + base_file_len, "/..namedfork/rsrc", 18 );
561
562     *result_file_name = newpath;
563     *result_offset    = 0;
564
565     return FT_Err_Ok;
566   }
567
568
569   static FT_Error
570   raccess_guess_vfat( FT_Library  library,
571                       FT_Stream   stream,
572                       char       *base_file_name,
573                       char      **result_file_name,
574                       FT_Long    *result_offset )
575   {
576     char*      newpath;
577     FT_Memory  memory;
578
579     FT_UNUSED( stream );
580
581
582     memory = library->memory;
583
584     newpath = raccess_make_file_name( memory, base_file_name,
585                                       "resource.frk/" );
586     if ( !newpath )
587       return FT_THROW( Out_Of_Memory );
588
589     *result_file_name = newpath;
590     *result_offset    = 0;
591
592     return FT_Err_Ok;
593   }
594
595
596   static FT_Error
597   raccess_guess_linux_cap( FT_Library  library,
598                            FT_Stream   stream,
599                            char       *base_file_name,
600                            char      **result_file_name,
601                            FT_Long    *result_offset )
602   {
603     char*      newpath;
604     FT_Memory  memory;
605
606     FT_UNUSED( stream );
607
608
609     memory = library->memory;
610
611     newpath = raccess_make_file_name( memory, base_file_name, ".resource/" );
612     if ( !newpath )
613       return FT_THROW( Out_Of_Memory );
614
615     *result_file_name = newpath;
616     *result_offset    = 0;
617
618     return FT_Err_Ok;
619   }
620
621
622   static FT_Error
623   raccess_guess_linux_double( FT_Library  library,
624                               FT_Stream   stream,
625                               char       *base_file_name,
626                               char      **result_file_name,
627                               FT_Long    *result_offset )
628   {
629     char*      newpath;
630     FT_Error   error;
631     FT_Memory  memory;
632
633     FT_UNUSED( stream );
634
635
636     memory = library->memory;
637
638     newpath = raccess_make_file_name( memory, base_file_name, "%" );
639     if ( !newpath )
640       return FT_THROW( Out_Of_Memory );
641
642     error = raccess_guess_linux_double_from_file_name( library, newpath,
643                                                        result_offset );
644     if ( !error )
645       *result_file_name = newpath;
646     else
647       FT_FREE( newpath );
648
649     return error;
650   }
651
652
653   static FT_Error
654   raccess_guess_linux_netatalk( FT_Library  library,
655                                 FT_Stream   stream,
656                                 char       *base_file_name,
657                                 char      **result_file_name,
658                                 FT_Long    *result_offset )
659   {
660     char*      newpath;
661     FT_Error   error;
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                                       ".AppleDouble/" );
671     if ( !newpath )
672       return FT_THROW( Out_Of_Memory );
673
674     error = raccess_guess_linux_double_from_file_name( library, newpath,
675                                                        result_offset );
676     if ( !error )
677       *result_file_name = newpath;
678     else
679       FT_FREE( newpath );
680
681     return error;
682   }
683
684
685   static FT_Error
686   raccess_guess_apple_generic( FT_Library  library,
687                                FT_Stream   stream,
688                                char       *base_file_name,
689                                FT_Int32    magic,
690                                FT_Long    *result_offset )
691   {
692     FT_Int32   magic_from_stream;
693     FT_Error   error;
694     FT_Int32   version_number = 0;
695     FT_UShort  n_of_entries;
696
697     int        i;
698     FT_UInt32  entry_id, entry_offset, entry_length = 0;
699
700     const FT_UInt32  resource_fork_entry_id = 0x2;
701
702     FT_UNUSED( library );
703     FT_UNUSED( base_file_name );
704     FT_UNUSED( version_number );
705     FT_UNUSED( entry_length   );
706
707
708     if ( FT_READ_LONG( magic_from_stream ) )
709       return error;
710     if ( magic_from_stream != magic )
711       return FT_THROW( Unknown_File_Format );
712
713     if ( FT_READ_LONG( version_number ) )
714       return error;
715
716     /* filler */
717     error = FT_Stream_Skip( stream, 16 );
718     if ( error )
719       return error;
720
721     if ( FT_READ_USHORT( n_of_entries ) )
722       return error;
723     if ( n_of_entries == 0 )
724       return FT_THROW( Unknown_File_Format );
725
726     for ( i = 0; i < n_of_entries; i++ )
727     {
728       if ( FT_READ_LONG( entry_id ) )
729         return error;
730       if ( entry_id == resource_fork_entry_id )
731       {
732         if ( FT_READ_LONG( entry_offset ) ||
733              FT_READ_LONG( entry_length ) )
734           continue;
735         *result_offset = entry_offset;
736
737         return FT_Err_Ok;
738       }
739       else
740       {
741         error = FT_Stream_Skip( stream, 4 + 4 );    /* offset + length */
742         if ( error )
743           return error;
744       }
745     }
746
747     return FT_THROW( Unknown_File_Format );
748   }
749
750
751   static FT_Error
752   raccess_guess_linux_double_from_file_name( FT_Library  library,
753                                              char       *file_name,
754                                              FT_Long    *result_offset )
755   {
756     FT_Open_Args  args2;
757     FT_Stream     stream2;
758     char *        nouse = NULL;
759     FT_Error      error;
760
761
762     args2.flags    = FT_OPEN_PATHNAME;
763     args2.pathname = file_name;
764     error = FT_Stream_New( library, &args2, &stream2 );
765     if ( error )
766       return error;
767
768     error = raccess_guess_apple_double( library, stream2, file_name,
769                                         &nouse, result_offset );
770
771     FT_Stream_Free( stream2, 0 );
772
773     return error;
774   }
775
776
777   static char*
778   raccess_make_file_name( FT_Memory    memory,
779                           const char  *original_name,
780                           const char  *insertion )
781   {
782     char*        new_name = NULL;
783     const char*  tmp;
784     const char*  slash;
785     size_t       new_length;
786     FT_Error     error = FT_Err_Ok;
787
788     FT_UNUSED( error );
789
790
791     new_length = ft_strlen( original_name ) + ft_strlen( insertion );
792     if ( FT_ALLOC( new_name, new_length + 1 ) )
793       return NULL;
794
795     tmp = ft_strrchr( original_name, '/' );
796     if ( tmp )
797     {
798       ft_strncpy( new_name, original_name, tmp - original_name + 1 );
799       new_name[tmp - original_name + 1] = '\0';
800       slash = tmp + 1;
801     }
802     else
803     {
804       slash       = original_name;
805       new_name[0] = '\0';
806     }
807
808     ft_strcat( new_name, insertion );
809     ft_strcat( new_name, slash );
810
811     return new_name;
812   }
813
814
815 #else   /* !FT_CONFIG_OPTION_GUESSING_EMBEDDED_RFORK */
816
817
818   /*************************************************************************/
819   /*                  Dummy function; just sets errors                     */
820   /*************************************************************************/
821
822   FT_BASE_DEF( void )
823   FT_Raccess_Guess( FT_Library  library,
824                     FT_Stream   stream,
825                     char       *base_name,
826                     char      **new_names,
827                     FT_Long    *offsets,
828                     FT_Error   *errors )
829   {
830     FT_Int  i;
831
832     FT_UNUSED( library );
833     FT_UNUSED( stream );
834     FT_UNUSED( base_name );
835
836
837     for ( i = 0; i < FT_RACCESS_N_RULES; i++ )
838     {
839       new_names[i] = NULL;
840       offsets[i]   = 0;
841       errors[i]    = FT_ERR( Unimplemented_Feature );
842     }
843   }
844
845
846 #endif  /* !FT_CONFIG_OPTION_GUESSING_EMBEDDED_RFORK */
847
848
849 /* END */