1 /* $MirOS: src/lib/libz/gzfopen.c,v 1.5 2013/08/05 21:27:37 tg Exp $ */
2
3 /*-
4 * Copyright (c) 2006, 2013
5 * Thorsten Glaser <tg@mirbsd.de>
6 *
7 * Licensee is hereby permitted to deal in this work without restric-
8 * tion, including unlimited rights to use, publicly perform, modify,
9 * merge, distribute, sell, give away or sublicence, provided all co-
10 * pyright notices above, these terms and the disclaimer are retained
11 * in all redistributions or reproduced in accompanying documentation
12 * or other materials provided with binary redistributions.
13 *
14 * All advertising materials mentioning features or use of this soft-
15 * ware must display the following acknowledgement:
16 * This product includes material provided by Thorsten Glaser.
17 *
18 * Licensor offers the work "AS IS" and WITHOUT WARRANTY of any kind,
19 * express, or implied, to the maximum extent permitted by applicable
20 * law, without malicious intent or gross negligence; in no event may
21 * licensor, an author or contributor be held liable for any indirect
22 * or other damage, or direct damage except proven a consequence of a
23 * direct error of said person and intended use of this work, loss or
24 * other issues arising in any way out of its use, even if advised of
25 * the possibility of such damage or existence of a nontrivial bug.
26 */
27
28 #include <errno.h>
29 #include <stdbool.h>
30 #include <stdio.h>
31 #include "zutil.h"
32 #include "gzguts.h"
33
34 __RCSID("$MirOS: src/lib/libz/gzfopen.c,v 1.5 2013/08/05 21:27:37 tg Exp $");
35
36 static FILE *zf_open(const char *, const char *, int);
37 static int zf_read(void *, char *, int);
38 static int zf_write(void *, const char *, int);
39 static fpos_t zf_seek(void *, fpos_t, int);
40 static int zf_close(void *);
41
42 FILE *
gzfopen(const char * path,const char * mode)43 gzfopen(const char *path, const char *mode)
44 {
45 if (path == NULL) {
46 errno = EINVAL;
47 return (NULL);
48 }
49
50 return (zf_open(path, mode, -1));
51 }
52
53 FILE *
gzfdopen(int fd,const char * mode)54 gzfdopen(int fd, const char *mode)
55 {
56 return (zf_open(NULL, mode, fd));
57 }
58
59 FILE *
zf_open(const char * path,const char * mode,int fd)60 zf_open(const char *path, const char *mode, int fd)
61 {
62 gzFile s;
63 FILE *f;
64
65 if (mode == NULL) {
66 errno = EINVAL;
67 return (NULL);
68 }
69
70 s = (path == NULL) ? gzdopen(fd, mode) : gzopen(path, mode);
71 if (s == (gzFile)Z_NULL) {
72 errno = ENXIO;
73 return (NULL);
74 }
75
76 if ((f = funopen((void *)s,
77 ((gz_statep)s)->mode == GZ_READ ? zf_read : NULL,
78 ((gz_statep)s)->mode == GZ_READ ? NULL : zf_write,
79 zf_seek, zf_close)) == NULL) {
80 int e = errno;
81
82 gzclose(s);
83 errno = e;
84 return (NULL);
85 }
86
87 if (path == NULL)
88 f->_file = fd;
89
90 return (f);
91 }
92
93 static int
zf_read(void * s,char * buf,int len)94 zf_read(void *s, char *buf, int len)
95 {
96 int rv;
97
98 rv = gzread((gzFile)s, buf, len);
99
100 if (rv == Z_STREAM_ERROR) {
101 errno = EBADF;
102 return (-1);
103 }
104
105 if (rv == -1)
106 if (((gz_statep)s)->err != Z_ERRNO)
107 errno = EIO;
108
109 return (rv);
110 }
111
112 static int
zf_write(void * s,const char * buf,int len)113 zf_write(void *s, const char *buf, int len)
114 {
115 int rv;
116
117 rv = gzwrite((gzFile)s, buf, len);
118
119 if (rv == Z_STREAM_ERROR) {
120 errno = EBADF;
121 return (-1);
122 }
123
124 if (rv == -1)
125 if (((gz_statep)s)->err != Z_ERRNO)
126 errno = EIO;
127
128 return (rv);
129 }
130
131 static fpos_t
zf_seek(void * s,fpos_t pos,int how)132 zf_seek(void *s, fpos_t pos, int how)
133 {
134 z_off_t rv;
135
136 if (s == NULL) {
137 errno = EBADF;
138 return (-1);
139 }
140
141 if (how == SEEK_END) {
142 errno = ESPIPE;
143 return (-1);
144 }
145
146 rv = gzseek((gzFile)s, pos, how);
147 if (rv == -1L)
148 errno = EINVAL;
149
150 return (rv);
151 }
152
153 static int
zf_close(void * s)154 zf_close(void *s)
155 {
156 int rv;
157
158 rv = gzclose((gzFile)s);
159 if (rv == Z_ERRNO) {
160 return (-1);
161 } else if (rv == Z_BUF_ERROR) {
162 errno = EILSEQ;
163 return (-1);
164 } else if (rv == Z_STREAM_ERROR) {
165 errno = EBADF;
166 return (-1);
167 } else if (rv == Z_OK) {
168 return (0);
169 }
170
171 errno = ENOCOFFEE; /* unknown code */
172 return (-1);
173 }
174