set_*_comment support.
XXX: there's a double free somewhere, but I currently don't find its cause

--HG--
branch : HEAD
diff --git a/lib/Makefile.am b/lib/Makefile.am
index aaf9fcc..7e6af93 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -30,11 +30,14 @@
 	zip_get_file_comment.c \
 	zip_get_num_files.c \
 	zip_get_name.c \
+	zip_memdup.c \
 	zip_name_locate.c \
 	zip_new.c \
 	zip_open.c \
 	zip_rename.c \
 	zip_replace.c \
+	zip_set_archive_comment.c \
+	zip_set_file_comment.c \
 	zip_source_buffer.c \
 	zip_source_file.c \
 	zip_source_filep.c \
diff --git a/lib/zip.h b/lib/zip.h
index 8ddeb9d..f1aff76 100644
--- a/lib/zip.h
+++ b/lib/zip.h
@@ -2,7 +2,7 @@
 #define _HAD_ZIP_H
 
 /*
-  $NiH: zip.h,v 1.52 2006/04/09 14:52:02 wiz Exp $
+  $NiH: zip.h,v 1.53 2006/04/09 19:05:47 wiz Exp $
 
   zip.h -- exported declarations.
   Copyright (C) 1999, 2003, 2004, 2005, 2006 Dieter Baron and Thomas Klausner
@@ -162,6 +162,8 @@
 struct zip *zip_open(const char *, int, int *);
 int zip_rename(struct zip *, int, const char *);
 int zip_replace(struct zip *, int, struct zip_source *);
+int zip_set_archive_comment(struct zip *, const char *, int);
+int zip_set_file_comment(struct zip *, int, const char *, int);
 struct zip_source *zip_source_buffer(struct zip *, const void *, off_t, int);
 struct zip_source *zip_source_file(struct zip *, const char *, off_t, off_t);
 struct zip_source *zip_source_filep(struct zip *, FILE *, off_t, off_t);
diff --git a/lib/zip_close.c b/lib/zip_close.c
index 1482ae0..19a4553 100644
--- a/lib/zip_close.c
+++ b/lib/zip_close.c
@@ -1,5 +1,5 @@
 /*
-  $NiH: zip_close.c,v 1.52 2006/02/21 09:13:32 dillo Exp $
+  $NiH: zip_close.c,v 1.53 2006/02/21 09:41:00 dillo Exp $
 
   zip_close.c -- close zip archive and update changes
   Copyright (C) 1999, 2004, 2005 Dieter Baron and Thomas Klausner
@@ -68,8 +68,11 @@
     struct zip_dirent de;
 
     changed = survivors = 0;
+    if (za->ch_comment_len != -1)
+	changed = 1;
     for (i=0; i<za->nentry; i++) {
-	if (za->entry[i].state != ZIP_ST_UNCHANGED)
+	if ((za->entry[i].state != ZIP_ST_UNCHANGED)
+	    || (za->entry[i].ch_comment_len != -1))
 	    changed = 1;
 	if (za->entry[i].state != ZIP_ST_DELETED)
 	    survivors++;
@@ -95,6 +98,18 @@
     if ((cd=_zip_cdir_new(survivors, &za->error)) == NULL)
 	return -1;
 
+    if (za->ch_comment_len != -1) {
+	free(cd->comment);
+	if ((cd->comment=(char *)_zip_memdup(za->ch_comment,
+					    za->ch_comment_len,
+					    &za->error)) == NULL) {
+	    	
+	    _zip_cdir_free(cd);
+	    return -1;
+	}
+	cd->comment_len = za->ch_comment_len;
+    }
+
     if ((temp=(char *)malloc(strlen(za->zn)+8)) == NULL) {
 	_zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
 	_zip_cdir_free(cd);
@@ -157,17 +172,34 @@
 
 	if (za->entry[i].ch_filename) {
 	    free(de.filename);
-	    de.filename = strdup(za->entry[i].ch_filename);
+	    de.filename_len = 0;
+	    if ((de.filename=strdup(za->entry[i].ch_filename)) == NULL) {
+		error = 1;
+		break;
+	    }
 	    de.filename_len = strlen(de.filename);
 	    cd->entry[j].filename = za->entry[i].ch_filename;
 	    cd->entry[j].filename_len = de.filename_len;
 	}
 
+	if (za->entry[i].ch_comment_len != -1) {
+	    free(cd->entry[j].comment);
+	    cd->entry[j].comment_len = 0;
+	    cd->entry[j].comment=(char*)_zip_memdup(za->entry[i].ch_comment,
+						    za->entry[i].ch_comment_len,
+						    &za->error);
+	    if (cd->entry[j].comment == NULL) {
+		error = 1;
+		break;
+	    }
+	    cd->entry[j].comment_len = za->entry[i].ch_comment_len;
+	}
+
 	cd->entry[j].offset = ftell(tfp);
 
 	if (ZIP_ENTRY_DATA_CHANGED(za->entry+i)) {
 	    if (add_data(za, i, &de, tfp) < 0) {
-		error = -1;
+		error = 1;
 		break;
 	    }
 	    cd->entry[j].last_mod = de.last_mod;
diff --git a/lib/zip_get_archive_comment.c b/lib/zip_get_archive_comment.c
index 754b61d..5f20f81 100644
--- a/lib/zip_get_archive_comment.c
+++ b/lib/zip_get_archive_comment.c
@@ -1,5 +1,5 @@
 /*
-  $NiH$
+  $NiH: zip_get_archive_comment.c,v 1.1 2006/04/09 19:05:47 wiz Exp $
 
   zip_get_archive_comment.c -- get archive comment
   Copyright (C) 2006 Dieter Baron and Thomas Klausner
@@ -46,13 +46,13 @@
     if (za == NULL)
 	return NULL;
 
-    if (za->cdir->ch_comment_len == -1) {
+    if (za->ch_comment_len == -1) {
 	if (lenp != NULL)
 	    *lenp = za->cdir->comment_len;
 	return za->cdir->comment;
     }
     
     if (lenp != NULL)
-	*lenp = za->cdir->ch_comment_len;
-    return za->cdir->ch_comment;
+	*lenp = za->ch_comment_len;
+    return za->ch_comment;
 }
diff --git a/lib/zip_memdup.c b/lib/zip_memdup.c
new file mode 100644
index 0000000..20a2700
--- /dev/null
+++ b/lib/zip_memdup.c
@@ -0,0 +1,58 @@
+/*
+  $NiH: zip_memdup.c,v 1.34 2006/04/09 19:05:47 wiz Exp $
+
+  zip_memdup.c -- internal zip function, "strdup" with len
+  Copyright (C) 1999, 2003, 2004, 2005, 2006 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 <sys/types.h>
+#include <stdlib.h>
+
+#include "zip.h"
+#include "zipint.h"
+
+
+
+void *
+_zip_memdup(const void *mem, size_t len, struct zip_error *error)
+{
+    void *ret;
+
+    ret = malloc(len);
+    if (!ret) {
+	_zip_error_set(error, ZIP_ER_MEMORY, 0);
+	return NULL;
+    }
+
+    memcpy(ret, mem, len);
+
+    return ret;
+}
diff --git a/lib/zip_new.c b/lib/zip_new.c
index 0344cfc..8c614ed 100644
--- a/lib/zip_new.c
+++ b/lib/zip_new.c
@@ -1,5 +1,5 @@
 /*
-  $NiH: zip_new.c,v 1.10 2005/01/11 18:38:55 dillo Exp $
+  $NiH: zip_new.c,v 1.11 2005/06/09 19:57:10 dillo Exp $
 
   zip_new.c -- create and init struct zip
   Copyright (C) 1999, 2004, 2005 Dieter Baron and Thomas Klausner
@@ -60,6 +60,8 @@
     za->zp = NULL;
     _zip_error_init(&za->error);
     za->cdir = NULL;
+    za->ch_comment = NULL;
+    za->ch_comment_len = -1;
     za->nentry = za->nentry_alloc = 0;
     za->entry = NULL;
     za->nfile = za->nfile_alloc = 0;
diff --git a/lib/zip_open.c b/lib/zip_open.c
index 6b30f20..cfb54d8 100644
--- a/lib/zip_open.c
+++ b/lib/zip_open.c
@@ -1,5 +1,5 @@
 /*
-  $NiH: zip_open.c,v 1.33 2006/02/22 19:52:20 dillo Exp $
+  $NiH: zip_open.c,v 1.34 2006/04/09 19:05:47 wiz Exp $
 
   zip_open.c -- open zip archive
   Copyright (C) 1999, 2003, 2004, 2005, 2006 Dieter Baron and Thomas Klausner
@@ -36,11 +36,9 @@
 
 
 #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"
@@ -50,7 +48,6 @@
 static int _zip_checkcons(FILE *, struct zip_cdir *, struct zip_error *);
 static int _zip_headercomp(struct zip_dirent *, int,
 			   struct zip_dirent *, int);
-static void *_zip_memdup(const void *, size_t, struct zip_error *);
 static unsigned char *_zip_memmem(const unsigned char *, int,
 				  const unsigned char *, int);
 static struct zip_cdir *_zip_readcdir(FILE *, unsigned char *, unsigned char *,
@@ -270,8 +267,6 @@
     cd->offset = _zip_read4(&cdp);
     cd->comment = NULL;
     cd->comment_len = _zip_read2(&cdp);
-    cd->ch_comment = NULL;
-    cd->ch_comment_len = -1;
 
     /* some zip files are broken; their internal comment length
        says 0, but they have 1 or 2 comment bytes */
@@ -455,21 +450,3 @@
 
     return NULL;
 }
-
-
-
-static void *
-_zip_memdup(const void *mem, size_t len, struct zip_error *error)
-{
-    void *ret;
-
-    ret = malloc(len);
-    if (!ret) {
-	_zip_error_set(error, ZIP_ER_MEMORY, 0);
-	return NULL;
-    }
-
-    memcpy(ret, mem, len);
-
-    return ret;
-}
diff --git a/lib/zip_set_archive_comment.c b/lib/zip_set_archive_comment.c
new file mode 100644
index 0000000..97a655e
--- /dev/null
+++ b/lib/zip_set_archive_comment.c
@@ -0,0 +1,64 @@
+/*
+  $NiH$
+
+  zip_set_archive_comment.c -- set archive comment
+  Copyright (C) 2006 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 "zip.h"
+#include "zipint.h"
+
+
+
+int
+zip_set_archive_comment(struct zip *za, const char *comment, int len)
+{
+    char *tmpcom;
+
+    if (len < 0 || len > MAXCOMLEN) {
+	_zip_error_set(&za->error, ZIP_ER_INVAL, 0);
+	return -1;
+    }
+
+    if ((tmpcom=(char *)malloc(len)) == NULL) {
+	_zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
+	return -1;
+    }
+
+    memcpy(tmpcom, comment, len);
+    free(za->ch_comment);
+    za->ch_comment = tmpcom;
+    za->ch_comment_len = len;
+    
+    return 0;
+}
diff --git a/lib/zip_set_file_comment.c b/lib/zip_set_file_comment.c
new file mode 100644
index 0000000..f6a7b13
--- /dev/null
+++ b/lib/zip_set_file_comment.c
@@ -0,0 +1,64 @@
+/*
+  $NiH$
+
+  zip_set_file_comment.c -- set comment for file in archive
+  Copyright (C) 2006 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 "zip.h"
+#include "zipint.h"
+
+
+
+int
+zip_set_file_comment(struct zip *za, int idx, const char *comment, int len)
+{
+    char *tmpcom;
+
+    if (len < 0 || len > MAXCOMLEN) {
+	_zip_error_set(&za->error, ZIP_ER_INVAL, 0);
+	return -1;
+    }
+
+    if ((tmpcom=(char *)malloc(len)) == NULL) {
+	_zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
+	return -1;
+    }
+
+    memcpy(tmpcom, comment, len);
+    free(za->entry[idx].ch_comment);
+    za->entry[idx].ch_comment = tmpcom;
+    za->entry[idx].ch_comment_len = len;
+    
+    return 0;
+}
diff --git a/lib/zip_unchange_all.c b/lib/zip_unchange_all.c
index 81e37bc..1cb6a8a 100644
--- a/lib/zip_unchange_all.c
+++ b/lib/zip_unchange_all.c
@@ -1,5 +1,5 @@
 /*
-  $NiH: zip_unchange_all.c,v 1.7 2004/11/30 23:02:47 wiz Exp $
+  $NiH: zip_unchange_all.c,v 1.8 2006/04/09 19:05:47 wiz Exp $
 
   zip_unchange.c -- undo changes to all files in zip archive
   Copyright (C) 1999, 2006 Dieter Baron and Thomas Klausner
@@ -50,9 +50,9 @@
     for (i=0; i<za->nentry; i++)
 	ret |= _zip_unchange(za, i, 1);
 
-    free(za->cdir->ch_comment);
-    za->cdir->ch_comment = NULL;
-    za->cdir->ch_comment_len = -1;
+    free(za->ch_comment);
+    za->ch_comment = NULL;
+    za->ch_comment_len = -1;
 
     return ret;
 }
diff --git a/lib/zipint.h b/lib/zipint.h
index b1815a3..87f28f3 100644
--- a/lib/zipint.h
+++ b/lib/zipint.h
@@ -2,7 +2,7 @@
 #define _HAD_ZIPINT_H
 
 /*
-  $NiH: zipint.h,v 1.45 2006/02/22 19:52:20 dillo Exp $
+  $NiH: zipint.h,v 1.46 2006/04/09 19:05:47 wiz Exp $
 
   zipint.h -- internal declarations.
   Copyright (C) 1999, 2003, 2004, 2005, 2006 Dieter Baron and Thomas Klausner
@@ -92,6 +92,9 @@
     struct zip_error error;	/* error information */
 
     struct zip_cdir *cdir;	/* central directory */
+    char *ch_comment;		/* changed archive comment */
+    int ch_comment_len;		/* length of changed zip archive
+				 * comment, -1 if unchanged */
     int nentry;			/* number of entries */
     int nentry_alloc;		/* number of entries allocated */
     struct zip_entry *entry;	/* entries */
@@ -152,9 +155,6 @@
     unsigned int offset;	/* offset of central directory in file */
     char *comment;		/* zip archive comment */
     unsigned short comment_len;	/* length of zip archive comment */
-    char *ch_comment;		/* changed archive comment */
-    int ch_comment_len;		/* length of changed zip archive
-				 * comment, -1 if unchanged */
 };
 
 
@@ -215,6 +215,7 @@
 void _zip_free(struct zip *);
 const char *_zip_get_name(struct zip *, int, int, struct zip_error *);
 int _zip_local_header_read(struct zip *, int);
+void *_zip_memdup(const void *, size_t, struct zip_error *);
 int _zip_name_locate(struct zip *, const char *, int, struct zip_error *);
 struct zip *_zip_new(struct zip_error *);
 unsigned short _zip_read2(unsigned char **);