Remove changing uids/timestamps from zip/jar files
Pass -X to zip so that Unix UID/GID and extra timestamps aren't
saved into the zip files.
Add a new option to zipalign, -t, to replace all timestamps with static
timestamps (2008 Jan 1 00:00:00). Use this for all non-APK zip files.
APK zip timestamps are set based on the certificate date in SignApk.
Bug: 24201956
Change-Id: Ifb619fc499ba9d99fc624f2acd5f8de36d78ef8e
diff --git a/tools/zipalign/README.txt b/tools/zipalign/README.txt
index 0b80b35..1cdf612 100644
--- a/tools/zipalign/README.txt
+++ b/tools/zipalign/README.txt
@@ -6,6 +6,7 @@
-c : check alignment only (does not modify file)
-f : overwrite existing outfile.zip
-p : page align stored shared object files
+ -t : remove dynamic timestamps
-v : verbose output
<align> is in bytes, e.g. "4" provides 32-bit alignment
infile.zip is an existing Zip archive
@@ -38,3 +39,5 @@
uncompressed in the zip archive, to a 4096-byte page boundary. This
facilitates directly loading shared libraries from inside a zip archive.
+The "-t" flag removes all timestamps that could change from the archive.
+
diff --git a/tools/zipalign/ZipAlign.cpp b/tools/zipalign/ZipAlign.cpp
index a2dfd02..2c81a03 100644
--- a/tools/zipalign/ZipAlign.cpp
+++ b/tools/zipalign/ZipAlign.cpp
@@ -39,6 +39,7 @@
fprintf(stderr, " -c: check alignment only (does not modify file)\n");
fprintf(stderr, " -f: overwrite existing outfile.zip\n");
fprintf(stderr, " -p: page align stored shared object files\n");
+ fprintf(stderr, " -t: remove dynamic timestamps\n");
fprintf(stderr, " -v: verbose output\n");
fprintf(stderr, " -z: recompress using Zopfli\n");
}
@@ -64,7 +65,7 @@
* Copy all entries from "pZin" to "pZout", aligning as needed.
*/
static int copyAndAlign(ZipFile* pZin, ZipFile* pZout, int alignment, bool zopfli,
- bool pageAlignSharedLibs)
+ bool pageAlignSharedLibs, bool removeTime)
{
int numEntries = pZin->getNumEntries();
ZipEntry* pEntry;
@@ -88,10 +89,10 @@
// (long) pEntry->getUncompressedLen());
if (zopfli) {
- status = pZout->addRecompress(pZin, pEntry, &pNewEntry);
+ status = pZout->addRecompress(pZin, pEntry, removeTime, &pNewEntry);
bias += pNewEntry->getCompressedLen() - pEntry->getCompressedLen();
} else {
- status = pZout->add(pZin, pEntry, padding, &pNewEntry);
+ status = pZout->add(pZin, pEntry, padding, removeTime, &pNewEntry);
}
} else {
const int alignTo = getAlignment(pageAlignSharedLibs, alignment, pEntry);
@@ -107,7 +108,7 @@
//printf("--- %s: orig at %ld(+%d) len=%ld, adding pad=%d\n",
// pEntry->getFileName(), (long) pEntry->getFileOffset(),
// bias, (long) pEntry->getUncompressedLen(), padding);
- status = pZout->add(pZin, pEntry, padding, &pNewEntry);
+ status = pZout->add(pZin, pEntry, padding, removeTime, &pNewEntry);
}
if (status != NO_ERROR)
@@ -126,7 +127,8 @@
* output file exists and "force" wasn't specified.
*/
static int process(const char* inFileName, const char* outFileName,
- int alignment, bool force, bool zopfli, bool pageAlignSharedLibs)
+ int alignment, bool force, bool zopfli, bool pageAlignSharedLibs,
+ bool removeTime)
{
ZipFile zin, zout;
@@ -157,7 +159,7 @@
return 1;
}
- int result = copyAndAlign(&zin, &zout, alignment, zopfli, pageAlignSharedLibs);
+ int result = copyAndAlign(&zin, &zout, alignment, zopfli, pageAlignSharedLibs, removeTime);
if (result != 0) {
printf("zipalign: failed rewriting '%s' to '%s'\n",
inFileName, outFileName);
@@ -228,6 +230,7 @@
bool verbose = false;
bool zopfli = false;
bool pageAlignSharedLibs = false;
+ bool removeTime = false;
int result = 1;
int alignment;
char* endp;
@@ -260,6 +263,9 @@
case 'p':
pageAlignSharedLibs = true;
break;
+ case 't':
+ removeTime = true;
+ break;
default:
fprintf(stderr, "ERROR: unknown flag -%c\n", *cp);
wantUsage = true;
@@ -290,7 +296,7 @@
result = verify(argv[1], alignment, verbose, pageAlignSharedLibs);
} else {
/* create the new archive */
- result = process(argv[1], argv[2], alignment, force, zopfli, pageAlignSharedLibs);
+ result = process(argv[1], argv[2], alignment, force, zopfli, pageAlignSharedLibs, removeTime);
/* trust, but verify */
if (result == 0) {
diff --git a/tools/zipalign/ZipEntry.cpp b/tools/zipalign/ZipEntry.cpp
index b2270cb..9347451 100644
--- a/tools/zipalign/ZipEntry.cpp
+++ b/tools/zipalign/ZipEntry.cpp
@@ -386,6 +386,14 @@
mCDE.mLastModFileDate = mLFH.mLastModFileDate = zdate;
}
+/*
+ * Set static timestamps
+ */
+void ZipEntry::removeTimestamps()
+{
+ mCDE.mLastModFileTime = mLFH.mLastModFileTime = 0;
+ mCDE.mLastModFileDate = mLFH.mLastModFileDate = 28 << 9 | 1 << 5 | 1;
+}
/*
* ===========================================================================
diff --git a/tools/zipalign/ZipEntry.h b/tools/zipalign/ZipEntry.h
index 7f721b4..0acd051 100644
--- a/tools/zipalign/ZipEntry.h
+++ b/tools/zipalign/ZipEntry.h
@@ -186,6 +186,12 @@
void setModWhen(time_t when);
/*
+ * Set a static modification date. This only affects the standard
+ * zip modification date, not the universal time extra field.
+ */
+ void removeTimestamps();
+
+ /*
* Return the offset of the local file header.
*/
off_t getLFHOffset(void) const { return mCDE.mLocalHeaderRelOffset; }
diff --git a/tools/zipalign/ZipFile.cpp b/tools/zipalign/ZipFile.cpp
index 3c5ec15..0ca4d0d 100644
--- a/tools/zipalign/ZipFile.cpp
+++ b/tools/zipalign/ZipFile.cpp
@@ -359,7 +359,7 @@
*/
status_t ZipFile::addCommon(const char* fileName, const void* data, size_t size,
const char* storageName, int sourceType, int compressionMethod,
- ZipEntry** ppEntry)
+ bool removeTime, ZipEntry** ppEntry)
{
ZipEntry* pEntry = NULL;
status_t result = NO_ERROR;
@@ -499,8 +499,12 @@
*/
pEntry->setDataInfo(uncompressedLen, endPosn - startPosn, crc,
compressionMethod);
- modWhen = getModTime(inputFp ? fileno(inputFp) : fileno(mZipFp));
- pEntry->setModWhen(modWhen);
+ if (removeTime) {
+ pEntry->removeTimestamps();
+ } else {
+ modWhen = getModTime(inputFp ? fileno(inputFp) : fileno(mZipFp));
+ pEntry->setModWhen(modWhen);
+ }
pEntry->setLFHOffset(lfhPosn);
mEOCD.mNumEntries++;
mEOCD.mTotalNumEntries++;
@@ -539,7 +543,7 @@
* If "ppEntry" is non-NULL, a pointer to the new entry will be returned.
*/
status_t ZipFile::add(const ZipFile* pSourceZip, const ZipEntry* pSourceEntry,
- int padding, ZipEntry** ppEntry)
+ int padding, bool removeTime, ZipEntry** ppEntry)
{
ZipEntry* pEntry = NULL;
status_t result;
@@ -571,6 +575,8 @@
if (result != NO_ERROR)
goto bail;
}
+ if (removeTime)
+ pEntry->removeTimestamps();
/*
* From here on out, failures are more interesting.
@@ -646,7 +652,7 @@
* If "ppEntry" is non-NULL, a pointer to the new entry will be returned.
*/
status_t ZipFile::addRecompress(const ZipFile* pSourceZip, const ZipEntry* pSourceEntry,
- ZipEntry** ppEntry)
+ bool removeTime, ZipEntry** ppEntry)
{
ZipEntry* pEntry = NULL;
status_t result;
@@ -674,6 +680,9 @@
if (result != NO_ERROR)
goto bail;
+ if (removeTime)
+ pEntry->removeTimestamps();
+
/*
* From here on out, failures are more interesting.
*/
diff --git a/tools/zipalign/ZipFile.h b/tools/zipalign/ZipFile.h
index b99cda5..787576f 100644
--- a/tools/zipalign/ZipFile.h
+++ b/tools/zipalign/ZipFile.h
@@ -77,17 +77,17 @@
*
* If "ppEntry" is non-NULL, a pointer to the new entry will be returned.
*/
- status_t add(const char* fileName, int compressionMethod,
+ status_t add(const char* fileName, int compressionMethod, bool removeTime,
ZipEntry** ppEntry)
{
- return add(fileName, fileName, compressionMethod, ppEntry);
+ return add(fileName, fileName, compressionMethod, removeTime, ppEntry);
}
status_t add(const char* fileName, const char* storageName,
- int compressionMethod, ZipEntry** ppEntry)
+ int compressionMethod, bool removeTime, ZipEntry** ppEntry)
{
return addCommon(fileName, NULL, 0, storageName,
ZipEntry::kCompressStored,
- compressionMethod, ppEntry);
+ compressionMethod, removeTime, ppEntry);
}
/*
@@ -96,11 +96,12 @@
* If "ppEntry" is non-NULL, a pointer to the new entry will be returned.
*/
status_t addGzip(const char* fileName, const char* storageName,
- ZipEntry** ppEntry)
+ bool removeTime, ZipEntry** ppEntry)
{
return addCommon(fileName, NULL, 0, storageName,
ZipEntry::kCompressDeflated,
- ZipEntry::kCompressDeflated, ppEntry);
+ ZipEntry::kCompressDeflated,
+ removeTime, ppEntry);
}
/*
@@ -109,11 +110,11 @@
* If "ppEntry" is non-NULL, a pointer to the new entry will be returned.
*/
status_t add(const void* data, size_t size, const char* storageName,
- int compressionMethod, ZipEntry** ppEntry)
+ int compressionMethod, bool removeTime, ZipEntry** ppEntry)
{
return addCommon(NULL, data, size, storageName,
ZipEntry::kCompressStored,
- compressionMethod, ppEntry);
+ compressionMethod, removeTime, ppEntry);
}
/*
@@ -124,7 +125,7 @@
* If "ppEntry" is non-NULL, a pointer to the new entry will be returned.
*/
status_t add(const ZipFile* pSourceZip, const ZipEntry* pSourceEntry,
- int padding, ZipEntry** ppEntry);
+ int padding, bool removeTime, ZipEntry** ppEntry);
/*
* Add an entry by copying it from another zip file, recompressing with
@@ -133,7 +134,7 @@
* If "ppEntry" is non-NULL, a pointer to the new entry will be returned.
*/
status_t addRecompress(const ZipFile* pSourceZip, const ZipEntry* pSourceEntry,
- ZipEntry** ppEntry);
+ bool removeTime, ZipEntry** ppEntry);
/*
* Mark an entry as having been removed. It is not actually deleted
@@ -232,7 +233,7 @@
/* common handler for all "add" functions */
status_t addCommon(const char* fileName, const void* data, size_t size,
const char* storageName, int sourceType, int compressionMethod,
- ZipEntry** ppEntry);
+ bool removeTime, ZipEntry** ppEntry);
/* copy all of "srcFp" into "dstFp" */
status_t copyFpToFp(FILE* dstFp, FILE* srcFp, unsigned long* pCRC32);