diff options
author | 2024-12-02 08:43:09 +0000 | |
---|---|---|
committer | 2024-12-03 17:00:19 +0000 | |
commit | c5b74085376aae52052c27c9518eb47d37cf0b73 (patch) | |
tree | c908b922a2c1e4fc97cbcd730c32b4c96686aabc | |
parent | 3177b994cc9e8ef626c337eab5b51961b6de9b3b (diff) |
Modify FuseDaemon#DeriveVolumeName to better handle invalid paths.
Test: atest FuseUtilsTest.cpp
Bug: 378021978
Flag: EXEMPT, bug fix
Change-Id: I66c05397a1350c3fd1af52218f803e1202ed9b3d
-rw-r--r-- | jni/FuseDaemon.cpp | 24 | ||||
-rw-r--r-- | jni/FuseUtils.cpp | 20 | ||||
-rw-r--r-- | jni/FuseUtilsTest.cpp | 14 | ||||
-rw-r--r-- | jni/include/libfuse_jni/FuseUtils.h | 9 |
4 files changed, 50 insertions, 17 deletions
diff --git a/jni/FuseDaemon.cpp b/jni/FuseDaemon.cpp index e77fe5705..2a2e6310f 100644 --- a/jni/FuseDaemon.cpp +++ b/jni/FuseDaemon.cpp @@ -124,11 +124,6 @@ const std::regex PATTERN_BPF_BACKING_PATH("^/storage/[^/]+/[0-9]+/Android/(data| static constexpr char TRANSFORM_SYNTHETIC_DIR[] = "synthetic"; static constexpr char TRANSFORM_TRANSCODE_DIR[] = "transcode"; -static constexpr char PRIMARY_VOLUME_PREFIX[] = "/storage/emulated"; -static constexpr char STORAGE_PREFIX[] = "/storage"; - -static constexpr char VOLUME_INTERNAL[] = "internal"; -static constexpr char VOLUME_EXTERNAL_PRIMARY[] = "external_primary"; static constexpr char OWNERSHIP_RELATION[] = "ownership"; @@ -282,7 +277,7 @@ struct fuse { inline bool IsRoot(const node* node) const { return node == root; } inline string GetEffectiveRootPath() { - if (android::base::StartsWith(path, PRIMARY_VOLUME_PREFIX)) { + if (android::base::StartsWith(path, mediaprovider::fuse::PRIMARY_VOLUME_PREFIX)) { return path + "/" + MY_USER_ID_STRING; } return path; @@ -356,7 +351,7 @@ struct fuse { return false; } - if (!android::base::StartsWithIgnoreCase(path, PRIMARY_VOLUME_PREFIX)) { + if (!android::base::StartsWithIgnoreCase(path, mediaprovider::fuse::PRIMARY_VOLUME_PREFIX)) { // Uncached path config applies only to primary volumes. return false; } @@ -2639,7 +2634,7 @@ void FuseDaemon::SetupLevelDbInstances() { // Setup leveldb instance for both external primary and internal volume. fuse->level_db_mutex.lock(); // Create level db instance for internal volume - SetupLevelDbConnection(VOLUME_INTERNAL); + SetupLevelDbConnection(mediaprovider::fuse::VOLUME_INTERNAL); // Create level db instance for external primary volume SetupLevelDbConnection(VOLUME_EXTERNAL_PRIMARY); // Create level db instance to store owner id to owner package name and vice versa relation @@ -2657,16 +2652,11 @@ void FuseDaemon::SetupPublicVolumeLevelDbInstance(const std::string& volume_name } std::string deriveVolumeName(const std::string& path) { - std::string volume_name; - if (!android::base::StartsWith(path, STORAGE_PREFIX)) { - volume_name = VOLUME_INTERNAL; - } else if (android::base::StartsWith(path, PRIMARY_VOLUME_PREFIX)) { - volume_name = VOLUME_EXTERNAL_PRIMARY; + std::string volume_name = mediaprovider::fuse::getVolumeNameFromPath(path); + if (volume_name.empty()) { + LOG(ERROR) << "Invalid input URI for extracting volume name." << path; } else { - // Return "C58E-1702" from the path like "/storage/C58E-1702/Download/1935694997673.png" - volume_name = path.substr(9, 9); - // Convert to lowercase - std::transform(volume_name.begin(), volume_name.end(), volume_name.begin(), ::tolower); + LOG(DEBUG) << "Volume name from input path: " << path << " , volName: " + volume_name; } return volume_name; } diff --git a/jni/FuseUtils.cpp b/jni/FuseUtils.cpp index 7b0816488..a74b56033 100644 --- a/jni/FuseUtils.cpp +++ b/jni/FuseUtils.cpp @@ -16,6 +16,7 @@ #include "include/libfuse_jni/FuseUtils.h" +#include <regex> #include <string> #include <vector> @@ -51,5 +52,24 @@ bool containsMount(const string& path) { android::base::EqualsIgnoreCase(path_suffix, obb_suffix); } +string getVolumeNameFromPath(const std::string& path) { + std::string volume_name = ""; + if (!android::base::StartsWith(path, STORAGE_PREFIX)) { + volume_name = VOLUME_INTERNAL; + } else if (android::base::StartsWith(path, PRIMARY_VOLUME_PREFIX) || path == STORAGE_PREFIX) { + volume_name = VOLUME_EXTERNAL_PRIMARY; + } else { + // Use regex to extract volume name + std::regex volumeRegex(R"(/storage/([a-zA-Z0-9-]+)/)"); + std::smatch match; + if (std::regex_search(path, match, volumeRegex)) { + volume_name = match[1].str(); + // Convert to lowercase + std::transform(volume_name.begin(), volume_name.end(), volume_name.begin(), ::tolower); + } + } + return volume_name; +} + } // namespace fuse } // namespace mediaprovider diff --git a/jni/FuseUtilsTest.cpp b/jni/FuseUtilsTest.cpp index d76a89c6f..a1b03e0c2 100644 --- a/jni/FuseUtilsTest.cpp +++ b/jni/FuseUtilsTest.cpp @@ -59,4 +59,18 @@ TEST(FuseUtilsTest, testContainsMount_isFalseForPathWithAdditionalSlash) { EXPECT_FALSE(containsMount("/storage/emulated/1234//Android/data")); } +TEST(FuseUtilsTest, getVolumeNameFromPath) { + EXPECT_EQ(getVolumeNameFromPath("/storage/emulated/0/Pictures"), VOLUME_EXTERNAL_PRIMARY); + EXPECT_EQ(getVolumeNameFromPath("/storage/emulated/0/DCIM"), VOLUME_EXTERNAL_PRIMARY); + EXPECT_EQ(getVolumeNameFromPath("/storage/emulated/0/"), VOLUME_EXTERNAL_PRIMARY); + EXPECT_EQ(getVolumeNameFromPath("/storage/emulated/0"), VOLUME_EXTERNAL_PRIMARY); + EXPECT_EQ(getVolumeNameFromPath("/storage/1234-5678/Music"), "1234-5678"); + EXPECT_EQ(getVolumeNameFromPath("/storage/ABCD-EFGH/Movies"), "abcd-efgh"); + EXPECT_EQ(getVolumeNameFromPath("/storage/AB12-E34g/Movies"), "ab12-e34g"); + EXPECT_EQ(getVolumeNameFromPath("/storage/"), ""); + EXPECT_EQ(getVolumeNameFromPath("/storage"), VOLUME_EXTERNAL_PRIMARY); + EXPECT_EQ(getVolumeNameFromPath("/data/media/0/"), VOLUME_INTERNAL); + EXPECT_EQ(getVolumeNameFromPath("/data/user_de/0/com.example.app/"), VOLUME_INTERNAL); +} + } // namespace mediaprovider::fuse diff --git a/jni/include/libfuse_jni/FuseUtils.h b/jni/include/libfuse_jni/FuseUtils.h index 0e350995e..11f880f7a 100644 --- a/jni/include/libfuse_jni/FuseUtils.h +++ b/jni/include/libfuse_jni/FuseUtils.h @@ -21,6 +21,10 @@ namespace mediaprovider { namespace fuse { +static constexpr char STORAGE_PREFIX[] = "/storage"; +static constexpr char VOLUME_INTERNAL[] = "internal"; +static constexpr char VOLUME_EXTERNAL_PRIMARY[] = "external_primary"; +static constexpr char PRIMARY_VOLUME_PREFIX[] = "/storage/emulated"; /** * Returns true if the given path (ignoring case) is mounted for any @@ -31,6 +35,11 @@ namespace fuse { */ bool containsMount(const std::string& path); +/** + * Returns the volume name extracted from a given path. + */ +std::string getVolumeNameFromPath(const std::string& path); + } // namespace fuse } // namespace mediaprovider |