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