Support setting last modification time for file in archive.
diff --git a/NEWS b/NEWS
index 23c4ab2..d3ea626 100644
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,7 @@
+X.XX.X [XXXX/XX/XX]
+
+* Support setting last modification time for file.
+
0.11.2 [2013/12/19]
* Support querying/setting operating system and external attributes.
diff --git a/TODO b/TODO
index 66bd0d4..1892ff6 100644
--- a/TODO
+++ b/TODO
@@ -36,7 +36,6 @@
* I/O methods
* support streaming output (creating new archive to e.g. stdout)
* add functions to:
- . set last modification time for entry
. read/set ASCII file flag? (wiz: more general options?)
* zip_commit (to finish changes without closing archive)
* add custom compression function support
diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt
index 358e212..b145230 100644
--- a/lib/CMakeLists.txt
+++ b/lib/CMakeLists.txt
@@ -83,6 +83,7 @@
zip_file_replace.c
zip_file_set_comment.c
zip_file_set_external_attributes.c
+ zip_file_set_mtime.c
zip_file_strerror.c
zip_filerange_crc.c
zip_fopen.c
diff --git a/lib/Makefile.am b/lib/Makefile.am
index a74f409..c258f0c 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -41,6 +41,7 @@
zip_file_replace.c \
zip_file_set_comment.c \
zip_file_set_external_attributes.c \
+ zip_file_set_mtime.c \
zip_file_strerror.c \
zip_filerange_crc.c \
zip_fopen.c \
diff --git a/lib/zip.h b/lib/zip.h
index ba38ac8..644af2f 100644
--- a/lib/zip.h
+++ b/lib/zip.h
@@ -285,6 +285,7 @@
ZIP_EXTERN int zip_file_replace(struct zip *, zip_uint64_t, struct zip_source *, zip_flags_t);
ZIP_EXTERN int zip_file_set_comment(struct zip *, zip_uint64_t, const char *, zip_uint16_t, zip_flags_t);
ZIP_EXTERN int zip_file_set_external_attributes(struct zip *, zip_uint64_t, zip_flags_t, zip_uint8_t, zip_uint32_t);
+ZIP_EXTERN int zip_file_set_mtime(struct zip *, zip_uint64_t, time_t, zip_flags_t);
ZIP_EXTERN const char *zip_file_strerror(struct zip_file *);
ZIP_EXTERN struct zip_file *zip_fopen(struct zip *, const char *, zip_flags_t);
ZIP_EXTERN struct zip_file *zip_fopen_encrypted(struct zip *, const char *, zip_flags_t, const char *);
diff --git a/lib/zip_close.c b/lib/zip_close.c
index 577e921..84ff9f9 100644
--- a/lib/zip_close.c
+++ b/lib/zip_close.c
@@ -423,10 +423,12 @@
return -1;
}
- if (st.valid & ZIP_STAT_MTIME)
- de->last_mod = st.mtime;
- else
- time(&de->last_mod);
+ if ((de->changed & ZIP_DIRENT_LAST_MOD) == 0) {
+ 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;
diff --git a/lib/zip_file_set_mtime.c b/lib/zip_file_set_mtime.c
new file mode 100644
index 0000000..f5ea0e8
--- /dev/null
+++ b/lib/zip_file_set_mtime.c
@@ -0,0 +1,74 @@
+/*
+ zip_file_set_mtime.c -- set modification time of entry.
+ Copyright (C) 2014 Dieter Baron and Thomas Klausner
+
+ This file is part of libzip, a library to manipulate ZIP archives.
+ The authors can be contacted at <libzip@nih.at>
+
+ 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 "zipint.h"
+
+ZIP_EXTERN int zip_file_set_mtime(struct zip *za, zip_uint64_t idx, time_t mtime, zip_flags_t flags)
+{
+ struct zip_entry *e;
+ int changed;
+
+ if (_zip_get_dirent(za, idx, 0, NULL) == NULL)
+ return -1;
+
+ if (ZIP_IS_RDONLY(za)) {
+ _zip_error_set(&za->error, ZIP_ER_RDONLY, 0);
+ return -1;
+ }
+
+ e = za->entry+idx;
+
+ changed = mtime != e->orig->last_mod;
+
+ if (changed) {
+ if (e->changes == NULL) {
+ if ((e->changes=_zip_dirent_clone(e->orig)) == NULL) {
+ _zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
+ return -1;
+ }
+ }
+ e->changes->last_mod = mtime;
+ e->changes->changed |= ZIP_DIRENT_LAST_MOD;
+ }
+ else {
+ if (e->changes) {
+ e->changes->changed &= ~ZIP_DIRENT_LAST_MOD;
+ if (e->changes->changed == 0) {
+ _zip_dirent_free(e->changes);
+ e->changes = NULL;
+ }
+ }
+ }
+
+ return 0;
+}
diff --git a/lib/zipint.h b/lib/zipint.h
index 7b7220c..e4cb066 100644
--- a/lib/zipint.h
+++ b/lib/zipint.h
@@ -307,6 +307,7 @@
#define ZIP_DIRENT_COMMENT 0x0004u
#define ZIP_DIRENT_EXTRA_FIELD 0x0008u
#define ZIP_DIRENT_ATTRIBUTES 0x0010u
+#define ZIP_DIRENT_LAST_MOD 0x0020u
#define ZIP_DIRENT_ALL 0xffffu
struct zip_dirent {
diff --git a/man/Makefile.am b/man/Makefile.am
index f2c4c99..4541545 100644
--- a/man/Makefile.am
+++ b/man/Makefile.am
@@ -30,6 +30,7 @@
zip_file_rename.mdoc \
zip_file_set_comment.mdoc \
zip_file_set_external_attributes.mdoc \
+ zip_file_set_mtime.mdoc \
zip_file_strerror.mdoc \
zip_fopen.mdoc \
zip_fopen_encrypted.mdoc \
diff --git a/man/zip_file_set_mtime.man b/man/zip_file_set_mtime.man
new file mode 100644
index 0000000..b821bf0
--- /dev/null
+++ b/man/zip_file_set_mtime.man
@@ -0,0 +1,55 @@
+.TH "ZIP_FILE_SET_MTIME" "3" "August 5, 2014" "NiH" "Library Functions Manual"
+.nh
+.if n .ad l
+.SH "NAME"
+\fBzip_file_set_mtime\fR
+\- set last modification time (mtime) for file in zip
+.SH "LIBRARY"
+libzip (-lzip)
+.SH "SYNOPSIS"
+\fB#include <zip.h>\fR
+.sp
+\fIint\fR
+.PD 0
+.HP 4n
+\fBzip_set_file_mtime\fR(\fIstruct\ zip\ *archive\fR, \fIzip_uint64_t\ index\fR, \fItime_t\ mtime\fR, \fIzip_flags_t\ flags\fR);
+.PD
+.SH "DESCRIPTION"
+The
+\fBzip_file_set_mtime\fR()
+function sets the last modification time (mtime) for the file at
+position
+\fIindex\fR
+in the zip archive to
+\fImtime\fR.
+Currently, no support for any
+\fIflags\fR
+is implemented.
+.SH "RETURN VALUES"
+Upon successful completion 0 is returned.
+Otherwise, \-1 is returned and the error information in
+\fIarchive\fR
+is set to indicate the error.
+.SH "ERRORS"
+\fBzip_file_set_mtime\fR()
+fails if:
+.TP 19n
+[\fRZIP_ER_INVAL\fR]
+\fIindex\fR
+is not a valid file index in
+\fIarchive\fR.
+.TP 19n
+[\fRZIP_ER_MEMORY\fR]
+Required memory could not be allocated.
+.TP 19n
+[\fRZIP_ER_RDONLY\fR]
+The
+\fIarchive\fR
+was opened in read-only mode.
+.SH "SEE ALSO"
+libzip(3),
+zip_stat(3)
+.SH "AUTHORS"
+Dieter Baron <\fIdillo@nih.at\fR>
+and
+Thomas Klausner <\fItk@giga.or.at\fR>
diff --git a/man/zip_file_set_mtime.mdoc b/man/zip_file_set_mtime.mdoc
new file mode 100644
index 0000000..ac435eb
--- /dev/null
+++ b/man/zip_file_set_mtime.mdoc
@@ -0,0 +1,83 @@
+.\" zip_file_set_mtime.mdoc -- set mtime for file in zip
+.\" Copyright (C) 2014 Dieter Baron and Thomas Klausner
+.\"
+.\" This file is part of libzip, a library to manipulate ZIP files.
+.\" The authors can be contacted at <libzip@nih.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.
+.\"
+.Dd August 5, 2014
+.Dt ZIP_FILE_SET_MTIME 3
+.Os
+.Sh NAME
+.Nm zip_file_set_mtime
+.Nd set last modification time (mtime) for file in zip
+.Sh LIBRARY
+libzip (-lzip)
+.Sh SYNOPSIS
+.In zip.h
+.Ft int
+.Fn zip_set_file_mtime "struct zip *archive" "zip_uint64_t index" \
+"time_t mtime" "zip_flags_t flags"
+.Sh DESCRIPTION
+The
+.Fn zip_file_set_mtime
+function sets the last modification time (mtime) for the file at
+position
+.Ar index
+in the zip archive to
+.Ar mtime .
+Currently, no support for any
+.Ar flags
+is implemented.
+.Sh RETURN VALUES
+Upon successful completion 0 is returned.
+Otherwise, \-1 is returned and the error information in
+.Ar archive
+is set to indicate the error.
+.Sh ERRORS
+.Fn zip_file_set_mtime
+fails if:
+.Bl -tag -width Er
+.It Bq Er ZIP_ER_INVAL
+.Ar index
+is not a valid file index in
+.Ar archive .
+.It Bq Er ZIP_ER_MEMORY
+Required memory could not be allocated.
+.It Bq Er ZIP_ER_RDONLY
+The
+.Ar archive
+was opened in read-only mode.
+.El
+.Sh SEE ALSO
+.Xr libzip 3 ,
+.Xr zip_stat 3
+.Sh AUTHORS
+.An -nosplit
+.An Dieter Baron Aq Mt dillo@nih.at
+and
+.An Thomas Klausner Aq Mt tk@giga.or.at
diff --git a/regress/Makefile.am b/regress/Makefile.am
index 70da41c..671a258 100644
--- a/regress/Makefile.am
+++ b/regress/Makefile.am
@@ -96,6 +96,7 @@
testfile-cp437.zip \
testfile-plus-extra.zip \
testfile-UTF8.zip \
+ testfile2014.zip \
testnottorrent.zip \
teststdin.zip \
teststored.zip \
diff --git a/regress/modify.c b/regress/modify.c
index b98f319..5d6e5ff 100644
--- a/regress/modify.c
+++ b/regress/modify.c
@@ -73,6 +73,7 @@
"\tset_extra index extra_id extra_index flags value\n"
"\tset_file_comment index comment\n"
"\tset_file_compression index method flags\n"
+ "\tset_file_mtime index timestamp\n"
"\tzin_close\n"
"\nThe index is zero-based.\n";
@@ -423,6 +424,18 @@
break;
}
arg += 4;
+ } else if (strcmp(argv[arg], "set_mtime") == 0 && arg+2 < argc) {
+ /* set file last modification time (mtime) */
+ time_t mtime;
+ idx = atoi(argv[arg+1]);
+ /* TODO: add configure check for strtoll or similar, and use it */
+ mtime = atoi(argv[arg+2]);
+ if (zip_file_set_mtime(za, idx, mtime, 0) < 0) {
+ fprintf(stderr, "can't set file mtime at index '%d' to `%ld': %s\n", idx, mtime, zip_strerror(za));
+ err = 1;
+ break;
+ }
+ arg += 3;
} else if (strcmp(argv[arg], "zin_close") == 0) {
if (zip_close(z_in) < 0) {
fprintf(stderr, "can't close source archive: %s\n", zip_strerror(z_in));
diff --git a/regress/set_mtime.test b/regress/set_mtime.test
new file mode 100644
index 0000000..d88195a
--- /dev/null
+++ b/regress/set_mtime.test
@@ -0,0 +1,5 @@
+# change mtime in a zip archive
+program modify
+return 0
+args testfile set_mtime 0 1407272201
+file testfile testfile.zip testfile2014.zip
diff --git a/regress/testfile2014.zip b/regress/testfile2014.zip
new file mode 100644
index 0000000..1d91853
--- /dev/null
+++ b/regress/testfile2014.zip
Binary files differ