Checkpoint commit of stacked sources to implement encryption/compression.
Used for zip_fread.
Not yet used for writing (zip_close).
Traditional PKWARE encryption untested.
--HG--
branch : HEAD
diff --git a/lib/zip_source_filep.c b/lib/zip_source_filep.c
index 6d13972..7ca0704 100644
--- a/lib/zip_source_filep.c
+++ b/lib/zip_source_filep.c
@@ -1,6 +1,6 @@
/*
zip_source_filep.c -- create data source from FILE *
- Copyright (C) 1999-2008 Dieter Baron and Thomas Klausner
+ Copyright (C) 1999-2009 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>
@@ -44,6 +44,9 @@
struct read_file {
char *fname; /* name of file to copy from */
FILE *f; /* file to copy from */
+ int closep; /* close f */
+ struct zip_stat st; /* stat information passed in */
+
zip_uint64_t off; /* start offset of */
zip_int64_t len; /* length of data to copy */
zip_int64_t remain; /* bytes remaining to be copied */
@@ -67,14 +70,15 @@
return NULL;
}
- return _zip_source_file_or_p(za, NULL, file, start, len);
+ return _zip_source_file_or_p(za, NULL, file, start, len, 1, NULL);
}
struct zip_source *
_zip_source_file_or_p(struct zip *za, const char *fname, FILE *file,
- zip_uint64_t start, zip_int64_t len)
+ zip_uint64_t start, zip_int64_t len, int closep,
+ const struct zip_stat *st)
{
struct read_file *f;
struct zip_source *zs;
@@ -100,7 +104,12 @@
f->f = file;
f->off = start;
f->len = (len ? len : -1);
-
+ f->closep = f->fname ? 1 : closep;
+ if (st)
+ memcpy(&f->st, st, sizeof(f->st));
+ else
+ zip_stat_init(&f->st);
+
if ((zs=zip_source_function(za, read_file, f)) == NULL) {
free(f);
return NULL;
@@ -131,10 +140,12 @@
}
}
- if (fseeko(z->f, (off_t)z->off, SEEK_SET) < 0) {
- z->e[0] = ZIP_ER_SEEK;
- z->e[1] = errno;
- return -1;
+ if (z->closep) {
+ if (fseeko(z->f, (off_t)z->off, SEEK_SET) < 0) {
+ z->e[0] = ZIP_ER_SEEK;
+ z->e[1] = errno;
+ return -1;
+ }
}
z->remain = z->len;
return 0;
@@ -144,7 +155,17 @@
n = len > z->remain ? z->remain : len;
else
n = len;
-
+
+ if (!z->closep) {
+ /* we might share this file with others, so let's be save */
+ if (fseeko(z->f, (off_t)(z->off + z->len-z->remain),
+ SEEK_SET) < 0) {
+ z->e[0] = ZIP_ER_SEEK;
+ z->e[1] = errno;
+ return -1;
+ }
+ }
+
if ((i=fread(buf, 1, n, z->f)) < 0) {
z->e[0] = ZIP_ER_READ;
z->e[1] = errno;
@@ -172,26 +193,29 @@
if (len < sizeof(*st))
return -1;
- if (z->f)
- err = fstat(fileno(z->f), &fst);
- else
- err = stat(z->fname, &fst);
+ if (z->st.size != -1)
+ memcpy(st, &z->st, sizeof(st));
+ else {
+ 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;
+ if (err != 0) {
+ z->e[0] = ZIP_ER_READ; /* best match */
+ z->e[1] = errno;
+ return -1;
+ }
+
+ st = (struct zip_stat *)data;
+
+ zip_stat_init(st);
+ st->mtime = fst.st_mtime;
+ if (z->len != -1)
+ st->size = z->len;
+ else if ((fst.st_mode&S_IFMT) == S_IFREG)
+ st->size = fst.st_size;
}
-
- st = (struct zip_stat *)data;
-
- zip_stat_init(st);
- st->mtime = fst.st_mtime;
- if (z->len != -1)
- st->size = z->len;
- else if ((fst.st_mode&S_IFMT) == S_IFREG)
- st->size = fst.st_size;
-
return sizeof(*st);
}
@@ -204,7 +228,7 @@
case ZIP_SOURCE_FREE:
free(z->fname);
- if (z->f)
+ if (z->closep && z->f)
fclose(z->f);
free(z);
return 0;