summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--minzip/Zip.c164
-rw-r--r--minzip/Zip.h13
-rw-r--r--updater/install.c2
3 files changed, 65 insertions, 114 deletions
diff --git a/minzip/Zip.c b/minzip/Zip.c
index 12e06f6d8..d3ff79be6 100644
--- a/minzip/Zip.c
+++ b/minzip/Zip.c
@@ -828,7 +828,7 @@ static const char *targetEntryPath(MzPathHelper *helper, ZipEntry *pEntry)
*/
bool mzExtractRecursive(const ZipArchive *pArchive,
const char *zipDir, const char *targetDir,
- int flags, const struct utimbuf *timestamp,
+ const struct utimbuf *timestamp,
void (*callback)(const char *fn, void *), void *cookie,
struct selabel_handle *sehnd)
{
@@ -932,30 +932,19 @@ bool mzExtractRecursive(const ZipArchive *pArchive,
break;
}
- /* With DRY_RUN set, invoke the callback but don't do anything else.
- */
- if (flags & MZ_EXTRACT_DRY_RUN) {
- if (callback != NULL) callback(targetFile, cookie);
- continue;
- }
-
- /* Create the file or directory.
- */
#define UNZIP_DIRMODE 0755
#define UNZIP_FILEMODE 0644
- if (pEntry->fileName[pEntry->fileNameLen-1] == '/') {
- if (!(flags & MZ_EXTRACT_FILES_ONLY)) {
- int ret = dirCreateHierarchy(
- targetFile, UNZIP_DIRMODE, timestamp, false, sehnd);
- if (ret != 0) {
- LOGE("Can't create containing directory for \"%s\": %s\n",
- targetFile, strerror(errno));
- ok = false;
- break;
- }
- LOGD("Extracted dir \"%s\"\n", targetFile);
- }
- } else {
+ /*
+ * Create the file or directory. We ignore directory entries
+ * because we recursively create paths to each file entry we encounter
+ * in the zip archive anyway.
+ *
+ * NOTE: A "directory entry" in a zip archive is just a zero length
+ * entry that ends in a "/". They're not mandatory and many tools get
+ * rid of them. We need to process them only if we want to preserve
+ * empty directories from the archive.
+ */
+ if (pEntry->fileName[pEntry->fileNameLen-1] != '/') {
/* This is not a directory. First, make sure that
* the containing directory exists.
*/
@@ -968,97 +957,62 @@ bool mzExtractRecursive(const ZipArchive *pArchive,
break;
}
- /* With FILES_ONLY set, we need to ignore metadata entirely,
- * so treat symlinks as regular files.
+ /*
+ * The entry is a regular file or a symlink. Open the target for writing.
+ *
+ * TODO: This behavior for symlinks seems rather bizarre. For a
+ * symlink foo/bar/baz -> foo/tar/taz, we will create a file called
+ * "foo/bar/baz" whose contents are the literal "foo/tar/taz". We
+ * warn about this for now and preserve older behavior.
*/
- if (!(flags & MZ_EXTRACT_FILES_ONLY) && mzIsZipEntrySymlink(pEntry)) {
- /* The entry is a symbolic link.
- * The relative target of the symlink is in the
- * data section of this entry.
- */
- if (pEntry->uncompLen == 0) {
- LOGE("Symlink entry \"%s\" has no target\n",
- targetFile);
- ok = false;
- break;
- }
- char *linkTarget = malloc(pEntry->uncompLen + 1);
- if (linkTarget == NULL) {
- ok = false;
- break;
- }
- ok = mzReadZipEntry(pArchive, pEntry, linkTarget,
- pEntry->uncompLen);
- if (!ok) {
- LOGE("Can't read symlink target for \"%s\"\n",
- targetFile);
- free(linkTarget);
- break;
- }
- linkTarget[pEntry->uncompLen] = '\0';
-
- /* Make the link.
- */
- ret = symlink(linkTarget, targetFile);
- if (ret != 0) {
- LOGE("Can't symlink \"%s\" to \"%s\": %s\n",
- targetFile, linkTarget, strerror(errno));
- free(linkTarget);
- ok = false;
- break;
- }
- LOGD("Extracted symlink \"%s\" -> \"%s\"\n",
- targetFile, linkTarget);
- free(linkTarget);
- } else {
- /* The entry is a regular file.
- * Open the target for writing.
- */
-
- char *secontext = NULL;
+ if (mzIsZipEntrySymlink(pEntry)) {
+ LOGE("Symlink entry \"%.*s\" will be output as a regular file.",
+ pEntry->fileNameLen, pEntry->fileName);
+ }
- if (sehnd) {
- selabel_lookup(sehnd, &secontext, targetFile, UNZIP_FILEMODE);
- setfscreatecon(secontext);
- }
+ char *secontext = NULL;
- int fd = open(targetFile, O_CREAT|O_WRONLY|O_TRUNC|O_SYNC
- , UNZIP_FILEMODE);
+ if (sehnd) {
+ selabel_lookup(sehnd, &secontext, targetFile, UNZIP_FILEMODE);
+ setfscreatecon(secontext);
+ }
- if (secontext) {
- freecon(secontext);
- setfscreatecon(NULL);
- }
+ int fd = open(targetFile, O_CREAT|O_WRONLY|O_TRUNC|O_SYNC,
+ UNZIP_FILEMODE);
- if (fd < 0) {
- LOGE("Can't create target file \"%s\": %s\n",
- targetFile, strerror(errno));
- ok = false;
- break;
- }
+ if (secontext) {
+ freecon(secontext);
+ setfscreatecon(NULL);
+ }
- bool ok = mzExtractZipEntryToFile(pArchive, pEntry, fd);
- if (ok) {
- ok = (fsync(fd) == 0);
- }
- if (close(fd) != 0) {
- ok = false;
- }
- if (!ok) {
- LOGE("Error extracting \"%s\"\n", targetFile);
- ok = false;
- break;
- }
+ if (fd < 0) {
+ LOGE("Can't create target file \"%s\": %s\n",
+ targetFile, strerror(errno));
+ ok = false;
+ break;
+ }
- if (timestamp != NULL && utime(targetFile, timestamp)) {
- LOGE("Error touching \"%s\"\n", targetFile);
- ok = false;
- break;
- }
+ bool ok = mzExtractZipEntryToFile(pArchive, pEntry, fd);
+ if (ok) {
+ ok = (fsync(fd) == 0);
+ }
+ if (close(fd) != 0) {
+ ok = false;
+ }
+ if (!ok) {
+ LOGE("Error extracting \"%s\"\n", targetFile);
+ ok = false;
+ break;
+ }
- LOGV("Extracted file \"%s\"\n", targetFile);
- ++extractCount;
+ if (timestamp != NULL && utime(targetFile, timestamp)) {
+ LOGE("Error touching \"%s\"\n", targetFile);
+ ok = false;
+ break;
}
+
+ LOGV("Extracted file \"%s\"\n", targetFile);
+ ++extractCount;
}
if (callback != NULL) callback(targetFile, cookie);
diff --git a/minzip/Zip.h b/minzip/Zip.h
index 54eab3222..a2b2c26fc 100644
--- a/minzip/Zip.h
+++ b/minzip/Zip.h
@@ -143,9 +143,12 @@ bool mzExtractZipEntryToBuffer(const ZipArchive *pArchive,
const ZipEntry *pEntry, unsigned char* buffer);
/*
- * Inflate all entries under zipDir to the directory specified by
+ * Inflate all files under zipDir to the directory specified by
* targetDir, which must exist and be a writable directory.
*
+ * Directory entries and symlinks are not extracted.
+ *
+ *
* The immediate children of zipDir will become the immediate
* children of targetDir; e.g., if the archive contains the entries
*
@@ -160,21 +163,15 @@ bool mzExtractZipEntryToBuffer(const ZipArchive *pArchive,
* /tmp/two
* /tmp/d/three
*
- * flags is zero or more of the following:
- *
- * MZ_EXTRACT_FILES_ONLY - only unpack files, not directories or symlinks
- * MZ_EXTRACT_DRY_RUN - don't do anything, but do invoke the callback
- *
* If timestamp is non-NULL, file timestamps will be set accordingly.
*
* If callback is non-NULL, it will be invoked with each unpacked file.
*
* Returns true on success, false on failure.
*/
-enum { MZ_EXTRACT_FILES_ONLY = 1, MZ_EXTRACT_DRY_RUN = 2 };
bool mzExtractRecursive(const ZipArchive *pArchive,
const char *zipDir, const char *targetDir,
- int flags, const struct utimbuf *timestamp,
+ const struct utimbuf *timestamp,
void (*callback)(const char *fn, void*), void *cookie,
struct selabel_handle *sehnd);
diff --git a/updater/install.c b/updater/install.c
index 2b2ffb0c5..01a5dd24b 100644
--- a/updater/install.c
+++ b/updater/install.c
@@ -496,7 +496,7 @@ Value* PackageExtractDirFn(const char* name, State* state,
struct utimbuf timestamp = { 1217592000, 1217592000 }; // 8/1/2008 default
bool success = mzExtractRecursive(za, zip_path, dest_path,
- MZ_EXTRACT_FILES_ONLY, &timestamp,
+ &timestamp,
NULL, NULL, sehandle);
free(zip_path);
free(dest_path);