Add leftover from sync, fixes build.
[reactos.git] / lib / 3rdparty / freetype / src / base / ftrfork.c
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 )
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
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;
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 )
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
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
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
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
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
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
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
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
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
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
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
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*
750 raccess_make_file_name( FT_Memory memory,
751 const char *original_name,
752 const char *insertion )
753 {
754 char* new_name;
755 const char* tmp;
756 const char* slash;
757 size_t 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 )
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 */