diff options
Diffstat (limited to 'ext/zip/lib/zip_source_filep.c')
-rw-r--r-- | ext/zip/lib/zip_source_filep.c | 53 |
1 files changed, 48 insertions, 5 deletions
diff --git a/ext/zip/lib/zip_source_filep.c b/ext/zip/lib/zip_source_filep.c index 48a122d4bd..10f9602e1e 100644 --- a/ext/zip/lib/zip_source_filep.c +++ b/ext/zip/lib/zip_source_filep.c @@ -1,6 +1,6 @@ /* zip_source_filep.c -- create data source from FILE * - Copyright (C) 1999-2007 Dieter Baron and Thomas Klausner + Copyright (C) 1999-2008 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at <libzip@nih.at> @@ -42,6 +42,7 @@ #include "zipint.h" struct read_file { + char *fname; /* name of file to copy from */ FILE *f; /* file to copy from */ off_t off; /* start offset of */ off_t len; /* lengt of data to copy */ @@ -57,9 +58,6 @@ static ssize_t read_file(void *state, void *data, size_t len, ZIP_EXTERN(struct zip_source *) zip_source_filep(struct zip *za, FILE *file, off_t start, off_t len) { - struct read_file *f; - struct zip_source *zs; - if (za == NULL) return NULL; @@ -68,11 +66,36 @@ zip_source_filep(struct zip *za, FILE *file, off_t start, off_t len) return NULL; } + return _zip_source_file_or_p(za, NULL, file, start, len); +} + + + +struct zip_source * +_zip_source_file_or_p(struct zip *za, const char *fname, FILE *file, + off_t start, off_t len) +{ + struct read_file *f; + struct zip_source *zs; + + if (file == NULL && fname == NULL) { + _zip_error_set(&za->error, ZIP_ER_INVAL, 0); + return NULL; + } + if ((f=(struct read_file *)malloc(sizeof(struct read_file))) == NULL) { _zip_error_set(&za->error, ZIP_ER_MEMORY, 0); return NULL; } + f->fname = NULL; + if (fname) { + if ((f->fname=strdup(fname)) == NULL) { + _zip_error_set(&za->error, ZIP_ER_MEMORY, 0); + free(f); + return NULL; + } + } f->f = file; f->off = start; f->len = (len ? len : -1); @@ -99,6 +122,14 @@ read_file(void *state, void *data, size_t len, enum zip_source_cmd cmd) switch (cmd) { case ZIP_SOURCE_OPEN: + if (z->fname) { + if ((z->f=fopen(z->fname, "rb")) == NULL) { + z->e[0] = ZIP_ER_OPEN; + z->e[1] = errno; + return -1; + } + } + if (fseeko(z->f, z->off, SEEK_SET) < 0) { z->e[0] = ZIP_ER_SEEK; z->e[1] = errno; @@ -125,17 +156,27 @@ read_file(void *state, void *data, size_t len, enum zip_source_cmd cmd) return i; case ZIP_SOURCE_CLOSE: + if (z->fname) { + fclose(z->f); + z->f = NULL; + } return 0; case ZIP_SOURCE_STAT: { struct zip_stat *st; struct stat fst; + int err; if (len < sizeof(*st)) return -1; - if (fstat(fileno(z->f), &fst) != 0) { + if (z->f) + err = fstat(fileno(z->f), &fst); + else + err = stat(z->fname, &fst); + + if (err != 0) { z->e[0] = ZIP_ER_READ; /* best match */ z->e[1] = errno; return -1; @@ -161,6 +202,8 @@ read_file(void *state, void *data, size_t len, enum zip_source_cmd cmd) return sizeof(int)*2; case ZIP_SOURCE_FREE: + free(z->fname); + if (z->f) fclose(z->f); free(z); return 0; |