source: bootcd/isolinux/syslinux-6.03/com32/lib/sys/zfile.c

Last change on this file was e16e8f2, checked in by Edwin Eefting <edwin@datux.nl>, 3 years ago

bootstuff

  • Property mode set to 100644
File size: 4.0 KB
RevLine 
[e16e8f2]1/* ----------------------------------------------------------------------- *
2 *
3 *   Copyright 2003-2008 H. Peter Anvin - All Rights Reserved
4 *
5 *   Permission is hereby granted, free of charge, to any person
6 *   obtaining a copy of this software and associated documentation
7 *   files (the "Software"), to deal in the Software without
8 *   restriction, including without limitation the rights to use,
9 *   copy, modify, merge, publish, distribute, sublicense, and/or
10 *   sell copies of the Software, and to permit persons to whom
11 *   the Software is furnished to do so, subject to the following
12 *   conditions:
13 *
14 *   The above copyright notice and this permission notice shall
15 *   be included in all copies or substantial portions of the Software.
16 *
17 *   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18 *   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
19 *   OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20 *   NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
21 *   HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
22 *   WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
23 *   FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
24 *   OTHER DEALINGS IN THE SOFTWARE.
25 *
26 * ----------------------------------------------------------------------- */
27
28#include <errno.h>
29#include <string.h>
30#include <unistd.h>
31#include <fcntl.h>
32#include <stdlib.h>
33#include <syslinux/zio.h>
34
35#include "file.h"
36#include "zlib.h"
37
38/*
39 * zopen.c
40 *
41 * Open an ordinary file, possibly compressed; if so, insert
42 * an appropriate decompressor.
43 */
44
45int __file_get_block(struct file_info *fp);
46int __file_close(struct file_info *fp);
47
48static ssize_t gzip_file_read(struct file_info *, void *, size_t);
49static int gzip_file_close(struct file_info *);
50
51static const struct input_dev gzip_file_dev = {
52    .dev_magic = __DEV_MAGIC,
53    .flags = __DEV_FILE | __DEV_INPUT,
54    .fileflags = O_RDONLY,
55    .read = gzip_file_read,
56    .close = gzip_file_close,
57    .open = NULL,
58};
59
60static int gzip_file_init(struct file_info *fp)
61{
62    z_streamp zs = calloc(1, sizeof(z_stream));
63
64    if (!zs)
65        return -1;
66
67    fp->i.pvt = zs;
68
69    zs->next_in = (void *)fp->i.datap;
70    zs->avail_in = fp->i.nbytes;
71
72    if (inflateInit2(zs, 15 + 32) != Z_OK) {
73        errno = EIO;
74        return -1;
75    }
76
77    fp->iop = &gzip_file_dev;
78    fp->i.fd.size = -1;         /* Unknown */
79
80    return 0;
81}
82
83static ssize_t gzip_file_read(struct file_info *fp, void *ptr, size_t n)
84{
85    z_streamp zs = fp->i.pvt;
86    int rv;
87    ssize_t bytes;
88    ssize_t nout = 0;
89    unsigned char *p = ptr;
90
91    while (n) {
92        zs->next_out = p;
93        zs->avail_out = n;
94
95        if (!zs->avail_in && fp->i.fd.handle) {
96            if (__file_get_block(fp))
97                return nout ? nout : -1;
98
99            zs->next_in = (void *)fp->i.datap;
100            zs->avail_in = fp->i.nbytes;
101        }
102
103        rv = inflate(zs, Z_SYNC_FLUSH);
104
105        bytes = n - zs->avail_out;
106        nout += bytes;
107        p += bytes;
108        n -= bytes;
109
110        switch (rv) {
111        case Z_DATA_ERROR:
112        case Z_NEED_DICT:
113        case Z_BUF_ERROR:
114        case Z_STREAM_ERROR:
115        default:
116            errno = EIO;
117            return nout ? nout : -1;
118        case Z_MEM_ERROR:
119            errno = ENOMEM;
120            return nout ? nout : -1;
121        case Z_STREAM_END:
122            return nout;
123        case Z_OK:
124            break;
125        }
126    }
127
128    return nout;
129}
130
131static int gzip_file_close(struct file_info *fp)
132{
133    z_streamp zs = fp->i.pvt;
134
135    inflateEnd(zs);
136    free(zs);
137    return __file_close(fp);
138}
139
140int zopen(const char *pathname, int flags, ...)
141{
142    int fd, rv;
143    struct file_info *fp;
144
145    /* We don't actually give a hoot about the creation bits... */
146    fd = open(pathname, flags, 0);
147
148    if (fd < 0)
149        return -1;
150
151    fp = &__file_info[fd];
152
153    /* Need to get the first block into the buffer, but not consumed */
154    if (__file_get_block(fp))
155        goto err;
156
157    if (fp->i.nbytes >= 14 &&
158        (uint8_t) fp->i.buf[0] == 037 &&
159        (uint8_t) fp->i.buf[1] == 0213 &&       /* gzip */
160        fp->i.buf[2] == 8)      /* deflate */
161        rv = gzip_file_init(fp);
162    else
163        rv = 0;                 /* Plain file */
164
165    if (!rv)
166        return fd;
167
168err:
169    close(fd);
170    return -1;
171}
Note: See TracBrowser for help on using the repository browser.