Zip64 write support; zipcmp -p compares comments.
diff --git a/lib/zip.h b/lib/zip.h
index 2edec7b..4f00f68 100644
--- a/lib/zip.h
+++ b/lib/zip.h
@@ -77,6 +77,7 @@
 #define ZIP_FL_NAME_STRICT    128 /* follow specification strictly */
 #define ZIP_FL_LOCAL	      256 /* in local header */
 #define ZIP_FL_CENTRAL	      512 /* in central directory */
+/*                           1024    reserved for internal use */
 
 /* archive global flags flags */
 
@@ -86,6 +87,7 @@
 
 /* create a new extra field */
 
+#define ZIP_EXTRA_FIELD_ALL	ZIP_UINT16_MAX
 #define ZIP_EXTRA_FIELD_NEW	ZIP_UINT16_MAX
 
 /* flags for compression and encryption sources */
@@ -213,6 +215,8 @@
 struct zip_file;
 struct zip_source;
 
+typedef zip_uint32_t zip_flags_t;    
+
 typedef zip_int64_t (*zip_source_callback)(void *, void *, zip_uint64_t,
 					   enum zip_source_cmd);
 
@@ -223,8 +227,8 @@
 ZIP_EXTERN int zip_close(struct zip *);
 ZIP_EXTERN void zip_discard(struct zip *);
 ZIP_EXTERN int zip_delete(struct zip *, zip_uint64_t);
-ZIP_EXTERN int zip_delete_file_extra_field(struct zip *, zip_uint64_t, zip_uint32_t, zip_uint16_t);
-ZIP_EXTERN int zip_delete_file_extra_field_by_id(struct zip *, zip_uint64_t, zip_uint32_t, zip_uint16_t, zip_uint16_t);
+ZIP_EXTERN int zip_delete_file_extra_field(struct zip *, zip_uint64_t, zip_flags_t, zip_uint16_t);
+ZIP_EXTERN int zip_delete_file_extra_field_by_id(struct zip *, zip_uint64_t, zip_flags_t, zip_uint16_t, zip_uint16_t);
 ZIP_EXTERN void zip_error_clear(struct zip *);
 ZIP_EXTERN void zip_error_get(struct zip *, int *, int *);
 ZIP_EXTERN int zip_error_get_sys_type(int);
@@ -246,10 +250,10 @@
 ZIP_EXTERN int zip_get_archive_flag(struct zip *, int, int);
 ZIP_EXTERN const char *zip_get_file_comment(struct zip *, zip_uint64_t,
 					    int *, int);
-ZIP_EXTERN const zip_uint8_t *zip_get_file_extra_field(struct zip *, zip_uint64_t, zip_uint32_t, zip_uint16_t, zip_uint16_t *, zip_uint16_t *);
-ZIP_EXTERN const zip_uint8_t *zip_get_file_extra_field_by_id(struct zip *, zip_uint64_t, zip_uint32_t, zip_uint16_t, zip_uint16_t, zip_uint16_t *);
-ZIP_EXTERN zip_int16_t zip_get_file_num_extra_fields(struct zip *, zip_uint64_t, zip_uint32_t);
-ZIP_EXTERN zip_int16_t zip_get_file_num_extra_fields_by_id(struct zip *, zip_uint64_t, zip_uint32_t, zip_uint16_t);
+ZIP_EXTERN const zip_uint8_t *zip_get_file_extra_field(struct zip *, zip_uint64_t, zip_flags_t, zip_uint16_t, zip_uint16_t *, zip_uint16_t *);
+ZIP_EXTERN const zip_uint8_t *zip_get_file_extra_field_by_id(struct zip *, zip_uint64_t, zip_flags_t, zip_uint16_t, zip_uint16_t, zip_uint16_t *);
+ZIP_EXTERN zip_int16_t zip_get_file_num_extra_fields(struct zip *, zip_uint64_t, zip_flags_t);
+ZIP_EXTERN zip_int16_t zip_get_file_num_extra_fields_by_id(struct zip *, zip_uint64_t, zip_flags_t, zip_uint16_t);
 ZIP_EXTERN const char *zip_get_name(struct zip *, zip_uint64_t, int);
 ZIP_EXTERN zip_uint64_t zip_get_num_entries(struct zip *, int);
 ZIP_EXTERN int zip_get_num_files(struct zip *);  /* deprecated, use zip_get_num_entries instead */
@@ -264,7 +268,7 @@
 				    const char *, int);
 ZIP_EXTERN int zip_set_file_compression(struct zip *, zip_uint64_t,
 					zip_int32_t, zip_uint32_t);
-ZIP_EXTERN int zip_set_file_extra_field(struct zip *, zip_uint64_t, zip_uint32_t, zip_uint16_t, zip_uint16_t, const zip_uint8_t *, zip_uint16_t);
+ZIP_EXTERN int zip_set_file_extra_field(struct zip *, zip_uint64_t, zip_flags_t, zip_uint16_t, zip_uint16_t, const zip_uint8_t *, zip_uint16_t);
 ZIP_EXTERN struct zip_source *zip_source_buffer(struct zip *, const void *,
 						zip_uint64_t, int);
 ZIP_EXTERN struct zip_source *zip_source_file(struct zip *, const char *,
diff --git a/lib/zip_close.c b/lib/zip_close.c
index aee16aa..bd0d9b7 100644
--- a/lib/zip_close.c
+++ b/lib/zip_close.c
@@ -51,8 +51,10 @@
 
 
 
-static int add_data(struct zip *, struct zip_source *, struct zip_dirent *,
-		    FILE *);
+/* max deflate size increase: size + ceil(size/16k)*5+6 */
+#define MAX_DEFLATE_SIZE_32	4293656963
+
+static int add_data(struct zip *, struct zip_source *, struct zip_dirent *, FILE *);
 static int copy_data(FILE *, off_t, FILE *, struct zip_error *);
 static int copy_source(struct zip *, struct zip_source *, FILE *);
 static int write_cdir(struct zip *, const struct zip_filelist *, int, FILE *);
@@ -75,10 +77,9 @@
     int reopen_on_error;
     int new_torrentzip;
     enum zip_encoding_type com_enc, enc;
-    int changed, is_zip64;
+    int changed;
 
     reopen_on_error = 0;
-    is_zip64 = 0; /* for wiz */
 
     if (za == NULL)
 	return -1;
@@ -201,7 +202,7 @@
 	else {
 	    zip_uint64_t offset;
 	    
-	    if (_zip_dirent_write(de, out, 1, &za->error) < 0) {
+	    if (_zip_dirent_write(de, out, ZIP_FL_LOCAL, &za->error) < 0) {
 		error = 1;
 		break;
 	    }
@@ -278,26 +279,53 @@
     struct zip_stat st;
     struct zip_source *s2;
     int ret;
+    int is_zip64;
+    zip_flags_t flags;
     
     if (zip_source_stat(src, &st) < 0) {
 	_zip_error_set_from_source(&za->error, src);
 	return -1;
     }
 
-    offstart = ftello(ft);
-
-    if (_zip_dirent_write(de, ft, 1, &za->error) < 0)
-	return -1;
-
     if ((st.valid & ZIP_STAT_COMP_METHOD) == 0) {
 	st.valid |= ZIP_STAT_COMP_METHOD;
 	st.comp_method = ZIP_CM_STORE;
     }
 
-    if (de->comp_method == ZIP_CM_DEFAULT) {
-	/* XXX: set changed? */
-	de->comp_method = ZIP_CM_DEFLATE;
+    if (de->comp_method == ZIP_CM_DEFAULT && st.comp_method != ZIP_CM_STORE)
+	de->comp_method = st.comp_method;
+    else if (de->comp_method == ZIP_CM_STORE && (st.valid & ZIP_STAT_SIZE)) {
+	st.valid |= ZIP_STAT_COMP_SIZE;
+	st.comp_size = st.size;
     }
+    else {
+	/* we'll recompress */
+	st.valid &= ~ZIP_STAT_COMP_SIZE;
+    }
+
+
+    flags = ZIP_EF_LOCAL;
+
+    if ((st.valid & ZIP_STAT_SIZE) == 0)
+	flags |= ZIP_FL_FORCE_ZIP64;
+    else {
+	de->uncomp_size = st.size;
+	
+	if ((st.valid & ZIP_STAT_COMP_SIZE) == 0) {
+	    if ((((de->comp_method == ZIP_CM_DEFLATE || de->comp_method == ZIP_CM_DEFAULT) && st.size > MAX_DEFLATE_SIZE_32)
+		 || de->comp_method != ZIP_CM_STORE && de->comp_method != ZIP_CM_DEFLATE && de->comp_method != ZIP_CM_DEFAULT))
+		flags |= ZIP_FL_FORCE_ZIP64;
+	}
+	else
+	    de->comp_size = st.comp_size;
+    }
+
+
+    offstart = ftello(ft);
+
+    if ((is_zip64=_zip_dirent_write(de, ft, flags, &za->error)) < 0)
+	return -1;
+
 
     if (st.comp_method == ZIP_CM_STORE || (de->comp_method != ZIP_CM_DEFAULT && st.comp_method != de->comp_method)) {
 	struct zip_source *s_store, *s_crc;
@@ -369,7 +397,15 @@
 	return -1;
     }
 
-    de->last_mod = st.mtime;
+    if ((st.valid & (ZIP_STAT_COMP_METHOD|ZIP_STAT_CRC|ZIP_STAT_SIZE)) != (ZIP_STAT_COMP_METHOD|ZIP_STAT_CRC|ZIP_STAT_SIZE)) {
+	_zip_error_set(&za->error, ZIP_ER_INTERNAL, 0);
+	return -1;
+    }
+
+    if (st.valid & ZIP_STAT_MTIME)
+	de->last_mod = st.mtime;
+    else
+	time(&de->last_mod);
     de->comp_method = st.comp_method;
     de->crc = st.crc;
     de->uncomp_size = st.size;
@@ -378,9 +414,16 @@
     if (zip_get_archive_flag(za, ZIP_AFL_TORRENT, 0))
 	_zip_dirent_torrent_normalize(de);
 
-    if (_zip_dirent_write(de, ft, 1, &za->error) < 0)
+    if ((ret=_zip_dirent_write(de, ft, flags, &za->error)) < 0)
 	return -1;
-    
+ 
+    if (is_zip64 != ret) {
+	/* Zip64 mismatch between preliminary file header written before data and final file header written afterwards */
+	_zip_error_set(&za->error, ZIP_ER_INTERNAL, 0);
+	return -1;
+    }
+
+   
     if (fseeko(ft, offend, SEEK_SET) < 0) {
 	_zip_error_set(&za->error, ZIP_ER_SEEK, errno);
 	return -1;
diff --git a/lib/zip_dirent.c b/lib/zip_dirent.c
index 0e025a0..523c524 100644
--- a/lib/zip_dirent.c
+++ b/lib/zip_dirent.c
@@ -132,27 +132,53 @@
     zip_uint64_t offset, size;
     struct zip_string *comment;
     int i;
+    int is_zip64;
+    int ret;
 
     offset = ftello(fp);
 
+    is_zip64 = 0;
+
     for (i=0; i<survivors; i++) {
 	struct zip_entry *entry = za->entry+filelist[i].idx;
 
-	if (_zip_dirent_write(entry->changes ? entry->changes : entry->orig, fp, 0, &za->error) != 0)
+	if ((ret=_zip_dirent_write(entry->changes ? entry->changes : entry->orig, fp, ZIP_FL_CENTRAL, &za->error)) < 0)
 	    return -1;
+	if (ret)
+	    is_zip64 = 1;
     }
 
     size = ftello(fp) - offset;
-    
-    /* EOCD64 */
+
+    if (offset > ZIP_UINT32_MAX || survivors > ZIP_UINT16_MAX)
+	is_zip64 = 1;
+
+    if (is_zip64) {
+	fwrite(EOCD64_MAGIC, 1, 4, fp);
+	_zip_write8(EOCD64LEN, fp);
+	_zip_write2(45, fp);
+	_zip_write2(45, fp);
+	_zip_write4(1, fp);
+	_zip_write4(1, fp);
+	_zip_write8(survivors, fp);
+	_zip_write8(survivors, fp);
+	_zip_write8(size, fp);
+	_zip_write8(offset, fp);
+
+	fwrite(EOCD64LOC_MAGIC, 1, 4, fp);
+	_zip_write4(1, fp);
+	_zip_write8(offset+size, fp);
+	_zip_write4(1, fp);
+		    
+    }
 
     /* clearerr(fp); */
     fwrite(EOCD_MAGIC, 1, 4, fp);
     _zip_write4(0, fp);
-    _zip_write2((unsigned short)survivors, fp);
-    _zip_write2((unsigned short)survivors, fp);
-    _zip_write4(size, fp);
-    _zip_write4(offset, fp);
+    _zip_write2(survivors >= ZIP_UINT16_MAX ? ZIP_UINT16_MAX : survivors, fp);
+    _zip_write2(survivors >= ZIP_UINT16_MAX ? ZIP_UINT16_MAX : survivors, fp);
+    _zip_write4(size >= ZIP_UINT32_MAX ? ZIP_UINT32_MAX : size, fp);
+    _zip_write4(offset >= ZIP_UINT32_MAX ? ZIP_UINT32_MAX : offset, fp);
 
     comment = za->comment_changed ? za->comment_changes : za->comment_orig;
 
@@ -240,6 +266,18 @@
 
 
 
+int
+_zip_dirent_needs_zip64(const struct zip_dirent *de, zip_flags_t flags)
+{
+    if (de->uncomp_size >= ZIP_UINT32_MAX || de->comp_size >= ZIP_UINT32_MAX
+	|| ((flags & ZIP_FL_CENTRAL) && de->offset >= ZIP_UINT32_MAX))
+	return 1;
+
+    return 0;
+}
+
+
+
 struct zip_dirent *
 _zip_dirent_new(void)
 {
@@ -435,6 +473,8 @@
 	    if (zde->disk_number == ZIP_UINT16_MAX)
 		zde->disk_number = _zip_read4(&ef);
 	}
+
+	zde->extra_fields = _zip_ef_delete_by_id(zde->extra_fields, ZIP_EF_ZIP64, ZIP_EXTRA_FIELD_ALL, local ? ZIP_EF_LOCAL : ZIP_EF_CENTRAL);
     }
 
     if (bufp)
@@ -532,27 +572,31 @@
 
 
 
-/* _zip_dirent_write(zde, fp, localp, error):
+/* _zip_dirent_write(zde, fp, flags, error):
    Writes zip directory entry zde to file fp.
 
-   If localp != 0, it writes a local header instead of a central
-   directory entry.
+   If flags & ZIP_EF_LOCAL, it writes a local header instead of a central
+   directory entry.  If flags & ZIP_EF_FORCE_ZIP64, a ZIP64 extra field is written, even if not needed.
 
-   Returns 0 if successful. On error, error is filled in and -1 is
+   Returns 0 if successful, 1 if successful and wrote ZIP64 extra field. On error, error is filled in and -1 is
    returned.
 */
 
 int
-_zip_dirent_write(struct zip_dirent *zde, FILE *fp, int localp,
+_zip_dirent_write(struct zip_dirent *zde, FILE *fp, int flags,
 		  struct zip_error *error)
 {
     unsigned short dostime, dosdate;
+    zip_uint16_t zip64_ef_size;
 
-    fwrite(localp ? LOCAL_MAGIC : CENTRAL_MAGIC, 1, 4, fp);
+    zip64_ef_size = 0;
 
-    if (!localp)
+    fwrite((flags & ZIP_FL_LOCAL) ? LOCAL_MAGIC : CENTRAL_MAGIC, 1, 4, fp);
+
+
+    if ((flags & ZIP_FL_LOCAL) == 0)
 	_zip_write2(zde->version_madeby, fp);
-    _zip_write2(zde->version_needed, fp);
+    _zip_write2(zde->version_needed, fp);    /* XXX: at least 4.5 if zip64 */
     _zip_write2(zde->bitflags, fp);
     _zip_write2(zde->comp_method, fp);
 
@@ -561,27 +605,58 @@
     _zip_write2(dosdate, fp);
     
     _zip_write4(zde->crc, fp);
-    _zip_write4(zde->comp_size, fp);
-    _zip_write4(zde->uncomp_size, fp);
-    
+    if (zde->comp_size < ZIP_UINT32_MAX)
+	_zip_write4(zde->comp_size, fp);
+    else {
+	_zip_write4(ZIP_UINT32_MAX-1, fp);
+	zip64_ef_size += 8;
+    }
+    if (zde->uncomp_size < ZIP_UINT32_MAX)
+	_zip_write4(zde->uncomp_size, fp);
+    else {
+	_zip_write4(ZIP_UINT32_MAX-1, fp);
+	zip64_ef_size += 8;
+    }
+
+    if (flags & ZIP_FL_LOCAL) {
+	if (zip64_ef_size > 0 || (flags & ZIP_FL_FORCE_ZIP64))
+	    zip64_ef_size = 16;
+    }
+    else if (zde->offset >= ZIP_UINT32_MAX)
+	zip64_ef_size += 8;
+
     _zip_write2(_zip_string_length(zde->filename), fp);
-    _zip_write2(_zip_ef_size(zde->extra_fields, localp ? ZIP_EF_LOCAL : ZIP_EF_CENTRAL), fp);
+    _zip_write2(_zip_ef_size(zde->extra_fields, flags) + (zip64_ef_size ? (zip64_ef_size+4) : 0), fp);
     
-    if (!localp) {
+    if ((flags & ZIP_FL_LOCAL) == 0) {
 	_zip_write2(_zip_string_length(zde->comment), 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->offset < ZIP_UINT32_MAX)
+	    _zip_write4(zde->offset, fp);
+	else
+	    _zip_write4(ZIP_UINT32_MAX-1, fp);
     }
 
     if (zde->filename)
 	_zip_string_write(zde->filename, fp);
 
     if (zde->extra_fields)
-	_zip_ef_write(zde->extra_fields, localp ? ZIP_EF_LOCAL : ZIP_EF_CENTRAL, fp);
+	_zip_ef_write(zde->extra_fields, flags, fp);
 
-    if (!localp) {
+    if (zip64_ef_size > 0) {
+	_zip_write2(ZIP_EF_ZIP64, fp);
+	_zip_write2(zip64_ef_size, fp);
+	if ((flags & ZIP_EF_LOCAL) || zde->uncomp_size >= ZIP_UINT32_MAX)
+	    _zip_write8(zde->uncomp_size, fp);
+	if ((flags & ZIP_EF_LOCAL) || zde->comp_size >= ZIP_UINT32_MAX)
+	    _zip_write8(zde->comp_size, fp);
+	if (((flags & ZIP_EF_LOCAL) == 0) && zde->offset >= ZIP_UINT32_MAX)
+	    _zip_write8(zde->offset, fp);
+    }
+
+    if ((flags & ZIP_FL_LOCAL) == 0) {
 	if (zde->comment)
 	    _zip_string_write(zde->comment, fp);
     }
@@ -591,7 +666,7 @@
 	return -1;
     }
 
-    return 0;
+    return zip64_ef_size > 0;
 }
 
 
@@ -765,6 +840,23 @@
 
 
 void
+_zip_write8(zip_uint64_t i, FILE *fp)
+{
+    putc(i&0xff, fp);
+    putc((i>>8)&0xff, fp);
+    putc((i>>16)&0xff, fp);
+    putc((i>>24)&0xff, fp);
+    putc((i>>32)&0xff, fp);
+    putc((i>>40)&0xff, fp);
+    putc((i>>48)&0xff, fp);
+    putc((i>>56)&0xff, fp);
+    
+    return;
+}
+
+
+
+void
 _zip_u2d_time(time_t time, unsigned short *dtime, unsigned short *ddate)
 {
     struct tm *tm;
diff --git a/lib/zip_extra_field.c b/lib/zip_extra_field.c
index 1c5a414..9799880 100644
--- a/lib/zip_extra_field.c
+++ b/lib/zip_extra_field.c
@@ -41,6 +41,45 @@
 
 
 
+struct zip_extra_field *
+_zip_ef_delete_by_id(struct zip_extra_field *ef, zip_uint16_t id, zip_uint16_t id_idx, zip_flags_t flags)
+{
+    struct zip_extra_field *head, *prev;
+    int i;
+
+    i = 0;
+    head = ef;
+    prev = NULL;
+    for (; ef; ef=(prev ? prev->next : head)) {
+	if ((ef->flags & flags & ZIP_EF_BOTH) && ef->id == id) {
+	    if (id_idx == ZIP_EXTRA_FIELD_ALL || i == id_idx) {
+		ef->flags &= ~(flags & ZIP_EF_BOTH);
+		if ((ef->flags & ZIP_EF_BOTH) == 0) {
+		    if (prev)
+			prev->next = ef->next;
+		    else
+			head = ef->next;
+		    ef->next = NULL;
+		    _zip_ef_free(ef);
+
+		    if (id_idx == ZIP_EXTRA_FIELD_ALL)
+			continue;
+		}
+	    }
+	    
+	    i++;
+	    if (i > id_idx)
+		break;
+	}
+	prev = ef;
+    }
+
+    return head;
+}
+
+
+
+
 void
 _zip_ef_free(struct zip_extra_field *ef)
 {
@@ -57,7 +96,7 @@
 
 
 const zip_uint8_t *
-_zip_ef_get_by_id(struct zip_extra_field *ef, zip_uint16_t *lenp, zip_uint16_t id, zip_uint16_t id_idx, zip_uint16_t flags, struct zip_error *error)
+_zip_ef_get_by_id(struct zip_extra_field *ef, zip_uint16_t *lenp, zip_uint16_t id, zip_uint16_t id_idx, zip_flags_t flags, struct zip_error *error)
 {
     static const zip_uint8_t empty[1];
     
@@ -123,7 +162,7 @@
 
 
 struct zip_extra_field *
-_zip_ef_new(zip_uint16_t id, zip_uint16_t size, const zip_uint8_t *data, zip_uint16_t flags)
+_zip_ef_new(zip_uint16_t id, zip_uint16_t size, const zip_uint8_t *data, zip_flags_t flags)
 {
     struct zip_extra_field *ef;
 
@@ -149,7 +188,7 @@
 
 
 struct zip_extra_field *
-_zip_ef_parse(const zip_uint8_t *data, zip_uint16_t len, zip_uint16_t flags, struct zip_error *error)
+_zip_ef_parse(const zip_uint8_t *data, zip_uint16_t len, zip_flags_t flags, struct zip_error *error)
 {
     struct zip_extra_field *ef, *ef2, *ef_head;
     int i;
@@ -194,7 +233,7 @@
 
 
 zip_uint16_t
-_zip_ef_size(struct zip_extra_field *ef, zip_uint16_t flags)
+_zip_ef_size(struct zip_extra_field *ef, zip_flags_t flags)
 {
     zip_uint16_t size;
 
@@ -210,7 +249,7 @@
 
 
 void
-_zip_ef_write(struct zip_extra_field *ef, zip_uint16_t flags, FILE *f)
+_zip_ef_write(struct zip_extra_field *ef, zip_flags_t flags, FILE *f)
 {
     for (; ef; ef=ef->next) {
 	if (ef->flags & flags & ZIP_EF_BOTH) {
diff --git a/lib/zip_extra_field_api.c b/lib/zip_extra_field_api.c
index 4aafa2e..17bbd60 100644
--- a/lib/zip_extra_field_api.c
+++ b/lib/zip_extra_field_api.c
@@ -177,6 +177,9 @@
 ZIP_EXTERN int
 zip_set_file_extra_field(struct zip *za, zip_uint64_t idx, zip_uint32_t flags, zip_uint16_t ef_id, zip_uint16_t ef_idx, const zip_uint8_t *data, zip_uint16_t len)
 {
+    /* XXX: ZIP_ER_INVAL if ef_id == ZIP_EF_ZIP64 */
+    /* XXX: size of ef + new <= ZIP_UINT16_MAX */
+
     /* XXX */
     return -1;
 }
diff --git a/lib/zip_source_crc.c b/lib/zip_source_crc.c
index 59e8a19..d8cc6ce 100644
--- a/lib/zip_source_crc.c
+++ b/lib/zip_source_crc.c
@@ -139,7 +139,10 @@
 		        After all, this only works for uncompressed data. */
 		st->size = ctx->size;
 		st->crc = ctx->crc;
-		st->valid |= ZIP_STAT_SIZE|ZIP_STAT_CRC;
+		st->comp_size = ctx->size;
+		st->comp_method = ZIP_CM_STORE;
+		st->encryption_method = ZIP_EM_NONE;
+		st->valid |= ZIP_STAT_SIZE|ZIP_STAT_CRC|ZIP_STAT_COMP_SIZE|ZIP_STAT_COMP_METHOD|ZIP_STAT_ENCRYPTION_METHOD;;
 	    }
 	}
 	return 0;
diff --git a/lib/zipint.h b/lib/zipint.h
index 0c334c5..b9f26a7 100644
--- a/lib/zipint.h
+++ b/lib/zipint.h
@@ -197,6 +197,8 @@
 #define ZIP_EF_CENTRAL		ZIP_FL_CENTRAL			/* include in central directory */
 #define ZIP_EF_BOTH		(ZIP_EF_LOCAL|ZIP_EF_CENTRAL)	/* include in both */
 
+#define ZIP_FL_FORCE_ZIP64	1024  /* force zip64 extra field (_zip_dirent_write) */
+
 
 /* encoding type */
 enum zip_encoding_type {
@@ -371,6 +373,7 @@
 void _zip_dirent_free(struct zip_dirent *);
 void _zip_dirent_finalize(struct zip_dirent *);
 void _zip_dirent_init(struct zip_dirent *);
+int _zip_dirent_needs_zip64(const struct zip_dirent *, zip_flags_t);
 struct zip_dirent *_zip_dirent_new(void);
 int _zip_dirent_read(struct zip_dirent *, FILE *, const unsigned char **,
 		     zip_uint32_t *, int, struct zip_error *);
@@ -378,13 +381,14 @@
 void _zip_dirent_torrent_normalize(struct zip_dirent *);
 int _zip_dirent_write(struct zip_dirent *, FILE *, int, struct zip_error *);
 
+struct zip_extra_field *_zip_ef_delete_by_id(struct zip_extra_field *, zip_uint16_t, zip_uint16_t, zip_flags_t);
 void _zip_ef_free(struct zip_extra_field *);
-const zip_uint8_t *_zip_ef_get_by_id(struct zip_extra_field *, zip_uint16_t *, zip_uint16_t, zip_uint16_t, zip_uint16_t, struct zip_error *);
+const zip_uint8_t *_zip_ef_get_by_id(struct zip_extra_field *, zip_uint16_t *, zip_uint16_t, zip_uint16_t, zip_flags_t, struct zip_error *);
 struct zip_extra_field *_zip_ef_merge(struct zip_extra_field *, struct zip_extra_field *);
-struct zip_extra_field *_zip_ef_new(zip_uint16_t, zip_uint16_t, const zip_uint8_t *, zip_uint16_t);
-struct zip_extra_field *_zip_ef_parse(const zip_uint8_t *, zip_uint16_t, zip_uint16_t, struct zip_error *);
-zip_uint16_t _zip_ef_size(struct zip_extra_field *, zip_uint16_t);
-void _zip_ef_write(struct zip_extra_field *, zip_uint16_t, FILE *);
+struct zip_extra_field *_zip_ef_new(zip_uint16_t, zip_uint16_t, const zip_uint8_t *, zip_flags_t);
+struct zip_extra_field *_zip_ef_parse(const zip_uint8_t *, zip_uint16_t, zip_flags_t, struct zip_error *);
+zip_uint16_t _zip_ef_size(struct zip_extra_field *, zip_flags_t);
+void _zip_ef_write(struct zip_extra_field *, zip_flags_t, FILE *);
 
 void _zip_entry_finalize(struct zip_entry *);
 void _zip_entry_init(struct zip_entry *);
@@ -448,6 +452,7 @@
 
 void _zip_write2(zip_uint16_t, FILE *);
 void _zip_write4(zip_uint32_t, FILE *);
+void _zip_write8(zip_uint64_t, FILE *);
 
 
 #endif /* zipint.h */