diff options
Diffstat (limited to 'libs')
| -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 |
5 files changed, 283 insertions, 24 deletions
diff --git a/libs/androidfw/Android.bp b/libs/androidfw/Android.bp index fa9447afbeab..47a7f3579764 100644 --- a/libs/androidfw/Android.bp +++ b/libs/androidfw/Android.bp @@ -85,7 +85,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: { @@ -137,6 +140,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 |