|
- /*
- * TOIlet The Other Implementation’s letters
- * Copyright (c) 2006 Sam Hocevar <sam@zoy.org>
- * All Rights Reserved
- *
- * $Id$
- *
- * This program is free software. It comes without any warranty, to
- * the extent permitted by applicable law. You can redistribute it
- * and/or modify it under the terms of the Do What The Fuck You Want
- * To Public License, Version 2, as published by Sam Hocevar. See
- * http://sam.zoy.org/wtfpl/COPYING for more details.
- */
-
- /*
- * This file contains functions for compressed file I/O.
- */
-
- #include "config.h"
-
- #include <stdio.h>
- #include <stdlib.h>
- #include <stdint.h>
- #include <string.h>
-
- #if defined HAVE_ZLIB_H
- # include <zlib.h>
- # define READSIZE 128 /* Read buffer size */
- # define WRITESIZE 128 /* Inflate buffer size */
- #endif
-
- #include "io.h"
-
- #if defined HAVE_ZLIB_H
- static int zipread(TOIFILE *, void *, unsigned int);
- #endif
-
- struct toifile
- {
- #if defined HAVE_ZLIB_H
- unsigned char read_buffer[READSIZE];
- z_stream stream;
- gzFile gz;
- int eof, zip;
- #endif
- FILE *f;
- };
-
- TOIFILE *toiopen(char const *path, const char *mode)
- {
- TOIFILE *toif = malloc(sizeof(*toif));
-
- #if defined HAVE_ZLIB_H
- uint8_t buf[4];
- unsigned int skip_size = 0;
-
- toif->gz = gzopen(path, "rb");
- if(!toif->gz)
- {
- free(toif);
- return NULL;
- }
-
- toif->eof = 0;
- toif->zip = 0;
-
- /* Parse ZIP file and go to start of first file */
- gzread(toif->gz, buf, 4);
- if(memcmp(buf, "PK\3\4", 4))
- {
- gzseek(toif->gz, 0, SEEK_SET);
- return toif;
- }
-
- toif->zip = 1;
-
- gzseek(toif->gz, 22, SEEK_CUR);
-
- gzread(toif->gz, buf, 2); /* Filename size */
- skip_size += (uint16_t)buf[0] | ((uint16_t)buf[1] << 8);
- gzread(toif->gz, buf, 2); /* Extra field size */
- skip_size += (uint16_t)buf[0] | ((uint16_t)buf[1] << 8);
-
- gzseek(toif->gz, skip_size, SEEK_CUR);
-
- /* Initialise inflate stream */
- toif->stream.total_out = 0;
- toif->stream.zalloc = NULL;
- toif->stream.zfree = NULL;
- toif->stream.opaque = NULL;
- toif->stream.next_in = NULL;
- toif->stream.avail_in = 0;
-
- if(inflateInit2(&toif->stream, -MAX_WBITS))
- {
- free(toif);
- gzclose(toif->gz);
- return NULL;
- }
- #else
- toif->f = fopen(path, mode);
-
- if(!toif->f)
- {
- free(toif);
- return NULL;
- }
- #endif
-
- return toif;
- }
-
- int toiclose(TOIFILE *toif)
- {
- #if defined HAVE_ZLIB_H
- gzFile gz = toif->gz;
- if(toif->zip)
- inflateEnd(&toif->stream);
- free(toif);
- return gzclose(gz);
- #else
- FILE *f = toif->f;
- free(toif);
- return fclose(f);
- #endif
- }
-
- int toieof(TOIFILE *toif)
- {
- #if defined HAVE_ZLIB_H
- return toif->zip ? toif->eof : gzeof(toif->gz);
- #else
- return feof(toif->f);
- #endif
- }
-
- char *toigets(char *s, int size, TOIFILE *toif)
- {
- #if defined HAVE_ZLIB_H
- if(toif->zip)
- {
- int i;
-
- for(i = 0; i < size; i++)
- {
- int ret = zipread(toif, s + i, 1);
-
- if(ret < 0)
- return NULL;
-
- if(ret == 0 || s[i] == '\n')
- {
- if(i + 1 < size)
- s[i + 1] = '\0';
- return s;
- }
- }
-
- return s;
- }
-
- return gzgets(toif->gz, s, size);
- #else
- return fgets(s, size, toif->f);
- #endif
- }
-
- #if defined HAVE_ZLIB_H
- static int zipread(TOIFILE *toif, void *buf, unsigned int len)
- {
- unsigned int total_read = 0;
-
- if(len == 0)
- return 0;
-
- toif->stream.next_out = buf;
- toif->stream.avail_out = len;
-
- while(toif->stream.avail_out > 0)
- {
- unsigned int tmp;
- int ret = 0;
-
- if(toif->stream.avail_in == 0 && !gzeof(toif->gz))
- {
- int bytes_read;
-
- bytes_read = gzread(toif->gz, toif->read_buffer, READSIZE);
- if(bytes_read < 0)
- return -1;
-
- toif->stream.next_in = toif->read_buffer;
- toif->stream.avail_in = bytes_read;
- }
-
- tmp = toif->stream.total_out;
- ret = inflate(&toif->stream, Z_SYNC_FLUSH);
- total_read += toif->stream.total_out - tmp;
-
- if(ret == Z_STREAM_END)
- {
- toif->eof = 1;
- return total_read;
- }
-
- if(ret != Z_OK)
- return ret;
- }
-
- return total_read;
- }
- #endif
|