source: libcaca/trunk/cucul/file.c @ 2144

Last change on this file since 2144 was 2144, checked in by Sam Hocevar, 12 years ago
  • Disable file operations in kernel mode.
  • Implement strchr() in kernel.c.
  • Check for snprintf() at configure time.
File size: 4.6 KB
Line 
1/*
2 *  libcucul      Canvas for ultrafast compositing of Unicode letters
3 *  Copyright (c) 2006-2007 Sam Hocevar <sam@zoy.org>
4 *                All Rights Reserved
5 *
6 *  $Id$
7 *
8 *  This library is free software. It comes without any warranty, to
9 *  the extent permitted by applicable law. You can redistribute it
10 *  and/or modify it under the terms of the Do What The Fuck You Want
11 *  To Public License, Version 2, as published by Sam Hocevar. See
12 *  http://sam.zoy.org/wtfpl/COPYING for more details.
13 */
14
15/*
16 *  This file contains functions for compressed file I/O.
17 */
18
19#include "config.h"
20#include "common.h"
21
22#if !defined __KERNEL__
23#   include <stdio.h>
24#   include <stdlib.h>
25#   include <string.h>
26#   if defined HAVE_ZLIB_H
27#       include <zlib.h>
28#       define READSIZE  128 /* Read buffer size */
29#       define WRITESIZE 128 /* Inflate buffer size */
30#   endif
31#endif
32
33#include "cucul.h"
34#include "cucul_internals.h"
35
36#if !defined __KERNEL__ && defined HAVE_ZLIB_H
37static int zipread(cucul_file_t *, void *, unsigned int);
38#endif
39
40#if !defined __KERNEL__
41struct cucul_file
42{
43#   if defined HAVE_ZLIB_H
44    unsigned char read_buffer[READSIZE];
45    z_stream stream;
46    gzFile gz;
47    int eof, zip;
48#   endif
49    FILE *f;
50};
51#endif
52
53cucul_file_t *_cucul_file_open(char const *path, const char *mode)
54{
55#if defined __KERNEL__
56    return NULL;
57#else
58    cucul_file_t *fp = malloc(sizeof(*fp));
59
60#   if defined HAVE_ZLIB_H
61    uint8_t buf[4];
62    unsigned int skip_size = 0;
63
64    fp->gz = gzopen(path, "rb");
65    if(!fp->gz)
66    {
67        free(fp);
68        return NULL;
69    }
70
71    fp->eof = 0;
72    fp->zip = 0;
73
74    /* Parse ZIP file and go to start of first file */
75    gzread(fp->gz, buf, 4);
76    if(memcmp(buf, "PK\3\4", 4))
77    {
78        gzseek(fp->gz, 0, SEEK_SET);
79        return fp;
80    }
81
82    fp->zip = 1;
83
84    gzseek(fp->gz, 22, SEEK_CUR);
85
86    gzread(fp->gz, buf, 2); /* Filename size */
87    skip_size += (uint16_t)buf[0] | ((uint16_t)buf[1] << 8);
88    gzread(fp->gz, buf, 2); /* Extra field size */
89    skip_size += (uint16_t)buf[0] | ((uint16_t)buf[1] << 8);
90
91    gzseek(fp->gz, skip_size, SEEK_CUR);
92
93    /* Initialise inflate stream */
94    fp->stream.total_out = 0;
95    fp->stream.zalloc = NULL;
96    fp->stream.zfree = NULL;
97    fp->stream.opaque = NULL;
98    fp->stream.next_in = NULL;
99    fp->stream.avail_in = 0;
100
101    if(inflateInit2(&fp->stream, -MAX_WBITS))
102    {
103        free(fp);
104        gzclose(fp->gz);
105        return NULL;
106    }
107#   else
108    fp->f = fopen(path, mode);
109
110    if(!fp->f)
111    {
112        free(fp);
113        return NULL;
114    }
115#   endif
116
117    return fp;
118#endif
119}
120
121int _cucul_file_close(cucul_file_t *fp)
122{
123#if defined __KERNEL__
124    return 0;
125#elif defined HAVE_ZLIB_H
126    gzFile gz = fp->gz;
127    if(fp->zip)
128        inflateEnd(&fp->stream);
129    free(fp);
130    return gzclose(gz);
131#else
132    FILE *f = fp->f;
133    free(fp);
134    return fclose(f);
135#endif
136}
137
138int _cucul_file_eof(cucul_file_t *fp)
139{
140#if defined __KERNEL__
141    return 1;
142#elif defined HAVE_ZLIB_H
143    return fp->zip ? fp->eof : gzeof(fp->gz);
144#else
145    return feof(fp->f);
146#endif
147}
148
149char *_cucul_file_gets(char *s, int size, cucul_file_t *fp)
150{
151#if defined __KERNEL__
152    return NULL;
153#elif defined HAVE_ZLIB_H
154    if(fp->zip)
155    {
156        int i;
157
158        for(i = 0; i < size; i++)
159        {
160            int ret = zipread(fp, s + i, 1);
161
162            if(ret < 0)
163                return NULL;
164
165            if(ret == 0 || s[i] == '\n')
166            {
167                if(i + 1 < size)
168                    s[i + 1] = '\0';
169                return s;
170            }
171        }
172
173        return s;
174    }
175
176    return gzgets(fp->gz, s, size);
177#else
178    return fgets(s, size, fp->f);
179#endif
180}
181
182#if !defined __KERNEL__ && defined HAVE_ZLIB_H
183static int zipread(cucul_file_t *fp, void *buf, unsigned int len)
184{
185    unsigned int total_read = 0;
186
187    if(len == 0)
188        return 0;
189
190    fp->stream.next_out = buf;
191    fp->stream.avail_out = len;
192
193    while(fp->stream.avail_out > 0)
194    {
195        unsigned int tmp;
196        int ret = 0;
197
198        if(fp->stream.avail_in == 0 && !gzeof(fp->gz))
199        {
200            int bytes_read;
201
202            bytes_read = gzread(fp->gz, fp->read_buffer, READSIZE);
203            if(bytes_read < 0)
204                return -1;
205
206            fp->stream.next_in = fp->read_buffer;
207            fp->stream.avail_in = bytes_read;
208        }
209
210        tmp = fp->stream.total_out;
211        ret = inflate(&fp->stream, Z_SYNC_FLUSH);
212        total_read += fp->stream.total_out - tmp;
213
214        if(ret == Z_STREAM_END)
215        {
216            fp->eof = 1;
217            return total_read;
218        }
219
220        if(ret != Z_OK)
221            return ret;
222    }
223
224    return total_read;
225}
226#endif
227
Note: See TracBrowser for help on using the repository browser.