Busybox: Upgrade to 1.21.1 (stable). lsof active.
[tomato.git] / release / src / router / php / ext / zip / zip_stream.c
blob400edd6e6c0b9d46d66fc315429d1561cf9de34b
1 /* $Id$ */
2 #ifdef HAVE_CONFIG_H
3 # include "config.h"
4 #endif
5 #include "php.h"
6 #if HAVE_ZIP
7 #ifdef ZEND_ENGINE_2
9 #include "lib/zip.h"
11 #include "php_streams.h"
12 #include "ext/standard/file.h"
13 #include "ext/standard/php_string.h"
14 #include "fopen_wrappers.h"
15 #include "php_zip.h"
17 #include "ext/standard/url.h"
19 struct php_zip_stream_data_t {
20 struct zip *za;
21 struct zip_file *zf;
22 size_t cursor;
23 php_stream *stream;
26 #define STREAM_DATA_FROM_STREAM() \
27 struct php_zip_stream_data_t *self = (struct php_zip_stream_data_t *) stream->abstract;
30 /* {{{ php_zip_ops_read */
31 static size_t php_zip_ops_read(php_stream *stream, char *buf, size_t count TSRMLS_DC)
33 ssize_t n = 0;
34 STREAM_DATA_FROM_STREAM();
36 if (self->za && self->zf) {
37 n = zip_fread(self->zf, buf, count);
38 if (n < 0) {
39 int ze, se;
40 zip_file_error_get(self->zf, &ze, &se);
41 stream->eof = 1;
42 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Zip stream error: %s", zip_file_strerror(self->zf));
43 return 0;
45 /* cast count to signed value to avoid possibly negative n
46 * being cast to unsigned value */
47 if (n == 0 || n < (ssize_t)count) {
48 stream->eof = 1;
49 } else {
50 self->cursor += n;
53 return (n < 1 ? 0 : (size_t)n);
55 /* }}} */
57 /* {{{ php_zip_ops_write */
58 static size_t php_zip_ops_write(php_stream *stream, const char *buf, size_t count TSRMLS_DC)
60 if (!stream) {
61 return 0;
64 return count;
66 /* }}} */
68 /* {{{ php_zip_ops_close */
69 static int php_zip_ops_close(php_stream *stream, int close_handle TSRMLS_DC)
71 STREAM_DATA_FROM_STREAM();
72 if (close_handle) {
73 if (self->zf) {
74 zip_fclose(self->zf);
75 self->zf = NULL;
78 if (self->za) {
79 zip_close(self->za);
80 self->za = NULL;
83 efree(self);
84 stream->abstract = NULL;
85 return EOF;
87 /* }}} */
89 /* {{{ php_zip_ops_flush */
90 static int php_zip_ops_flush(php_stream *stream TSRMLS_DC)
92 if (!stream) {
93 return 0;
96 return 0;
98 /* }}} */
100 static int php_zip_ops_stat(php_stream *stream, php_stream_statbuf *ssb TSRMLS_DC) /* {{{ */
102 struct zip_stat sb;
103 const char *path = stream->orig_path;
104 int path_len = strlen(stream->orig_path);
105 char *file_basename;
106 size_t file_basename_len;
107 char file_dirname[MAXPATHLEN];
108 struct zip *za;
109 char *fragment;
110 int fragment_len;
111 int err;
113 fragment = strchr(path, '#');
114 if (!fragment) {
115 return -1;
119 if (strncasecmp("zip://", path, 6) == 0) {
120 path += 6;
123 fragment_len = strlen(fragment);
125 if (fragment_len < 1) {
126 return -1;
128 path_len = strlen(path);
129 if (path_len >= MAXPATHLEN) {
130 return -1;
133 memcpy(file_dirname, path, path_len - fragment_len);
134 file_dirname[path_len - fragment_len] = '\0';
136 php_basename((char *)path, path_len - fragment_len, NULL, 0, &file_basename, &file_basename_len TSRMLS_CC);
137 fragment++;
139 if (ZIP_OPENBASEDIR_CHECKPATH(file_dirname)) {
140 efree(file_basename);
141 return -1;
144 za = zip_open(file_dirname, ZIP_CREATE, &err);
145 if (za) {
146 memset(ssb, 0, sizeof(php_stream_statbuf));
147 if (zip_stat(za, fragment, ZIP_FL_NOCASE, &sb) != 0) {
148 efree(file_basename);
149 return -1;
151 zip_close(za);
153 if (path[path_len-1] != '/') {
154 ssb->sb.st_size = sb.size;
155 ssb->sb.st_mode |= S_IFREG; /* regular file */
156 } else {
157 ssb->sb.st_size = 0;
158 ssb->sb.st_mode |= S_IFDIR; /* regular directory */
161 ssb->sb.st_mtime = sb.mtime;
162 ssb->sb.st_atime = sb.mtime;
163 ssb->sb.st_ctime = sb.mtime;
164 ssb->sb.st_nlink = 1;
165 ssb->sb.st_rdev = -1;
166 #ifndef PHP_WIN32
167 ssb->sb.st_blksize = -1;
168 ssb->sb.st_blocks = -1;
169 #endif
170 ssb->sb.st_ino = -1;
172 efree(file_basename);
173 return 0;
175 /* }}} */
177 php_stream_ops php_stream_zipio_ops = {
178 php_zip_ops_write, php_zip_ops_read,
179 php_zip_ops_close, php_zip_ops_flush,
180 "zip",
181 NULL, /* seek */
182 NULL, /* cast */
183 php_zip_ops_stat, /* stat */
184 NULL /* set_option */
187 /* {{{ php_stream_zip_open */
188 php_stream *php_stream_zip_open(char *filename, char *path, char *mode STREAMS_DC TSRMLS_DC)
190 struct zip_file *zf = NULL;
191 int err = 0;
193 php_stream *stream = NULL;
194 struct php_zip_stream_data_t *self;
195 struct zip *stream_za;
197 if (strncmp(mode,"r", strlen("r")) != 0) {
198 return NULL;
201 if (filename) {
202 if (ZIP_OPENBASEDIR_CHECKPATH(filename)) {
203 return NULL;
206 /* duplicate to make the stream za independent (esp. for MSHUTDOWN) */
207 stream_za = zip_open(filename, ZIP_CREATE, &err);
208 if (!stream_za) {
209 return NULL;
212 zf = zip_fopen(stream_za, path, 0);
213 if (zf) {
214 self = emalloc(sizeof(*self));
216 self->za = stream_za;
217 self->zf = zf;
218 self->stream = NULL;
219 self->cursor = 0;
220 stream = php_stream_alloc(&php_stream_zipio_ops, self, NULL, mode);
221 stream->orig_path = estrdup(path);
222 } else {
223 zip_close(stream_za);
227 if (!stream) {
228 return NULL;
229 } else {
230 return stream;
234 /* }}} */
236 /* {{{ php_stream_zip_opener */
237 php_stream *php_stream_zip_opener(php_stream_wrapper *wrapper,
238 char *path,
239 char *mode,
240 int options,
241 char **opened_path,
242 php_stream_context *context STREAMS_DC TSRMLS_DC)
244 int path_len;
246 char *file_basename;
247 size_t file_basename_len;
248 char file_dirname[MAXPATHLEN];
250 struct zip *za;
251 struct zip_file *zf = NULL;
252 char *fragment;
253 int fragment_len;
254 int err;
256 php_stream *stream = NULL;
257 struct php_zip_stream_data_t *self;
259 fragment = strchr(path, '#');
260 if (!fragment) {
261 return NULL;
264 if (strncasecmp("zip://", path, 6) == 0) {
265 path += 6;
268 fragment_len = strlen(fragment);
270 if (fragment_len < 1) {
271 return NULL;
273 path_len = strlen(path);
274 if (path_len >= MAXPATHLEN || mode[0] != 'r') {
275 return NULL;
278 memcpy(file_dirname, path, path_len - fragment_len);
279 file_dirname[path_len - fragment_len] = '\0';
281 php_basename(path, path_len - fragment_len, NULL, 0, &file_basename, &file_basename_len TSRMLS_CC);
282 fragment++;
284 if (ZIP_OPENBASEDIR_CHECKPATH(file_dirname)) {
285 efree(file_basename);
286 return NULL;
289 za = zip_open(file_dirname, ZIP_CREATE, &err);
290 if (za) {
291 zf = zip_fopen(za, fragment, 0);
292 if (zf) {
293 self = emalloc(sizeof(*self));
295 self->za = za;
296 self->zf = zf;
297 self->stream = NULL;
298 self->cursor = 0;
299 stream = php_stream_alloc(&php_stream_zipio_ops, self, NULL, mode);
301 if (opened_path) {
302 *opened_path = estrdup(path);
304 } else {
305 zip_close(za);
309 efree(file_basename);
311 if (!stream) {
312 return NULL;
313 } else {
314 return stream;
317 /* }}} */
319 static php_stream_wrapper_ops zip_stream_wops = {
320 php_stream_zip_opener,
321 NULL, /* close */
322 NULL, /* fstat */
323 NULL, /* stat */
324 NULL, /* opendir */
325 "zip wrapper",
326 NULL, /* unlink */
327 NULL, /* rename */
328 NULL, /* mkdir */
329 NULL /* rmdir */
332 php_stream_wrapper php_stream_zip_wrapper = {
333 &zip_stream_wops,
334 NULL,
335 0 /* is_url */
337 #endif /* ZEND_ENGINE_2 */
338 #endif /* HAVE_ZIP */