1 : /*
2 : +----------------------------------------------------------------------+
3 : | PHP Version 6 |
4 : +----------------------------------------------------------------------+
5 : | Copyright (c) 1997-2009 The PHP Group |
6 : +----------------------------------------------------------------------+
7 : | This source file is subject to version 3.01 of the PHP license, |
8 : | that is bundled with this package in the file LICENSE, and is |
9 : | available through the world-wide-web at the following url: |
10 : | http://www.php.net/license/3_01.txt |
11 : | If you did not receive a copy of the PHP license and are unable to |
12 : | obtain it through the world-wide-web, please send a note to |
13 : | license@php.net so we can mail you a copy immediately. |
14 : +----------------------------------------------------------------------+
15 : | Author: Wez Furlong <wez@thebrainroom.com>, based on work by: |
16 : | Hartmut Holzgraefe <hholzgra@php.net> |
17 : +----------------------------------------------------------------------+
18 : */
19 :
20 : /* $Id: zlib_fopen_wrapper.c 276986 2009-03-10 23:40:06Z helly $ */
21 :
22 : #define _GNU_SOURCE
23 :
24 : #include "php.h"
25 : #include "php_zlib.h"
26 : #include "fopen_wrappers.h"
27 :
28 : struct php_gz_stream_data_t {
29 : gzFile gz_file;
30 : php_stream *stream;
31 : };
32 :
33 : static size_t php_gziop_read(php_stream *stream, char *buf, size_t count TSRMLS_DC)
34 388 : {
35 388 : struct php_gz_stream_data_t *self = (struct php_gz_stream_data_t *) stream->abstract;
36 : int read;
37 :
38 388 : read = gzread(self->gz_file, buf, count);
39 :
40 388 : if (gzeof(self->gz_file)) {
41 154 : stream->eof = 1;
42 : }
43 :
44 388 : return (read < 0) ? 0 : read;
45 : }
46 :
47 : static size_t php_gziop_write(php_stream *stream, const char *buf, size_t count TSRMLS_DC)
48 80 : {
49 80 : struct php_gz_stream_data_t *self = (struct php_gz_stream_data_t *) stream->abstract;
50 : int wrote;
51 :
52 80 : wrote = gzwrite(self->gz_file, (char *) buf, count);
53 :
54 80 : return (wrote < 0) ? 0 : wrote;
55 : }
56 :
57 : static int php_gziop_seek(php_stream *stream, off_t offset, int whence, off_t *newoffs TSRMLS_DC)
58 22 : {
59 22 : struct php_gz_stream_data_t *self = (struct php_gz_stream_data_t *) stream->abstract;
60 :
61 : assert(self != NULL);
62 :
63 22 : if (whence == SEEK_END) {
64 2 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "SEEK_END is not supported");
65 2 : return -1;
66 : }
67 20 : *newoffs = gzseek(self->gz_file, offset, whence);
68 :
69 20 : return (*newoffs < 0) ? -1 : 0;
70 : }
71 :
72 : static int php_gziop_close(php_stream *stream, int close_handle TSRMLS_DC)
73 190 : {
74 190 : struct php_gz_stream_data_t *self = (struct php_gz_stream_data_t *) stream->abstract;
75 190 : int ret = EOF;
76 :
77 190 : if (close_handle) {
78 190 : if (self->gz_file) {
79 190 : ret = gzclose(self->gz_file);
80 190 : self->gz_file = NULL;
81 : }
82 190 : if (self->stream) {
83 190 : php_stream_close(self->stream);
84 190 : self->stream = NULL;
85 : }
86 : }
87 190 : efree(self);
88 :
89 190 : return ret;
90 : }
91 :
92 : static int php_gziop_flush(php_stream *stream TSRMLS_DC)
93 192 : {
94 192 : struct php_gz_stream_data_t *self = (struct php_gz_stream_data_t *) stream->abstract;
95 :
96 192 : return gzflush(self->gz_file, Z_SYNC_FLUSH);
97 : }
98 :
99 : php_stream_ops php_stream_gzio_ops = {
100 : php_gziop_write, php_gziop_read,
101 : php_gziop_close, php_gziop_flush,
102 : "ZLIB",
103 : php_gziop_seek,
104 : NULL, /* cast */
105 : NULL, /* stat */
106 : NULL /* set_option */
107 : };
108 :
109 : php_stream *php_stream_gzopen(php_stream_wrapper *wrapper, char *path, char *mode, int options,
110 : char **opened_path, php_stream_context *context STREAMS_DC TSRMLS_DC)
111 288 : {
112 288 : struct php_gz_stream_data_t *self = {0};
113 288 : php_stream *stream = NULL, *innerstream = NULL;
114 :
115 : /* sanity check the stream: it can be either read-only or write-only */
116 288 : if (strchr(mode, '+')) {
117 8 : if (options & REPORT_ERRORS) {
118 8 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "cannot open a zlib stream for reading and writing at the same time!");
119 : }
120 8 : return NULL;
121 : }
122 :
123 280 : self = emalloc(sizeof(*self));
124 :
125 280 : if (strncasecmp("compress.zlib://", path, 16) == 0) {
126 14 : path += 16;
127 266 : } else if (strncasecmp("zlib:", path, 5) == 0) {
128 0 : path += 5;
129 : }
130 :
131 280 : innerstream = php_stream_open_wrapper(path, mode, STREAM_MUST_SEEK | options | STREAM_WILL_CAST, opened_path);
132 :
133 280 : if (innerstream) {
134 : int fd;
135 :
136 196 : if (SUCCESS == php_stream_cast(innerstream, PHP_STREAM_AS_FD, (void **) &fd, REPORT_ERRORS)) {
137 190 : self->gz_file = gzdopen(dup(fd), mode);
138 190 : self->stream = innerstream;
139 190 : if (self->gz_file) {
140 190 : stream = php_stream_alloc_rel(&php_stream_gzio_ops, self, 0, mode);
141 190 : if (stream) {
142 190 : stream->flags |= PHP_STREAM_FLAG_NO_BUFFER;
143 190 : return stream;
144 : }
145 0 : gzclose(self->gz_file);
146 : }
147 0 : if (options & REPORT_ERRORS) {
148 0 : php_error_docref(NULL TSRMLS_CC, E_WARNING, "gzopen failed");
149 : }
150 6 : } else if (innerstream) {
151 6 : php_stream_close(innerstream);
152 : }
153 : }
154 :
155 90 : if (stream) {
156 0 : php_stream_close(stream);
157 : }
158 :
159 90 : if (self) {
160 90 : efree(self);
161 : }
162 :
163 90 : return NULL;
164 : }
165 :
166 : static php_stream_wrapper_ops gzip_stream_wops = {
167 : php_stream_gzopen,
168 : NULL, /* close */
169 : NULL, /* stat */
170 : NULL, /* stat_url */
171 : NULL, /* opendir */
172 : "ZLIB",
173 : NULL, /* unlink */
174 : NULL, /* rename */
175 : NULL, /* mkdir */
176 : NULL /* rmdir */
177 : };
178 :
179 : php_stream_wrapper php_stream_gzip_wrapper = {
180 : &gzip_stream_wops,
181 : NULL,
182 : 0, /* is_url */
183 : };
184 :
185 : /*
186 : * Local variables:
187 : * tab-width: 4
188 : * c-basic-offset: 4
189 : * End:
190 : * vim600: noet sw=4 ts=4 fdm=marker
191 : * vim<600: noet sw=4 ts=4
192 : */
|