1a96d7823Smrg/* Based on src/fontfile/gunzip.c 2a96d7823Smrg written by Mark Eichin <eichin@kitten.gen.ma.us> September 1996. 3a96d7823Smrg intended for inclusion in X11 public releases. */ 4a96d7823Smrg 5a96d7823Smrg/* 66a46240fSmrg * Copyright (c) 2008, Oracle and/or its affiliates. 7a96d7823Smrg * 8a96d7823Smrg * Permission is hereby granted, free of charge, to any person obtaining a 9a96d7823Smrg * copy of this software and associated documentation files (the "Software"), 10a96d7823Smrg * to deal in the Software without restriction, including without limitation 11a96d7823Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 12a96d7823Smrg * and/or sell copies of the Software, and to permit persons to whom the 13a96d7823Smrg * Software is furnished to do so, subject to the following conditions: 14a96d7823Smrg * 15a96d7823Smrg * The above copyright notice and this permission notice (including the next 16a96d7823Smrg * paragraph) shall be included in all copies or substantial portions of the 17a96d7823Smrg * Software. 18a96d7823Smrg * 19a96d7823Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20a96d7823Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21a96d7823Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 22a96d7823Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 23a96d7823Smrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 24a96d7823Smrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 25a96d7823Smrg * DEALINGS IN THE SOFTWARE. 26a96d7823Smrg */ 27a96d7823Smrg 28a96d7823Smrg 29a96d7823Smrg#ifdef HAVE_CONFIG_H 30a96d7823Smrg#include "config.h" 31a96d7823Smrg#endif 32a96d7823Smrg#include "libxfontint.h" 33a96d7823Smrg 34a96d7823Smrg#include <X11/fonts/fontmisc.h> 35a96d7823Smrg#include <X11/fonts/bufio.h> 36a96d7823Smrg#include <bzlib.h> 37a96d7823Smrg 38a96d7823Smrgtypedef struct _xzip_buf { 39a96d7823Smrg bz_stream z; 40a96d7823Smrg int zstat; 41a96d7823Smrg BufChar b[BUFFILESIZE]; 42a96d7823Smrg BufChar b_in[BUFFILESIZE]; 43a96d7823Smrg BufFilePtr f; 44a96d7823Smrg} xzip_buf; 45a96d7823Smrg 46a96d7823Smrgstatic int BufBzip2FileClose ( BufFilePtr f, int flag ); 47a96d7823Smrgstatic int BufBzip2FileFill ( BufFilePtr f ); 48a96d7823Smrgstatic int BufBzip2FileSkip ( BufFilePtr f, int c ); 49a96d7823Smrg 50a96d7823Smrg_X_HIDDEN BufFilePtr 51a96d7823SmrgBufFilePushBZIP2 (BufFilePtr f) 52a96d7823Smrg{ 53a96d7823Smrg xzip_buf *x; 54a96d7823Smrg 55a96d7823Smrg x = malloc (sizeof (xzip_buf)); 56a96d7823Smrg if (!x) return NULL; 57a96d7823Smrg 58a96d7823Smrg bzero(&(x->z), sizeof(bz_stream)); 59a96d7823Smrg x->f = f; 60a96d7823Smrg 61a96d7823Smrg x->zstat = BZ2_bzDecompressInit(&(x->z), 62a96d7823Smrg 0, /* verbosity: 0 silent, 4 max */ 63a96d7823Smrg 0); /* 0: go faster, 1: use less memory */ 64a96d7823Smrg if (x->zstat != BZ_OK) { 65a96d7823Smrg free(x); 66a96d7823Smrg return NULL; 67a96d7823Smrg } 68a96d7823Smrg 69a96d7823Smrg /* now that the history buffer is allocated, we provide the data buffer */ 70a96d7823Smrg x->z.next_out = (char *) x->b; 71a96d7823Smrg x->z.avail_out = BUFFILESIZE; 72a96d7823Smrg x->z.next_in = (char *) x->b_in; 73a96d7823Smrg x->z.avail_in = 0; 74a96d7823Smrg 75a96d7823Smrg return BufFileCreate((char *)x, 76a96d7823Smrg BufBzip2FileFill, 77a96d7823Smrg NULL, 78a96d7823Smrg BufBzip2FileSkip, 79a96d7823Smrg BufBzip2FileClose); 80a96d7823Smrg} 81a96d7823Smrg 82a96d7823Smrgstatic int 83a96d7823SmrgBufBzip2FileClose(BufFilePtr f, int flag) 84a96d7823Smrg{ 85a96d7823Smrg xzip_buf *x = (xzip_buf *)f->private; 86a96d7823Smrg BZ2_bzDecompressEnd (&(x->z)); 87a96d7823Smrg BufFileClose (x->f, flag); 88a96d7823Smrg free (x); 89a96d7823Smrg return 1; 90a96d7823Smrg} 91a96d7823Smrg 92a96d7823Smrg/* here's the real work. 93a96d7823Smrg -- we need to put stuff in f.buffer, update f.left and f.bufp, 94a96d7823Smrg then return the first byte (or BUFFILEEOF). 95a96d7823Smrg -- to do this, we need to get stuff into avail_in, and next_in, 96a96d7823Smrg and call BZ2_bzDecompress appropriately. 97a96d7823Smrg -- we may also need to add CRC maintenance - if BZ2_bzDecompress tells us 98a96d7823Smrg BZ_STREAM_END, we then have 4bytes CRC and 4bytes length... 99a96d7823Smrg*/ 100a96d7823Smrgstatic int 101a96d7823SmrgBufBzip2FileFill (BufFilePtr f) 102a96d7823Smrg{ 103a96d7823Smrg xzip_buf *x = (xzip_buf *)f->private; 104a96d7823Smrg 105a96d7823Smrg /* we only get called when left == 0... */ 106a96d7823Smrg /* but just in case, deal */ 107a96d7823Smrg if (f->left >= 0) { 108a96d7823Smrg f->left--; 109a96d7823Smrg return *(f->bufp++); 110a96d7823Smrg } 111a96d7823Smrg /* did we run out last time? */ 112a96d7823Smrg switch (x->zstat) { 113a96d7823Smrg case BZ_OK: 114a96d7823Smrg break; 115a96d7823Smrg case BZ_STREAM_END: 116a96d7823Smrg case BZ_DATA_ERROR: 117a96d7823Smrg case BZ_DATA_ERROR_MAGIC: 118a96d7823Smrg f->left = 0; 119a96d7823Smrg return BUFFILEEOF; 120a96d7823Smrg default: 121a96d7823Smrg return BUFFILEEOF; 122a96d7823Smrg } 123a96d7823Smrg /* now we work to consume what we can */ 124a96d7823Smrg /* let libbz2 know what we can handle */ 125a96d7823Smrg x->z.next_out = (char *) x->b; 126a96d7823Smrg x->z.avail_out = BUFFILESIZE; 127a96d7823Smrg 128a96d7823Smrg /* and try to consume all of it */ 129a96d7823Smrg while (x->z.avail_out > 0) { 130a96d7823Smrg /* if we don't have anything to work from... */ 131a96d7823Smrg if (x->z.avail_in == 0) { 132a96d7823Smrg /* ... fill the z buf from underlying file */ 133a96d7823Smrg int i, c; 134a96d7823Smrg for (i = 0; i < sizeof(x->b_in); i++) { 135a96d7823Smrg c = BufFileGet(x->f); 136a96d7823Smrg if (c == BUFFILEEOF) break; 137a96d7823Smrg x->b_in[i] = c; 138a96d7823Smrg } 139a96d7823Smrg x->z.avail_in += i; 140a96d7823Smrg x->z.next_in = (char *) x->b_in; 141a96d7823Smrg } 142a96d7823Smrg /* so now we have some output space and some input data */ 143a96d7823Smrg x->zstat = BZ2_bzDecompress(&(x->z)); 144a96d7823Smrg /* the inflation output happens in the f buffer directly... */ 145a96d7823Smrg if (x->zstat == BZ_STREAM_END) { 146a96d7823Smrg /* deal with EOF, crc */ 147a96d7823Smrg break; 148a96d7823Smrg } 149a96d7823Smrg if (x->zstat != BZ_OK) { 150a96d7823Smrg break; 151a96d7823Smrg } 152a96d7823Smrg } 153a96d7823Smrg f->bufp = x->b; 154a96d7823Smrg f->left = BUFFILESIZE - x->z.avail_out; 155a96d7823Smrg 156a96d7823Smrg if (f->left >= 0) { 157a96d7823Smrg f->left--; 158a96d7823Smrg return *(f->bufp++); 159a96d7823Smrg } else { 160a96d7823Smrg return BUFFILEEOF; 161a96d7823Smrg } 162a96d7823Smrg} 163a96d7823Smrg 164a96d7823Smrg/* there should be a BufCommonSkip... */ 165a96d7823Smrgstatic int 166a96d7823SmrgBufBzip2FileSkip (BufFilePtr f, int c) 167a96d7823Smrg{ 168a96d7823Smrg /* BufFileRawSkip returns the count unchanged. 169a96d7823Smrg BufCompressedSkip returns 0. 170a96d7823Smrg That means it probably never gets called... */ 171a96d7823Smrg int retval = c; 172a96d7823Smrg while(c--) { 173a96d7823Smrg int get = BufFileGet(f); 174a96d7823Smrg if (get == BUFFILEEOF) return get; 175a96d7823Smrg } 176a96d7823Smrg return retval; 177a96d7823Smrg} 178