ReactOS  0.4.15-dev-489-g75a0787
ftbzip2.c
Go to the documentation of this file.
1 /***************************************************************************/
2 /* */
3 /* ftbzip2.c */
4 /* */
5 /* FreeType support for .bz2 compressed files. */
6 /* */
7 /* This optional component relies on libbz2. It should mainly be used to */
8 /* parse compressed PCF fonts, as found with many X11 server */
9 /* distributions. */
10 /* */
11 /* Copyright 2010-2018 by */
12 /* Joel Klinghed. */
13 /* */
14 /* based on `src/gzip/ftgzip.c' */
15 /* */
16 /* This file is part of the FreeType project, and may only be used, */
17 /* modified, and distributed under the terms of the FreeType project */
18 /* license, LICENSE.TXT. By continuing to use, modify, or distribute */
19 /* this file you indicate that you have read the license and */
20 /* understand and accept it fully. */
21 /* */
22 /***************************************************************************/
23 
24 
25 #include <ft2build.h>
26 #include FT_INTERNAL_MEMORY_H
27 #include FT_INTERNAL_STREAM_H
28 #include FT_INTERNAL_DEBUG_H
29 #include FT_BZIP2_H
30 #include FT_CONFIG_STANDARD_LIBRARY_H
31 
32 
33 #include FT_MODULE_ERRORS_H
34 
35 #undef FTERRORS_H_
36 
37 #undef FT_ERR_PREFIX
38 #define FT_ERR_PREFIX Bzip2_Err_
39 #define FT_ERR_BASE FT_Mod_Err_Bzip2
40 
41 #include FT_ERRORS_H
42 
43 
44 #ifdef FT_CONFIG_OPTION_USE_BZIP2
45 
46 #ifdef FT_CONFIG_OPTION_PIC
47 #error "bzip2 code does not support PIC yet"
48 #endif
49 
50 #define BZ_NO_STDIO /* Do not need FILE */
51 #include <bzlib.h>
52 
53 
54 /***************************************************************************/
55 /***************************************************************************/
56 /***** *****/
57 /***** B Z I P 2 M E M O R Y M A N A G E M E N T *****/
58 /***** *****/
59 /***************************************************************************/
60 /***************************************************************************/
61 
62  /* it is better to use FreeType memory routines instead of raw
63  'malloc/free' */
64 
65  typedef void *(* alloc_func)(void*, int, int);
66  typedef void (* free_func)(void*, void*);
67 
68  static void*
69  ft_bzip2_alloc( FT_Memory memory,
70  int items,
71  int size )
72  {
75  FT_Pointer p = NULL;
76 
77 
78  (void)FT_ALLOC( p, sz );
79  return p;
80  }
81 
82 
83  static void
84  ft_bzip2_free( FT_Memory memory,
85  void* address )
86  {
88  }
89 
90 
91 /***************************************************************************/
92 /***************************************************************************/
93 /***** *****/
94 /***** B Z I P 2 F I L E D E S C R I P T O R *****/
95 /***** *****/
96 /***************************************************************************/
97 /***************************************************************************/
98 
99 #define FT_BZIP2_BUFFER_SIZE 4096
100 
101  typedef struct FT_BZip2FileRec_
102  {
103  FT_Stream source; /* parent/source stream */
104  FT_Stream stream; /* embedding stream */
105  FT_Memory memory; /* memory allocator */
106  bz_stream bzstream; /* bzlib input stream */
107 
108  FT_Byte input[FT_BZIP2_BUFFER_SIZE]; /* input read buffer */
109 
110  FT_Byte buffer[FT_BZIP2_BUFFER_SIZE]; /* output buffer */
111  FT_ULong pos; /* position in output */
112  FT_Byte* cursor;
113  FT_Byte* limit;
114 
115  } FT_BZip2FileRec, *FT_BZip2File;
116 
117 
118  /* check and skip .bz2 header - we don't support `transparent' compression */
119  static FT_Error
120  ft_bzip2_check_header( FT_Stream stream )
121  {
123  FT_Byte head[4];
124 
125 
126  if ( FT_STREAM_SEEK( 0 ) ||
127  FT_STREAM_READ( head, 4 ) )
128  goto Exit;
129 
130  /* head[0] && head[1] are the magic numbers; */
131  /* head[2] is the version, and head[3] the blocksize */
132  if ( head[0] != 0x42 ||
133  head[1] != 0x5A ||
134  head[2] != 0x68 ) /* only support bzip2 (huffman) */
135  {
136  error = FT_THROW( Invalid_File_Format );
137  goto Exit;
138  }
139 
140  Exit:
141  return error;
142  }
143 
144 
145  static FT_Error
146  ft_bzip2_file_init( FT_BZip2File zip,
148  FT_Stream source )
149  {
150  bz_stream* bzstream = &zip->bzstream;
152 
153 
154  zip->stream = stream;
155  zip->source = source;
156  zip->memory = stream->memory;
157 
158  zip->limit = zip->buffer + FT_BZIP2_BUFFER_SIZE;
159  zip->cursor = zip->limit;
160  zip->pos = 0;
161 
162  /* check .bz2 header */
163  {
164  stream = source;
165 
166  error = ft_bzip2_check_header( stream );
167  if ( error )
168  goto Exit;
169 
170  if ( FT_STREAM_SEEK( 0 ) )
171  goto Exit;
172  }
173 
174  /* initialize bzlib */
175  bzstream->bzalloc = (alloc_func)ft_bzip2_alloc;
176  bzstream->bzfree = (free_func) ft_bzip2_free;
177  bzstream->opaque = zip->memory;
178 
179  bzstream->avail_in = 0;
180  bzstream->next_in = (char*)zip->buffer;
181 
182  if ( BZ2_bzDecompressInit( bzstream, 0, 0 ) != BZ_OK ||
183  !bzstream->next_in )
184  error = FT_THROW( Invalid_File_Format );
185 
186  Exit:
187  return error;
188  }
189 
190 
191  static void
192  ft_bzip2_file_done( FT_BZip2File zip )
193  {
194  bz_stream* bzstream = &zip->bzstream;
195 
196 
197  BZ2_bzDecompressEnd( bzstream );
198 
199  /* clear the rest */
200  bzstream->bzalloc = NULL;
201  bzstream->bzfree = NULL;
202  bzstream->opaque = NULL;
203  bzstream->next_in = NULL;
204  bzstream->next_out = NULL;
205  bzstream->avail_in = 0;
206  bzstream->avail_out = 0;
207 
208  zip->memory = NULL;
209  zip->source = NULL;
210  zip->stream = NULL;
211  }
212 
213 
214  static FT_Error
215  ft_bzip2_file_reset( FT_BZip2File zip )
216  {
217  FT_Stream stream = zip->source;
218  FT_Error error;
219 
220 
221  if ( !FT_STREAM_SEEK( 0 ) )
222  {
223  bz_stream* bzstream = &zip->bzstream;
224 
225 
226  BZ2_bzDecompressEnd( bzstream );
227 
228  bzstream->avail_in = 0;
229  bzstream->next_in = (char*)zip->input;
230  bzstream->avail_out = 0;
231  bzstream->next_out = (char*)zip->buffer;
232 
233  zip->limit = zip->buffer + FT_BZIP2_BUFFER_SIZE;
234  zip->cursor = zip->limit;
235  zip->pos = 0;
236 
237  BZ2_bzDecompressInit( bzstream, 0, 0 );
238  }
239 
240  return error;
241  }
242 
243 
244  static FT_Error
245  ft_bzip2_file_fill_input( FT_BZip2File zip )
246  {
247  bz_stream* bzstream = &zip->bzstream;
248  FT_Stream stream = zip->source;
249  FT_ULong size;
250 
251 
252  if ( stream->read )
253  {
254  size = stream->read( stream, stream->pos, zip->input,
255  FT_BZIP2_BUFFER_SIZE );
256  if ( size == 0 )
257  {
258  zip->limit = zip->cursor;
259  return FT_THROW( Invalid_Stream_Operation );
260  }
261  }
262  else
263  {
264  size = stream->size - stream->pos;
265  if ( size > FT_BZIP2_BUFFER_SIZE )
266  size = FT_BZIP2_BUFFER_SIZE;
267 
268  if ( size == 0 )
269  {
270  zip->limit = zip->cursor;
271  return FT_THROW( Invalid_Stream_Operation );
272  }
273 
274  FT_MEM_COPY( zip->input, stream->base + stream->pos, size );
275  }
276  stream->pos += size;
277 
278  bzstream->next_in = (char*)zip->input;
279  bzstream->avail_in = size;
280 
281  return FT_Err_Ok;
282  }
283 
284 
285  static FT_Error
286  ft_bzip2_file_fill_output( FT_BZip2File zip )
287  {
288  bz_stream* bzstream = &zip->bzstream;
290 
291 
292  zip->cursor = zip->buffer;
293  bzstream->next_out = (char*)zip->cursor;
294  bzstream->avail_out = FT_BZIP2_BUFFER_SIZE;
295 
296  while ( bzstream->avail_out > 0 )
297  {
298  int err;
299 
300 
301  if ( bzstream->avail_in == 0 )
302  {
303  error = ft_bzip2_file_fill_input( zip );
304  if ( error )
305  break;
306  }
307 
308  err = BZ2_bzDecompress( bzstream );
309 
310  if ( err == BZ_STREAM_END )
311  {
312  zip->limit = (FT_Byte*)bzstream->next_out;
313  if ( zip->limit == zip->cursor )
314  error = FT_THROW( Invalid_Stream_Operation );
315  break;
316  }
317  else if ( err != BZ_OK )
318  {
319  zip->limit = zip->cursor;
320  error = FT_THROW( Invalid_Stream_Operation );
321  break;
322  }
323  }
324 
325  return error;
326  }
327 
328 
329  /* fill output buffer; `count' must be <= FT_BZIP2_BUFFER_SIZE */
330  static FT_Error
331  ft_bzip2_file_skip_output( FT_BZip2File zip,
332  FT_ULong count )
333  {
335  FT_ULong delta;
336 
337 
338  for (;;)
339  {
340  delta = (FT_ULong)( zip->limit - zip->cursor );
341  if ( delta >= count )
342  delta = count;
343 
344  zip->cursor += delta;
345  zip->pos += delta;
346 
347  count -= delta;
348  if ( count == 0 )
349  break;
350 
351  error = ft_bzip2_file_fill_output( zip );
352  if ( error )
353  break;
354  }
355 
356  return error;
357  }
358 
359 
360  static FT_ULong
361  ft_bzip2_file_io( FT_BZip2File zip,
362  FT_ULong pos,
363  FT_Byte* buffer,
364  FT_ULong count )
365  {
366  FT_ULong result = 0;
367  FT_Error error;
368 
369 
370  /* Reset inflate stream if we're seeking backwards. */
371  /* Yes, that is not too efficient, but it saves memory :-) */
372  if ( pos < zip->pos )
373  {
374  error = ft_bzip2_file_reset( zip );
375  if ( error )
376  goto Exit;
377  }
378 
379  /* skip unwanted bytes */
380  if ( pos > zip->pos )
381  {
382  error = ft_bzip2_file_skip_output( zip, (FT_ULong)( pos - zip->pos ) );
383  if ( error )
384  goto Exit;
385  }
386 
387  if ( count == 0 )
388  goto Exit;
389 
390  /* now read the data */
391  for (;;)
392  {
393  FT_ULong delta;
394 
395 
396  delta = (FT_ULong)( zip->limit - zip->cursor );
397  if ( delta >= count )
398  delta = count;
399 
400  FT_MEM_COPY( buffer, zip->cursor, delta );
401  buffer += delta;
402  result += delta;
403  zip->cursor += delta;
404  zip->pos += delta;
405 
406  count -= delta;
407  if ( count == 0 )
408  break;
409 
410  error = ft_bzip2_file_fill_output( zip );
411  if ( error )
412  break;
413  }
414 
415  Exit:
416  return result;
417  }
418 
419 
420 /***************************************************************************/
421 /***************************************************************************/
422 /***** *****/
423 /***** B Z E M B E D D I N G S T R E A M *****/
424 /***** *****/
425 /***************************************************************************/
426 /***************************************************************************/
427 
428  static void
429  ft_bzip2_stream_close( FT_Stream stream )
430  {
431  FT_BZip2File zip = (FT_BZip2File)stream->descriptor.pointer;
432  FT_Memory memory = stream->memory;
433 
434 
435  if ( zip )
436  {
437  /* finalize bzip file descriptor */
438  ft_bzip2_file_done( zip );
439 
440  FT_FREE( zip );
441 
442  stream->descriptor.pointer = NULL;
443  }
444  }
445 
446 
447  static unsigned long
448  ft_bzip2_stream_io( FT_Stream stream,
449  unsigned long offset,
450  unsigned char* buffer,
451  unsigned long count )
452  {
453  FT_BZip2File zip = (FT_BZip2File)stream->descriptor.pointer;
454 
455 
456  return ft_bzip2_file_io( zip, offset, buffer, count );
457  }
458 
459 
462  FT_Stream source )
463  {
464  FT_Error error;
466  FT_BZip2File zip = NULL;
467 
468 
469  if ( !stream || !source )
470  {
471  error = FT_THROW( Invalid_Stream_Handle );
472  goto Exit;
473  }
474 
475  memory = source->memory;
476 
477  /*
478  * check the header right now; this prevents allocating unnecessary
479  * objects when we don't need them
480  */
481  error = ft_bzip2_check_header( source );
482  if ( error )
483  goto Exit;
484 
485  FT_ZERO( stream );
486  stream->memory = memory;
487 
488  if ( !FT_QNEW( zip ) )
489  {
490  error = ft_bzip2_file_init( zip, stream, source );
491  if ( error )
492  {
493  FT_FREE( zip );
494  goto Exit;
495  }
496 
497  stream->descriptor.pointer = zip;
498  }
499 
500  stream->size = 0x7FFFFFFFL; /* don't know the real size! */
501  stream->pos = 0;
502  stream->base = 0;
503  stream->read = ft_bzip2_stream_io;
504  stream->close = ft_bzip2_stream_close;
505 
506  Exit:
507  return error;
508  }
509 
510 #else /* !FT_CONFIG_OPTION_USE_BZIP2 */
511 
514  FT_Stream source )
515  {
516  FT_UNUSED( stream );
517  FT_UNUSED( source );
518 
519  return FT_THROW( Unimplemented_Feature );
520  }
521 
522 #endif /* !FT_CONFIG_OPTION_USE_BZIP2 */
523 
524 
525 /* END */
#define FT_ALLOC(ptr, size)
Definition: ftmemory.h:303
int FT_Error
Definition: fttypes.h:300
unsigned long FT_ULong
Definition: fttypes.h:253
struct png_info_def **typedef void(__cdecl typeof(png_destroy_read_struct))(struct png_struct_def **
Definition: typeof.h:49
#define error(str)
Definition: mkdosfs.c:1605
struct outqueuenode * head
Definition: adnsresfilter.c:66
GLuint GLuint GLsizei count
Definition: gl.h:1545
GLintptr offset
Definition: glext.h:5920
GLuint buffer
Definition: glext.h:5915
return FT_Err_Ok
Definition: ftbbox.c:511
static char memory[1024 *256]
Definition: process.c:116
#define FT_QNEW(ptr)
Definition: ftmemory.h:339
GLint limit
Definition: glext.h:10326
while(1)
Definition: macro.lex.yy.c:740
unsigned char FT_Byte
Definition: fttypes.h:154
#define FT_THROW(e)
Definition: ftdebug.h:213
smooth NULL
Definition: ftsmooth.c:416
#define FT_FREE(ptr)
Definition: ftmemory.h:329
FT_Stream_OpenBzip2(FT_Stream stream, FT_Stream source)
Definition: ftbzip2.c:513
GLsizeiptr size
Definition: glext.h:5919
#define FT_ZERO(p)
Definition: ftmemory.h:237
if(!(yy_init))
Definition: macro.lex.yy.c:714
static void Exit(void)
Definition: sock.c:1331
#define FT_MEM_FREE(ptr)
Definition: ftmemory.h:156
GLuint address
Definition: glext.h:9393
static const WCHAR L[]
Definition: oid.c:1250
unsigned int size
Definition: parse.h:27
Definition: parse.h:22
GLuint GLuint stream
Definition: glext.h:7522
typedefFT_BEGIN_HEADER struct FT_MemoryRec_ * FT_Memory
Definition: ftsystem.h:66
#define err(...)
#define FT_STREAM_SEEK(position)
Definition: ftstream.h:489
ULARGE_INTEGER pos
Definition: request.c:4380
GLenum GLenum GLenum input
Definition: glext.h:9031
const char cursor[]
Definition: icontest.c:13
#define FT_EXPORT_DEF(x)
Definition: ftconfig.h:483
GLsizei GLsizei GLchar * source
Definition: glext.h:6048
#define FT_MEM_COPY(dest, source, count)
Definition: ftmemory.h:228
GLfloat GLfloat p
Definition: glext.h:8902
static TCHAR * items[]
Definition: page1.c:45
GLuint64EXT * result
Definition: glext.h:11304
#define FT_STREAM_READ(buffer, count)
Definition: ftstream.h:497
#define FT_UNUSED(arg)
Definition: ftconfig.h:101
unsigned int(__cdecl typeof(jpeg_read_scanlines))(struct jpeg_decompress_struct *
Definition: typeof.h:31