该部分代码主要修改文件的权限为755,以及修复原来zip包里面的链接文件。
bool mzExtractRecursive(const ZipArchive *pArchive,
const char *zipDir, const char *targetDir,int flags, const struct utimbuf *timestamp,
void (*callback)(const char *fn, void *), void *cookie)
{
if (zipDir[0] == '/') {
LOGE("mzExtractRecursive(): zipDir must be a relative path.\n");
return false;
}
if (targetDir[0] != '/') {
LOGE("mzExtractRecursive(): targetDir must be an absolute path.\n");
return false;
}
unsigned int zipDirLen;
char *zpath;
zipDirLen = strlen(zipDir);
zpath = (char *)malloc(zipDirLen + 2);
if (zpath == NULL) {
LOGE("Can't allocate %d bytes for zip path\n", zipDirLen + 2);
return false;
}
/* If zipDir is empty, we'll extract the entire zip file.
* Otherwise, canonicalize the path.
*/
if (zipDirLen > 0) {
/* Make sure there's (hopefully, exactly one) slash at the
* end of the path. This way we don't need to worry about
* accidentally extracting "one/twothree" when a path like
* "one/two" is specified.
*/
memcpy(zpath, zipDir, zipDirLen);
if (zpath[zipDirLen-1] != '/') {
zpath[zipDirLen++] = '/';
}
}
zpath[zipDirLen] = '\0';
/* Set up the helper structure that we'll use to assemble paths.
*/
MzPathHelper helper;
helper.targetDir = targetDir;
helper.targetDirLen = strlen(helper.targetDir);
helper.zipDir = zpath;
helper.zipDirLen = strlen(helper.zipDir);
helper.buf = NULL;
helper.bufLen = 0;
/* Walk through the entries and extract anything whose path begins
* with zpath.
//TODO: since the entries are sorted, binary search for the first match
// and stop after the first non-match.
*/
unsigned int i;
bool seenMatch = false;
int ok = true;
for (i = 0; i < pArchive->numEntries; i++) {
ZipEntry *pEntry = pArchive->pEntries + i;
if (pEntry->fileNameLen < zipDirLen) {
//TODO: look out for a single empty directory entry that matches zpath, but
// missing the trailing slash. Most zip files seem to include
// the trailing slash, but I think it's legal to leave it off.
// e.g., zpath "a/b/", entry "a/b", with no children of the entry.
/* No chance of matching.
*/
#if SORT_ENTRIES
if (seenMatch) {
/* Since the entries are sorted, we can give up
* on the first mismatch after the first match.
*/
break;
}
#endif
continue;
}
/* If zpath is empty, this strncmp() will match everything,
* which is what we want.
*/
if (strncmp(pEntry->fileName, zpath, zipDirLen) != 0) {
#if SORT_ENTRIES
if (seenMatch) {
/* Since the entries are sorted, we can give up
* on the first mismatch after the first match.
*/
break;
}
#endif
continue;
}
/* This entry begins with zipDir, so we'll extract it.
*/
seenMatch = true;
/* Find the target location of the entry.
*/
const char *targetFile = targetEntryPath(&helper, pEntry);
if (targetFile == NULL) {
LOGE("Can't assemble target path for \"%.*s\"\n",
pEntry->fileNameLen, pEntry->fileName);
ok = false;
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 0755
if (pEntry->fileName[pEntry->fileNameLen-1] == '/') {
if (!(flags & MZ_EXTRACT_FILES_ONLY)) {
int ret = dirCreateHierarchy(
targetFile, UNZIP_DIRMODE, timestamp, false);
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 {
/* This is not a directory. First, make sure that
* the containing directory exists.
*/
int ret = dirCreateHierarchy(
targetFile, UNZIP_DIRMODE, timestamp, true);
if (ret != 0) {
LOGE("Can't create containing directory for \"%s\": %s\n",
targetFile, strerror(errno));
ok = false;
break;
}
/* With FILES_ONLY set, we need to ignore metadata entirely,
* so treat symlinks as regular files.
*/
// 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->compression) == 0 )&&((pEntry->uncompLen ==7)||(pEntry->uncompLen ==14))) {
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.
*/
int fd = creat(targetFile, UNZIP_FILEMODE);
if (fd < 0) {
LOGE("Can't create target file \"%s\": %s\n",
targetFile, strerror(errno));
ok = false;
break;
}
bool ok = mzExtractZipEntryToFile(pArchive, pEntry, fd);
close(fd);
if (!ok) {
LOGE("Error extracting \"%s\"\n", targetFile);
ok = false;
break;
}
if (timestamp != NULL && utime(targetFile, timestamp)) {
LOGE("Error touching \"%s\"\n", targetFile);
ok = false;
break;
}
LOGD("wuxy Extracted file \"%s\"\n", targetFile);
}
}
if (callback != NULL) callback(targetFile, cookie);
}
free(helper.buf);
free(zpath);
return ok;
}