/* * Process a regular file, adding it to the archive if appropriate. * * This function is intended for use when creating a cached overlay package. * Only xml and .9.png files are processed and added to the package. * * If we're in "update" mode, and the file already exists in the archive, * delete the existing entry before adding the new one. */ bool processOverlayFile(Bundle* bundle, ZipFile* zip, String8 storageName, const sp<const AaptFile>& file) { const bool hasData = file->hasData(); storageName.convertToResPath(); ZipEntry* entry; bool fromGzip = false; status_t result; if (strcasecmp(storageName.getPathExtension().string(), ".gz") == 0) { fromGzip = true; storageName = storageName.getBasePath(); } if (bundle->getUpdate()) { entry = zip->getEntryByName(storageName.string()); if (entry != NULL) { /* file already exists in archive; there can be only one */ if (entry->getMarked()) { fprintf(stderr, "ERROR: '%s' exists twice (check for with & w/o '.gz'?)\n", file->getPrintableSource().string()); return false; } zip->remove(entry); } } if (hasData) { const char* name = storageName.string(); if (endsWith(name, ".9.png") || endsWith(name, ".xml") || endsWith(name, ".arsc")) { result = zip->add(file->getData(), file->getSize(), storageName.string(), file->getCompressionMethod(), &entry); if (result == NO_ERROR) { if (bundle->getVerbose()) { printf(" '%s'%s", storageName.string(), fromGzip ? " (from .gz)" : ""); if (entry->getCompressionMethod() == ZipEntry::kCompressStored) { printf(" (not compressed)\n"); } else { printf(" (compressed %d%%)\n", calcPercent(entry->getUncompressedLen(), entry->getCompressedLen())); } } entry->setMarked(true); } else { if (result == ALREADY_EXISTS) { fprintf(stderr, " Unable to add '%s': file already in archive (try '-u'?)\n", file->getPrintableSource().string()); } else { fprintf(stderr, " Unable to add '%s': Zip add failed\n", file->getPrintableSource().string()); } return false; } } } return true; }
ssize_t processJarFile(ZipFile* jar, ZipFile* out) { size_t N = jar->getNumEntries(); size_t count = 0; for (size_t i=0; i<N; i++) { ZipEntry* entry = jar->getEntryByIndex(i); const char* storageName = entry->getFileName(); if (endsWith(storageName, ".class")) { int compressionMethod = entry->getCompressionMethod(); size_t size = entry->getUncompressedLen(); const void* data = jar->uncompress(entry); if (data == NULL) { fprintf(stderr, "ERROR: unable to uncompress entry '%s'\n", storageName); return -1; } out->add(data, size, storageName, compressionMethod, NULL); free((void*)data); } count++; } return count; }
/* * Process a regular file, adding it to the archive if appropriate. * * If we're in "update" mode, and the file already exists in the archive, * delete the existing entry before adding the new one. */ bool processFile(Bundle* bundle, ZipFile* zip, String8 storageName, const sp<const AaptFile>& file) { const bool hasData = file->hasData(); ZipEntry* entry; bool fromGzip = false; status_t result; /* * See if the filename ends in ".EXCLUDE". We can't use * String8::getPathExtension() because the length of what it considers * to be an extension is capped. * * The Asset Manager doesn't check for ".EXCLUDE" in Zip archives, * so there's no value in adding them (and it makes life easier on * the AssetManager lib if we don't). * * NOTE: this restriction has been removed. If you're in this code, you * should clean this up, but I'm in here getting rid of Path Name, and I * don't want to make other potentially breaking changes --joeo */ int fileNameLen = storageName.length(); int excludeExtensionLen = strlen(kExcludeExtension); if (fileNameLen > excludeExtensionLen && (0 == strcmp(storageName.string() + (fileNameLen - excludeExtensionLen), kExcludeExtension))) { fprintf(stderr, "warning: '%s' not added to Zip\n", storageName.string()); return true; } if (strcasecmp(storageName.getPathExtension().string(), ".gz") == 0) { fromGzip = true; storageName = storageName.getBasePath(); } if (bundle->getUpdate()) { entry = zip->getEntryByName(storageName.string()); if (entry != NULL) { /* file already exists in archive; there can be only one */ if (entry->getMarked()) { fprintf(stderr, "ERROR: '%s' exists twice (check for with & w/o '.gz'?)\n", file->getPrintableSource().string()); return false; } if (!hasData) { const String8& srcName = file->getSourceFile(); time_t fileModWhen; fileModWhen = getFileModDate(srcName.string()); if (fileModWhen == (time_t) -1) { // file existence tested earlier, return false; // not expecting an error here } if (fileModWhen > entry->getModWhen()) { // mark as deleted so add() will succeed if (bundle->getVerbose()) { printf(" (removing old '%s')\n", storageName.string()); } zip->remove(entry); } else { // version in archive is newer if (bundle->getVerbose()) { printf(" (not updating '%s')\n", storageName.string()); } entry->setMarked(true); return true; } } else { // Generated files are always replaced. zip->remove(entry); } } } //android_setMinPriority(NULL, ANDROID_LOG_VERBOSE); if (fromGzip) { result = zip->addGzip(file->getSourceFile().string(), storageName.string(), &entry); } else if (!hasData) { /* don't compress certain files, e.g. PNGs */ int compressionMethod = bundle->getCompressionMethod(); if (!okayToCompress(bundle, storageName)) { compressionMethod = ZipEntry::kCompressStored; } result = zip->add(file->getSourceFile().string(), storageName.string(), compressionMethod, &entry); } else { result = zip->add(file->getData(), file->getSize(), storageName.string(), file->getCompressionMethod(), &entry); } if (result == NO_ERROR) { if (bundle->getVerbose()) { printf(" '%s'%s", storageName.string(), fromGzip ? " (from .gz)" : ""); if (entry->getCompressionMethod() == ZipEntry::kCompressStored) { printf(" (not compressed)\n"); } else { printf(" (compressed %d%%)\n", calcPercent(entry->getUncompressedLen(), entry->getCompressedLen())); } } entry->setMarked(true); } else { if (result == ALREADY_EXISTS) { fprintf(stderr, " Unable to add '%s': file already in archive (try '-u'?)\n", file->getPrintableSource().string()); } else { fprintf(stderr, " Unable to add '%s': Zip add failed (%d)\n", file->getPrintableSource().string(), result); } return false; } return true; }
ssize_t AaptAssets::slurpResourceZip(Bundle* bundle, const char* filename) { int count = 0; SortedVector<AaptGroupEntry> entries; ZipFile* zip = new ZipFile; status_t err = zip->open(filename, ZipFile::kOpenReadOnly); if (err != NO_ERROR) { fprintf(stderr, "error opening zip file %s\n", filename); count = err; delete zip; return -1; } const int N = zip->getNumEntries(); for (int i=0; i<N; i++) { ZipEntry* entry = zip->getEntryByIndex(i); if (entry->getDeleted()) { continue; } String8 entryName(entry->getFileName()); String8 dirName = entryName.getPathDir(); sp<AaptDir> dir = dirName == "" ? this : makeDir(dirName); String8 resType; AaptGroupEntry kind; String8 remain; if (entryName.walkPath(&remain) == kResourceDir) { // these are the resources, pull their type out of the directory name kind.initFromDirName(remain.walkPath().string(), &resType); } else { // these are untyped and don't have an AaptGroupEntry } if (entries.indexOf(kind) < 0) { entries.add(kind); mGroupEntries.add(kind); } // use the one from the zip file if they both exist. dir->removeFile(entryName.getPathLeaf()); sp<AaptFile> file = new AaptFile(entryName, kind, resType); status_t err = dir->addLeafFile(entryName.getPathLeaf(), file); if (err != NO_ERROR) { fprintf(stderr, "err=%s entryName=%s\n", strerror(err), entryName.string()); count = err; goto bail; } file->setCompressionMethod(entry->getCompressionMethod()); #if 0 if (entryName == "AndroidManifest.xml") { printf("AndroidManifest.xml\n"); } printf("\n\nfile: %s\n", entryName.string()); #endif size_t len = entry->getUncompressedLen(); void* data = zip->uncompress(entry); void* buf = file->editData(len); memcpy(buf, data, len); #if 0 const int OFF = 0; const unsigned char* p = (unsigned char*)data; const unsigned char* end = p+len; p += OFF; for (int i=0; i<32 && p < end; i++) { printf("0x%03x ", i*0x10 + OFF); for (int j=0; j<0x10 && p < end; j++) { printf(" %02x", *p); p++; } printf("\n"); } #endif free(data); count++; } bail: delete zip; return count; }