1 /***************************************************************************/ |
|
2 /* */ |
|
3 /* ftrfork.c */ |
|
4 /* */ |
|
5 /* Embedded resource forks accessor (body). */ |
|
6 /* */ |
|
7 /* Copyright 2004, 2005, 2006, 2007, 2008, 2009, 2010 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 typedef enum FT_RFork_Rule_ { |
|
353 FT_RFork_Rule_invalid = -2, |
|
354 FT_RFork_Rule_uknown, /* -1 */ |
|
355 FT_RFork_Rule_apple_double, |
|
356 FT_RFork_Rule_apple_single, |
|
357 FT_RFork_Rule_darwin_ufs_export, |
|
358 FT_RFork_Rule_darwin_newvfs, |
|
359 FT_RFork_Rule_darwin_hfsplus, |
|
360 FT_RFork_Rule_vfat, |
|
361 FT_RFork_Rule_linux_cap, |
|
362 FT_RFork_Rule_linux_double, |
|
363 FT_RFork_Rule_linux_netatalk |
|
364 } FT_RFork_Rule; |
|
365 |
|
366 /* For fast translation between rule index and rule type, |
|
367 * the macros FT_RFORK_xxx should be kept consistent with |
|
368 * the raccess_guess_funcs table |
|
369 */ |
|
370 typedef struct raccess_guess_rec_ { |
|
371 raccess_guess_func func; |
|
372 FT_RFork_Rule type; |
|
373 } raccess_guess_rec; |
|
374 |
|
375 static raccess_guess_rec raccess_guess_table[FT_RACCESS_N_RULES] = |
|
376 { |
|
377 { raccess_guess_apple_double, FT_RFork_Rule_apple_double, }, |
|
378 { raccess_guess_apple_single, FT_RFork_Rule_apple_single, }, |
|
379 { raccess_guess_darwin_ufs_export, FT_RFork_Rule_darwin_ufs_export, }, |
|
380 { raccess_guess_darwin_newvfs, FT_RFork_Rule_darwin_newvfs, }, |
|
381 { raccess_guess_darwin_hfsplus, FT_RFork_Rule_darwin_hfsplus, }, |
|
382 { raccess_guess_vfat, FT_RFork_Rule_vfat, }, |
|
383 { raccess_guess_linux_cap, FT_RFork_Rule_linux_cap, }, |
|
384 { raccess_guess_linux_double, FT_RFork_Rule_linux_double, }, |
|
385 { raccess_guess_linux_netatalk, FT_RFork_Rule_linux_netatalk, }, |
|
386 }; |
|
387 |
|
388 FT_BASE_DEF( void ) |
|
389 FT_Raccess_Guess( FT_Library library, |
|
390 FT_Stream stream, |
|
391 char* base_name, |
|
392 char **new_names, |
|
393 FT_Long *offsets, |
|
394 FT_Error *errors ) |
|
395 { |
|
396 FT_Long i; |
|
397 |
|
398 |
|
399 for ( i = 0; i < FT_RACCESS_N_RULES; i++ ) |
|
400 { |
|
401 new_names[i] = NULL; |
|
402 if ( NULL != stream ) |
|
403 errors[i] = FT_Stream_Seek( stream, 0 ); |
|
404 else |
|
405 errors[i] = FT_Err_Ok; |
|
406 |
|
407 if ( errors[i] ) |
|
408 continue ; |
|
409 |
|
410 errors[i] = (raccess_guess_table[i].func)( library, |
|
411 stream, base_name, |
|
412 &(new_names[i]), |
|
413 &(offsets[i]) ); |
|
414 } |
|
415 |
|
416 return; |
|
417 } |
|
418 |
|
419 |
|
420 static FT_RFork_Rule |
|
421 raccess_get_rule_type_from_rule_index( FT_UInt rule_index ) |
|
422 { |
|
423 if ( rule_index >= FT_RACCESS_N_RULES ) |
|
424 return FT_RFork_Rule_invalid; |
|
425 |
|
426 return raccess_guess_table[rule_index].type; |
|
427 } |
|
428 |
|
429 |
|
430 FT_LOCAL_DEF( FT_Bool ) |
|
431 raccess_rule_by_darwin_vfs( FT_UInt rule_index ) |
|
432 { |
|
433 switch( raccess_get_rule_type_from_rule_index( rule_index ) ) |
|
434 { |
|
435 case FT_RFork_Rule_darwin_newvfs: |
|
436 case FT_RFork_Rule_darwin_hfsplus: |
|
437 return TRUE; |
|
438 |
|
439 default: |
|
440 return FALSE; |
|
441 } |
|
442 } |
|
443 |
|
444 |
|
445 static FT_Error |
|
446 raccess_guess_apple_double( 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 0x07; |
|
456 |
|
457 |
|
458 *result_file_name = NULL; |
|
459 if ( NULL == stream ) |
|
460 return FT_Err_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_apple_single( FT_Library library, |
|
469 FT_Stream stream, |
|
470 char *base_file_name, |
|
471 char **result_file_name, |
|
472 FT_Long *result_offset ) |
|
473 { |
|
474 FT_Int32 magic = ( 0x00 << 24 ) | |
|
475 ( 0x05 << 16 ) | |
|
476 ( 0x16 << 8 ) | |
|
477 0x00; |
|
478 |
|
479 |
|
480 *result_file_name = NULL; |
|
481 if ( NULL == stream ) |
|
482 return FT_Err_Cannot_Open_Stream; |
|
483 |
|
484 return raccess_guess_apple_generic( library, stream, base_file_name, |
|
485 magic, result_offset ); |
|
486 } |
|
487 |
|
488 |
|
489 static FT_Error |
|
490 raccess_guess_darwin_ufs_export( FT_Library library, |
|
491 FT_Stream stream, |
|
492 char *base_file_name, |
|
493 char **result_file_name, |
|
494 FT_Long *result_offset ) |
|
495 { |
|
496 char* newpath; |
|
497 FT_Error error; |
|
498 FT_Memory memory; |
|
499 |
|
500 FT_UNUSED( stream ); |
|
501 |
|
502 |
|
503 memory = library->memory; |
|
504 newpath = raccess_make_file_name( memory, base_file_name, "._" ); |
|
505 if ( !newpath ) |
|
506 return FT_Err_Out_Of_Memory; |
|
507 |
|
508 error = raccess_guess_linux_double_from_file_name( library, newpath, |
|
509 result_offset ); |
|
510 if ( !error ) |
|
511 *result_file_name = newpath; |
|
512 else |
|
513 FT_FREE( newpath ); |
|
514 |
|
515 return error; |
|
516 } |
|
517 |
|
518 |
|
519 static FT_Error |
|
520 raccess_guess_darwin_hfsplus( FT_Library library, |
|
521 FT_Stream stream, |
|
522 char *base_file_name, |
|
523 char **result_file_name, |
|
524 FT_Long *result_offset ) |
|
525 { |
|
526 /* |
|
527 Only meaningful on systems with hfs+ drivers (or Macs). |
|
528 */ |
|
529 FT_Error error; |
|
530 char* newpath; |
|
531 FT_Memory memory; |
|
532 FT_Long base_file_len = ft_strlen( base_file_name ); |
|
533 |
|
534 FT_UNUSED( stream ); |
|
535 |
|
536 |
|
537 memory = library->memory; |
|
538 |
|
539 if ( base_file_len + 6 > FT_INT_MAX ) |
|
540 return FT_Err_Array_Too_Large; |
|
541 |
|
542 if ( FT_ALLOC( newpath, base_file_len + 6 ) ) |
|
543 return error; |
|
544 |
|
545 FT_MEM_COPY( newpath, base_file_name, base_file_len ); |
|
546 FT_MEM_COPY( newpath + base_file_len, "/rsrc", 6 ); |
|
547 |
|
548 *result_file_name = newpath; |
|
549 *result_offset = 0; |
|
550 |
|
551 return FT_Err_Ok; |
|
552 } |
|
553 |
|
554 |
|
555 static FT_Error |
|
556 raccess_guess_darwin_newvfs( FT_Library library, |
|
557 FT_Stream stream, |
|
558 char *base_file_name, |
|
559 char **result_file_name, |
|
560 FT_Long *result_offset ) |
|
561 { |
|
562 /* |
|
563 Only meaningful on systems with Mac OS X (> 10.1). |
|
564 */ |
|
565 FT_Error error; |
|
566 char* newpath; |
|
567 FT_Memory memory; |
|
568 FT_Long base_file_len = ft_strlen( base_file_name ); |
|
569 |
|
570 FT_UNUSED( stream ); |
|
571 |
|
572 |
|
573 memory = library->memory; |
|
574 |
|
575 if ( base_file_len + 18 > FT_INT_MAX ) |
|
576 return FT_Err_Array_Too_Large; |
|
577 |
|
578 if ( FT_ALLOC( newpath, base_file_len + 18 ) ) |
|
579 return error; |
|
580 |
|
581 FT_MEM_COPY( newpath, base_file_name, base_file_len ); |
|
582 FT_MEM_COPY( newpath + base_file_len, "/..namedfork/rsrc", 18 ); |
|
583 |
|
584 *result_file_name = newpath; |
|
585 *result_offset = 0; |
|
586 |
|
587 return FT_Err_Ok; |
|
588 } |
|
589 |
|
590 |
|
591 static FT_Error |
|
592 raccess_guess_vfat( FT_Library library, |
|
593 FT_Stream stream, |
|
594 char *base_file_name, |
|
595 char **result_file_name, |
|
596 FT_Long *result_offset ) |
|
597 { |
|
598 char* newpath; |
|
599 FT_Memory memory; |
|
600 |
|
601 FT_UNUSED( stream ); |
|
602 |
|
603 |
|
604 memory = library->memory; |
|
605 |
|
606 newpath = raccess_make_file_name( memory, base_file_name, |
|
607 "resource.frk/" ); |
|
608 if ( !newpath ) |
|
609 return FT_Err_Out_Of_Memory; |
|
610 |
|
611 *result_file_name = newpath; |
|
612 *result_offset = 0; |
|
613 |
|
614 return FT_Err_Ok; |
|
615 } |
|
616 |
|
617 |
|
618 static FT_Error |
|
619 raccess_guess_linux_cap( FT_Library library, |
|
620 FT_Stream stream, |
|
621 char *base_file_name, |
|
622 char **result_file_name, |
|
623 FT_Long *result_offset ) |
|
624 { |
|
625 char* newpath; |
|
626 FT_Memory memory; |
|
627 |
|
628 FT_UNUSED( stream ); |
|
629 |
|
630 |
|
631 memory = library->memory; |
|
632 |
|
633 newpath = raccess_make_file_name( memory, base_file_name, ".resource/" ); |
|
634 if ( !newpath ) |
|
635 return FT_Err_Out_Of_Memory; |
|
636 |
|
637 *result_file_name = newpath; |
|
638 *result_offset = 0; |
|
639 |
|
640 return FT_Err_Ok; |
|
641 } |
|
642 |
|
643 |
|
644 static FT_Error |
|
645 raccess_guess_linux_double( FT_Library library, |
|
646 FT_Stream stream, |
|
647 char *base_file_name, |
|
648 char **result_file_name, |
|
649 FT_Long *result_offset ) |
|
650 { |
|
651 char* newpath; |
|
652 FT_Error error; |
|
653 FT_Memory memory; |
|
654 |
|
655 FT_UNUSED( stream ); |
|
656 |
|
657 |
|
658 memory = library->memory; |
|
659 |
|
660 newpath = raccess_make_file_name( memory, base_file_name, "%" ); |
|
661 if ( !newpath ) |
|
662 return FT_Err_Out_Of_Memory; |
|
663 |
|
664 error = raccess_guess_linux_double_from_file_name( library, newpath, |
|
665 result_offset ); |
|
666 if ( !error ) |
|
667 *result_file_name = newpath; |
|
668 else |
|
669 FT_FREE( newpath ); |
|
670 |
|
671 return error; |
|
672 } |
|
673 |
|
674 |
|
675 static FT_Error |
|
676 raccess_guess_linux_netatalk( FT_Library library, |
|
677 FT_Stream stream, |
|
678 char *base_file_name, |
|
679 char **result_file_name, |
|
680 FT_Long *result_offset ) |
|
681 { |
|
682 char* newpath; |
|
683 FT_Error error; |
|
684 FT_Memory memory; |
|
685 |
|
686 FT_UNUSED( stream ); |
|
687 |
|
688 |
|
689 memory = library->memory; |
|
690 |
|
691 newpath = raccess_make_file_name( memory, base_file_name, |
|
692 ".AppleDouble/" ); |
|
693 if ( !newpath ) |
|
694 return FT_Err_Out_Of_Memory; |
|
695 |
|
696 error = raccess_guess_linux_double_from_file_name( library, newpath, |
|
697 result_offset ); |
|
698 if ( !error ) |
|
699 *result_file_name = newpath; |
|
700 else |
|
701 FT_FREE( newpath ); |
|
702 |
|
703 return error; |
|
704 } |
|
705 |
|
706 |
|
707 static FT_Error |
|
708 raccess_guess_apple_generic( FT_Library library, |
|
709 FT_Stream stream, |
|
710 char *base_file_name, |
|
711 FT_Int32 magic, |
|
712 FT_Long *result_offset ) |
|
713 { |
|
714 FT_Int32 magic_from_stream; |
|
715 FT_Error error; |
|
716 FT_Int32 version_number = 0; |
|
717 FT_UShort n_of_entries; |
|
718 |
|
719 int i; |
|
720 FT_UInt32 entry_id, entry_offset, entry_length = 0; |
|
721 |
|
722 const FT_UInt32 resource_fork_entry_id = 0x2; |
|
723 |
|
724 FT_UNUSED( library ); |
|
725 FT_UNUSED( base_file_name ); |
|
726 FT_UNUSED( version_number ); |
|
727 FT_UNUSED( entry_length ); |
|
728 |
|
729 |
|
730 if ( FT_READ_LONG( magic_from_stream ) ) |
|
731 return error; |
|
732 if ( magic_from_stream != magic ) |
|
733 return FT_Err_Unknown_File_Format; |
|
734 |
|
735 if ( FT_READ_LONG( version_number ) ) |
|
736 return error; |
|
737 |
|
738 /* filler */ |
|
739 error = FT_Stream_Skip( stream, 16 ); |
|
740 if ( error ) |
|
741 return error; |
|
742 |
|
743 if ( FT_READ_USHORT( n_of_entries ) ) |
|
744 return error; |
|
745 if ( n_of_entries == 0 ) |
|
746 return FT_Err_Unknown_File_Format; |
|
747 |
|
748 for ( i = 0; i < n_of_entries; i++ ) |
|
749 { |
|
750 if ( FT_READ_LONG( entry_id ) ) |
|
751 return error; |
|
752 if ( entry_id == resource_fork_entry_id ) |
|
753 { |
|
754 if ( FT_READ_LONG( entry_offset ) || |
|
755 FT_READ_LONG( entry_length ) ) |
|
756 continue; |
|
757 *result_offset = entry_offset; |
|
758 |
|
759 return FT_Err_Ok; |
|
760 } |
|
761 else |
|
762 { |
|
763 error = FT_Stream_Skip( stream, 4 + 4 ); /* offset + length */ |
|
764 if ( error ) |
|
765 return error; |
|
766 } |
|
767 } |
|
768 |
|
769 return FT_Err_Unknown_File_Format; |
|
770 } |
|
771 |
|
772 |
|
773 static FT_Error |
|
774 raccess_guess_linux_double_from_file_name( FT_Library library, |
|
775 char *file_name, |
|
776 FT_Long *result_offset ) |
|
777 { |
|
778 FT_Open_Args args2; |
|
779 FT_Stream stream2; |
|
780 char * nouse = NULL; |
|
781 FT_Error error; |
|
782 |
|
783 |
|
784 args2.flags = FT_OPEN_PATHNAME; |
|
785 args2.pathname = file_name; |
|
786 error = FT_Stream_New( library, &args2, &stream2 ); |
|
787 if ( error ) |
|
788 return error; |
|
789 |
|
790 error = raccess_guess_apple_double( library, stream2, file_name, |
|
791 &nouse, result_offset ); |
|
792 |
|
793 FT_Stream_Free( stream2, 0 ); |
|
794 |
|
795 return error; |
|
796 } |
|
797 |
|
798 |
|
799 static char* |
|
800 raccess_make_file_name( FT_Memory memory, |
|
801 const char *original_name, |
|
802 const char *insertion ) |
|
803 { |
|
804 char* new_name = NULL; |
|
805 const char* tmp; |
|
806 const char* slash; |
|
807 size_t new_length; |
|
808 FT_Error error = FT_Err_Ok; |
|
809 |
|
810 FT_UNUSED( error ); |
|
811 |
|
812 |
|
813 new_length = ft_strlen( original_name ) + ft_strlen( insertion ); |
|
814 if ( FT_ALLOC( new_name, new_length + 1 ) ) |
|
815 return NULL; |
|
816 |
|
817 tmp = ft_strrchr( original_name, '/' ); |
|
818 if ( tmp ) |
|
819 { |
|
820 ft_strncpy( new_name, original_name, tmp - original_name + 1 ); |
|
821 new_name[tmp - original_name + 1] = '\0'; |
|
822 slash = tmp + 1; |
|
823 } |
|
824 else |
|
825 { |
|
826 slash = original_name; |
|
827 new_name[0] = '\0'; |
|
828 } |
|
829 |
|
830 ft_strcat( new_name, insertion ); |
|
831 ft_strcat( new_name, slash ); |
|
832 |
|
833 return new_name; |
|
834 } |
|
835 |
|
836 |
|
837 #else /* !FT_CONFIG_OPTION_GUESSING_EMBEDDED_RFORK */ |
|
838 |
|
839 |
|
840 /*************************************************************************/ |
|
841 /* Dummy function; just sets errors */ |
|
842 /*************************************************************************/ |
|
843 |
|
844 FT_BASE_DEF( void ) |
|
845 FT_Raccess_Guess( FT_Library library, |
|
846 FT_Stream stream, |
|
847 char *base_name, |
|
848 char **new_names, |
|
849 FT_Long *offsets, |
|
850 FT_Error *errors ) |
|
851 { |
|
852 int i; |
|
853 |
|
854 FT_UNUSED( library ); |
|
855 FT_UNUSED( stream ); |
|
856 FT_UNUSED( base_name ); |
|
857 |
|
858 |
|
859 for ( i = 0; i < FT_RACCESS_N_RULES; i++ ) |
|
860 { |
|
861 new_names[i] = NULL; |
|
862 offsets[i] = 0; |
|
863 errors[i] = FT_Err_Unimplemented_Feature; |
|
864 } |
|
865 } |
|
866 |
|
867 |
|
868 #endif /* !FT_CONFIG_OPTION_GUESSING_EMBEDDED_RFORK */ |
|
869 |
|
870 |
|
871 /* END */ |
|