diff options
author | 2023-08-23 02:22:53 +0000 | |
---|---|---|
committer | 2023-09-01 19:05:34 +0000 | |
commit | 804e819c1bf64d4df483107e02e896b29e58b3f1 (patch) | |
tree | 300e8f502c5ca18104016ebe30885d0aecf49125 | |
parent | cc7212ddf54bc9ec55d1f08db39833a7c3d91078 (diff) |
Move String8 path functions to androidfw and aapt
Test: m checkbuild
Bug: 295394788
Change-Id: I9488bc5632cbd47c83f6b5f2df4c87eb324a1e8e
-rw-r--r-- | libs/androidfw/Android.bp | 27 | ||||
-rw-r--r-- | libs/androidfw/AssetManager.cpp | 40 | ||||
-rw-r--r-- | libs/androidfw/BackupHelpers.cpp | 7 | ||||
-rw-r--r-- | libs/androidfw/PathUtils.cpp | 135 | ||||
-rw-r--r-- | libs/androidfw/include_pathutils/androidfw/PathUtils.h | 98 | ||||
-rw-r--r-- | tools/aapt/AaptAssets.cpp | 46 | ||||
-rw-r--r-- | tools/aapt/Android.bp | 4 | ||||
-rw-r--r-- | tools/aapt/CacheUpdater.h | 11 | ||||
-rw-r--r-- | tools/aapt/Command.cpp | 13 | ||||
-rw-r--r-- | tools/aapt/CrunchCache.cpp | 11 | ||||
-rw-r--r-- | tools/aapt/DirectoryWalker.h | 3 | ||||
-rw-r--r-- | tools/aapt/FileFinder.cpp | 7 | ||||
-rw-r--r-- | tools/aapt/Images.cpp | 9 | ||||
-rw-r--r-- | tools/aapt/Package.cpp | 9 | ||||
-rw-r--r-- | tools/aapt/Resource.cpp | 18 | ||||
-rw-r--r-- | tools/aapt/ResourceTable.cpp | 3 | ||||
-rw-r--r-- | tools/aapt/Utils.cpp | 23 | ||||
-rw-r--r-- | tools/aapt/Utils.h | 10 |
18 files changed, 392 insertions, 82 deletions
diff --git a/libs/androidfw/Android.bp b/libs/androidfw/Android.bp index c80fb188e70f..86e1fe3d0503 100644 --- a/libs/androidfw/Android.bp +++ b/libs/androidfw/Android.bp @@ -80,7 +80,10 @@ cc_library { export_include_dirs: ["include"], export_shared_lib_headers: ["libz"], static_libs: ["libincfs-utils"], - whole_static_libs: ["libincfs-utils"], + whole_static_libs: [ + "libandroidfw_pathutils", + "libincfs-utils", + ], export_static_lib_headers: ["libincfs-utils"], target: { android: { @@ -132,6 +135,28 @@ cc_library { }, } +cc_library_static { + name: "libandroidfw_pathutils", + defaults: ["libandroidfw_defaults"], + host_supported: true, + export_include_dirs: ["include_pathutils"], + srcs: [ + "PathUtils.cpp", + ], + shared_libs: [ + "libutils", + ], + target: { + windows: { + enabled: true, + }, + }, + visibility: [ + ":__subpackages__", + "//frameworks/base/tools/aapt", + ], +} + common_test_libs = [ "libandroidfw", "libbase", diff --git a/libs/androidfw/AssetManager.cpp b/libs/androidfw/AssetManager.cpp index 795bb3c716d1..fd6e18ee364a 100644 --- a/libs/androidfw/AssetManager.cpp +++ b/libs/androidfw/AssetManager.cpp @@ -26,6 +26,7 @@ #include <androidfw/AssetDir.h> #include <androidfw/AssetManager.h> #include <androidfw/misc.h> +#include <androidfw/PathUtils.h> #include <androidfw/ResourceTypes.h> #include <androidfw/ZipFileRO.h> #include <cutils/atomic.h> @@ -88,7 +89,7 @@ String8 idmapPathForPackagePath(const String8& pkgPath) { const char* root = getenv("ANDROID_DATA"); LOG_ALWAYS_FATAL_IF(root == NULL, "ANDROID_DATA not set"); String8 path(root); - path.appendPath(kResourceCache); + appendPath(path, kResourceCache); char buf[256]; // 256 chars should be enough for anyone... strncpy(buf, pkgPath.c_str(), 255); @@ -104,7 +105,7 @@ String8 idmapPathForPackagePath(const String8& pkgPath) { } ++p; } - path.appendPath(filename); + appendPath(path, filename); path.append("@idmap"); return path; @@ -181,7 +182,7 @@ bool AssetManager::addAssetPath( String8 realPath(path); if (kAppZipName) { - realPath.appendPath(kAppZipName); + appendPath(realPath, kAppZipName); } ap.type = ::getFileType(realPath.c_str()); if (ap.type == kFileTypeRegular) { @@ -367,7 +368,7 @@ bool AssetManager::addDefaultAssets() LOG_ALWAYS_FATAL_IF(root == NULL, "ANDROID_ROOT not set"); String8 path(root); - path.appendPath(kSystemAssets); + appendPath(path, kSystemAssets); return addAssetPath(path, NULL, false /* appAsLib */, true /* isSystemAsset */); } @@ -439,7 +440,7 @@ Asset* AssetManager::open(const char* fileName, AccessMode mode) LOG_FATAL_IF(mAssetPaths.size() == 0, "No assets added to AssetManager"); String8 assetName(kAssetsRoot); - assetName.appendPath(fileName); + appendPath(assetName, fileName); /* * For each top-level asset path, search for the asset. @@ -587,8 +588,8 @@ bool AssetManager::appendPathToResTable(asset_path& ap, bool appAsLib) const { const char* data = getenv("ANDROID_DATA"); LOG_ALWAYS_FATAL_IF(data == NULL, "ANDROID_DATA not set"); String8 overlaysListPath(data); - overlaysListPath.appendPath(kResourceCache); - overlaysListPath.appendPath("overlays.list"); + appendPath(overlaysListPath, kResourceCache); + appendPath(overlaysListPath, "overlays.list"); addSystemOverlays(overlaysListPath.c_str(), ap.path, sharedRes, nextEntryIdx); #endif sharedRes = const_cast<AssetManager*>(this)-> @@ -789,7 +790,7 @@ Asset* AssetManager::openNonAssetInPathLocked(const char* fileName, AccessMode m /* look at the filesystem on disk */ if (ap.type == kFileTypeDirectory) { String8 path(ap.path); - path.appendPath(fileName); + appendPath(path, fileName); pAsset = openAssetFromFileLocked(path, mode); @@ -841,9 +842,9 @@ String8 AssetManager::createZipSourceNameLocked(const String8& zipFileName, sourceName.append(zipFileName); sourceName.append(":"); if (dirName.length() > 0) { - sourceName.appendPath(dirName); + appendPath(sourceName, dirName); } - sourceName.appendPath(fileName); + appendPath(sourceName, fileName); return sourceName; } @@ -853,7 +854,7 @@ String8 AssetManager::createZipSourceNameLocked(const String8& zipFileName, String8 AssetManager::createPathNameLocked(const asset_path& ap, const char* rootDir) { String8 path(ap.path); - if (rootDir != NULL) path.appendPath(rootDir); + if (rootDir != NULL) appendPath(path, rootDir); return path; } @@ -897,7 +898,7 @@ Asset* AssetManager::openAssetFromFileLocked(const String8& pathName, { Asset* pAsset = NULL; - if (strcasecmp(pathName.getPathExtension().c_str(), ".gz") == 0) { + if (strcasecmp(getPathExtension(pathName).c_str(), ".gz") == 0) { //printf("TRYING '%s'\n", (const char*) pathName); pAsset = Asset::createFromCompressedFile(pathName.c_str(), mode); } else { @@ -1078,8 +1079,7 @@ bool AssetManager::scanAndMergeDirLocked(SortedVector<AssetDir::FileInfo>* pMerg //printf("scanAndMergeDir: %s %s %s\n", ap.path.c_str(), rootDir, dirName); String8 path = createPathNameLocked(ap, rootDir); - if (dirName[0] != '\0') - path.appendPath(dirName); + if (dirName[0] != '\0') appendPath(path, dirName); SortedVector<AssetDir::FileInfo>* pContents = scanDirLocked(path); if (pContents == NULL) @@ -1176,7 +1176,7 @@ SortedVector<AssetDir::FileInfo>* AssetManager::scanDirLocked(const String8& pat fileType = kFileTypeUnknown; #else // stat the file - fileType = ::getFileType(path.appendPathCopy(entry->d_name).c_str()); + fileType = ::getFileType(appendPathCopy(path, entry->d_name).c_str()); #endif if (fileType != kFileTypeRegular && fileType != kFileTypeDirectory) @@ -1184,9 +1184,9 @@ SortedVector<AssetDir::FileInfo>* AssetManager::scanDirLocked(const String8& pat AssetDir::FileInfo info; info.set(String8(entry->d_name), fileType); - if (strcasecmp(info.getFileName().getPathExtension().c_str(), ".gz") == 0) - info.setFileName(info.getFileName().getBasePath()); - info.setSourceName(path.appendPathCopy(info.getFileName())); + if (strcasecmp(getPathExtension(info.getFileName()).c_str(), ".gz") == 0) + info.setFileName(getBasePath(info.getFileName())); + info.setSourceName(appendPathCopy(path, info.getFileName())); pContents->add(info); } @@ -1220,7 +1220,7 @@ bool AssetManager::scanAndMergeZipLocked(SortedVector<AssetDir::FileInfo>* pMerg /* convert "sounds" to "rootDir/sounds" */ if (rootDir != NULL) dirName = rootDir; - dirName.appendPath(baseDirName); + appendPath(dirName, baseDirName); /* * Scan through the list of files, looking for a match. The files in @@ -1269,7 +1269,7 @@ bool AssetManager::scanAndMergeZipLocked(SortedVector<AssetDir::FileInfo>* pMerg if (nextSlash == NULL) { /* this is a file in the requested directory */ - info.set(String8(nameBuf).getPathLeaf(), kFileTypeRegular); + info.set(getPathLeaf(String8(nameBuf)), kFileTypeRegular); info.setSourceName( createZipSourceNameLocked(zipName, dirName, info.getFileName())); diff --git a/libs/androidfw/BackupHelpers.cpp b/libs/androidfw/BackupHelpers.cpp index 35826090d6e5..1a6a952492f6 100644 --- a/libs/androidfw/BackupHelpers.cpp +++ b/libs/androidfw/BackupHelpers.cpp @@ -30,6 +30,7 @@ #include <utime.h> #include <zlib.h> +#include <androidfw/PathUtils.h> #include <log/log.h> #include <utils/ByteOrder.h> #include <utils/KeyedVector.h> @@ -606,14 +607,14 @@ int write_tarfile(const String8& packageName, const String8& domain, prefix += packageName; } if (domain.length() > 0) { - prefix.appendPath(domain); + appendPath(prefix, domain); } // pax extended means we don't put in a prefix field, and put a different // string in the basic name field. We can also construct the full path name // out of the substrings we've now built. fullname = prefix; - fullname.appendPath(relpath); + appendPath(fullname, relpath); // ustar: // [ 0 : 100 ]; file name/path @@ -654,7 +655,7 @@ int write_tarfile(const String8& packageName, const String8& domain, // Now build the pax *header* templated on the ustar header memcpy(paxHeader, buf, 512); - String8 leaf = fullname.getPathLeaf(); + String8 leaf = getPathLeaf(fullname); memset(paxHeader, 0, 100); // rewrite the name area snprintf(paxHeader, 100, "PaxHeader/%s", leaf.c_str()); memset(paxHeader + 345, 0, 155); // rewrite the prefix area diff --git a/libs/androidfw/PathUtils.cpp b/libs/androidfw/PathUtils.cpp new file mode 100644 index 000000000000..df7a9f06781b --- /dev/null +++ b/libs/androidfw/PathUtils.cpp @@ -0,0 +1,135 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <androidfw/PathUtils.h> + +#include <utils/Compat.h> + +namespace android { + +String8 getPathLeaf(const String8& str) { + const char* cp; + const char*const buf = str.c_str(); + + cp = strrchr(buf, OS_PATH_SEPARATOR); + if (cp == nullptr) + return str; + else + return String8(cp+1); +} + +String8 getPathDir(const String8& str8) { + const char* cp; + const char*const str = str8.c_str(); + + cp = strrchr(str, OS_PATH_SEPARATOR); + if (cp == nullptr) + return String8(); + else + return String8(str, cp - str); +} + +static char* findExtension(const String8& str8) { + const char* lastSlash; + const char* lastDot; + const char* const str = str8.c_str(); + + // only look at the filename + lastSlash = strrchr(str, OS_PATH_SEPARATOR); + if (lastSlash == nullptr) + lastSlash = str; + else + lastSlash++; + + // find the last dot + lastDot = strrchr(lastSlash, '.'); + if (lastDot == nullptr) + return nullptr; + + // looks good, ship it + return const_cast<char*>(lastDot); +} + +String8 getPathExtension(const String8& str) { + char* ext; + + ext = findExtension(str); + if (ext != nullptr) + return String8(ext); + else + return String8(); +} + +String8 getBasePath(const String8& str8) { + char* ext; + const char* const str = str8.c_str(); + + ext = findExtension(str8); + if (ext == nullptr) + return str8; + else + return String8(str, ext - str); +} + +static void setPathName(String8& s, const char* name) { + size_t len = strlen(name); + char* buf = s.lockBuffer(len); + + memcpy(buf, name, len); + + // remove trailing path separator, if present + if (len > 0 && buf[len - 1] == OS_PATH_SEPARATOR) len--; + buf[len] = '\0'; + + s.unlockBuffer(len); +} + +String8& appendPath(String8& str, const char* name) { + // TODO: The test below will fail for Win32 paths. Fix later or ignore. + if (name[0] != OS_PATH_SEPARATOR) { + if (*name == '\0') { + // nothing to do + return str; + } + + size_t len = str.length(); + if (len == 0) { + // no existing filename, just use the new one + setPathName(str, name); + return str; + } + + // make room for oldPath + '/' + newPath + int newlen = strlen(name); + + char* buf = str.lockBuffer(len+1+newlen); + + // insert a '/' if needed + if (buf[len-1] != OS_PATH_SEPARATOR) + buf[len++] = OS_PATH_SEPARATOR; + + memcpy(buf+len, name, newlen+1); + len += newlen; + + str.unlockBuffer(len); + return str; + } else { + setPathName(str, name); + return str; + } +} + +} // namespace android diff --git a/libs/androidfw/include_pathutils/androidfw/PathUtils.h b/libs/androidfw/include_pathutils/androidfw/PathUtils.h new file mode 100644 index 000000000000..4debe8d8da6d --- /dev/null +++ b/libs/androidfw/include_pathutils/androidfw/PathUtils.h @@ -0,0 +1,98 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include <utils/String8.h> + +/* This library contains path manipulation functions that are used only by androidfw and aapt. + * When it's possible, migrate all uses to std::filesystem::path. + */ + +namespace android { + +/** + * Get just the filename component. + * + * DEPRECATED: use std::filesystem::path::filename + * + * "/tmp/foo/bar.c" --> "bar.c" + */ +String8 getPathLeaf(const String8& str); + +/** + * Remove the last (file name) component, leaving just the directory + * name. + * + * DEPRECATED: use std::filesystem::path::parent_path + * + * "/tmp/foo/bar.c" --> "/tmp/foo" + * "/tmp" --> "" // ????? shouldn't this be "/" ???? XXX + * "bar.c" --> "" + */ +String8 getPathDir(const String8& str); + +/** + * Return the filename extension. This is the last '.' and any number + * of characters that follow it. The '.' is included in case we + * decide to expand our definition of what constitutes an extension. + * + * DEPRECATED: use std::filesystem::path::extension + * + * "/tmp/foo/bar.c" --> ".c" + * "/tmp" --> "" + * "/tmp/foo.bar/baz" --> "" + * "foo.jpeg" --> ".jpeg" + * "foo." --> "" + */ +String8 getPathExtension(const String8& str); + +/** + * Return the path without the extension. Rules for what constitutes + * an extension are described in the comment for getPathExtension(). + * + * DEPRECATED: use std::filesystem::path::stem and std::filesystem::path::parent_path + * + * "/tmp/foo/bar.c" --> "/tmp/foo/bar" + */ +String8 getBasePath(const String8& str); + +/** + * Add a component to the pathname. We guarantee that there is + * exactly one path separator between the old path and the new. + * If there is no existing name, we just copy the new name in. + * + * DEPRECATED: use std::filesystem::path::operator/= + * + * If leaf is a fully qualified path (i.e. starts with '/', it + * replaces whatever was there before. + */ +String8& appendPath(String8& str, const char* leaf); +inline String8& appendPath(String8& str, const String8& leaf) { + return appendPath(str, leaf.c_str()); +} + +/** + * Like appendPath(), but does not affect this string. Returns a new one instead. + * + * DEPRECATED: use std::filesystem::operator/ + */ +inline String8 appendPathCopy(String8 str, const char* leaf) { return appendPath(str, leaf); } +inline String8 appendPathCopy(String8 str, const String8& leaf) { + return appendPath(str, leaf.c_str()); +} + +} // namespace android diff --git a/tools/aapt/AaptAssets.cpp b/tools/aapt/AaptAssets.cpp index 0fc2617bb9f2..0aaf3e8fd6c7 100644 --- a/tools/aapt/AaptAssets.cpp +++ b/tools/aapt/AaptAssets.cpp @@ -7,7 +7,9 @@ #include "AaptUtil.h" #include "Main.h" #include "ResourceFilter.h" +#include "Utils.h" +#include <androidfw/PathUtils.h> #include <utils/misc.h> #include <utils/SortedVector.h> @@ -96,7 +98,7 @@ static bool isHidden(const char *root, const char *path) char *matchedPattern = NULL; String8 fullPath(root); - fullPath.appendPath(path); + appendPath(fullPath, String8(path)); FileType type = getFileType(fullPath); int plen = strlen(path); @@ -508,7 +510,7 @@ String8 AaptFile::getPrintableSource() const { if (hasData()) { String8 name(mGroupEntry.toDirName(String8())); - name.appendPath(mPath); + appendPath(name, mPath); name.append(" #generated"); return name; } @@ -615,7 +617,7 @@ sp<AaptDir> AaptDir::makeDir(const String8& path) String8 remain = path; sp<AaptDir> subdir = this; - while (name = remain.walkPath(&remain), remain != "") { + while (name = walkPath(remain, &remain), remain != "") { subdir = subdir->makeDir(name); } @@ -623,7 +625,7 @@ sp<AaptDir> AaptDir::makeDir(const String8& path) if (i >= 0) { return subdir->mDirs.valueAt(i); } - sp<AaptDir> dir = new AaptDir(name, subdir->mPath.appendPathCopy(name)); + sp<AaptDir> dir = new AaptDir(name, appendPathCopy(subdir->mPath, name)); subdir->mDirs.add(name, dir); return dir; } @@ -645,7 +647,7 @@ status_t AaptDir::addLeafFile(const String8& leafName, const sp<AaptFile>& file, if (mFiles.indexOfKey(leafName) >= 0) { group = mFiles.valueFor(leafName); } else { - group = new AaptGroup(leafName, mPath.appendPathCopy(leafName)); + group = new AaptGroup(leafName, appendPathCopy(mPath, leafName)); mFiles.add(leafName, group); } @@ -684,7 +686,7 @@ ssize_t AaptDir::slurpFullTree(Bundle* bundle, const String8& srcDir, // Add fully qualified path for dependency purposes // if we're collecting them if (fullResPaths != NULL) { - fullResPaths->add(srcDir.appendPathCopy(name)); + fullResPaths->add(appendPathCopy(srcDir, name)); } } closedir(dir); @@ -701,7 +703,7 @@ ssize_t AaptDir::slurpFullTree(Bundle* bundle, const String8& srcDir, String8 pathName(srcDir); FileType type; - pathName.appendPath(fileNames[i].c_str()); + appendPath(pathName, fileNames[i]); type = getFileType(pathName.c_str()); if (type == kFileTypeDirectory) { sp<AaptDir> subdir; @@ -709,7 +711,7 @@ ssize_t AaptDir::slurpFullTree(Bundle* bundle, const String8& srcDir, if (mDirs.indexOfKey(fileNames[i]) >= 0) { subdir = mDirs.valueFor(fileNames[i]); } else { - subdir = new AaptDir(fileNames[i], mPath.appendPathCopy(fileNames[i])); + subdir = new AaptDir(fileNames[i], appendPathCopy(mPath, fileNames[i])); notAdded = true; } ssize_t res = subdir->slurpFullTree(bundle, pathName, kind, @@ -821,11 +823,11 @@ String8 AaptDir::getPrintableSource() const { if (mFiles.size() > 0) { // Arbitrarily pull the first file out of the list as the source dir. - return mFiles.valueAt(0)->getPrintableSource().getPathDir(); + return getPathDir(mFiles.valueAt(0)->getPrintableSource()); } if (mDirs.size() > 0) { // Or arbitrarily pull the first dir out of the list as the source dir. - return mDirs.valueAt(0)->getPrintableSource().getPathDir(); + return getPathDir(mDirs.valueAt(0)->getPrintableSource()); } // Should never hit this case, but to be safe... @@ -908,8 +910,8 @@ sp<AaptFile> AaptAssets::addFile( sp<AaptFile> file; String8 root, remain(filePath), partialPath; while (remain.length() > 0) { - root = remain.walkPath(&remain); - partialPath.appendPath(root); + root = walkPath(remain, &remain); + appendPath(partialPath, root); const String8 rootStr(root); @@ -924,7 +926,7 @@ sp<AaptFile> AaptAssets::addFile( return NULL; } } - file = new AaptFile(srcDir.appendPathCopy(filePath), entry, resType); + file = new AaptFile(appendPathCopy(srcDir, filePath), entry, resType); status_t res = group->addFile(file); if (res != NO_ERROR) { return NULL; @@ -981,7 +983,7 @@ ssize_t AaptAssets::slurpFromArgs(Bundle* bundle) if (bundle->getAndroidManifestFile() != NULL) { // place at root of zip. String8 srcFile(bundle->getAndroidManifestFile()); - addFile(srcFile.getPathLeaf(), AaptGroupEntry(), srcFile.getPathDir(), + addFile(getPathLeaf(srcFile), AaptGroupEntry(), getPathDir(srcFile), NULL, String8()); totalCount++; } @@ -1154,7 +1156,7 @@ ssize_t AaptAssets::slurpResourceTree(Bundle* bundle, const String8& srcDir) } String8 subdirName(srcDir); - subdirName.appendPath(entry->d_name); + appendPath(subdirName, entry->d_name); AaptGroupEntry group; String8 resType; @@ -1239,16 +1241,16 @@ AaptAssets::slurpResourceZip(Bundle* /* bundle */, const char* filename) String8 entryName(entry->getFileName()); - String8 dirName = entryName.getPathDir(); + String8 dirName = getPathDir(entryName); sp<AaptDir> dir = dirName == "" ? this : makeDir(dirName); String8 resType; AaptGroupEntry kind; String8 remain; - if (entryName.walkPath(&remain) == kResourceDir) { + if (walkPath(entryName, &remain) == kResourceDir) { // these are the resources, pull their type out of the directory name - kind.initFromDirName(remain.walkPath().c_str(), &resType); + kind.initFromDirName(walkPath(remain).c_str(), &resType); } else { // these are untyped and don't have an AaptGroupEntry } @@ -1258,10 +1260,10 @@ AaptAssets::slurpResourceZip(Bundle* /* bundle */, const char* filename) } // use the one from the zip file if they both exist. - dir->removeFile(entryName.getPathLeaf()); + dir->removeFile(getPathLeaf(entryName)); sp<AaptFile> file = new AaptFile(entryName, kind, resType); - status_t err = dir->addLeafFile(entryName.getPathLeaf(), file); + status_t err = dir->addLeafFile(getPathLeaf(entryName), file); if (err != NO_ERROR) { fprintf(stderr, "err=%s entryName=%s\n", strerror(err), entryName.c_str()); count = err; @@ -1374,7 +1376,7 @@ status_t AaptAssets::filter(Bundle* bundle) // containing no entries. continue; } - if (file->getPath().getPathExtension() == ".xml") { + if (getPathExtension(file->getPath()) == ".xml") { // We can't remove .xml files at this point, because when // we parse them they may add identifier resources, so // removing them can cause our resource identifiers to @@ -1411,7 +1413,7 @@ status_t AaptAssets::filter(Bundle* bundle) // containing no entries. continue; } - if (file->getPath().getPathExtension() == ".xml") { + if (getPathExtension(file->getPath()) == ".xml") { // We can't remove .xml files at this point, because when // we parse them they may add identifier resources, so // removing them can cause our resource identifiers to diff --git a/tools/aapt/Android.bp b/tools/aapt/Android.bp index cecd95a5e616..68db56d58b16 100644 --- a/tools/aapt/Android.bp +++ b/tools/aapt/Android.bp @@ -51,6 +51,10 @@ cc_defaults { "libz", ], + whole_static_libs: [ + "libandroidfw_pathutils", + ], + cflags: [ "-Wall", "-Werror", diff --git a/tools/aapt/CacheUpdater.h b/tools/aapt/CacheUpdater.h index 2dc143c6a66d..dc5493f9e500 100644 --- a/tools/aapt/CacheUpdater.h +++ b/tools/aapt/CacheUpdater.h @@ -7,6 +7,7 @@ #ifndef CACHE_UPDATER_H #define CACHE_UPDATER_H +#include <androidfw/PathUtils.h> #include <utils/String8.h> #include <sys/types.h> #include <sys/stat.h> @@ -16,6 +17,8 @@ #include <direct.h> #endif +#include "Utils.h" + using namespace android; /** CacheUpdater @@ -72,14 +75,14 @@ public: do { // As we remove the end of existsPath add it to // the string of paths to create. - toCreate = existsPath.getPathLeaf().appendPath(toCreate); - existsPath = existsPath.getPathDir(); + toCreate = appendPathCopy(getPathLeaf(existsPath), toCreate); + existsPath = getPathDir(existsPath); } while (stat(existsPath.c_str(),&s) == -1); // Walk forwards and build directories as we go do { // Advance to the next segment of the path - existsPath.appendPath(toCreate.walkPath(&remains)); + appendPath(existsPath, walkPath(toCreate, &remains)); toCreate = remains; #ifdef _WIN32 _mkdir(existsPath.c_str()); @@ -101,7 +104,7 @@ public: virtual void processImage(String8 source, String8 dest) { // Make sure we're trying to write to a directory that is extant - ensureDirectoriesExist(dest.getPathDir()); + ensureDirectoriesExist(getPathDir(dest)); preProcessImageToCache(bundle, source, dest); }; diff --git a/tools/aapt/Command.cpp b/tools/aapt/Command.cpp index 60f3f2715395..800466aa587f 100644 --- a/tools/aapt/Command.cpp +++ b/tools/aapt/Command.cpp @@ -12,6 +12,7 @@ #include "ResourceTable.h" #include "XMLNode.h" +#include <androidfw/PathUtils.h> #include <utils/Errors.h> #include <utils/KeyedVector.h> #include <utils/List.h> @@ -2486,12 +2487,12 @@ int doAdd(Bundle* bundle) for (int i = 1; i < bundle->getFileSpecCount(); i++) { const char* fileName = bundle->getFileSpecEntry(i); - if (strcasecmp(String8(fileName).getPathExtension().c_str(), ".gz") == 0) { + if (strcasecmp(getPathExtension(String8(fileName)).c_str(), ".gz") == 0) { printf(" '%s'... (from gzip)\n", fileName); - result = zip->addGzip(fileName, String8(fileName).getBasePath().c_str(), NULL); + result = zip->addGzip(fileName, getBasePath(String8(fileName)).c_str(), NULL); } else { if (bundle->getJunkPath()) { - String8 storageName = String8(fileName).getPathLeaf(); + String8 storageName = getPathLeaf(String8(fileName)); printf(" '%s' as '%s'...\n", fileName, ResTable::normalizeForOutput(storageName.c_str()).c_str()); result = zip->add(fileName, storageName.c_str(), @@ -2617,10 +2618,10 @@ static String8 buildApkName(const String8& original, const sp<ApkSplit>& split) return original; } - String8 ext(original.getPathExtension()); + String8 ext(getPathExtension(original)); if (ext == String8(".apk")) { return String8::format("%s_%s%s", - original.getBasePath().c_str(), + getBasePath(original).c_str(), split->getDirectorySafeName().c_str(), ext.c_str()); } @@ -2756,7 +2757,7 @@ int doPackage(Bundle* bundle) // generate the dependency file in the R.java package subdirectory // e.g. gen/com/foo/app/R.java.d dependencyFile = String8(bundle->getRClassDir()); - dependencyFile.appendPath("R.java.d"); + appendPath(dependencyFile, "R.java.d"); } // Make sure we have a clean dependency file to start with fp = fopen(dependencyFile, "w"); diff --git a/tools/aapt/CrunchCache.cpp b/tools/aapt/CrunchCache.cpp index 1f2febec2230..e731ce0d5ccf 100644 --- a/tools/aapt/CrunchCache.cpp +++ b/tools/aapt/CrunchCache.cpp @@ -5,6 +5,7 @@ // This file defines functions laid out and documented in // CrunchCache.h +#include <androidfw/PathUtils.h> #include <utils/Compat.h> #include <utils/Vector.h> #include <utils/String8.h> @@ -52,15 +53,15 @@ size_t CrunchCache::crunch(CacheUpdater* cu, bool forceOverwrite) relativePath = String8(rPathPtr + offset); if (forceOverwrite || needsUpdating(relativePath)) { - cu->processImage(mSourcePath.appendPathCopy(relativePath), - mDestPath.appendPathCopy(relativePath)); + cu->processImage(appendPathCopy(mSourcePath, relativePath), + appendPathCopy(mDestPath, relativePath)); numFilesUpdated++; // crunchFile(relativePath); } // Delete this file from the source files and (if it exists) from the // dest files. mSourceFiles.removeItemsAt(0); - mDestFiles.removeItem(mDestPath.appendPathCopy(relativePath)); + mDestFiles.removeItem(appendPathCopy(mDestPath, relativePath)); } // Iterate through what's left of destFiles and delete leftovers @@ -99,7 +100,7 @@ bool CrunchCache::needsUpdating(const String8& relativePath) const // Retrieve modification dates for this file entry under the source and // cache directory trees. The vectors will return a modification date of 0 // if the file doesn't exist. - time_t sourceDate = mSourceFiles.valueFor(mSourcePath.appendPathCopy(relativePath)); - time_t destDate = mDestFiles.valueFor(mDestPath.appendPathCopy(relativePath)); + time_t sourceDate = mSourceFiles.valueFor(appendPathCopy(mSourcePath, relativePath)); + time_t destDate = mDestFiles.valueFor(appendPathCopy(mDestPath, relativePath)); return sourceDate > destDate; } diff --git a/tools/aapt/DirectoryWalker.h b/tools/aapt/DirectoryWalker.h index cea3a6eb0ecf..7f60d4db9626 100644 --- a/tools/aapt/DirectoryWalker.h +++ b/tools/aapt/DirectoryWalker.h @@ -7,6 +7,7 @@ #ifndef DIRECTORYWALKER_H #define DIRECTORYWALKER_H +#include <androidfw/PathUtils.h> #include <dirent.h> #include <sys/types.h> #include <sys/param.h> @@ -77,7 +78,7 @@ public: mEntry = *entryPtr; // Get stats - String8 fullPath = mBasePath.appendPathCopy(mEntry.d_name); + String8 fullPath = appendPathCopy(mBasePath, mEntry.d_name); stat(fullPath.c_str(),&mStats); return &mEntry; }; diff --git a/tools/aapt/FileFinder.cpp b/tools/aapt/FileFinder.cpp index a5c19806c804..69a8fa9fc6f2 100644 --- a/tools/aapt/FileFinder.cpp +++ b/tools/aapt/FileFinder.cpp @@ -5,6 +5,7 @@ // File Finder implementation. // Implementation for the functions declared and documented in FileFinder.h +#include <androidfw/PathUtils.h> #include <utils/Vector.h> #include <utils/String8.h> #include <utils/KeyedVector.h> @@ -57,7 +58,7 @@ bool SystemFileFinder::findFiles(String8 basePath, Vector<String8>& extensions, if (entry->d_name[0] == '.') // Skip hidden files and directories continue; - String8 fullPath = basePath.appendPathCopy(entryName); + String8 fullPath = appendPathCopy(basePath, entryName); // If this entry is a directory we'll recurse into it if (isDirectory(fullPath.c_str()) ) { DirectoryWalker* copy = dw->clone(); @@ -83,10 +84,10 @@ void SystemFileFinder::checkAndAddFile(const String8& path, const struct stat* s { // Loop over the extensions, checking for a match bool done = false; - String8 ext(path.getPathExtension()); + String8 ext(getPathExtension(path)); ext.toLower(); for (size_t i = 0; i < extensions.size() && !done; ++i) { - String8 ext2 = extensions[i].getPathExtension(); + String8 ext2 = getPathExtension(extensions[i]); ext2.toLower(); // Compare the extensions. If a match is found, add to storage. if (ext == ext2) { diff --git a/tools/aapt/Images.cpp b/tools/aapt/Images.cpp index c6c7e960ba2a..cd4de90f12f6 100644 --- a/tools/aapt/Images.cpp +++ b/tools/aapt/Images.cpp @@ -8,6 +8,7 @@ #include "Images.h" +#include <androidfw/PathUtils.h> #include <androidfw/ResourceTypes.h> #include <utils/ByteOrder.h> @@ -1357,7 +1358,7 @@ static bool write_png_protected(png_structp write_ptr, String8& printableName, p status_t preProcessImage(const Bundle* bundle, const sp<AaptAssets>& /* assets */, const sp<AaptFile>& file, String8* /* outNewLeafName */) { - String8 ext(file->getPath().getPathExtension()); + String8 ext(getPathExtension(file->getPath())); // We currently only process PNG images. if (strcmp(ext.c_str(), ".png") != 0) { @@ -1518,7 +1519,7 @@ status_t preProcessImageToCache(const Bundle* bundle, const String8& source, con // Check to see if we're dealing with a 9-patch // If we are, process appropriately - if (source.getBasePath().getPathExtension() == ".9") { + if (getPathExtension(getBasePath(source)) == ".9") { if (do_9patch(source.c_str(), &imageInfo) != NO_ERROR) { return error; } @@ -1584,12 +1585,12 @@ status_t preProcessImageToCache(const Bundle* bundle, const String8& source, con status_t postProcessImage(const Bundle* bundle, const sp<AaptAssets>& assets, ResourceTable* table, const sp<AaptFile>& file) { - String8 ext(file->getPath().getPathExtension()); + String8 ext(getPathExtension(file->getPath())); // At this point, now that we have all the resource data, all we need to // do is compile XML files. if (strcmp(ext.c_str(), ".xml") == 0) { - String16 resourceName(parseResourceName(file->getSourceFile().getPathLeaf())); + String16 resourceName(parseResourceName(getPathLeaf(file->getSourceFile()))); return compileXmlFile(bundle, assets, resourceName, file, table); } diff --git a/tools/aapt/Package.cpp b/tools/aapt/Package.cpp index a7ff5fabf495..5e0f87f0dcaf 100644 --- a/tools/aapt/Package.cpp +++ b/tools/aapt/Package.cpp @@ -10,6 +10,7 @@ #include "ResourceFilter.h" #include "Utils.h" +#include <androidfw/PathUtils.h> #include <androidfw/misc.h> #include <utils/Log.h> @@ -170,7 +171,7 @@ status_t writeAPK(Bundle* bundle, const String8& outputFile, const sp<OutputSet> /* anything here? */ if (zip->getNumEntries() == 0) { if (bundle->getVerbose()) { - printf("Archive is empty -- removing %s\n", outputFile.getPathLeaf().c_str()); + printf("Archive is empty -- removing %s\n", getPathLeaf(outputFile).c_str()); } delete zip; // close the file so we can remove it in Win32 zip = NULL; @@ -274,9 +275,9 @@ bool processFile(Bundle* bundle, ZipFile* zip, return true; } - if (strcasecmp(storageName.getPathExtension().c_str(), ".gz") == 0) { + if (strcasecmp(getPathExtension(storageName).c_str(), ".gz") == 0) { fromGzip = true; - storageName = storageName.getBasePath(); + storageName = getBasePath(storageName); } if (bundle->getUpdate()) { @@ -366,7 +367,7 @@ bool processFile(Bundle* bundle, ZipFile* zip, */ bool okayToCompress(Bundle* bundle, const String8& pathName) { - String8 ext = pathName.getPathExtension(); + String8 ext = getPathExtension(pathName); int i; if (ext.length() == 0) diff --git a/tools/aapt/Resource.cpp b/tools/aapt/Resource.cpp index 4a360ed1c80e..647790b01bfa 100644 --- a/tools/aapt/Resource.cpp +++ b/tools/aapt/Resource.cpp @@ -19,6 +19,8 @@ #include "WorkQueue.h" #include "XMLNode.h" +#include <androidfw/PathUtils.h> + #include <algorithm> // STATUST: mingw does seem to redefine UNKNOWN_ERROR from our enum value, so a cast is necessary. @@ -143,8 +145,8 @@ public: mParams.inputFlags, mParams.navigation); } mPath = "res"; - mPath.appendPath(file->getGroupEntry().toDirName(mResType)); - mPath.appendPath(leaf); + appendPath(mPath, file->getGroupEntry().toDirName(mResType)); + appendPath(mPath, leaf); mBaseName = parseResourceName(leaf); if (mBaseName == "") { fprintf(stderr, "Error: malformed resource filename %s\n", @@ -1686,7 +1688,7 @@ status_t buildResources(Bundle* bundle, const sp<AaptAssets>& assets, sp<ApkBuil ResourceDirIterator it(fonts, String8("font")); while ((err=it.next()) == NO_ERROR) { // fonts can be resources other than xml. - if (it.getFile()->getPath().getPathExtension() == ".xml") { + if (getPathExtension(it.getFile()->getPath()) == ".xml") { String8 src = it.getFile()->getPrintableSource(); err = compileXmlFile(bundle, assets, String16(it.getBaseName()), it.getFile(), &table, xmlFlags); @@ -1716,7 +1718,7 @@ status_t buildResources(Bundle* bundle, const sp<AaptAssets>& assets, sp<ApkBuil workItem.file, &table, xmlCompilationFlags); if (err == NO_ERROR && workItem.file->hasData()) { - assets->addResource(workItem.resPath.getPathLeaf(), + assets->addResource(getPathLeaf(workItem.resPath), workItem.resPath, workItem.file, workItem.file->getResourceType()); @@ -2851,7 +2853,7 @@ status_t writeResourceSymbols(Bundle* bundle, const sp<AaptAssets>& assets, s++; if (s > last && (*s == '.' || *s == 0)) { String8 part(last, s-last); - dest.appendPath(part); + appendPath(dest, part); #ifdef _WIN32 _mkdir(dest.c_str()); #else @@ -2861,7 +2863,7 @@ status_t writeResourceSymbols(Bundle* bundle, const sp<AaptAssets>& assets, } } while (*s); } - dest.appendPath(className); + appendPath(dest, className); dest.append(".java"); FILE* fp = fopen(dest.c_str(), "w+"); if (fp == NULL) { @@ -2892,7 +2894,7 @@ status_t writeResourceSymbols(Bundle* bundle, const sp<AaptAssets>& assets, if (textSymbolsDest != NULL && R == className) { String8 textDest(textSymbolsDest); - textDest.appendPath(className); + appendPath(textDest, className); textDest.append(".txt"); FILE* fp = fopen(textDest.c_str(), "w+"); @@ -2918,7 +2920,7 @@ status_t writeResourceSymbols(Bundle* bundle, const sp<AaptAssets>& assets, if (bundle->getGenDependencies() && R == className) { // Add this R.java to the dependency file String8 dependencyFile(bundle->getRClassDir()); - dependencyFile.appendPath("R.java.d"); + appendPath(dependencyFile, "R.java.d"); FILE *fp = fopen(dependencyFile.c_str(), "a"); fprintf(fp,"%s \\\n", dest.c_str()); diff --git a/tools/aapt/ResourceTable.cpp b/tools/aapt/ResourceTable.cpp index bccf73e69c34..421cae78b08b 100644 --- a/tools/aapt/ResourceTable.cpp +++ b/tools/aapt/ResourceTable.cpp @@ -14,6 +14,7 @@ #include "Utils.h" #include <algorithm> +#include <androidfw/PathUtils.h> #include <androidfw/ResourceTypes.h> #include <utils/ByteOrder.h> #include <utils/TypeHelpers.h> @@ -83,7 +84,7 @@ status_t compileXmlFile(const Bundle* bundle, sp<AaptDir> resDir = assets->getDirs().valueFor(String8("res")); sp<AaptDir> dir = resDir->getDirs().valueFor(target->getGroupEntry().toDirName( target->getResourceType())); - dir->removeFile(target->getPath().getPathLeaf()); + dir->removeFile(getPathLeaf(target->getPath())); return NO_ERROR; } diff --git a/tools/aapt/Utils.cpp b/tools/aapt/Utils.cpp index 36b018e7dd2c..946916a0598a 100644 --- a/tools/aapt/Utils.cpp +++ b/tools/aapt/Utils.cpp @@ -36,3 +36,26 @@ void convertToResPath([[maybe_unused]] String8& s) { } #endif } + +String8 walkPath(const String8& path, String8* outRemains) { + const char* cp; + const char* const str = path.c_str(); + const char* buf = str; + + cp = strchr(buf, OS_PATH_SEPARATOR); + if (cp == buf) { + // don't include a leading '/'. + buf = buf + 1; + cp = strchr(buf, OS_PATH_SEPARATOR); + } + + if (cp == nullptr) { + String8 res = buf != str ? String8(buf) : path; + if (outRemains) *outRemains = String8(); + return res; + } + + String8 res(buf, cp - buf); + if (outRemains) *outRemains = String8(cp + 1); + return res; +} diff --git a/tools/aapt/Utils.h b/tools/aapt/Utils.h index 8eb594138478..f0d69799f7e2 100644 --- a/tools/aapt/Utils.h +++ b/tools/aapt/Utils.h @@ -26,3 +26,13 @@ // If the default OS separator is backslash, this converts all // backslashes to slashes, in-place. Otherwise it does nothing. void convertToResPath(android::String8&); + +/** + * Retrieve the front (root dir) component. Optionally also return the + * remaining components. + * + * "/tmp/foo/bar.c" --> "tmp" (remain = "foo/bar.c") + * "/tmp" --> "tmp" (remain = "") + * "bar.c" --> "bar.c" (remain = "") + */ +android::String8 walkPath(const android::String8& path, android::String8* outRemains = nullptr); |