Loading libs/androidfw/Android.bp +26 −1 Original line number Diff line number Diff line Loading @@ -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: { Loading Loading @@ -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", Loading libs/androidfw/AssetManager.cpp +20 −20 Original line number Diff line number Diff line Loading @@ -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> Loading Loading @@ -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); Loading @@ -104,7 +105,7 @@ String8 idmapPathForPackagePath(const String8& pkgPath) { } ++p; } path.appendPath(filename); appendPath(path, filename); path.append("@idmap"); return path; Loading Loading @@ -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) { Loading Loading @@ -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 */); } Loading Loading @@ -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. Loading Loading @@ -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)-> Loading Loading @@ -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); Loading Loading @@ -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; } Loading @@ -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; } Loading Loading @@ -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 { Loading Loading @@ -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) Loading Loading @@ -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) Loading @@ -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); } Loading Loading @@ -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 Loading Loading @@ -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())); Loading libs/androidfw/BackupHelpers.cpp +4 −3 Original line number Diff line number Diff line Loading @@ -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> Loading Loading @@ -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 Loading Loading @@ -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 Loading libs/androidfw/PathUtils.cpp 0 → 100644 +135 −0 Original line number Diff line number Diff line /* * 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 libs/androidfw/include_pathutils/androidfw/PathUtils.h 0 → 100644 +98 −0 Original line number Diff line number Diff line /* * 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 Loading
libs/androidfw/Android.bp +26 −1 Original line number Diff line number Diff line Loading @@ -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: { Loading Loading @@ -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", Loading
libs/androidfw/AssetManager.cpp +20 −20 Original line number Diff line number Diff line Loading @@ -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> Loading Loading @@ -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); Loading @@ -104,7 +105,7 @@ String8 idmapPathForPackagePath(const String8& pkgPath) { } ++p; } path.appendPath(filename); appendPath(path, filename); path.append("@idmap"); return path; Loading Loading @@ -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) { Loading Loading @@ -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 */); } Loading Loading @@ -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. Loading Loading @@ -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)-> Loading Loading @@ -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); Loading Loading @@ -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; } Loading @@ -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; } Loading Loading @@ -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 { Loading Loading @@ -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) Loading Loading @@ -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) Loading @@ -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); } Loading Loading @@ -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 Loading Loading @@ -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())); Loading
libs/androidfw/BackupHelpers.cpp +4 −3 Original line number Diff line number Diff line Loading @@ -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> Loading Loading @@ -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 Loading Loading @@ -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 Loading
libs/androidfw/PathUtils.cpp 0 → 100644 +135 −0 Original line number Diff line number Diff line /* * 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
libs/androidfw/include_pathutils/androidfw/PathUtils.h 0 → 100644 +98 −0 Original line number Diff line number Diff line /* * 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