Merge no-meta branch --HG-- branch : HEAD
diff --git a/lib/Makefile.am b/lib/Makefile.am index 53612c8..f7441a9 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am
@@ -12,28 +12,27 @@ zip_add_zip.c \ zip_close.c \ zip_delete.c \ + zip_dirent.c \ zip_err_str.c \ zip_error.c \ zip_error_str.c \ zip_error_strerror.c \ + zip_error_sys_type.c \ zip_fclose.c \ zip_file_get_error.c \ + zip_file_get_offset.c \ zip_file_strerror.c \ zip_fopen.c \ zip_fopen_index.c \ zip_fread.c \ zip_free.c \ zip_free_entry.c \ - zip_free_meta.c \ zip_get_error.c \ - zip_get_meta.c \ zip_get_num_files.c \ zip_get_name.c \ - zip_merge_meta.c \ zip_name_locate.c \ zip_new.c \ zip_new_entry.c \ - zip_new_meta.c \ zip_open.c \ zip_rename.c \ zip_replace.c \
diff --git a/lib/zip.h b/lib/zip.h index 6853136..d97f489 100644 --- a/lib/zip.h +++ b/lib/zip.h
@@ -2,7 +2,7 @@ #define _HAD_ZIP_H /* - $NiH: zip.h,v 1.34 2003/10/05 16:05:22 dillo Exp $ + $NiH: zip.h,v 1.35.4.6 2004/04/14 09:21:33 dillo Exp $ zip.h -- exported declarations. Copyright (C) 1999, 2003 Dieter Baron and Thomas Klausner @@ -43,21 +43,25 @@ #include <zlib.h> #include <time.h> -enum zip_state { ZIP_ST_UNCHANGED, ZIP_ST_DELETED, ZIP_ST_REPLACED, - ZIP_ST_ADDED, ZIP_ST_RENAMED }; -enum zip_cmd { ZIP_CMD_INIT, ZIP_CMD_READ, ZIP_CMD_META, ZIP_CMD_CLOSE }; - /* flags for zip_open */ + #define ZIP_CREATE 1 #define ZIP_EXCL 2 #define ZIP_CHECKCONS 4 -/* flags for zip_name_locate */ -#define ZIP_NAME_NOCASE 1 -#define ZIP_NAME_NODIR 2 -int zip_err; /* global variable for errors returned by the low-level - library */ +/* flags for zip_name_locate, zip_fopen, zip_stat, ... */ + +#define ZIP_FL_NOCASE 1 /* ignore case on name lookup */ +#define ZIP_FL_NODIR 2 /* ignore directory component */ +#define ZIP_FL_COMPRESSED 4 /* read compressed data (XXX: rename) */ +#define ZIP_FL_UNCHANGED 8 /* use original data, ignoring changes */ + +/* flags for zip_add and zip_replace */ + +#define ZIP_CH_ISCOMP 1 /* data returned by ch_func is compressed */ + +/* libzip error codes */ #define ZERR_OK 0 /* N No error */ #define ZERR_MULTIDISK 1 /* N Multi-disk zip archives not supported */ @@ -82,33 +86,47 @@ #define ZERR_INTERNAL 20 /* N Internal error */ #define ZERR_INCONS 21 /* N Zip archive inconsistent */ + +/* type of system error value */ + #define ZIP_ET_NONE 0 /* sys_err unused */ #define ZIP_ET_SYS 1 /* sys_err is errno */ #define ZIP_ET_ZIP 2 /* sys_err is zlib error code */ -/* zip file */ +/* compression methods */ -typedef int (*zip_read_func)(void *state, void *data, - int len, enum zip_cmd cmd); +#define ZIP_CM_DEFAULT -1 /* better of deflate or store */ +#define ZIP_CM_STORE 0 /* stored (uncompressed) */ +#define ZIP_CM_SHRINK 1 /* shrunk */ +#define ZIP_CM_REDUCE_1 2 /* reduced with factor 1 */ +#define ZIP_CM_REDUCE_2 3 /* reduced with factor 2 */ +#define ZIP_CM_REDUCE_3 4 /* reduced with factor 3 */ +#define ZIP_CM_REDUCE_4 5 /* reduced with factor 4 */ +#define ZIP_CM_IMPLODE 6 /* imploded */ +#define ZIP_CM_DEFLATE 8 /* deflated */ +#define ZIP_CM_DEFLATE64 9 /* deflate64 */ +#define ZIP_CM_PKWARE_IMPLODE 10 /* PKWARE imploding */ -struct zip_meta { - unsigned short version_made, version_need, bitflags, comp_method, - disknrstart, int_attr; - time_t last_mod; - unsigned int crc, comp_size, uncomp_size, ext_attr, local_offset; - unsigned short ef_len, lef_len, fc_len; - unsigned char *ef, *lef, *fc; + + +enum zip_cmd { + ZIP_CMD_INIT, /* prepare for reading */ + ZIP_CMD_READ, /* read data */ + ZIP_CMD_CLOSE, /* close and cleanup */ + ZIP_CMD_STAT /* for compressed data */ }; +typedef ssize_t (*zip_read_func)(void *state, void *data, + size_t len, enum zip_cmd cmd); + struct zip_stat { const char *name; /* name of the file */ int index; /* index within archive */ unsigned int crc; /* crc of file data */ - unsigned int size; /* size of file (uncompressed) */ time_t mtime; /* modification time */ - unsigned int comp_size; /* size of file (compressed) */ + off_t size; /* size of file (uncompressed) */ + off_t comp_size; /* size of file (compressed) */ unsigned short comp_method; /* compression method used */ - /* unsigned short bitflags; */ }; struct zip; @@ -116,47 +134,35 @@ -int zip_add(struct zip *, const char *, struct zip_meta *, - zip_read_func, void *, int); -int zip_add_data(struct zip *, const char *, struct zip_meta *, - const char *, int, int); -int zip_add_file(struct zip *, const char *, struct zip_meta *, - const char *, int, int); -int zip_add_filep(struct zip *, const char *, struct zip_meta *, - FILE *, int, int); -int zip_add_zip(struct zip *, const char *, struct zip_meta *, - struct zip *, int, int, int); +int zip_add(struct zip *, const char *, zip_read_func, void *, int); +int zip_add_data(struct zip *, const char *, const void *, off_t, int); +int zip_add_file(struct zip *, const char *, const char *, off_t, off_t); +int zip_add_filep(struct zip *, const char *, FILE *, off_t, off_t); +int zip_add_zip(struct zip *, const char *, struct zip *, int, int, + off_t, off_t); int zip_close(struct zip *); int zip_delete(struct zip *, int); -int zip_error_str(char *, int, int, int); +int zip_error_str(char *, size_t, int, int); int zip_error_sys_type(int); int zip_fclose(struct zip_file *); void zip_file_get_error(struct zip_file *, int *, int *); const char *zip_file_strerror(struct zip_file *); struct zip_file *zip_fopen(struct zip *, const char *, int); -struct zip_file *zip_fopen_index(struct zip *, int); -int zip_fread(struct zip_file *, char *, int); -void zip_free_meta(struct zip_meta *); +struct zip_file *zip_fopen_index(struct zip *, int, int); +ssize_t zip_fread(struct zip_file *, void *, size_t); void zip_get_error(struct zip *, int *, int *); -struct zip_meta *zip_get_meta(struct zip *, int); const char *zip_get_name(struct zip *, int); int zip_get_num_files(struct zip *); int zip_name_locate(struct zip *, const char *, int); -struct zip_meta *zip_new_meta(void); struct zip *zip_open(const char *, int, int *); int zip_rename(struct zip *, int, const char *); -int zip_replace(struct zip *, int, const char *, struct zip_meta *, - zip_read_func, void *, int); -int zip_replace_data(struct zip *, int, const char *, struct zip_meta *, - const char *, int, int); -int zip_replace_file(struct zip *, int, const char *, struct zip_meta *, - const char *, int, int); -int zip_replace_filep(struct zip *, int, const char *, struct zip_meta *, - FILE *, int, int); -int zip_replace_zip(struct zip *, int, const char *, struct zip_meta *, - struct zip *, int, int, int); +int zip_replace(struct zip *, int, zip_read_func, void *, int); +int zip_replace_data(struct zip *, int, const void *, off_t, int); +int zip_replace_file(struct zip *, int, const char *, off_t, off_t); +int zip_replace_filep(struct zip *, int, FILE *, off_t, off_t); +int zip_replace_zip(struct zip *, int, struct zip *, int, int, off_t, off_t); int zip_stat(struct zip *, const char *, int, struct zip_stat *); -int zip_stat_index(struct zip *, int, struct zip_stat *); +int zip_stat_index(struct zip *, int, int, struct zip_stat *); const char *zip_strerror(struct zip *); int zip_unchange(struct zip *, int); int zip_unchange_all(struct zip *);
diff --git a/lib/zip_add.c b/lib/zip_add.c index 8f0c54c..9ebc7b0 100644 --- a/lib/zip_add.c +++ b/lib/zip_add.c
@@ -1,5 +1,5 @@ /* - $NiH: zip_add.c,v 1.8 2003/10/01 09:50:59 dillo Exp $ + $NiH: zip_add.c,v 1.9.4.1 2004/03/20 09:54:03 dillo Exp $ zip_add.c -- add file via callback function Copyright (C) 1999, 2003 Dieter Baron and Thomas Klausner @@ -41,8 +41,13 @@ int -zip_add(struct zip *zf, const char *name, struct zip_meta *meta, - zip_read_func fn, void *state, int comp) +zip_add(struct zip *zf, const char *name, + zip_read_func fn, void *state, int flags) { - return zip_replace(zf, -1, name, meta, fn, state, comp); + if (name == NULL) { + _zip_error_set(&zf->error, ZERR_INVAL, 0); + return -1; + } + + return _zip_replace(zf, -1, name, fn, state, flags); }
diff --git a/lib/zip_add_data.c b/lib/zip_add_data.c index 7e53e75..d9fdd2c 100644 --- a/lib/zip_add_data.c +++ b/lib/zip_add_data.c
@@ -1,5 +1,5 @@ /* - $NiH: zip_add_data.c,v 1.5 2003/10/01 09:50:59 dillo Exp $ + $NiH: zip_add_data.c,v 1.6.4.1 2004/03/20 09:54:03 dillo Exp $ zip_add_data.c -- add file from buffer Copyright (C) 1999, 2003 Dieter Baron and Thomas Klausner @@ -41,8 +41,13 @@ int -zip_add_data(struct zip *zf, const char *name, struct zip_meta *meta, - const char *data, int len, int freep) +zip_add_data(struct zip *zf, const char *name, + const void *data, off_t len, int freep) { - return zip_replace_data(zf, -1, name, meta, data, len, freep); + if (name == NULL) { + _zip_error_set(&zf->error, ZERR_INVAL, 0); + return -1; + } + + return _zip_replace_data(zf, -1, name, data, len, freep); }
diff --git a/lib/zip_add_file.c b/lib/zip_add_file.c index cf45214..8a845b5 100644 --- a/lib/zip_add_file.c +++ b/lib/zip_add_file.c
@@ -1,5 +1,5 @@ /* - $NiH: zip_add_file.c,v 1.6 2003/10/01 09:50:59 dillo Exp $ + $NiH: zip_add_file.c,v 1.7.4.1 2004/03/20 09:54:04 dillo Exp $ zip_add_file.c -- add file from file system Copyright (C) 1999, 2003 Dieter Baron and Thomas Klausner @@ -41,8 +41,13 @@ int -zip_add_file(struct zip *zf, const char *name, struct zip_meta *meta, - const char *fname, int start, int len) +zip_add_file(struct zip *zf, const char *name, + const char *fname, off_t start, off_t len) { - return zip_replace_file(zf, -1, name, meta, fname, start, len); + if (name == NULL) { + _zip_error_set(&zf->error, ZERR_INVAL, 0); + return -1; + } + + return _zip_replace_file(zf, -1, name, fname, start, len); }
diff --git a/lib/zip_add_filep.c b/lib/zip_add_filep.c index d942e16..c4e0acd 100644 --- a/lib/zip_add_filep.c +++ b/lib/zip_add_filep.c
@@ -1,5 +1,5 @@ /* - $NiH: zip_add_filep.c,v 1.5 2003/10/01 09:51:00 dillo Exp $ + $NiH: zip_add_filep.c,v 1.6.4.1 2004/03/20 09:54:04 dillo Exp $ zip_add_filep.c -- add file from FILE* Copyright (C) 1999, 2003 Dieter Baron and Thomas Klausner @@ -41,8 +41,13 @@ int -zip_add_filep(struct zip *zf, const char *name, struct zip_meta *meta, - FILE *file, int start, int len) +zip_add_filep(struct zip *zf, const char *name, + FILE *file, off_t start, off_t len) { - return zip_replace_filep(zf, -1, name, meta, file, start, len); + if (name == NULL) { + _zip_error_set(&zf->error, ZERR_INVAL, 0); + return -1; + } + + return _zip_replace_filep(zf, -1, name, file, start, len); }
diff --git a/lib/zip_add_zip.c b/lib/zip_add_zip.c index 260a4d9..44468fa 100644 --- a/lib/zip_add_zip.c +++ b/lib/zip_add_zip.c
@@ -1,5 +1,5 @@ /* - $NiH: zip_add_zip.c,v 1.6 2003/10/01 09:51:00 dillo Exp $ + $NiH: zip_add_zip.c,v 1.7.4.2 2004/04/14 09:21:33 dillo Exp $ zip_add_zip.c -- add file from zip file Copyright (C) 1999, 2003 Dieter Baron and Thomas Klausner @@ -41,8 +41,13 @@ int -zip_add_zip(struct zip *zf, const char *name, struct zip_meta *meta, - struct zip *srczf, int srcidx, int start, int len) +zip_add_zip(struct zip *zf, const char *name, + struct zip *srczf, int srcidx, int flags, off_t start, off_t len) { - return zip_replace_zip(zf, -1, name, meta, srczf, srcidx, start, len); + if (name == NULL) { + _zip_error_set(&zf->error, ZERR_INVAL, 0); + return -1; + } + + return _zip_replace_zip(zf, -1, name, srczf, srcidx, flags, start, len); }
diff --git a/lib/zip_close.c b/lib/zip_close.c index 43e7bd5..244aba4 100644 --- a/lib/zip_close.c +++ b/lib/zip_close.c
@@ -1,5 +1,5 @@ /* - $NiH: zip_close.c,v 1.36 2003/10/06 16:37:40 dillo Exp $ + $NiH: zip_close.c,v 1.37.4.9 2004/04/13 19:47:58 dillo Exp $ zip_close.c -- close zip archive and update changes Copyright (C) 1999 Dieter Baron and Thomas Klausner @@ -46,656 +46,390 @@ #include "zip.h" #include "zipint.h" -static int _zip_entry_copy(struct zip *dest, struct zip *src, - int entry_no, struct zip_meta *meta); -static int _zip_entry_add(struct zip *dest, struct zip_entry *se); -static int _zip_writecdir(struct zip *zfp); -static void _zip_write2(FILE *fp, int i); -static void _zip_write4(FILE *fp, int i); -static void _zip_writestr(FILE *fp, char *str, int len); -static int _zip_writecdentry(FILE *fp, struct zip_entry *zfe, int localp); -static struct zip_entry *_zip_create_entry(struct zip *dest, - struct zip_entry *src_entry, - char *name, struct zip_meta *meta); -static void _zip_u2d_time(time_t time, int *ddate, int *dtime); -static int _zip_fwrite(char *b, int s, int n, FILE *f); +static int add_data(struct zip *, int, struct zip_dirent *, FILE *); +static int add_data_comp(zip_read_func, void *, struct zip_dirent *, FILE *, + struct zip_error *); +static int add_data_uncomp(zip_read_func, void *, struct zip_dirent *, FILE *, + struct zip_error *); +static int copy_data(FILE *, off_t, FILE *, struct zip_error *); -/* zip_close: - Tries to commit all changes and close the zipfile; if it fails, - zip_err (and errno) are set and *zf is unchanged, except for - problems in _zip_free. */ - int -zip_close(struct zip *zf) +zip_close(struct zip *za) { - int i, count, tfd, ret, survivors; + int changed, survivors; + int i, j, count, tfd, ret, error; char *temp; FILE *tfp; - struct zip *tzf; mode_t mask; + struct zip_cdir *cd; + struct zip_dirent de; - if (zf->changes == 0) { - _zip_free(zf); - return 0; + changed = survivors = 0; + for (i=0; i<za->nentry; i++) { + if (za->entry[i].state != ZIP_ST_UNCHANGED) + changed = 1; + if (za->entry[i].state != ZIP_ST_DELETED) + survivors++; } - /* look if there really are any changes */ - count = survivors = 0; - for (i=0; i<zf->nentry; i++) { - if (zf->entry[i].state != ZIP_ST_UNCHANGED) - count = 1; - if (zf->entry[i].state != ZIP_ST_DELETED) - survivors = 1; - if (survivors && count) - break; - } - - /* no changes, all has been unchanged */ - if (count == 0) { - _zip_free(zf); + if (!changed) { + _zip_free(za); return 0; } /* don't create zip files with no entries */ if (survivors == 0) { ret = 0; - if (zf->zn) - ret = remove(zf->zn); - _zip_free(zf); - /* XXX: inconsistent: zf freed, returned -1 */ + if (za->zn) + ret = remove(za->zn); + _zip_free(za); + /* XXX: inconsistent: za freed, returned -1 */ return ret; } - temp = (char *)malloc(strlen(zf->zn)+8); - if (!temp) { - _zip_error_set(&zf->error, ZERR_MEMORY, 0); + if ((cd=_zip_cdir_new(survivors, &za->error)) == NULL) + return -1; + + if ((temp=malloc(strlen(za->zn)+8)) == NULL) { + _zip_error_set(&za->error, ZERR_MEMORY, 0); + _zip_cdir_free(cd); return -1; } - sprintf(temp, "%s.XXXXXX", zf->zn); + sprintf(temp, "%s.XXXXXX", za->zn); - tfd = mkstemp(temp); - if (tfd == -1) { - _zip_error_set(&zf->error, ZERR_TMPOPEN, errno); + if ((tfd=mkstemp(temp)) == -1) { + _zip_error_set(&za->error, ZERR_TMPOPEN, errno); + _zip_cdir_free(cd); free(temp); return -1; } if ((tfp=fdopen(tfd, "r+b")) == NULL) { - _zip_error_set(&zf->error, ZERR_TMPOPEN, errno); + _zip_error_set(&za->error, ZERR_TMPOPEN, errno); + _zip_cdir_free(cd); close(tfd); remove(temp); free(temp); return -1; } - if ((tzf=_zip_new(&zf->error.zip_err)) == NULL) { + error = 0; + for (i=j=0; i<za->nentry; i++) { + if (za->entry[i].state == ZIP_ST_DELETED) + continue; + + if (ZIP_ENTRY_DATA_CHANGED(za->entry+i)) { + _zip_dirent_init(&de); + memcpy(cd->entry+j, &de, sizeof(cd->entry[i])); + if (za->entry[i].ch_filename == NULL) { + if (za->entry[i].state == ZIP_ST_REPLACED) { + de.filename = strdup(za->cdir->entry[i].filename); + de.filename_len = strlen(de.filename); + cd->entry[j].filename = za->cdir->entry[i].filename; + cd->entry[j].filename_len = de.filename_len; + } + else { + de.filename = strdup("-"); + de.filename_len = 1; + cd->entry[j].filename = "-"; + cd->entry[j].filename_len = de.filename_len; + } + } + } + else { + if (fseek(za->zp, za->cdir->entry[i].offset, SEEK_SET) != 0) { + _zip_error_set(&za->error, ZERR_SEEK, errno); + error = 1; + break; + } + if (_zip_dirent_read(&de, za->zp, NULL, 0, 1, &za->error) != 0) { + error = 1; + break; + } + memcpy(cd->entry+j, za->cdir->entry+i, sizeof(cd->entry[i])); + } + + if (za->entry[i].ch_filename) { + free(de.filename); + de.filename = strdup(za->entry[i].ch_filename); + de.filename_len = strlen(de.filename); + cd->entry[j].filename = za->entry[i].ch_filename; + cd->entry[j].filename_len = de.filename_len; + } + + cd->entry[j].offset = ftell(tfp); + + if (ZIP_ENTRY_DATA_CHANGED(za->entry+i)) { + de.last_mod = za->entry[i].ch_mtime; + if (add_data(za, i, &de, tfp) < 0) { + error -1; + break; + } + cd->entry[j].comp_method = de.comp_method; + cd->entry[j].comp_size = de.comp_size; + cd->entry[j].uncomp_size = de.uncomp_size; + cd->entry[j].crc = de.crc; + } + else { + if (_zip_dirent_write(&de, tfp, 1, &za->error) < 0) { + error = 1; + break; + } + /* we just read the local dirent, file is at correct position */ + if (copy_data(za->zp, de.uncomp_size, tfp, &za->error) < 0) { + error = 1; + break; + } + } + + j++; + + _zip_dirent_finalize(&de); + } + + if (!error) { + if (_zip_cdir_write(cd, tfp, &za->error) < 0) + error = 1; + } + + /* pointers in cd are owned by za */ + cd->nentry = 0; + _zip_cdir_free(cd); + + if (error) { + _zip_dirent_finalize(&de); fclose(tfp); remove(temp); free(temp); return -1; } - tzf->zp = tfp; - tzf->zn = temp; - tzf->comlen = zf->comlen; - if ((tzf->com=(unsigned char *)_zip_memdup(zf->com, zf->comlen)) == NULL) { - _zip_error_set(&zf->error, ZERR_MEMORY, 0); - _zip_free(tzf); + + if (fclose(tfp) != 0) { + /* XXX: handle fclose(tfp) error */ + remove(temp); + free(temp); return -1; } - - count = 0; - if (zf->entry) { - for (i=0; i<zf->nentry; i++) { - switch (zf->entry[i].state) { - case ZIP_ST_UNCHANGED: - case ZIP_ST_RENAMED: - if (_zip_local_header_read(zf, i) < 0) { - remove(tzf->zn); - _zip_free(tzf); - return -1; - } - if (_zip_entry_copy(tzf, zf, i, zf->entry[i].ch_meta)) { - /* zip_err set by _zip_entry_copy */ - remove(tzf->zn); - _zip_free(tzf); - return -1; - } - break; - case ZIP_ST_DELETED: - break; - case ZIP_ST_REPLACED: - case ZIP_ST_ADDED: - if (_zip_entry_add(tzf, zf->entry+i)) { - /* zip_err set by _zip_entry_add */ - remove(tzf->zn); - _zip_free(tzf); - return -1; - } - break; - default: - /* can't happen */ - break; - } - } - } - - _zip_writecdir(tzf); - if (fclose(tzf->zp)==0) { - tzf->zp = NULL; - if (rename(tzf->zn, zf->zn) != 0) { - _zip_error_set(&zf->error, ZERR_RENAME, errno); - remove(tzf->zn); - _zip_free(tzf); - return -1; - } - if (zf->zp) { - fclose(zf->zp); - zf->zp = NULL; - } - mask = umask(0); - umask(mask); - chmod(zf->zn, 0666&~mask); + if (rename(temp, za->zn) != 0) { + _zip_error_set(&za->error, ZERR_RENAME, errno); + remove(temp); + free(temp); + return -1; } - /* XXX: handle fclose(tzf->fn) error */ + if (za->zp) { + fclose(za->zp); + za->zp = NULL; + } + mask = umask(0); + umask(mask); + chmod(za->zn, 0666&~mask); - _zip_free(zf); - _zip_free(tzf); - + _zip_free(za); + return 0; } static int -_zip_entry_copy(struct zip *dest, struct zip *src, int entry_no, - struct zip_meta *meta) +add_data(struct zip *za, int idx, struct zip_dirent *de, FILE *ft) { - char buf[BUFSIZE]; - unsigned int len, remainder; - struct zip_entry *ze; - - ze = _zip_create_entry(dest, src->entry+entry_no, NULL, meta); - if (!ze) - return -1; - - if (_zip_writecdentry(dest->zp, ze, 1) != 0) { - _zip_error_set(&src->error, ZERR_WRITE, errno); - return -1; - } - - if (fseek(src->zp, src->entry[entry_no].meta->local_offset - + LENTRYSIZE + src->entry[entry_no].meta->lef_len - + src->entry[entry_no].file_fnlen, SEEK_SET) != 0) { - _zip_error_set(&src->error, ZERR_SEEK, errno); - return -1; - } - + off_t offstart, offend; + zip_read_func rf; + void *ud; - remainder = src->entry[entry_no].meta->comp_size; - len = BUFSIZE; - while (remainder) { - if (len > remainder) - len = remainder; - if (fread(buf, 1, len, src->zp)!=len) { - _zip_error_set(&src->error, ZERR_READ, errno); + rf = za->entry[idx].ch_func; + ud = za->entry[idx].ch_data; + + if (rf(ud, NULL, 0, ZIP_CMD_INIT) < 0) { + /* XXX: set error */ + return -1; + } + + offstart = ftell(ft); + + if (_zip_dirent_write(de, ft, 1, &za->error) < 0) + return -1; + + if (za->entry[idx].ch_flags & ZIP_CH_ISCOMP) { + if (add_data_comp(rf, ud, de, ft, &za->error) < 0) return -1; - } - if (fwrite(buf, 1, len, dest->zp)!=len) { - _zip_error_set(&src->error, ZERR_WRITE, errno); + } + else { + if (add_data_uncomp(rf, ud, de, ft, &za->error) < 0) return -1; - } - remainder -= len; } - return 0; -} - - - -static int -_zip_entry_add(struct zip *zf, struct zip_entry *se) -{ - z_stream zstr; - char b1[BUFSIZE], b2[BUFSIZE]; - int n, size, crc, ret; - int flush, end, idx; - struct zip_meta *meta; - - if (_zip_create_entry(zf, NULL, se->fn, se->ch_meta) == NULL) - return -1; - - --zf->nentry; - idx = zf->nentry; - - zf->entry[idx].meta->local_offset = ftell(zf->zp); - - if (se->ch_func(se->ch_data, NULL, 0, ZIP_CMD_INIT) != 0) - return -1; - - if (_zip_writecdentry(zf->zp, zf->entry+idx, 1) != 0) { - zip_err = ZERR_WRITE; +#if 0 + /* XXX: this is also called in _zip_free */ + if (rf(ud, NULL, 0, ZIP_CMD_CLOSE) < 0) { + /* XXX: set error */ return -1; } - - if ((meta=zip_new_meta()) < 0) - return -1; - - size = 0; - - if ((se->ch_comp == 0) || (se->ch_meta - && (se->ch_meta->comp_method == 0))) { - /* we have to compress */ - if (se->ch_meta && ((se->ch_meta->comp_method > 0) - && (se->ch_meta->comp_method != 8))) { - /* unknown compression method */ - zip_err = ZERR_INVAL; - return -1; - } - zstr.zalloc = Z_NULL; - zstr.zfree = Z_NULL; - zstr.opaque = NULL; - zstr.avail_in = 0; - zstr.avail_out = 0; - - /* -15: undocumented feature of zlib to _not_ write a zlib header */ - deflateInit2(&zstr, Z_BEST_COMPRESSION, Z_DEFLATED, -15, 9, - Z_DEFAULT_STRATEGY); - - zstr.next_out = b2; - zstr.avail_out = BUFSIZE; - zstr.avail_in = 0; - flush = 0; - crc = crc32(0, NULL, 0); - - end = 0; - while (!end) { - if (zstr.avail_in == 0 && !flush) { - if ((n=se->ch_func(se->ch_data, b1, BUFSIZE, - ZIP_CMD_READ)) < 0) - return -1; - zstr.next_in = b1; - zstr.avail_in = n; - size += n; - crc = crc32(crc, b1, n); - - if (n == 0) - flush = Z_FINISH; - } - - ret = deflate(&zstr, flush); - if (ret != Z_OK && ret != Z_STREAM_END) { - zip_err = ZERR_ZLIB; - return -1; - } - - if (zstr.avail_out != BUFSIZE) { - if (_zip_fwrite(b2, 1, BUFSIZE-zstr.avail_out, zf->zp) < 0) - return -1; - zstr.next_out = b2; - zstr.avail_out = BUFSIZE; - } - - if (ret == Z_STREAM_END) { - if (se->ch_func(se->ch_data, meta, 0, ZIP_CMD_META) < 0) - return -1; - meta->comp_method = meta->version_need = -1; - meta->crc = crc; - meta->uncomp_size = size; - meta->comp_size = zstr.total_out; - - deflateEnd(&zstr); - end = 1; - } - } - - } - else { /* we get compressed data */ - while ((n=se->ch_func(se->ch_data, b1, BUFSIZE, ZIP_CMD_READ)) > 0) { - size += n; - if (_zip_fwrite(b1, 1, n, zf->zp) < 0) - return -1; - } - if (n < 0) - return -1; - if (se->ch_func(se->ch_data, meta, 0, ZIP_CMD_META) < 0) - return -1; - meta->comp_size = size; - } - - se->ch_func(se->ch_data, NULL, 0, ZIP_CMD_CLOSE); - free(se->ch_data); - se->ch_func = NULL; - se->ch_data = NULL; - - if (fseek(zf->zp, zf->entry[idx].meta->local_offset, SEEK_SET) < 0) { - zip_err = ZERR_SEEK; - return -1; - } - - meta->local_offset = -1; - _zip_merge_meta_fix(zf->entry[idx].meta, meta); - if (se->ch_meta) { - se->ch_meta->local_offset = se->ch_meta->comp_method - = se->ch_meta->uncomp_size = se->ch_meta->comp_size - = se->ch_meta->crc = -1; - _zip_merge_meta_fix(zf->entry[idx].meta, se->ch_meta); - } - zip_free_meta(meta); - - if (_zip_writecdentry(zf->zp, zf->entry+idx, 1) != 0) { - zip_err = ZERR_WRITE; - return -1; - } - - if (fseek(zf->zp, 0, SEEK_END) < 0) { - zip_err = ZERR_SEEK; - return -1; - } - - zf->nentry++; - return 0; -} - - - -static int -_zip_fwrite(char *b, int s, int n, FILE *f) -{ - int ret, writ; - - writ = 0; - - while (writ<n) { - if ((ret=fwrite(b, s, n-writ, f)) < 0) { - zip_err = ZERR_WRITE; - return ret; - } - writ += ret; - } - - return writ; -} - - - -static int -_zip_writecdir(struct zip *zfp) -{ - int i; - long cd_offset, cd_size; - - cd_offset = ftell(zfp->zp); - - for (i=0; i<zfp->nentry; i++) { - if (_zip_writecdentry(zfp->zp, zfp->entry+i, 0) != 0) { - zip_err = ZERR_WRITE; - return -1; - } - } - - cd_size = ftell(zfp->zp) - cd_offset; - - clearerr(zfp->zp); - fprintf(zfp->zp, EOCD_MAGIC); - fprintf(zfp->zp, "%c%c%c%c", 0, 0, 0, 0); - _zip_write2(zfp->zp, zfp->nentry); - _zip_write2(zfp->zp, zfp->nentry); - _zip_write4(zfp->zp, cd_size); - _zip_write4(zfp->zp, cd_offset); - _zip_write2(zfp->zp, zfp->comlen); - _zip_writestr(zfp->zp, zfp->com, zfp->comlen); - - return 0; -} - - - -static void -_zip_write2(FILE *fp, int i) -{ - putc(i&0xff, fp); - putc((i>>8)&0xff, fp); - - return; -} - - - -static void -_zip_write4(FILE *fp, int i) -{ - putc(i&0xff, fp); - putc((i>>8)&0xff, fp); - putc((i>>16)&0xff, fp); - putc((i>>24)&0xff, fp); - - return; -} - - - -static void -_zip_writestr(FILE *fp, char *str, int len) -{ -#if WIZ - int i; - for (i=0; i<len; i++) - putc(str[i], fp); -#else - fwrite(str, 1, len, fp); #endif - - return; -} - + offend = ftell(ft); -/* _zip_writecdentry: - if localp, writes local header for zfe to zf->zp, - else write central directory entry for zfe to zf->zp. - if after writing ferror(fp), return -1, else return 0.*/ - -static int -_zip_writecdentry(FILE *fp, struct zip_entry *zfe, int localp) -{ - int ltime, ldate; - - fprintf(fp, "%s", localp?LOCAL_MAGIC:CENTRAL_MAGIC); - - if (!localp) - _zip_write2(fp, zfe->meta->version_made); - _zip_write2(fp, zfe->meta->version_need); - _zip_write2(fp, zfe->meta->bitflags); - _zip_write2(fp, zfe->meta->comp_method); - _zip_u2d_time(zfe->meta->last_mod, &ldate, <ime); - _zip_write2(fp, ltime); - _zip_write2(fp, ldate); - - _zip_write4(fp, zfe->meta->crc); - _zip_write4(fp, zfe->meta->comp_size); - _zip_write4(fp, zfe->meta->uncomp_size); - - _zip_write2(fp, strlen(zfe->fn)); - if (localp) - _zip_write2(fp, zfe->meta->lef_len); - else { - _zip_write2(fp, zfe->meta->ef_len); - _zip_write2(fp, zfe->meta->fc_len); - _zip_write2(fp, zfe->meta->disknrstart); - _zip_write2(fp, zfe->meta->int_attr); - _zip_write4(fp, zfe->meta->ext_attr); - _zip_write4(fp, zfe->meta->local_offset); + if (fseek(ft, offstart, SEEK_SET) < 0) { + _zip_error_set(&za->error, ZERR_SEEK, errno); + return -1; } - _zip_writestr(fp, zfe->fn, strlen(zfe->fn)); - if (localp) { - if (zfe->meta->lef_len) - _zip_writestr(fp, zfe->meta->lef, zfe->meta->lef_len); - } - else { - if (zfe->meta->ef_len) - _zip_writestr(fp, zfe->meta->ef, zfe->meta->ef_len); - if (zfe->meta->fc_len) - _zip_writestr(fp, zfe->meta->fc, zfe->meta->fc_len); - } - - if (ferror(fp)) + if (_zip_dirent_write(de, ft, 1, &za->error) < 0) return -1; + if (fseek(ft, offend, SEEK_SET) < 0) { + _zip_error_set(&za->error, ZERR_SEEK, errno); + return -1; + } + return 0; } -static struct zip_entry * -_zip_create_entry(struct zip *dest, struct zip_entry *se, - char *name, struct zip_meta *meta) +static int +add_data_comp(zip_read_func rf, void *ud, struct zip_dirent *de, FILE *ft, + struct zip_error *error) { - struct zip_entry *de; + char buf[8192]; + ssize_t n; + struct zip_stat st; - if (!dest) - return NULL; - - if ((de=_zip_new_entry(dest)) == NULL) - return NULL; - - if (!se) { - /* set default values for central directory entry */ - de->meta->version_made = 20; - de->meta->version_need = 20; - /* maximum compression */ - de->meta->bitflags = 2; - /* deflate algorithm */ - de->meta->comp_method = 8; - de->meta->last_mod = time(NULL)+1; - de->meta->fc_len = 0; - de->meta->ef_len = 0; - de->meta->lef_len = 0; - de->meta->disknrstart = 0; - /* binary data */ - de->meta->int_attr = 0; - /* init CRC-32, compressed and uncompressed size - XXX: will be updated later */ - de->meta->crc = crc32(0, 0, 0); - de->meta->comp_size = 0; - de->meta->uncomp_size = 0; - de->meta->ext_attr = 0; - de->meta->ef = NULL; - de->meta->lef = NULL; - de->meta->fc = NULL; - } else { - /* copy values from original zf_entry */ - de->meta->version_made = se->meta->version_made; - de->meta->version_need = se->meta->version_need; - de->meta->bitflags = se->meta->bitflags; - de->meta->comp_method = se->meta->comp_method; - de->meta->last_mod = se->meta->last_mod; - de->meta->disknrstart = se->meta->disknrstart; - de->meta->int_attr = se->meta->int_attr; - de->meta->crc = se->meta->crc; - de->meta->comp_size = se->meta->comp_size; - de->meta->uncomp_size = se->meta->uncomp_size; - de->meta->ext_attr = se->meta->ext_attr; - if (se->meta->ef_len != (unsigned short)-1 && se->meta->ef) { - de->meta->ef_len = se->meta->ef_len; - de->meta->ef = (char *)_zip_memdup(se->meta->ef, - se->meta->ef_len); - } - else { - de->meta->ef_len = 0; - de->meta->ef = NULL; - } - if (se->meta->lef_len != (unsigned short)-1 && se->meta->lef) { - de->meta->lef_len = se->meta->lef_len; - de->meta->lef = (char *)_zip_memdup(se->meta->lef, - se->meta->lef_len); - } - else { - de->meta->lef_len = 0; - de->meta->lef = NULL; - } - if (se->meta->fc_len != (unsigned short)-1 && se->meta->fc) { - de->meta->fc_len = se->meta->fc_len; - de->meta->fc = (char *)_zip_memdup(se->meta->fc, - se->meta->fc_len); - } - else { - de->meta->fc_len = 0; - de->meta->fc = NULL; - } + if (rf(ud, &st, sizeof(st), ZIP_CMD_STAT) < 0) { + /* XXX: set error */ + return -1; } + + de->comp_size = 0; + while ((n=rf(ud, buf, sizeof(buf), ZIP_CMD_READ)) > 0) { + if (fwrite(buf, 1, n, ft) != n) { + _zip_error_set(error, ZERR_WRITE, errno); + return -1; + } - de->meta->local_offset = ftell(dest->zp); - - if (name) - de->fn = strdup(name); - else if (se && se->fn) - de->fn = strdup(se->fn); - else { - de->fn = strdup("-"); + de->comp_size += n; } + if (n < 0) { + /* XXX: set error */ + return -1; + } - if (!de->fn) { - dest->nentry--; - zip_err = ZERR_MEMORY; - return NULL; - } + de->comp_method = st.comp_method; + /* de->last_mod = st.mtime; */ + de->crc = st.crc; + de->uncomp_size = st.size; - if (_zip_merge_meta(de->meta, meta) < 0) { - dest->nentry--; - return NULL; - } - - return de; + return 0; } -static void -_zip_u2d_time(time_t time, int *ddate, int *dtime) +static int +add_data_uncomp(zip_read_func rf, void *ud, struct zip_dirent *de, FILE *ft, + struct zip_error *error) { - struct tm *tm; + char b1[8192], b2[8192]; + int end, flush, ret; + ssize_t n; + z_stream zstr; - tm = localtime(&time); - *ddate = ((tm->tm_year+1900-1980)<<9)+ ((tm->tm_mon+1)<<5) - + tm->tm_mday; - *dtime = ((tm->tm_hour)<<11)+ ((tm->tm_min)<<5) - + ((tm->tm_sec)>>1); + /* ZIP_CMD_STAT for mtime? */ - return; + de->comp_method = ZIP_CM_DEFLATE; + de->comp_size = de->uncomp_size = 0; + de->crc = crc32(0, NULL, 0); + + zstr.zalloc = Z_NULL; + zstr.zfree = Z_NULL; + zstr.opaque = NULL; + zstr.avail_in = 0; + zstr.avail_out = 0; + + /* -15: undocumented feature of zlib to _not_ write a zlib header */ + deflateInit2(&zstr, Z_BEST_COMPRESSION, Z_DEFLATED, -15, 9, + Z_DEFAULT_STRATEGY); + + zstr.next_out = b2; + zstr.avail_out = sizeof(b2); + zstr.avail_in = 0; + + flush = 0; + end = 0; + while (!end) { + if (zstr.avail_in == 0 && !flush) { + if ((n=rf(ud, b1, sizeof(b1), ZIP_CMD_READ)) < 0) { + /* XXX: set error */ + deflateEnd(&zstr); + return -1; + } + if (n > 0) { + zstr.avail_in = n; + zstr.next_in = b1; + de->uncomp_size += n; + de->crc = crc32(de->crc, b1, n); + } + else + flush = Z_FINISH; + } + + ret = deflate(&zstr, flush); + if (ret != Z_OK && ret != Z_STREAM_END) { + _zip_error_set(error, ZERR_ZLIB, ret); + return -1; + } + + if (zstr.avail_out != sizeof(b2)) { + n = sizeof(b2) - zstr.avail_out; + + if (fwrite(b2, 1, n, ft) != n) { + _zip_error_set(error, ZERR_WRITE, errno); + return -1; + } + + zstr.next_out = b2; + zstr.avail_out = sizeof(b2); + de->comp_size += n; + } + + if (ret == Z_STREAM_END) { + deflateEnd(&zstr); + end = 1; + } + } + + return 0; } -int -_zip_local_header_read(struct zip *zf, int idx) +static int +copy_data(FILE *fs, off_t len, FILE *ft, struct zip_error *error) { - struct zip_entry *ze; - - if (zf->entry[idx].meta->lef_len != 0) + char buf[8192]; + int n, nn; + + if (len == 0) return 0; - if ((ze=_zip_new_entry(NULL)) == NULL) { - zip_err = ZERR_MEMORY; - return -1; + while (len > 0) { + nn = len > sizeof(buf) ? sizeof(buf) : len; + if ((n=fread(buf, 1, nn, fs)) < 0) { + _zip_error_set(error, ZERR_READ, errno); + return -1; + } + + if (fwrite(buf, 1, n, ft) != n) { + _zip_error_set(error, ZERR_WRITE, errno); + return -1; + } + + len -= n; } - if (fseek(zf->zp, zf->entry[idx].meta->local_offset, SEEK_SET) < 0) { - zip_err = ZERR_SEEK; - return -1; - } - - if (_zip_readcdentry(zf->zp, ze, NULL, 0, 1, 1) < 0) - return -1; - - zf->entry[idx].meta->lef_len = ze->meta->lef_len; - zf->entry[idx].meta->lef = ze->meta->lef; - ze->meta->lef = NULL; - _zip_free_entry(ze); - return 0; }
diff --git a/lib/zip_delete.c b/lib/zip_delete.c index c430788..8913ec9 100644 --- a/lib/zip_delete.c +++ b/lib/zip_delete.c
@@ -1,5 +1,5 @@ /* - $NiH: zip_delete.c,v 1.10 2003/10/03 08:34:11 dillo Exp $ + $NiH: zip_delete.c,v 1.11.4.1 2004/03/20 09:54:05 dillo Exp $ zip_delete.c -- delete file from zip archive Copyright (C) 1999 Dieter Baron and Thomas Klausner @@ -51,7 +51,6 @@ if (zip_unchange(zf, idx) != 0) return -1; - zf->changes = 1; zf->entry[idx].state = ZIP_ST_DELETED; return 0;
diff --git a/lib/zip_dirent.c b/lib/zip_dirent.c new file mode 100644 index 0000000..6335053 --- /dev/null +++ b/lib/zip_dirent.c
@@ -0,0 +1,531 @@ +/* + $NiH: zip_dirent.c,v 1.1.2.10 2004/04/13 19:47:58 dillo Exp $ + + zip_dirent.c -- read directory entry (local or central), clean dirent + Copyright (C) 1999, 2003, 2004 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at <nih@giga.or.at> + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + + + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <errno.h> +#include <unistd.h> +#include <sys/types.h> +#include <sys/stat.h> + +#include "zip.h" +#include "zipint.h" + +static time_t _zip_d2u_time(int, int); +static char *_zip_readfpstr(FILE *, int, int, struct zip_error *); +static char *_zip_readstr(unsigned char **, int, int, struct zip_error *); +static void _zip_u2d_time(time_t, int *, int *); +static void _zip_write2(unsigned short, FILE *); +static void _zip_write4(unsigned int, FILE *); + + + +void +_zip_cdir_free(struct zip_cdir *cd) +{ + int i; + + if (!cd) + return; + + for (i=0; i<cd->nentry; i++) + _zip_dirent_finalize(cd->entry+i); + free(cd->comment); + free(cd->entry); + free(cd); +} + + + +struct zip_cdir * +_zip_cdir_new(int nentry, struct zip_error *error) +{ + struct zip_cdir *cd; + + if ((cd=malloc(sizeof(*cd))) == NULL) { + _zip_error_set(error, ZERR_MEMORY, 0); + return NULL; + } + + if ((cd->entry=malloc(sizeof(*(cd->entry))*nentry)) == NULL) { + _zip_error_set(error, ZERR_MEMORY, 0); + free(cd); + return NULL; + } + + /* entries must be initialized by caller */ + + cd->nentry = nentry; + cd->size = cd->offset = 0; + cd->comment = NULL; + cd->comment_len = 0; + + return cd; +} + + + +int +_zip_cdir_write(struct zip_cdir *cd, FILE *fp, struct zip_error *error) +{ + int i; + + cd->offset = ftell(fp); + + for (i=0; i<cd->nentry; i++) { + if (_zip_dirent_write(cd->entry+i, fp, 0, error) != 0) + return -1; + } + + cd->size = ftell(fp) - cd->offset; + + /* clearerr(fp); */ + fwrite(EOCD_MAGIC, 1, 4, fp); + _zip_write4(0, fp); + _zip_write2(cd->nentry, fp); + _zip_write2(cd->nentry, fp); + _zip_write4(cd->size, fp); + _zip_write4(cd->offset, fp); + _zip_write2(cd->comment_len, fp); + fwrite(cd->comment, 1, cd->comment_len, fp); + + if (ferror(fp)) { + _zip_error_set(error, ZERR_WRITE, errno); + return -1; + } + + return 0; +} + + + +void +_zip_dirent_finalize(struct zip_dirent *zde) +{ + free(zde->filename); + zde->filename = NULL; + free(zde->extrafield); + zde->extrafield = NULL; + free(zde->comment); + zde->comment = NULL; +} + + + +void +_zip_dirent_init(struct zip_dirent *de) +{ + de->version_madeby = 0; /* XXX */ + de->version_needed = 0; /* XXX */ + de->bitflags = 0; + de->comp_method = 0; + de->last_mod = 0; + de->crc = 0; + de->comp_size = 0; + de->uncomp_size = 0; + de->filename = NULL; + de->filename_len = 0; + de->extrafield = NULL; + de->extrafield_len = 0; + de->comment = NULL; + de->comment_len = 0; + de->disk_number = 0; + de->int_attrib = 0; + de->ext_attrib = 0; + de->offset = 0; +} + + + +/* _zip_dirent_read(zde, fp, bufp, left, localp, error): + Fills the zip directory entry zde. + + If bufp is non-NULL, data is taken from there and bufp is advanced + by the amount of data used; no more than left bytes are used. + Otherwise data is read from fp as needed. + + If localp != 0, it reads a local header instead of a central + directory entry. + + Returns 0 if successful. On error, error is filled in and -1 is + returned. +*/ + +int +_zip_dirent_read(struct zip_dirent *zde, FILE *fp, + unsigned char **bufp, int left, int localp, + struct zip_error *error) +{ + unsigned char buf[CDENTRYSIZE]; + unsigned char *cur; + unsigned short dostime, dosdate; + int size; + + if (localp) + size = LENTRYSIZE; + else + size = CDENTRYSIZE; + + if (bufp) { + /* use data from buffer */ + cur = *bufp; + if (left < size) { + _zip_error_set(error, ZERR_NOZIP, 0); + return -1; + } + } + else { + /* read entry from disk */ + if ((fread(buf, 1, size, fp)<size)) { + _zip_error_set(error, ZERR_READ, errno); + return -1; + } + left = size; + cur = buf; + } + + if (memcmp(cur, (localp ? LOCAL_MAGIC : CENTRAL_MAGIC), 4) != 0) { + /* XXX: zip_err = ZERR_NOZIP; */ + return -1; + } + cur += 4; + + + /* convert buffercontents to zip_dirent */ + + if (!localp) + zde->version_madeby = _zip_read2(&cur); + else + zde->version_madeby = 0; + zde->version_needed = _zip_read2(&cur); + zde->bitflags = _zip_read2(&cur); + zde->comp_method = _zip_read2(&cur); + + /* convert to time_t */ + dostime = _zip_read2(&cur); + dosdate = _zip_read2(&cur); + zde->last_mod = _zip_d2u_time(dostime, dosdate); + + zde->crc = _zip_read4(&cur); + zde->comp_size = _zip_read4(&cur); + zde->uncomp_size = _zip_read4(&cur); + + zde->filename_len = _zip_read2(&cur); + zde->extrafield_len = _zip_read2(&cur); + + if (localp) { + zde->comment_len = 0; + zde->disk_number = 0; + zde->int_attrib = 0; + zde->ext_attrib = 0; + zde->offset = 0; + } else { + zde->comment_len = _zip_read2(&cur); + zde->disk_number = _zip_read2(&cur); + zde->int_attrib = _zip_read2(&cur); + zde->ext_attrib = _zip_read4(&cur); + zde->offset = _zip_read4(&cur); + } + + zde->filename = NULL; + zde->extrafield = NULL; + zde->comment = NULL; + + if (bufp) { + if (left < CDENTRYSIZE + (zde->filename_len+zde->extrafield_len + +zde->comment_len)) { + _zip_error_set(error, ZERR_NOZIP, 0); + return -1; + } + + if (zde->filename_len) { + zde->filename = _zip_readstr(&cur, zde->filename_len, 1, error); + if (!zde->filename) + return -1; + } + + if (zde->extrafield_len) { + zde->extrafield = _zip_readstr(&cur, zde->extrafield_len, 0, + error); + if (!zde->extrafield) + return -1; + } + + if (zde->comment_len) { + zde->comment = _zip_readstr(&cur, zde->comment_len, 0, error); + if (!zde->comment) + return -1; + } + } + else { + if (zde->filename_len) { + zde->filename = _zip_readfpstr(fp, zde->filename_len, 1, error); + if (!zde->filename) + return -1; + } + + if (zde->extrafield_len) { + zde->extrafield = _zip_readfpstr(fp, zde->extrafield_len, 0, + error); + if (!zde->extrafield) + return -1; + } + + if (zde->comment_len) { + zde->comment = _zip_readfpstr(fp, zde->comment_len, 0, error); + if (!zde->comment) + return -1; + } + } + + if (bufp) + *bufp = cur; + + return 0; +} + + + +/* _zip_dirent_write(zde, fp, localp, error): + Writes zip directory entry zde to file fp. + + If localp != 0, it writes a local header instead of a central + directory entry. + + Returns 0 if successful. On error, error is filled in and -1 is + returned. +*/ + +int +_zip_dirent_write(struct zip_dirent *zde, FILE *fp, int localp, + struct zip_error *error) +{ + int dostime, dosdate; + + fwrite(localp ? LOCAL_MAGIC : CENTRAL_MAGIC, 1, 4, fp); + + if (!localp) + _zip_write2(zde->version_madeby, fp); + _zip_write2(zde->version_needed, fp); + _zip_write2(zde->bitflags, fp); + _zip_write2(zde->comp_method, fp); + + _zip_u2d_time(zde->last_mod, &dostime, &dosdate); + _zip_write2(dostime, fp); + _zip_write2(dosdate, fp); + + _zip_write4(zde->crc, fp); + _zip_write4(zde->comp_size, fp); + _zip_write4(zde->uncomp_size, fp); + + _zip_write2(zde->filename_len, fp); + _zip_write2(zde->extrafield_len, fp); + + if (!localp) { + _zip_write2(zde->comment_len, fp); + _zip_write2(zde->disk_number, fp); + _zip_write2(zde->int_attrib, fp); + _zip_write4(zde->ext_attrib, fp); + _zip_write4(zde->offset, fp); + } + + if (zde->filename_len) + fwrite(zde->filename, 1, zde->filename_len, fp); + + if (zde->extrafield_len) + fwrite(zde->extrafield, 1, zde->extrafield_len, fp); + + if (!localp) { + if (zde->comment_len) + fwrite(zde->comment, 1, zde->comment_len, fp); + } + + if (ferror(fp)) { + _zip_error_set(error, ZERR_WRITE, errno); + return -1; + } + + return 0; +} + + + +static time_t +_zip_d2u_time(int dtime, int ddate) +{ + struct tm *tm; + time_t now; + + now = time(NULL); + tm = localtime(&now); + + tm->tm_year = ((ddate>>9)&127) + 1980 - 1900; + tm->tm_mon = ((ddate>>5)&15) - 1; + tm->tm_mday = ddate&31; + + tm->tm_hour = (dtime>>11)&31; + tm->tm_min = (dtime>>5)&63; + tm->tm_sec = (dtime<<1)&62; + + return mktime(tm); +} + + + +unsigned short +_zip_read2(unsigned char **a) +{ + unsigned short ret; + + ret = (*a)[0]+((*a)[1]<<8); + *a += 2; + + return ret; +} + + + +unsigned int +_zip_read4(unsigned char **a) +{ + unsigned int ret; + + ret = ((((((*a)[3]<<8)+(*a)[2])<<8)+(*a)[1])<<8)+(*a)[0]; + *a += 4; + + return ret; +} + + + +static char * +_zip_readfpstr(FILE *fp, int len, int nulp, struct zip_error *error) +{ + char *r, *o; + + r = (char *)malloc(nulp?len+1:len); + if (!r) { + _zip_error_set(error, ZERR_MEMORY, 0); + return NULL; + } + + if (fread(r, 1, len, fp)<len) { + free(r); + _zip_error_set(error, ZERR_READ, errno); + return NULL; + } + + if (nulp) { + /* elephant */ + /* XXX: what does this do? */ + r[len] = 0; + o = r-1; + while (((o=memchr(o+1, 0, r+len-(o+1))) < r+len) && o) + *o = ' '; + } + + return r; +} + + + +static char * +_zip_readstr(unsigned char **buf, int len, int nulp, struct zip_error *error) +{ + char *r, *o; + + r = (char *)malloc(nulp?len+1:len); + if (!r) { + _zip_error_set(error, ZERR_MEMORY, 0); + return NULL; + } + + memcpy(r, *buf, len); + *buf += len; + + if (nulp) { + /* elephant */ + /* XXX: what does this do? */ + r[len] = 0; + o = r-1; + while (((o=memchr(o+1, 0, r+len-(o+1))) < r+len) && o) + *o = ' '; + } + + return r; +} + + + +static void +_zip_write2(unsigned short i, FILE *fp) +{ + putc(i&0xff, fp); + putc((i>>8)&0xff, fp); + + return; +} + + + +static void +_zip_write4(unsigned int i, FILE *fp) +{ + putc(i&0xff, fp); + putc((i>>8)&0xff, fp); + putc((i>>16)&0xff, fp); + putc((i>>24)&0xff, fp); + + return; +} + + + +static void +_zip_u2d_time(time_t time, int *dtime, int *ddate) +{ + struct tm *tm; + + tm = localtime(&time); + *ddate = ((tm->tm_year+1900-1980)<<9) + ((tm->tm_mon+1)<<5) + + tm->tm_mday; + *dtime = ((tm->tm_hour)<<11) + ((tm->tm_min)<<5) + + ((tm->tm_sec)>>1); + + return; +}
diff --git a/lib/zip_error.c b/lib/zip_error.c index 3d5c3e1..99a2f77 100644 --- a/lib/zip_error.c +++ b/lib/zip_error.c
@@ -1,5 +1,5 @@ /* - $NiH: zip_error.c,v 1.2 2003/10/06 02:50:05 dillo Exp $ + $NiH: zip_error.c,v 1.3.4.1 2004/03/23 16:07:21 dillo Exp $ zip_error.c -- struct zip_error helper functions Copyright (C) 1999, 2003 Dieter Baron and Thomas Klausner @@ -85,6 +85,8 @@ void _zip_error_set(struct zip_error *err, int ze, int se) { - err->zip_err = ze; - err->sys_err = se; + if (err) { + err->zip_err = ze; + err->sys_err = se; + } }
diff --git a/lib/zip_error_str.c b/lib/zip_error_str.c index 548b2c0..dfe4db3 100644 --- a/lib/zip_error_str.c +++ b/lib/zip_error_str.c
@@ -1,5 +1,5 @@ /* - $NiH$ + $NiH: zip_error_str.c,v 1.1.4.1 2004/03/20 09:54:05 dillo Exp $ zip_error_str.c -- get string representation of zip error code Copyright (C) 1999, 2003 Dieter Baron and Thomas Klausner @@ -46,7 +46,7 @@ int -zip_error_str(char *buf, int len, int ze, int se) +zip_error_str(char *buf, size_t len, int ze, int se) { const char *zs, *ss;
diff --git a/lib/zip_fclose.c b/lib/zip_fclose.c index 2bca2a6..6fd1ed8 100644 --- a/lib/zip_fclose.c +++ b/lib/zip_fclose.c
@@ -1,5 +1,5 @@ /* - $NiH: zip_fclose.c,v 1.7 2003/10/02 14:13:29 dillo Exp $ + $NiH: zip_fclose.c,v 1.8.4.1 2004/04/13 19:47:58 dillo Exp $ zip_fclose.c -- close file in zip archive Copyright (C) 1999 Dieter Baron and Thomas Klausner @@ -61,10 +61,10 @@ } /* if EOF, compare CRC */ - if (zff->flags == -1) + if (zff->flags & ZIP_ZF_EOF) ret = (zff->crc_orig == zff->crc); else - ret = zff->flags; + ret = zff->error.zip_err; free(zff); return ret;
diff --git a/lib/zip_free_meta.c b/lib/zip_file_get_offset.c similarity index 62% rename from lib/zip_free_meta.c rename to lib/zip_file_get_offset.c index 5733ed5..2d25c3d 100644 --- a/lib/zip_free_meta.c +++ b/lib/zip_file_get_offset.c
@@ -1,8 +1,8 @@ /* - $NiH: zip_free_meta.c,v 1.7 2003/03/16 10:21:39 wiz Exp $ + $NiH: zip_file_get_offset.c,v 1.1.2.2 2004/04/06 20:27:22 dillo Exp $ - zip_free_meta.c -- free struct zip_meta - Copyright (C) 1999 Dieter Baron and Thomas Klausner + zip_file_get_offset.c -- get offset of file data in archive. + Copyright (C) 1999, 2003, 2004 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at <nih@giga.or.at> @@ -35,20 +35,44 @@ +#include <stdio.h> #include <stdlib.h> +#include <string.h> +#include <errno.h> +#include <unistd.h> +#include <sys/types.h> +#include <sys/stat.h> + #include "zip.h" +#include "zipint.h" -void -zip_free_meta(struct zip_meta *meta) + + +/* _zip_file_get_offset(za, ze): + Returns the offset of the file data for entry ze. + + On error, fills in za->error and returns 0. +*/ + +unsigned int +_zip_file_get_offset(struct zip *za, int idx) { - if (!meta) - return; - - free(meta->ef); - free(meta->lef); - free(meta->fc); + struct zip_dirent de; + unsigned int offset; - free(meta); - - return; + offset = za->cdir->entry[idx].offset; + + if (fseek(za->zp, offset, SEEK_SET) != 0) { + _zip_error_set(&za->error, ZERR_SEEK, errno); + return 0; + } + + if (_zip_dirent_read(&de, za->zp, NULL, 0, 1, &za->error) != 0) + return 0; + + offset += LENTRYSIZE + de.filename_len + de.extrafield_len; + + _zip_dirent_finalize(&de); + + return offset; }
diff --git a/lib/zip_fopen.c b/lib/zip_fopen.c index 3c31bce..3e542cd 100644 --- a/lib/zip_fopen.c +++ b/lib/zip_fopen.c
@@ -1,5 +1,5 @@ /* - $NiH: zip_fopen.c,v 1.7 2003/10/03 08:34:11 dillo Exp $ + $NiH: zip_fopen.c,v 1.8.4.1 2004/04/08 16:53:07 dillo Exp $ zip_fopen.c -- open file in zip archvie for reading Copyright (C) 1999, 2003 Dieter Baron and Thomas Klausner @@ -48,5 +48,5 @@ if ((idx=zip_name_locate(za, fname, flags)) < 0) return NULL; - return zip_fopen_index(za, idx); + return zip_fopen_index(za, idx, flags); }
diff --git a/lib/zip_fopen_index.c b/lib/zip_fopen_index.c index 193d9b2..c24af9f 100644 --- a/lib/zip_fopen_index.c +++ b/lib/zip_fopen_index.c
@@ -1,5 +1,5 @@ /* - $NiH: zip_fopen_index.c,v 1.14 2003/10/06 16:37:41 dillo Exp $ + $NiH: zip_fopen_index.c,v 1.15.4.10 2004/04/14 09:21:33 dillo Exp $ zip_fopen_index.c -- open file in zip archive for reading by index Copyright (C) 1999 Dieter Baron and Thomas Klausner @@ -47,10 +47,10 @@ struct zip_file * -zip_fopen_index(struct zip *zf, int fileno) +zip_fopen_index(struct zip *zf, int fileno, int flags) { - unsigned char buf[4]; int len, ret; + int zfflags; struct zip_file *zff; if ((fileno < 0) || (fileno >= zf->nentry)) { @@ -58,78 +58,71 @@ return NULL; } -#if 0 - if (zf->entry[fileno].state != ZIP_ST_UNCHANGED - && zf->entry[fileno].state != ZIP_ST_RENAMED) { + if ((flags & ZIP_FL_UNCHANGED) == 0 + && ZIP_ENTRY_DATA_CHANGED(zf->entry+fileno)) { _zip_error_set(&zf->error, ZERR_CHANGED, 0); return NULL; } -#endif - if ((zf->entry[fileno].meta->comp_method != 0) - && (zf->entry[fileno].meta->comp_method != 8)) { - _zip_error_set(&zf->error, ZERR_COMPNOTSUPP, 0); - return NULL; + if ((flags & ZIP_FL_COMPRESSED) + || (zf->cdir->entry[fileno].comp_method == ZIP_CM_STORE)) + zfflags = ZIP_ZF_COMP; + else { + if (zf->cdir->entry[fileno].comp_method != ZIP_CM_DEFLATE) { + _zip_error_set(&zf->error, ZERR_COMPNOTSUPP, 0); + return NULL; + } + zfflags = 0; } zff = _zip_file_new(zf); - zff->name = zf->entry[fileno].fn; - zff->method = zf->entry[fileno].meta->comp_method; - zff->bytes_left = zf->entry[fileno].meta->uncomp_size; - zff->cbytes_left = zf->entry[fileno].meta->comp_size; - zff->crc_orig = zf->entry[fileno].meta->crc; + zff->flags = zfflags; + /* zff->name = zf->cdir->entry[fileno].filename; */ + zff->method = zf->cdir->entry[fileno].comp_method; + zff->bytes_left = zf->cdir->entry[fileno].uncomp_size; + zff->cbytes_left = zf->cdir->entry[fileno].comp_size; + zff->crc_orig = zf->cdir->entry[fileno].crc; - /* go to start of actual data */ - if (fseek(zf->zp, zf->entry[fileno].meta->local_offset+LENTRYSIZE-4, - SEEK_SET) < 0) { - _zip_error_set(&zf->error, ZERR_SEEK, errno); - zip_fclose(zff); - return NULL; - } - len = fread(buf, 1, 4, zf->zp); - if (len != 4) { - _zip_error_set(&zf->error, ZERR_READ, errno); + if ((zff->fpos=_zip_file_get_offset(zf, fileno)) == 0) { zip_fclose(zff); return NULL; } - zff->fpos = zf->entry[fileno].meta->local_offset+LENTRYSIZE; - zff->fpos += (buf[3]<<8)+buf[2]+(buf[1]<<8)+buf[0]; + if (zff->flags & ZIP_ZF_COMP) + zff->bytes_left = zff->cbytes_left; + else { + /* XXX: don't use BUFSIZE */ + if ((zff->buffer=(char *)malloc(BUFSIZE)) == NULL) { + _zip_error_set(&zf->error, ZERR_MEMORY, 0); + zip_fclose(zff); + return NULL; + } + + len = _zip_file_fillbuf(zff->buffer, BUFSIZE, zff); + if (len <= 0) { + _zip_error_copy(&zf->error, &zff->error); + zip_fclose(zff); + return NULL; + } + + if ((zff->zstr = (z_stream *)malloc(sizeof(z_stream))) == NULL) { + _zip_error_set(&zf->error, ZERR_MEMORY, 0); + zip_fclose(zff); + return NULL; + } + zff->zstr->zalloc = Z_NULL; + zff->zstr->zfree = Z_NULL; + zff->zstr->opaque = NULL; + zff->zstr->next_in = zff->buffer; + zff->zstr->avail_in = len; - if ((zf->entry[fileno].meta->comp_method == 0) - || (zff->bytes_left == 0)) - return zff; - - if ((zff->buffer=(char *)malloc(BUFSIZE)) == NULL) { - _zip_error_set(&zf->error, ZERR_MEMORY, 0); - zip_fclose(zff); - return NULL; - } - - len = _zip_file_fillbuf (zff->buffer, BUFSIZE, zff); - if (len <= 0) { - _zip_error_copy(&zf->error, &zff->error); - zip_fclose(zff); - return NULL; - } - - if ((zff->zstr = (z_stream *)malloc(sizeof(z_stream))) == NULL) { - _zip_error_set(&zf->error, ZERR_MEMORY, 0); - zip_fclose(zff); - return NULL; - } - zff->zstr->zalloc = Z_NULL; - zff->zstr->zfree = Z_NULL; - zff->zstr->opaque = NULL; - zff->zstr->next_in = zff->buffer; - zff->zstr->avail_in = len; - - /* negative value to tell zlib that there is no header */ - if ((ret=inflateInit2(zff->zstr, -MAX_WBITS)) != Z_OK) { - _zip_error_set(&zf->error, ZERR_ZLIB, ret); - zip_fclose(zff); - return NULL; + /* negative value to tell zlib that there is no header */ + if ((ret=inflateInit2(zff->zstr, -MAX_WBITS)) != Z_OK) { + _zip_error_set(&zf->error, ZERR_ZLIB, ret); + zip_fclose(zff); + return NULL; + } } return zff; @@ -138,17 +131,18 @@ int -_zip_file_fillbuf(char *buf, int buflen, struct zip_file *zff) +_zip_file_fillbuf(void *buf, size_t buflen, struct zip_file *zff) { int i, j; - if (zff->flags != 0) + if (zff->error.zip_err != ZERR_OK) return -1; - if (zff->cbytes_left <= 0 || buflen <= 0) + + if ((zff->flags & ZIP_ZF_EOF) || zff->cbytes_left <= 0 || buflen <= 0) return 0; if (fseek(zff->zf->zp, zff->fpos, SEEK_SET) < 0) { - zff->flags = ZERR_SEEK; + _zip_error_set(&zff->error, ZERR_SEEK, errno); return -1; } if (buflen < zff->cbytes_left) @@ -158,11 +152,11 @@ j = fread(buf, 1, i, zff->zf->zp); if (j == 0) { - zff->flags = ZERR_EOF; + _zip_error_set(&zff->error, ZERR_EOF, 0); j = -1; } else if (j < 0) - zff->flags = ZERR_READ; + _zip_error_set(&zff->error, ZERR_READ, errno); else { zff->fpos += j; zff->cbytes_left -= j; @@ -200,6 +194,7 @@ zf->file[zf->nfile++] = zff; zff->zf = zf; + _zip_error_init(&zff->error); zff->flags = 0; zff->crc = crc32(0L, Z_NULL, 0); zff->crc_orig = 0;
diff --git a/lib/zip_fread.c b/lib/zip_fread.c index 7950dc9..1e21326 100644 --- a/lib/zip_fread.c +++ b/lib/zip_fread.c
@@ -1,5 +1,5 @@ /* - $NiH: zip_fread.c,v 1.7 2003/03/16 10:21:39 wiz Exp $ + $NiH: zip_fread.c,v 1.8.4.3 2004/04/13 19:47:59 dillo Exp $ zip_fread.c -- read from file Copyright (C) 1999 Dieter Baron and Thomas Klausner @@ -40,30 +40,30 @@ -int -zip_fread(struct zip_file *zff, char *outbuf, int toread) +ssize_t +zip_fread(struct zip_file *zff, void *outbuf, size_t toread) { int len, out_before, ret; if (!zff) return -1; - if ((zff->flags == -1) || (toread == 0)) - return 0; - - if (zff->flags != 0) + if (zff->error.zip_err != 0) return -1; + if ((zff->flags & ZIP_ZF_EOF) || (toread == 0)) + return 0; + if (zff->bytes_left == 0) { - zff->flags = -1; + zff->flags |= ZIP_ZF_EOF; if (zff->crc != zff->crc_orig) { - zff->flags = ZERR_CRC; + _zip_error_set(&zff->error, ZERR_CRC, 0); return -1; } return 0; } - if (zff->method == 0) { + if (zff->flags & ZIP_ZF_COMP) { ret = _zip_file_fillbuf(outbuf, toread, zff); if (ret > 0) { zff->crc = crc32(zff->crc, outbuf, ret); @@ -90,16 +90,15 @@ if (len >= zff->bytes_left || len >= toread) { zff->crc = crc32(zff->crc, outbuf, len); zff->bytes_left -= len; - return(len); + return len; } break; case Z_BUF_ERROR: if (zff->zstr->avail_in == 0) { - /* read some more bytes */ len = _zip_file_fillbuf(zff->buffer, BUFSIZE, zff); if (len == 0) { - zff->flags = ZERR_INCONS; + _zip_error_set(&zff->error, ZERR_INCONS, 0); return -1; } else if (len < 0) @@ -108,13 +107,12 @@ zff->zstr->avail_in = len; continue; } - zff->flags = ZERR_ZLIB; - return -1; + /* fallthrough */ case Z_NEED_DICT: case Z_DATA_ERROR: case Z_STREAM_ERROR: case Z_MEM_ERROR: - zff->flags = ZERR_ZLIB; + _zip_error_set(&zff->error, ZERR_ZLIB, ret); return -1; } }
diff --git a/lib/zip_free.c b/lib/zip_free.c index e927466..38d8947 100644 --- a/lib/zip_free.c +++ b/lib/zip_free.c
@@ -1,5 +1,5 @@ /* - $NiH: zip_free.c,v 1.7 2003/10/06 16:37:41 dillo Exp $ + $NiH: zip_free.c,v 1.8.4.2 2004/04/08 16:55:36 dillo Exp $ zip_free.c -- free struct zip Copyright (C) 1999 Dieter Baron and Thomas Klausner @@ -59,8 +59,7 @@ if (zf->zp) fclose(zf->zp); - if (zf->com) - free(zf->com); + _zip_cdir_free(zf->cdir); if (zf->entry) { for (i=0; i<zf->nentry; i++) { @@ -72,7 +71,6 @@ for (i=0; i<zf->nfile; i++) { zf->file[i]->flags = ZERR_ZIPCLOSED; zf->file[i]->zf = NULL; - zf->file[i]->name = NULL; } free(zf->file);
diff --git a/lib/zip_free_entry.c b/lib/zip_free_entry.c index b725525..259befb 100644 --- a/lib/zip_free_entry.c +++ b/lib/zip_free_entry.c
@@ -1,5 +1,5 @@ /* - $NiH: zip_free_entry.c,v 1.8 2003/10/01 09:51:00 dillo Exp $ + $NiH: zip_free_entry.c,v 1.9.4.3 2004/04/06 20:30:05 dillo Exp $ zip_free_entry.c -- free struct zip_entry Copyright (C) 1999, 2003 Dieter Baron and Thomas Klausner @@ -49,15 +49,10 @@ ret = 0; - free(ze->fn); - free(ze->fn_old); + free(ze->ch_filename); - zip_free_meta(ze->meta); - zip_free_meta(ze->ch_meta); if (ze->ch_func) ret = ze->ch_func(ze->ch_data, NULL, 0, ZIP_CMD_CLOSE); - - free(ze->ch_data); return ret; }
diff --git a/lib/zip_get_name.c b/lib/zip_get_name.c index d9a88d7..b3672c9 100644 --- a/lib/zip_get_name.c +++ b/lib/zip_get_name.c
@@ -1,5 +1,5 @@ /* - $NiH: zip_get_name.c,v 1.5 2003/10/02 14:13:30 dillo Exp $ + $NiH: zip_get_name.c,v 1.6.4.1 2004/04/06 20:30:05 dillo Exp $ zip_get_name.c -- get filename for a file in zip file Copyright (C) 1999, 2003 Dieter Baron and Thomas Klausner @@ -48,5 +48,8 @@ return NULL; } - return zf->entry[idx].fn; + if (zf->entry[idx].ch_filename) + return zf->entry[idx].ch_filename; + + return zf->cdir->entry[idx].filename; }
diff --git a/lib/zip_merge_meta.c b/lib/zip_merge_meta.c deleted file mode 100644 index 9c101c4..0000000 --- a/lib/zip_merge_meta.c +++ /dev/null
@@ -1,127 +0,0 @@ -/* - $NiH: zip_merge_meta.c,v 1.7 2003/03/16 10:21:40 wiz Exp $ - - zip_merge_meta.c -- merge two meta information structures - Copyright (C) 1999 Dieter Baron and Thomas Klausner - - This file is part of libzip, a library to manipulate ZIP archives. - The authors can be contacted at <nih@giga.or.at> - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions - are met: - 1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the - distribution. - 3. The names of the authors may not be used to endorse or promote - products derived from this software without specific prior - written permission. - - THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS - OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY - DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER - IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN - IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - - - -#include <stdlib.h> -#include "zip.h" -#include "zipint.h" - -int -_zip_merge_meta_fix(struct zip_meta *dest, struct zip_meta *src) -{ - if (!src) - return 0; - if (!dest) { - zip_err = ZERR_INTERNAL; - return -1; - } - - if (src->version_made != (unsigned short)-1) - dest->version_made = src->version_made; - if (src->version_need != (unsigned short)-1) - dest->version_need = src->version_need; - if (src->bitflags != (unsigned short)-1) - dest->bitflags = src->bitflags; - if (src->comp_method != (unsigned short)-1) - dest->comp_method = src->comp_method; - if (src->disknrstart != (unsigned short)-1) - dest->disknrstart = src->disknrstart; - if (src->int_attr != (unsigned short)-1) - dest->int_attr = src->int_attr; - - if (src->crc != (unsigned int)-1) - dest->crc = src->crc; - if (src->uncomp_size != (unsigned int)-1) - dest->uncomp_size = src->uncomp_size; - if (src->comp_size != (unsigned int)-1) - dest->comp_size = src->comp_size; - if (src->ext_attr != (unsigned int)-1) - dest->ext_attr = src->ext_attr; - if (src->local_offset != (unsigned int)-1) - dest->local_offset = src->local_offset; - - if (src->last_mod != 0) - dest->last_mod = src->last_mod; - - return 0; -} - - - -int -_zip_merge_meta(struct zip_meta *dest, struct zip_meta *src) -{ - if (!src) - return 0; - if (!dest) { - zip_err = ZERR_INTERNAL; - return -1; - } - - _zip_merge_meta_fix(dest, src); - - if ((src->ef_len != (unsigned short)-1) && src->ef) { - free(dest->ef); - dest->ef = _zip_memdup(src->ef, src->ef_len); - if (!dest->ef) { - zip_err = ZERR_MEMORY; - return -1; - } - dest->ef_len = src->ef_len; - } - - if ((src->lef_len != (unsigned short)-1) && src->lef) { - free(dest->lef); - dest->lef = _zip_memdup(src->lef, src->lef_len); - if (!dest->lef) { - zip_err = ZERR_MEMORY; - return -1; - } - dest->lef_len = src->lef_len; - } - - if ((src->fc_len != (unsigned short)-1) && src->fc) { - free(dest->fc); - dest->fc = _zip_memdup(src->fc, src->fc_len); - if (!dest->fc) { - zip_err = ZERR_MEMORY; - return -1; - } - dest->fc_len = src->fc_len; - } - - return 0; -}
diff --git a/lib/zip_name_locate.c b/lib/zip_name_locate.c index eb7c9a9..07010dc 100644 --- a/lib/zip_name_locate.c +++ b/lib/zip_name_locate.c
@@ -1,5 +1,5 @@ /* - $NiH: zip_name_locate.c,v 1.8 2003/10/02 14:13:30 dillo Exp $ + $NiH: zip_name_locate.c,v 1.9.4.3 2004/04/14 13:58:52 dillo Exp $ zip_name_locate.c -- get index by name Copyright (C) 1999, 2003 Dieter Baron and Thomas Klausner @@ -46,19 +46,25 @@ zip_name_locate(struct zip *za, const char *fname, int flags) { int (*cmp)(); - const char *fn; + const char *fn, *p; int i; - cmp = (flags & ZIP_NAME_NOCASE) ? strcmp : strcasecmp; + if (fname == NULL) { + _zip_error_set(&za->error, ZERR_INVAL, 0); + return -1; + } + + cmp = (flags & ZIP_FL_NOCASE) ? strcmp : strcasecmp; + + /* XXX: honour ZIP_FL_UNCHANGED */ for (i=0; i<za->nentry; i++) { - if (flags & ZIP_NAME_NODIR) { + fn = zip_get_name(za, i); + if (flags & ZIP_FL_NODIR) { /* XXX: handle '\' */ - if ((fn=strrchr(za->entry[i].fn, '/')) == NULL) - fn = za->entry[i].fn; + if ((p=strrchr(fn, '/')) != NULL) + fn = p; } - else - fn = za->entry[i].fn; if (cmp(fname, fn) == 0) return i;
diff --git a/lib/zip_new.c b/lib/zip_new.c index 0c34f30..9129c20 100644 --- a/lib/zip_new.c +++ b/lib/zip_new.c
@@ -1,5 +1,5 @@ /* - $NiH: zip_new.c,v 1.5 2003/10/02 14:13:31 dillo Exp $ + $NiH: zip_new.c,v 1.6.4.3 2004/04/06 20:30:05 dillo Exp $ zip_new.c -- create and init struct zip Copyright (C) 1999 Dieter Baron and Thomas Klausner @@ -46,25 +46,23 @@ the new struct. */ struct zip * -_zip_new(int *errp) +_zip_new(struct zip_error *error) { - struct zip *zf; + struct zip *za; - zf = (struct zip *)malloc(sizeof(struct zip)); - if (!zf) { - if (errp) - *errp = ZERR_MEMORY; + za = (struct zip *)malloc(sizeof(struct zip)); + if (!za) { + _zip_error_set(error, ZERR_MEMORY, 0); return NULL; } - zf->zn = NULL; - zf->zp = NULL; - zf->comlen = zf->changes = 0; - zf->nentry = zf->nentry_alloc = zf->cd_size = zf->cd_offset = 0; - zf->nfile = zf->nfile_alloc = 0; - zf->com = NULL; - zf->entry = NULL; - zf->file = NULL; + za->zn = NULL; + za->zp = NULL; + za->nentry = za->nentry_alloc = 0; + za->nfile = za->nfile_alloc = 0; + za->cdir = NULL; + za->entry = NULL; + za->file = NULL; - return zf; + return za; }
diff --git a/lib/zip_new_entry.c b/lib/zip_new_entry.c index c006e45..0c59f51 100644 --- a/lib/zip_new_entry.c +++ b/lib/zip_new_entry.c
@@ -1,5 +1,5 @@ /* - $NiH: zip_new_entry.c,v 1.6 2003/10/01 09:51:00 dillo Exp $ + $NiH: zip_new_entry.c,v 1.7.4.4 2004/04/07 12:08:22 dillo Exp $ zip_new_entry.c -- create and init struct zip_entry Copyright (C) 1999, 2003 Dieter Baron and Thomas Klausner @@ -49,32 +49,31 @@ if (!zf) { ze = (struct zip_entry *)malloc(sizeof(struct zip_entry)); if (!ze) { - zip_err = ZERR_MEMORY; + _zip_error_set(&zf->error, ZERR_MEMORY, 0); return NULL; } - } else { + } + else { if (zf->nentry >= zf->nentry_alloc-1) { zf->nentry_alloc += 16; zf->entry = (struct zip_entry *)realloc(zf->entry, sizeof(struct zip_entry) * zf->nentry_alloc); if (!zf->entry) { - zip_err = ZERR_MEMORY; + _zip_error_set(&zf->error, ZERR_MEMORY, 0); return NULL; } } ze = zf->entry+zf->nentry; } - if ((ze->meta = zip_new_meta()) == NULL) - return NULL; - ze->fn = ze->fn_old = NULL; ze->state = ZIP_ST_UNCHANGED; + ze->ch_filename = NULL; ze->ch_func = NULL; ze->ch_data = NULL; - ze->ch_comp = -1; - ze->ch_meta = NULL; + ze->ch_flags = 0; + ze->ch_mtime = -1; if (zf) zf->nentry++;
diff --git a/lib/zip_new_meta.c b/lib/zip_new_meta.c deleted file mode 100644 index a2c5e5b..0000000 --- a/lib/zip_new_meta.c +++ /dev/null
@@ -1,61 +0,0 @@ -/* - $NiH: zip_new_meta.c,v 1.5 2003/03/16 10:21:40 wiz Exp $ - - zip_new_meta.c -- create and init struct zip_meta - Copyright (C) 1999 Dieter Baron and Thomas Klausner - - This file is part of libzip, a library to manipulate ZIP archives. - The authors can be contacted at <nih@giga.or.at> - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions - are met: - 1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the - distribution. - 3. The names of the authors may not be used to endorse or promote - products derived from this software without specific prior - written permission. - - THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS - OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY - DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE - GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER - IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN - IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - - - -#include <stdlib.h> -#include "zip.h" - -struct zip_meta * -zip_new_meta(void) -{ - struct zip_meta *meta; - - if ((meta=(struct zip_meta *)malloc(sizeof(struct zip_meta)))==NULL) { - zip_err = ZERR_MEMORY; - return NULL; - } - - meta->version_made = meta->version_need = meta->bitflags = -1; - meta->comp_method = meta->disknrstart = meta->int_attr = -1; - meta->crc = meta->comp_size = meta->uncomp_size = -1; - meta->ext_attr = meta->local_offset = -1; - meta->ef_len = meta->lef_len = meta->fc_len = -1; - - meta->last_mod = 0; - meta->ef = meta->lef = meta->fc = NULL; - - return meta; -}
diff --git a/lib/zip_open.c b/lib/zip_open.c index 163ef28..4341258 100644 --- a/lib/zip_open.c +++ b/lib/zip_open.c
@@ -1,5 +1,5 @@ /* - $NiH: zip_open.c,v 1.18 2003/10/06 16:37:41 dillo Exp $ + $NiH: zip_open.c,v 1.19.4.6 2004/04/13 19:47:59 dillo Exp $ zip_open.c -- open zip archive Copyright (C) 1999, 2003 Dieter Baron and Thomas Klausner @@ -46,69 +46,63 @@ #include "zip.h" #include "zipint.h" -static void set_error(int *errp, int err); -static struct zip *_zip_readcdir(FILE *fp, unsigned char *buf, - unsigned char *eocd, int buflen, int *errp); -static int _zip_read2(unsigned char **a); -static int _zip_read4(unsigned char **a); -static char *_zip_readstr(unsigned char **buf, int len, int nulp); -static char *_zip_readfpstr(FILE *fp, int len, int nulp); -static int _zip_checkcons(FILE *fp, struct zip *zf); -static int _zip_headercomp(struct zip_entry *h1, int local1p, - struct zip_entry *h2, int local2p); -static unsigned char *_zip_memmem(const unsigned char *big, int biglen, - const unsigned char *little, int littlelen); -static time_t _zip_d2u_time(int dtime, int ddate); +static void set_error(int *, struct zip_error *, int); +static int _zip_checkcons(FILE *, struct zip_cdir *, struct zip_error *); +static int _zip_headercomp(struct zip_dirent *, int, + struct zip_dirent *, int); +static unsigned char *_zip_memmem(const unsigned char *, int, + const unsigned char *, int); +static struct zip_cdir *_zip_readcdir(FILE *, unsigned char *, unsigned char *, + int, struct zip_error *); -/* zip_open: - Tries to open the file 'fn' as a zipfile. If flags & ZIP_CHECKCONS, - also does some consistency checks (comparing local headers to - central directory entries). If flags & ZIP_CREATE, make a new file - (if flags & ZIP_EXCL, error if already existing). Returns a - zipfile struct, or NULL if unsuccessful, setting zip_err. */ - struct zip * -zip_open(const char *fn, int flags, int *errp) +zip_open(const char *fn, int flags, int *zep) { FILE *fp; unsigned char *buf, *match; int a, i, buflen, best; - struct zip *cdir, *cdirnew; + struct zip *za; + struct zip_cdir *cdir, *cdirnew; long len; struct stat st; + struct zip_error error, err2; if (fn == NULL) { - set_error(errp, ZERR_INVAL); + set_error(zep, NULL, ZERR_INVAL); return NULL; } if (stat(fn, &st) != 0) { if (flags & ZIP_CREATE) { - if ((cdir=_zip_new(errp)) == NULL) - return NULL; - - cdir->zn = strdup(fn); - if (!cdir->zn) { - _zip_free(cdir); - set_error(errp, ZERR_MEMORY); + if ((za=_zip_new(&error)) == NULL) { + set_error(zep, &error, 0); return NULL; } - return cdir; - } else { - set_error(errp, ZERR_NOENT); + + za->zn = strdup(fn); + if (!za->zn) { + _zip_free(za); + set_error(zep, NULL, ZERR_MEMORY); + return NULL; + } + return za; + } + else { + set_error(zep, NULL, ZERR_OPEN); return NULL; } - } else if ((flags & ZIP_EXCL)) { - set_error(errp, ZERR_EXISTS); + } + else if ((flags & ZIP_EXCL)) { + set_error(zep, NULL, ZERR_EXISTS); return NULL; } /* ZIP_CREATE gets ignored if file exists and not ZIP_EXCL, just like open() */ - if ((fp=fopen(fn, "rb"))==NULL) { - set_error(errp, ZERR_OPEN); + if ((fp=fopen(fn, "rb")) == NULL) { + set_error(zep, NULL, ZERR_OPEN); return NULL; } @@ -118,15 +112,14 @@ i = fseek(fp, -(len < BUFSIZE ? len : BUFSIZE), SEEK_END); if (i == -1 && errno != EFBIG) { /* seek before start of file on my machine */ - set_error(errp, ZERR_SEEK); + set_error(zep, NULL, ZERR_SEEK); fclose(fp); return NULL; } - /* XXX: why not allocate statically? */ - buf = (unsigned char *)malloc(BUFSIZE); - if (!buf) { - set_error(errp, ZERR_MEMORY); + /* 64k is too much for stack */ + if ((buf=(unsigned char *)malloc(BUFSIZE)) == NULL) { + set_error(zep, NULL, ZERR_MEMORY); fclose(fp); return NULL; } @@ -135,7 +128,7 @@ buflen = fread(buf, 1, BUFSIZE, fp); if (ferror(fp)) { - set_error(errp, ZERR_READ); + set_error(zep, NULL, ZERR_READ); free(buf); fclose(fp); return NULL; @@ -149,62 +142,83 @@ /* found match -- check, if good */ /* to avoid finding the same match all over again */ match++; - if ((cdirnew=_zip_readcdir(fp, buf, match-1, buflen, errp)) == NULL) + if ((cdirnew=_zip_readcdir(fp, buf, match-1, buflen, &err2)) == NULL) continue; if (cdir) { if (best <= 0) - best = _zip_checkcons(fp, cdir); - a = _zip_checkcons(fp, cdirnew); + best = _zip_checkcons(fp, cdir, &err2); + a = _zip_checkcons(fp, cdirnew, &err2); if (best < a) { - _zip_free(cdir); + _zip_cdir_free(cdir); cdir = cdirnew; best = a; } else - _zip_free(cdirnew); + _zip_cdir_free(cdirnew); } else { cdir = cdirnew; if (flags & ZIP_CHECKCONS) - best = _zip_checkcons(fp, cdir); + best = _zip_checkcons(fp, cdir, &err2); else best = 0; } cdirnew = NULL; } + free(buf); + if (best < 0) { /* no consistent eocd found */ - set_error(errp, ZERR_NOZIP); - free(buf); - _zip_free(cdir); + set_error(zep, NULL, ZERR_NOZIP); + _zip_cdir_free(cdir); fclose(fp); return NULL; } - free(buf); - - cdir->zn = strdup(fn); - if (!cdir->zn) { - set_error(errp, ZERR_MEMORY); - _zip_free(cdir); + if ((za=_zip_new(&error)) == NULL) { + set_error(zep, &error, 0); + _zip_cdir_free(cdir); fclose(fp); return NULL; } - cdir->zp = fp; + za->zp = fp; + za->cdir = cdir; - return cdir; + if ((za->zn=strdup(fn)) == NULL) { + set_error(zep, NULL, ZERR_MEMORY); + _zip_free(za); + return NULL; + } + + if ((za->entry=malloc(sizeof(*(za->entry))*cdir->nentry)) == NULL) { + set_error(zep, NULL, ZERR_MEMORY); + _zip_free(za); + return NULL; + } + for (i=0; i<cdir->nentry; i++) + _zip_new_entry(za); + + return za; } static void -set_error(int *errp, int err) +set_error(int *zep, struct zip_error *err, int ze) { - if (errp) - *errp = err; + int se; + + if (err) { + _zip_error_get(err, &ze, &se); + if (zip_error_sys_type(ze) == ZIP_ET_SYS) + errno = se; + } + + if (zep) + *zep = ze; } @@ -212,357 +226,95 @@ /* _zip_readcdir: tries to find a valid end-of-central-directory at the beginning of buf, and then the corresponding central directory entries. - Returns a struct zip which contains the central directory + Returns a struct zip_cdir which contains the central directory entries, or NULL if unsuccessful. */ -static struct zip * +static struct zip_cdir * _zip_readcdir(FILE *fp, unsigned char *buf, unsigned char *eocd, int buflen, - int *errp) + struct zip_error *error) { - struct zip *zf; - unsigned char *cdp; - int i, comlen, readp; - int entries; + struct zip_cdir *cd; + unsigned char *cdp, **bufp; + int i, comlen, nentry; comlen = buf + buflen - eocd - EOCDLEN; if (comlen < 0) { /* not enough bytes left for comment */ - set_error(errp, ZERR_NOZIP); + _zip_error_set(error, ZERR_NOZIP, 0); return NULL; } /* check for end-of-central-dir magic */ if (memcmp(eocd, EOCD_MAGIC, 4) != 0) { - set_error(errp, ZERR_NOZIP); + _zip_error_set(error, ZERR_NOZIP, 0); return NULL; } if (memcmp(eocd+4, "\0\0\0\0", 4) != 0) { - set_error(errp, ZERR_MULTIDISK); + _zip_error_set(error, ZERR_MULTIDISK, 0); return NULL; } - if ((zf=_zip_new(errp)) == NULL) - return NULL; - cdp = eocd + 8; /* number of cdir-entries on this disk */ i = _zip_read2(&cdp); /* number of cdir-entries */ - entries = _zip_read2(&cdp); - zf->cd_size = _zip_read4(&cdp); - zf->cd_offset = _zip_read4(&cdp); - zf->comlen = _zip_read2(&cdp); - zf->entry = NULL; + nentry = _zip_read2(&cdp); + + if ((cd=_zip_cdir_new(nentry, error)) == NULL) + return NULL; + + cd->size = _zip_read4(&cdp); + cd->offset = _zip_read4(&cdp); + cd->comment = NULL; + cd->comment_len = _zip_read2(&cdp); /* XXX: some zip files are broken; their internal comment length says 0, but they have 1 or 2 comment bytes */ - if (((zf->comlen != comlen) && (zf->comlen != comlen-1) && - (zf->comlen != comlen-2)) || (entries != i)) { + if ((comlen-cd->comment_len < 0) || (comlen-cd->comment_len > 2) + || (cd->nentry != i)) { /* comment size wrong -- too few or too many left after central dir */ /* or number of cdir-entries on this disk != number of cdir-entries */ - set_error(errp, ZERR_NOZIP); - _zip_free(zf); + _zip_error_set(error, ZERR_NOZIP, 0); + free(cd); return NULL; } - zf->com = (unsigned char *)_zip_memdup(eocd+EOCDLEN, zf->comlen); + if (cd->comment_len) + cd->comment = _zip_memdup(eocd+EOCDLEN, cd->comment_len); cdp = eocd; - if (zf->cd_size < eocd-buf) { + if (cd->size < eocd-buf) { /* if buffer already read in, use it */ - readp = 0; - cdp = eocd - zf->cd_size; + cdp = eocd - cd->size; + bufp = &cdp; } else { /* go to start of cdir and read it entry by entry */ - readp = 1; + bufp = NULL; clearerr(fp); - fseek(fp, -(zf->cd_size+zf->comlen+EOCDLEN), SEEK_END); - if (ferror(fp) || (ftell(fp) != zf->cd_offset)) { + fseek(fp, -(cd->size+cd->comment_len+EOCDLEN), SEEK_END); + if (ferror(fp) || (ftell(fp) != cd->offset)) { /* seek error or offset of cdir wrong */ if (ferror(fp)) - set_error(errp, ZERR_SEEK); + _zip_error_set(error, ZERR_SEEK, errno); else - set_error(errp, ZERR_NOZIP); - _zip_free(zf); + _zip_error_set(error, ZERR_NOZIP, 0); + free(cd); return NULL; } } - zf->entry = (struct zip_entry *)malloc(sizeof(struct zip_entry) - *entries); - if (!zf->entry) { - set_error(errp, ZERR_MEMORY); - _zip_free(zf); - return NULL; - } - - zf->nentry_alloc = entries; - - for (i=0; i<entries; i++) { - if (_zip_new_entry(zf) == NULL) { - /* shouldn't happen, since space already has been malloc'd */ - _zip_error_get(&zf->error, errp, NULL); - _zip_free(zf); + for (i=0; i<cd->nentry; i++) { + if ((_zip_dirent_read(cd->entry+i, fp, bufp, eocd-cdp, 0, + error)) < 0) { + cd->nentry = i; + _zip_cdir_free(cd); return NULL; } } - for (i=0; i<zf->nentry; i++) { - if ((_zip_readcdentry(fp, zf->entry+i, &cdp, eocd-cdp, - readp, 0)) < 0) { - _zip_free(zf); - return NULL; - } - } - - return zf; -} - - - -/* _zip_readcdentry: - fills the zipfile entry zfe with data from the buffer *cdpp, not reading - more than 'left' bytes from it; if readp != 0, it also reads more data - from fp, if necessary. If localp != 0, it reads a local header instead - of a central directory entry. Returns 0 if successful, -1 if not, - advancing *cdpp for each byte read. */ - -int -_zip_readcdentry(FILE *fp, struct zip_entry *zfe, unsigned char **cdpp, - int left, int readp, int localp) -{ - unsigned char buf[CDENTRYSIZE]; - unsigned char *cur; - unsigned short dostime, dosdate; - int size; - - if (localp) - size = LENTRYSIZE; - else - size = CDENTRYSIZE; - - if (readp) { - /* read entry from disk */ - if ((fread(buf, 1, size, fp)<size)) { - zip_err = ZERR_READ; - return -1; - } - left = size; - cur = buf; - } - else { - cur = *cdpp; - if (left < size) { - zip_err = ZERR_NOZIP; - return -1; - } - } - - if (localp) { - if (memcmp(cur, LOCAL_MAGIC, 4)!=0) { - zip_err = ZERR_NOZIP; - return -1; - } - } - else - if (memcmp(cur, CENTRAL_MAGIC, 4)!=0) { - zip_err = ZERR_NOZIP; - return -1; - } - - cur += 4; - - /* convert buffercontents to zf_entry */ - if (!localp) - zfe->meta->version_made = _zip_read2(&cur); - else - zfe->meta->version_made = 0; - zfe->meta->version_need = _zip_read2(&cur); - zfe->meta->bitflags = _zip_read2(&cur); - zfe->meta->comp_method = _zip_read2(&cur); - /* convert to time_t */ - dostime = _zip_read2(&cur); - dosdate = _zip_read2(&cur); - - zfe->meta->last_mod = _zip_d2u_time(dostime, dosdate); - - zfe->meta->crc = _zip_read4(&cur); - zfe->meta->comp_size = _zip_read4(&cur); - zfe->meta->uncomp_size = _zip_read4(&cur); - - zfe->file_fnlen = _zip_read2(&cur); - if (localp) { - zfe->meta->ef_len = 0; - zfe->meta->lef_len = _zip_read2(&cur); - zfe->meta->fc_len = zfe->meta->disknrstart = zfe->meta->int_attr = 0; - zfe->meta->ext_attr = zfe->meta->local_offset = 0; - } else { - zfe->meta->ef_len = _zip_read2(&cur); - zfe->meta->lef_len = 0; - zfe->meta->fc_len = _zip_read2(&cur); - zfe->meta->disknrstart = _zip_read2(&cur); - zfe->meta->int_attr = _zip_read2(&cur); - - zfe->meta->ext_attr = _zip_read4(&cur); - zfe->meta->local_offset = _zip_read4(&cur); - } - - if (left < CDENTRYSIZE+zfe->file_fnlen+zfe->meta->ef_len - +zfe->meta->lef_len+zfe->meta->fc_len) { - if (readp) { - if (zfe->file_fnlen) - zfe->fn = _zip_readfpstr(fp, zfe->file_fnlen, 1); - else - zfe->fn = strdup(""); - - if (!zfe->fn) { - zip_err = ZERR_MEMORY; - return -1; - } - - /* only set for local headers */ - if (zfe->meta->lef_len) { - zfe->meta->lef = _zip_readfpstr(fp, zfe->meta->lef_len, 0); - if (!zfe->meta->lef) - return -1; - } - - /* only set for central directory entries */ - if (zfe->meta->ef_len) { - zfe->meta->ef = _zip_readfpstr(fp, zfe->meta->ef_len, 0); - if (!zfe->meta->ef) - return -1; - } - - /* only set for central directory entries */ - if (zfe->meta->fc_len) { - zfe->meta->fc = _zip_readfpstr(fp, zfe->meta->fc_len, 0); - if (!zfe->meta->fc) - return -1; - } - } - else { - /* can't get more bytes if not allowed to read */ - zip_err = ZERR_NOZIP; - return -1; - } - } - else { - if (zfe->file_fnlen) { - zfe->fn = _zip_readstr(&cur, zfe->file_fnlen, 1); - if (!zfe->fn) - return -1; - } - - /* only set for local headers */ - if (zfe->meta->lef_len) { - zfe->meta->lef = _zip_readstr(&cur, zfe->meta->lef_len, 0); - if (!zfe->meta->lef) - return -1; - } - - /* only set for central directory entries */ - if (zfe->meta->ef_len) { - zfe->meta->ef = _zip_readstr(&cur, zfe->meta->ef_len, 0); - if (!zfe->meta->ef) - return -1; - } - - /* only set for central directory entries */ - if (zfe->meta->fc_len) { - zfe->meta->fc = _zip_readstr(&cur, zfe->meta->fc_len, 0); - if (!zfe->meta->fc) - return -1; - } - } - if (!readp) - *cdpp = cur; - - return 0; -} - - - -static int -_zip_read2(unsigned char **a) -{ - int ret; - - ret = (*a)[0]+((*a)[1]<<8); - *a += 2; - - return ret; -} - - - -static int -_zip_read4(unsigned char **a) -{ - int ret; - - ret = ((((((*a)[3]<<8)+(*a)[2])<<8)+(*a)[1])<<8)+(*a)[0]; - *a += 4; - - return ret; -} - - - -static char * -_zip_readstr(unsigned char **buf, int len, int nulp) -{ - char *r, *o; - - r = (char *)malloc(nulp?len+1:len); - if (!r) { - zip_err = ZERR_MEMORY; - return NULL; - } - - memcpy(r, *buf, len); - *buf += len; - - if (nulp) { - /* elephant */ - r[len] = 0; - o = r-1; - while (((o=memchr(o+1, 0, r+len-(o+1))) < r+len) && o) - *o = ' '; - } - - return r; -} - - - -static char * -_zip_readfpstr(FILE *fp, int len, int nulp) -{ - char *r, *o; - - r = (char *)malloc(nulp?len+1:len); - if (!r) { - zip_err = ZERR_MEMORY; - return NULL; - } - - if (fread(r, 1, len, fp)<len) { - free(r); - return NULL; - } - - if (nulp) { - /* elephant */ - r[len] = 0; - o = r-1; - while (((o=memchr(o+1, 0, r+len-(o+1))) < r+len) && o) - *o = ' '; - } - - return r; + return cd; } @@ -574,60 +326,51 @@ difference between the lowest and the highest fileposition reached */ static int -_zip_checkcons(FILE *fp, struct zip *zf) +_zip_checkcons(FILE *fp, struct zip_cdir *cd, struct zip_error *error) { int min, max, i, j; - struct zip_entry *temp; + struct zip_dirent temp; unsigned char *buf; buf = NULL; - if (zf->nentry) { - max = zf->entry[0].meta->local_offset; - min = zf->entry[0].meta->local_offset; + if (cd->nentry) { + max = cd->entry[0].offset; + min = cd->entry[0].offset; } - if ((temp=_zip_new_entry(NULL))==NULL) - return -1; - - for (i=0; i<zf->nentry; i++) { - if (zf->entry[i].meta->local_offset < min) - min = zf->entry[i].meta->local_offset; + for (i=0; i<cd->nentry; i++) { + if (cd->entry[i].offset < min) + min = cd->entry[i].offset; if (min < 0) { - zip_err = ZERR_NOZIP; - _zip_free_entry(temp); + _zip_error_set(error, ZERR_NOZIP, 0); return -1; } - j = zf->entry[i].meta->local_offset + zf->entry[i].meta->comp_size - + zf->entry[i].file_fnlen + zf->entry[i].meta->ef_len - + zf->entry[i].meta->fc_len + LENTRYSIZE; + j = cd->entry[i].offset + cd->entry[i].comp_size + + cd->entry[i].filename_len + LENTRYSIZE; if (j > max) max = j; - if (max > zf->cd_offset) { - zip_err = ZERR_NOZIP; - _zip_free_entry(temp); + if (max > cd->offset) { + _zip_error_set(error, ZERR_NOZIP, 0); return -1; } - if (fseek(fp, zf->entry[i].meta->local_offset, SEEK_SET) != 0) { - zip_err = ZERR_SEEK; - _zip_free_entry(temp); + if (fseek(fp, cd->entry[i].offset, SEEK_SET) != 0) { + _zip_error_set(error, ZERR_SEEK, 0); return -1; } - if (_zip_readcdentry(fp, temp, &buf, 0, 1, 1) == -1) { - _zip_free_entry(temp); + if (_zip_dirent_read(&temp, fp, NULL, 0, 1, error) == -1) return -1; - } - if (_zip_headercomp(zf->entry+i, 0, temp, 1) != 0) { - zip_err = ZERR_NOZIP; - _zip_free_entry(temp); + if (_zip_headercomp(cd->entry+i, 0, &temp, 1) != 0) { + _zip_error_set(error, ZERR_NOZIP, 0); + _zip_dirent_finalize(&temp); return -1; } + _zip_dirent_finalize(&temp); } - _zip_free_entry(temp); return max - min; } @@ -639,42 +382,45 @@ are identical, -1 if not. */ static int -_zip_headercomp(struct zip_entry *h1, int local1p, struct zip_entry *h2, +_zip_headercomp(struct zip_dirent *h1, int local1p, struct zip_dirent *h2, int local2p) { - if ((h1->meta->version_need != h2->meta->version_need) + if ((h1->version_needed != h2->version_needed) #if 0 /* some zip-files have different values in local and global headers for the bitflags */ - || (h1->meta->bitflags != h2->meta->bitflags) + || (h1->bitflags != h2->bitflags) #endif - || (h1->meta->comp_method != h2->meta->comp_method) - || (h1->meta->last_mod != h2->meta->last_mod) - || (h1->meta->crc != h2->meta->crc) - || (h1->meta->comp_size != h2->meta->comp_size) - || (h1->meta->uncomp_size != h2->meta->uncomp_size) - || !h1->fn - || !h2->fn - || strcmp(h1->fn, h2->fn)) + || (h1->comp_method != h2->comp_method) + || (h1->last_mod != h2->last_mod) + || (h1->crc != h2->crc) + || (h1->comp_size != h2->comp_size) + || (h1->uncomp_size != h2->uncomp_size) + || (h1->filename_len != h2->filename_len) + || !h1->filename || !h2->filename + || strcmp(h1->filename, h2->filename)) return -1; - /* if they are different type, nothing more to check */ - if (local1p != local2p) + if ((local1p == local2p) + && ((h1->extrafield_len != h2->extrafield_len) + || (h1->extrafield_len && h2->extrafield + && memcmp(h1->extrafield, h2->extrafield, + h1->extrafield_len)))) + return -1; + + /* if either is local, nothing more to check */ + if (local1p || local2p) return 0; - if ((h1->meta->version_made != h2->meta->version_made) - || (h1->meta->disknrstart != h2->meta->disknrstart) - || (h1->meta->int_attr != h2->meta->int_attr) - || (h1->meta->ext_attr != h2->meta->ext_attr) - || (h1->meta->local_offset != h2->meta->local_offset) - || (h1->meta->ef_len != h2->meta->ef_len) - || (h1->meta->ef_len && memcmp(h1->meta->ef, h2->meta->ef, - h1->meta->ef_len)) - || (h1->meta->fc_len != h2->meta->fc_len) - || (h1->meta->fc_len && memcmp(h1->meta->fc, h2->meta->fc, - h1->meta->fc_len))) { + if ((h1->version_madeby != h2->version_madeby) + || (h1->disk_number != h2->disk_number) + || (h1->int_attrib != h2->int_attrib) + || (h1->ext_attrib != h2->ext_attrib) + || (h1->offset != h2->offset) + || (h1->comment_len != h2->comment_len) + || (h1->comment_len && h2->comment + && memcmp(h1->comment, h2->comment, h1->comment_len))) return -1; - } return 0; } @@ -707,7 +453,7 @@ ret = malloc(len); if (!ret) { - zip_err = ZERR_MEMORY; + /* XXX: zip_err = ZERR_MEMORY; */ return NULL; } @@ -715,25 +461,3 @@ return ret; } - - - -static time_t -_zip_d2u_time(int dtime, int ddate) -{ - struct tm *tm; - time_t now; - - now = time(NULL); - tm = localtime(&now); - - tm->tm_year = ((ddate>>9)&127) + 1980 - 1900; - tm->tm_mon = ((ddate>>5)&15) - 1; - tm->tm_mday = ddate&31; - - tm->tm_hour = (dtime>>11)&31; - tm->tm_min = (dtime>>5)&63; - tm->tm_sec = (dtime<<1)&62; - - return mktime(tm); -}
diff --git a/lib/zip_rename.c b/lib/zip_rename.c index e9c1f9b..258f289 100644 --- a/lib/zip_rename.c +++ b/lib/zip_rename.c
@@ -1,5 +1,5 @@ /* - $NiH: zip_rename.c,v 1.9 2003/10/03 23:25:31 dillo Exp $ + $NiH: zip_rename.c,v 1.10.4.1 2004/03/20 09:54:07 dillo Exp $ zip_rename.c -- rename file in zip archive Copyright (C) 1999, 2003 Dieter Baron and Thomas Klausner @@ -48,11 +48,10 @@ return -1; } + /* XXX: move this to _zip_set_name */ if (zf->entry[idx].state == ZIP_ST_UNCHANGED) zf->entry[idx].state = ZIP_ST_RENAMED; - zf->changes = 1; - _zip_set_name(zf, idx, name); return 0;
diff --git a/lib/zip_replace.c b/lib/zip_replace.c index eed4d58..347c337 100644 --- a/lib/zip_replace.c +++ b/lib/zip_replace.c
@@ -1,5 +1,5 @@ /* - $NiH: zip_replace.c,v 1.10 2003/10/01 09:51:01 dillo Exp $ + $NiH: zip_replace.c,v 1.11.4.3 2004/04/10 23:52:15 dillo Exp $ zip_replace.c -- replace file via callback function Copyright (C) 1999, 2003 Dieter Baron and Thomas Klausner @@ -41,8 +41,22 @@ int -zip_replace(struct zip *zf, int idx, const char *name, struct zip_meta *meta, - zip_read_func fn, void *state, int comp) +zip_replace(struct zip *zf, int idx, zip_read_func fn, void *state, int flags) +{ + if (idx < 0 || idx >= zf->nentry) { + _zip_error_set(&zf->error, ZERR_INVAL, 0); + return -1; + } + + return _zip_replace(zf, idx, NULL, fn, state, flags); +} + + + + +int +_zip_replace(struct zip *zf, int idx, const char *name, + zip_read_func fn, void *state, int flags) { if (idx == -1) { if (_zip_new_entry(zf) == NULL) @@ -51,25 +65,17 @@ idx = zf->nentry - 1; } - if (idx < 0 || idx >= zf->nentry) { - zip_err = ZERR_INVAL; - return -1; - } - if (_zip_unchange_data(zf->entry+idx) != 0) return -1; if (_zip_set_name(zf, idx, name) != 0) return -1; - zf->changes = 1; - zf->entry[idx].state = ZIP_ST_REPLACED; - if (zf->entry[idx].ch_meta) - zip_free_meta(zf->entry[idx].ch_meta); - zf->entry[idx].ch_meta = meta; + zf->entry[idx].state = ((zf->cdir == NULL || idx >= zf->cdir->nentry) + ? ZIP_ST_ADDED : ZIP_ST_REPLACED); zf->entry[idx].ch_func = fn; zf->entry[idx].ch_data = state; - zf->entry[idx].ch_comp = comp; + zf->entry[idx].ch_flags = flags; return 0; }
diff --git a/lib/zip_replace_data.c b/lib/zip_replace_data.c index 75b1cb6..5b1c533 100644 --- a/lib/zip_replace_data.c +++ b/lib/zip_replace_data.c
@@ -1,5 +1,5 @@ /* - $NiH: zip_replace_data.c,v 1.11 2003/10/01 09:51:01 dillo Exp $ + $NiH: zip_replace_data.c,v 1.12.4.1 2004/03/20 09:54:08 dillo Exp $ zip_replace_data.c -- replace file from buffer Copyright (C) 1999, 2003 Dieter Baron and Thomas Klausner @@ -43,29 +43,37 @@ struct read_data { const char *buf, *data; - int len; + off_t len; int freep; }; -static int read_data(void *state, void *data, int len, enum zip_cmd cmd); - +static ssize_t read_data(void *state, void *data, size_t len, + enum zip_cmd cmd); int -zip_replace_data(struct zip *zf, int idx, const char *name, - struct zip_meta *meta, - const char *data, int len, int freep) +zip_replace_data(struct zip *zf, int idx, + const void *data, off_t len, int freep) { - struct read_data *f; - - if (idx < -1 || idx >= zf->nentry) { - zip_err = ZERR_INVAL; + if (idx < 0 || idx >= zf->nentry) { + _zip_error_set(&zf->error, ZERR_INVAL, 0); return -1; } - if ((f=(struct read_data *)malloc(sizeof(struct read_data))) == NULL) { - zip_err = ZERR_MEMORY; + return _zip_replace_data(zf, idx, NULL, data, len, freep); +} + + + +int +_zip_replace_data(struct zip *zf, int idx, const char *name, + const void *data, off_t len, int freep) +{ + struct read_data *f; + + if ((f=malloc(sizeof(*f))) == NULL) { + _zip_error_set(&zf->error, ZERR_MEMORY, 0); return -1; } @@ -73,13 +81,13 @@ f->len = len; f->freep = freep; - return zip_replace(zf, idx, name, meta, read_data, f, 0); + return _zip_replace(zf, idx, name, read_data, f, 0); } static int -read_data(void *state, void *data, int len, enum zip_cmd cmd) +read_data(void *state, void *data, size_t len, enum zip_cmd cmd) { struct read_data *z; char *buf; @@ -106,15 +114,16 @@ return n; - case ZIP_CMD_META: - return 0; - case ZIP_CMD_CLOSE: if (z->freep) { free((void *)z->data); z->data = NULL; } + free(z); return 0; + + default: + ; } return -1;
diff --git a/lib/zip_replace_file.c b/lib/zip_replace_file.c index 7a992d9..4d70e7b 100644 --- a/lib/zip_replace_file.c +++ b/lib/zip_replace_file.c
@@ -1,5 +1,5 @@ /* - $NiH: zip_replace_file.c,v 1.10 2003/10/01 09:51:01 dillo Exp $ + $NiH: zip_replace_file.c,v 1.11.4.1 2004/03/20 09:54:08 dillo Exp $ zip_replace_file.c -- replace file from file system Copyright (C) 1999, 2003 Dieter Baron and Thomas Klausner @@ -35,7 +35,8 @@ -#include <stdlib.h> +#include <errno.h> +#include <stdio.h> #include "zip.h" #include "zipint.h" @@ -43,22 +44,29 @@ int -zip_replace_file(struct zip *zf, int idx, const char *name, - struct zip_meta *meta, - const char *fname, int start, int len) +zip_replace_file(struct zip *zf, int idx, + const char *fname, off_t start, off_t len) +{ + if (idx < 0 || idx >= zf->nentry) { + _zip_error_set(&zf->error, ZERR_INVAL, 0); + return -1; + } + + return _zip_replace_file(zf, idx, NULL, fname, start, len); +} + + + +int +_zip_replace_file(struct zip *zf, int idx, const char *name, + const char *fname, off_t start, off_t len) { FILE *fp; - if (idx < -1 || idx >= zf->nentry) { - zip_err = ZERR_INVAL; - return -1; - } - if ((fp=fopen(fname, "rb")) == NULL) { - zip_err = ZERR_OPEN; + _zip_error_set(&zf->error, ZERR_OPEN, errno); return -1; } - return zip_replace_filep(zf, idx, (name ? name : fname), meta, - fp, start, len); + return _zip_replace_filep(zf, idx, name, fp, start, len); }
diff --git a/lib/zip_replace_filep.c b/lib/zip_replace_filep.c index 4a22616..d0bbb21 100644 --- a/lib/zip_replace_filep.c +++ b/lib/zip_replace_filep.c
@@ -1,5 +1,5 @@ /* - $NiH: zip_replace_filep.c,v 1.6 2003/10/01 09:51:01 dillo Exp $ + $NiH: zip_replace_filep.c,v 1.7.4.1 2004/03/20 09:54:08 dillo Exp $ zip_replace_filep.c -- replace file from FILE* Copyright (C) 1999, 2003 Dieter Baron and Thomas Klausner @@ -42,27 +42,35 @@ struct read_file { FILE *f; - int off, len; + off_t off, len; }; -static int read_file(void *state, void *data, int len, enum zip_cmd cmd); +static int read_file(void *state, void *data, size_t len, enum zip_cmd cmd); int -zip_replace_filep(struct zip *zf, int idx, const char *name, - struct zip_meta *meta, - FILE *file, int start, int len) +zip_replace_filep(struct zip *zf, int idx, + FILE *file, off_t start, off_t len) { - struct read_file *f; - - if (idx < -1 || idx >= zf->nentry) { - zip_err = ZERR_INVAL; + if (idx < 0 || idx >= zf->nentry) { + _zip_error_set(&zf->error, ZERR_INVAL, 0); return -1; } + return _zip_replace_filep(zf, idx, NULL, file, start, len); +} + + + +int +_zip_replace_filep(struct zip *zf, int idx, const char *name, + FILE *file, off_t start, off_t len) +{ + struct read_file *f; + if ((f=(struct read_file *)malloc(sizeof(struct read_file))) == NULL) { - zip_err = ZERR_MEMORY; + _zip_error_set(&zf->error, ZERR_MEMORY, 0); return -1; } @@ -70,13 +78,13 @@ f->off = start; f->len = (len ? len : -1); - return zip_replace(zf, idx, name, meta, read_file, f, 0); + return _zip_replace(zf, idx, name, read_file, f, 0); } static int -read_file(void *state, void *data, int len, enum zip_cmd cmd) +read_file(void *state, void *data, size_t len, enum zip_cmd cmd) { struct read_file *z; char *buf; @@ -87,8 +95,8 @@ switch (cmd) { case ZIP_CMD_INIT: - if (fseek(z->f, z->off, SEEK_SET) < 0) { - zip_err = ZERR_SEEK; + if (fseeko(z->f, z->off, SEEK_SET) < 0) { + /* XXX: zip_err = ZERR_SEEK; */ return -1; } return 0; @@ -100,7 +108,7 @@ n = len; if ((i=fread(buf, 1, n, z->f)) < 0) { - zip_err = ZERR_READ; + /* XXX: zip_err = ZERR_READ; */ return -1; } @@ -109,15 +117,16 @@ return i; - case ZIP_CMD_META: - return 0; - case ZIP_CMD_CLOSE: if (z->f) { fclose(z->f); z->f = NULL; } + free(z); return 0; + + default: + ; } return -1;
diff --git a/lib/zip_replace_zip.c b/lib/zip_replace_zip.c index e77447c..2ecf9a3 100644 --- a/lib/zip_replace_zip.c +++ b/lib/zip_replace_zip.c
@@ -1,5 +1,5 @@ /* - $NiH: zip_replace_zip.c,v 1.16 2003/10/01 09:51:01 dillo Exp $ + $NiH: zip_replace_zip.c,v 1.17.4.10 2004/04/14 09:21:34 dillo Exp $ zip_replace_zip.c -- replace file from zip file Copyright (C) 1999, 2003 Dieter Baron and Thomas Klausner @@ -40,131 +40,98 @@ #include "zipint.h" struct read_zip { - struct zip *zf; - int idx; - long fpos; - long avail; - /* XXX: ... */ + struct zip_file *zf; + struct zip_stat st; + off_t off, len; }; -struct read_part { - struct zip *zf; - int idx; - struct zip_file *zff; - int off, len; - /* XXX: ... */ -}; - -static int read_zip(void *state, void *data, int len, enum zip_cmd cmd); -static int read_part(void *state, void *data, int len, enum zip_cmd cmd); +static ssize_t read_zip(void *st, void *data, size_t len, enum zip_cmd cmd); int -zip_replace_zip(struct zip *zf, int idx, const char *name, - struct zip_meta *meta, - struct zip *srczf, int srcidx, int start, int len) +zip_replace_zip(struct zip *zf, int idx, + struct zip *srczf, int srcidx, int flags, + off_t start, off_t len) { - struct read_zip *z; - struct read_part *p; - - if (srcidx < -1 || srcidx >= srczf->nentry) { - zip_err = ZERR_INVAL; + if (srcidx < 0 || srcidx >= srczf->nentry) { + _zip_error_set(&zf->error, ZERR_INVAL, 0); return -1; } - if ((srczf->entry[srcidx].meta->comp_method != 0 - && start == 0 && (len == 0 || len == -1))) { - if ((z=(struct read_zip *)malloc(sizeof(struct read_zip))) == NULL) { - zip_err = ZERR_MEMORY; - return -1; - } - z->zf = srczf; - z->idx = srcidx; - return zip_replace(zf, idx, (name ? name : srczf->entry[srcidx].fn), - meta, read_zip, z, 1); - } - else { - if ((p=(struct read_part *)malloc(sizeof(struct read_part))) == NULL) { - zip_err = ZERR_MEMORY; - return -1; - } - p->zf = srczf; - p->idx = srcidx; - p->off = start; - p->len = (len ? len : -1); - p->zff = NULL; - return zip_replace(zf, idx, (name ? name : srczf->entry[srcidx].fn), - meta, read_part, p, 0); - } + return _zip_replace_zip(zf, idx, NULL, srczf, srcidx, flags, start, len); } -static int -read_zip(void *state, void *data, int len, enum zip_cmd cmd) +int +_zip_replace_zip(struct zip *zf, int idx, const char *name, + struct zip *srczf, int srcidx, int flags, + off_t start, off_t len) +{ + struct zip_error error; + struct read_zip *p; + + if ((flags & ZIP_FL_UNCHANGED) == 0 + && ZIP_ENTRY_DATA_CHANGED(srczf->entry+srcidx)) { + _zip_error_set(&zf->error, ZERR_CHANGED, 0); + return NULL; + } + + if (len == 0) + len = -1; + + if (start == 0 && len == -1) + flags |= ZIP_FL_COMPRESSED; + else + flags &= ~ZIP_FL_COMPRESSED; + + if ((p=malloc(sizeof(*p))) == NULL) { + _zip_error_set(&zf->error, ZERR_MEMORY, 0); + return -1; + } + + _zip_error_copy(&error, &srczf->error); + + if (zip_stat_index(srczf, srcidx, flags, &p->st) < 0 + || (p->zf=zip_fopen_index(srczf, srcidx, flags)) == NULL) { + free(p); + _zip_error_copy(&zf->error, &srczf->error); + _zip_error_copy(&srczf->error, &error); + + return -1; + } + p->off = start; + p->len = len; + + if ((flags & ZIP_FL_COMPRESSED) == 0) { + p->st.size = p->st.comp_size = len; + p->st.comp_method = ZIP_CM_STORE; + /* XXX: crc */ + } + + return _zip_replace(zf, idx, name, read_zip, p, 0); +} + + + +static ssize_t +read_zip(void *state, void *data, size_t len, enum zip_cmd cmd) { struct read_zip *z; - int ret; - - z = (struct read_zip *)state; - - switch (cmd) { - case ZIP_CMD_INIT: - _zip_local_header_read(z->zf, z->idx); - z->fpos = z->zf->entry[z->idx].meta->local_offset + LENTRYSIZE - + z->zf->entry[z->idx].meta->lef_len - + z->zf->entry[z->idx].meta->fc_len - + z->zf->entry[z->idx].file_fnlen; - z->avail = z->zf->entry[z->idx].meta->comp_size; - return 0; - - case ZIP_CMD_READ: - if (fseek(z->zf->zp, z->fpos, SEEK_SET) < 0) { - zip_err = ZERR_SEEK; - return -1; - } - if ((ret=fread(data, 1, len < z->avail ? len : z->avail, - z->zf->zp)) < 0) { - zip_err = ZERR_READ; - return -1; - } - z->fpos += ret; - z->avail -= ret; - return ret; - - case ZIP_CMD_META: - return _zip_merge_meta_fix((struct zip_meta *)data, - z->zf->entry[z->idx].meta); - case ZIP_CMD_CLOSE: - return 0; - } - - return -1; -} - - - -static int -read_part(void *state, void *data, int len, enum zip_cmd cmd) -{ - struct read_part *z; char b[8192], *buf; int i, n; - z = (struct read_part *)state; + z = (struct read_zip *)state; buf = (char *)data; switch (cmd) { case ZIP_CMD_INIT: - if ((z->zff=zip_fopen_index(z->zf, z->idx) ) == NULL) - return -1; - for (n=0; n<z->off; n+= i) { - i = (z->off-n > 8192 ? 8192 : z->off-n); - if ((i=zip_fread(z->zff, b, i)) < 0) { - zip_fclose(z->zff); - z->zff = NULL; + i = (z->off-n > sizeof(b) ? sizeof(b) : z->off-n); + if ((i=zip_fread(z->zf, b, i)) < 0) { + zip_fclose(z->zf); + z->zf = NULL; return -1; } } @@ -176,23 +143,31 @@ else n = len; - if ((i=zip_fread(z->zff, buf, n)) < 0) + + if ((i=zip_fread(z->zf, buf, n)) < 0) { + /* XXX: copy error from z->zff */ return -1; + } if (z->len != -1) z->len -= i; return i; - case ZIP_CMD_META: + case ZIP_CMD_CLOSE: + zip_fclose(z->zf); + free(z); return 0; - case ZIP_CMD_CLOSE: - if (z->zff) { - zip_fclose(z->zff); - z->zff = NULL; - } + case ZIP_CMD_STAT: + if (len < sizeof(z->st)) + return -1; + + memcpy(data, &z->st, sizeof(z->st)); return 0; + + default: + ; } return -1;
diff --git a/lib/zip_set_name.c b/lib/zip_set_name.c index 6647b01..57dcab8 100644 --- a/lib/zip_set_name.c +++ b/lib/zip_set_name.c
@@ -1,5 +1,5 @@ /* - $NiH: zip_set_name.c,v 1.9 2003/10/02 14:13:32 dillo Exp $ + $NiH: zip_set_name.c,v 1.10.4.1 2004/04/06 20:30:07 dillo Exp $ zip_set_name.c -- rename helper function Copyright (C) 1999, 2003 Dieter Baron and Thomas Klausner @@ -58,11 +58,8 @@ return -1; } - if (zf->entry[idx].fn_old == NULL) - zf->entry[idx].fn_old = zf->entry[idx].fn; - else - free(zf->entry[idx].fn); - zf->entry[idx].fn = s; + free(zf->entry[idx].ch_filename); + zf->entry[idx].ch_filename = s; } return 0;
diff --git a/lib/zip_stat.c b/lib/zip_stat.c index 44a1113..81f6b26 100644 --- a/lib/zip_stat.c +++ b/lib/zip_stat.c
@@ -1,5 +1,5 @@ /* - $NiH$ + $NiH: zip_stat.c,v 1.1.4.1 2004/04/14 09:21:34 dillo Exp $ zip_stat.c -- get information about file by name Copyright (C) 1999, 2003 Dieter Baron and Thomas Klausner @@ -48,5 +48,5 @@ if ((idx=zip_name_locate(za, fname, flags)) < 0) return -1; - return zip_stat_index(za, idx, st); + return zip_stat_index(za, idx, flags, st); }
diff --git a/lib/zip_stat_index.c b/lib/zip_stat_index.c index 06bda6e..a1c02aa 100644 --- a/lib/zip_stat_index.c +++ b/lib/zip_stat_index.c
@@ -1,5 +1,5 @@ /* - $NiH$ + $NiH: zip_stat_index.c,v 1.1.4.4 2004/04/14 09:21:34 dillo Exp $ zip_stat_index.c -- get information about file by index Copyright (C) 1999, 2003 Dieter Baron and Thomas Klausner @@ -41,21 +41,28 @@ int -zip_stat_index(struct zip *za, int index, struct zip_stat *st) +zip_stat_index(struct zip *za, int index, int flags, struct zip_stat *st) { if (index < 0 || index >= za->nentry) { _zip_error_set(&za->error, ZERR_INVAL, 0); return -1; } - st->name = za->entry[index].fn; + if ((flags & ZIP_FL_UNCHANGED) == 0 + && ZIP_ENTRY_DATA_CHANGED(za->entry+index)) { + /* XXX: call ch_func with ZIP_CMD_STAT */ + _zip_error_set(&za->error, ZERR_CHANGED, 0); + return NULL; + } + + st->name = zip_get_name(za, index); st->index = index; - st->crc = za->entry[index].meta->crc; - st->size = za->entry[index].meta->uncomp_size; - st->mtime = za->entry[index].meta->last_mod; - st->comp_size = za->entry[index].meta->comp_size; - st->comp_method = za->entry[index].meta->comp_method; - /* st->bitflags = za->entry[index].meta->bitflags; */ + st->crc = za->cdir->entry[index].crc; + st->size = za->cdir->entry[index].uncomp_size; + st->mtime = za->cdir->entry[index].last_mod; + st->comp_size = za->cdir->entry[index].comp_size; + st->comp_method = za->cdir->entry[index].comp_method; + /* st->bitflags = za->cdir->entry[index].bitflags; */ return 0; }
diff --git a/lib/zip_unchange.c b/lib/zip_unchange.c index 8b8ad25..7cd76ca 100644 --- a/lib/zip_unchange.c +++ b/lib/zip_unchange.c
@@ -1,5 +1,5 @@ /* - $NiH: zip_unchange.c,v 1.10 2003/10/03 08:34:11 dillo Exp $ + $NiH: zip_unchange.c,v 1.11.4.2 2004/04/06 20:30:07 dillo Exp $ zip_unchange.c -- undo changes to file in zip archive Copyright (C) 1999 Dieter Baron and Thomas Klausner @@ -51,13 +51,11 @@ return -1; } - if (zf->entry[idx].fn_old) { - free(zf->entry[idx].fn); - zf->entry[idx].fn = zf->entry[idx].fn_old; - zf->entry[idx].fn_old = NULL; + if (zf->entry[idx].ch_filename) { + free(zf->entry[idx].ch_filename); + zf->entry[idx].ch_filename = NULL; } - zip_free_meta(zf->entry[idx].ch_meta); ret = _zip_unchange_data(zf->entry+idx); return ret;
diff --git a/lib/zip_unchange_data.c b/lib/zip_unchange_data.c index aa81637..880f489 100644 --- a/lib/zip_unchange_data.c +++ b/lib/zip_unchange_data.c
@@ -1,5 +1,5 @@ /* - $NiH: zip_unchange_data.c,v 1.8 2003/03/16 10:21:42 wiz Exp $ + $NiH: zip_unchange_data.c,v 1.9.4.2 2004/04/06 20:30:07 dillo Exp $ zip_unchange_data.c -- undo helper function Copyright (C) 1999 Dieter Baron and Thomas Klausner @@ -51,13 +51,9 @@ ze->ch_func = NULL; } - free(ze->ch_data); - ze->ch_data = NULL; - - ze->ch_comp = 0; + ze->ch_flags = 0; - ze->state = (ze->fn_old || ze->ch_meta) ? ZIP_ST_RENAMED - : ZIP_ST_UNCHANGED; + ze->state = ze->ch_filename ? ZIP_ST_RENAMED : ZIP_ST_UNCHANGED; return ret; }
diff --git a/lib/zipint.h b/lib/zipint.h index 8a74463..ce43d06 100644 --- a/lib/zipint.h +++ b/lib/zipint.h
@@ -1,8 +1,9 @@ + #ifndef _HAD_ZIPINT_H #define _HAD_ZIPINT_H /* - $NiH: zipint.h,v 1.21 2003/10/06 16:37:42 dillo Exp $ + $NiH: zipint.h,v 1.22.4.12 2004/04/14 09:21:35 dillo Exp $ zipint.h -- internal declarations. Copyright (C) 1999, 2003 Dieter Baron and Thomas Klausner @@ -50,60 +51,103 @@ +/* state of change of a file in zip archive */ + +enum zip_state { ZIP_ST_UNCHANGED, ZIP_ST_DELETED, ZIP_ST_REPLACED, + ZIP_ST_ADDED, ZIP_ST_RENAMED }; + +/* constants for struct zip_file's member flags */ + +#define ZIP_ZF_EOF 1 /* EOF reached */ +#define ZIP_ZF_COMP 2 /* read compressed data */ + +/* error information */ + struct zip_error { int zip_err; /* libzip error code (ZERR_*) */ int sys_err; /* copy of errno (E*) or zlib error code */ char *str; /* string representation or NULL */ }; +/* zip archive, part of API */ + struct zip { - char *zn; - FILE *zp; - struct zip_error error; - unsigned short comlen, changes; - unsigned int cd_size, cd_offset; - char *com; - int nentry, nentry_alloc; - struct zip_entry *entry; - int nfile, nfile_alloc; - struct zip_file **file; + char *zn; /* file name */ + FILE *zp; /* file */ + struct zip_error error; /* error information */ + + struct zip_cdir *cdir; /* central directory */ + int nentry; /* number of entries */ + int nentry_alloc; /* number of entries allocated */ + struct zip_entry *entry; /* entries */ + int nfile; /* number of opened files within archvie */ + int nfile_alloc; /* number of files allocated */ + struct zip_file **file; /* opened files within archvie */ }; -/* file in zip file */ +/* file in zip archive, part of API */ struct zip_file { - struct zip *zf; - char *name; - struct zip_error error; - int flags; /* -1: eof, >0: error */ + struct zip *zf; /* zip archive containing this file */ + struct zip_error error; /* error information */ + int flags; /* -1: eof, >0: error */ - int method; - /* position within zip file (fread/fwrite) */ - long fpos; - /* no of bytes left to read */ - unsigned long bytes_left; - /* no of bytes of compressed data left */ - unsigned long cbytes_left; - /* crc so far */ - unsigned long crc, crc_orig; + int method; /* compression method */ + long fpos; /* position within zip file (fread/fwrite) */ + unsigned long bytes_left; /* number of bytes left to read */ + unsigned long cbytes_left; /* number of bytes of compressed data left */ + + unsigned long crc; /* crc so far */ + unsigned long crc_orig; /* CRC recorded in archive */ char *buffer; z_stream *zstr; }; -/* entry in zip file directory */ +/* zip archive directory entry (central or local) */ + +struct zip_dirent { + unsigned short version_madeby; /* (c) version of creator */ + unsigned short version_needed; /* (cl) version needed to extract */ + unsigned short bitflags; /* (cl) general purposee bit flag */ + unsigned short comp_method; /* (cl) compression method used */ + time_t last_mod; /* (cl) time of last modification */ + unsigned int crc; /* (cl) CRC-32 of uncompressed data */ + unsigned int comp_size; /* (cl) size of commpressed data */ + unsigned int uncomp_size; /* (cl) size of uncommpressed data */ + char *filename; /* (cl) file name (NUL-terminated) */ + unsigned short filename_len; /* (cl) length of filename (w/o NUL) */ + char *extrafield; /* (cl) extra field */ + unsigned short extrafield_len; /* (cl) length of extra field */ + char *comment; /* (c) file comment */ + unsigned short comment_len; /* (c) length of file comment */ + unsigned short disk_number; /* (c) disk number start */ + unsigned short int_attrib; /* (c) internal file attributes */ + unsigned int ext_attrib; /* (c) external file attributes */ + unsigned int offset; /* (c) offest of local header */ +}; + +/* zip archive central directory */ + +struct zip_cdir { + struct zip_dirent *entry; /* directory entries */ + int nentry; /* number of entries */ + + unsigned int size; /* size of central direcotry */ + unsigned int offset; /* offset of central directory in file */ + char *comment; /* zip archive comment */ + unsigned short comment_len; /* length of zip archive comment */ +}; + +/* entry in zip archive directory */ struct zip_entry { - struct zip_meta *meta; - char *fn; - char *fn_old; - unsigned int file_fnlen; - enum zip_state state; zip_read_func ch_func; void *ch_data; - int ch_comp; /* 1: data returned by ch_func is compressed */ - struct zip_meta *ch_meta; + int ch_flags; /* 1: data returned by ch_func is compressed */ + char *ch_filename; + time_t ch_mtime; }; @@ -114,6 +158,20 @@ +#define ZIP_ENTRY_DATA_CHANGED(x) \ + ((x)->state == ZIP_ST_REPLACED \ + || (x)->state == ZIP_ST_ADDED) + + + +void _zip_cdir_free(struct zip_cdir *); +struct zip_cdir *_zip_cdir_new(int, struct zip_error *); +int _zip_cdir_write(struct zip_cdir *, FILE *, struct zip_error *); +void _zip_dirent_finalize(struct zip_dirent *); +void _zip_dirent_init(struct zip_dirent *); +int _zip_dirent_read(struct zip_dirent *, FILE *, + unsigned char **, int, int, struct zip_error *); +int _zip_dirent_write(struct zip_dirent *, FILE *, int, struct zip_error *); void _zip_entry_init(struct zip *, int); void _zip_error_copy(struct zip_error *, struct zip_error *); void _zip_error_fini(struct zip_error *); @@ -121,17 +179,24 @@ void _zip_error_init(struct zip_error *); void _zip_error_set(struct zip_error *, int, int); const char *_zip_error_strerror(struct zip_error *); -int _zip_file_fillbuf(char *, int, struct zip_file *); +int _zip_file_fillbuf(void *, size_t, struct zip_file *); +unsigned int _zip_file_get_offset(struct zip *, int); void _zip_free(struct zip *); int _zip_free_entry(struct zip_entry *); int _zip_local_header_read(struct zip *, int); void *_zip_memdup(const void *, int); -int _zip_merge_meta(struct zip_meta *, struct zip_meta *); -int _zip_merge_meta_fix(struct zip_meta *, struct zip_meta *); -struct zip *_zip_new(int *); +struct zip *_zip_new(struct zip_error *); struct zip_entry *_zip_new_entry(struct zip *); -int _zip_readcdentry(FILE *, struct zip_entry *, unsigned char **, - int, int, int); +unsigned short _zip_read2(unsigned char **); +unsigned int _zip_read4(unsigned char **); +int _zip_replace(struct zip *, int, const char *,zip_read_func, void *, int); +int _zip_replace_data(struct zip *, int, const char *, + const void *, off_t, int); +int _zip_replace_file(struct zip *, int, const char *, + const char *, off_t, off_t); +int _zip_replace_filep(struct zip *, int, const char *, FILE *, off_t, off_t); +int _zip_replace_zip(struct zip *, int, const char *, + struct zip *, int, int, off_t, off_t); int _zip_set_name(struct zip *, int, const char *); int _zip_unchange(struct zip_entry *); int _zip_unchange_data(struct zip_entry *);