Loading libcutils/fs_config.cpp +32 −20 Original line number Diff line number Diff line Loading @@ -139,14 +139,8 @@ static const struct fs_path_config android_files[] = { { 00600, AID_ROOT, AID_ROOT, 0, "odm/default.prop" }, { 00444, AID_ROOT, AID_ROOT, 0, odm_conf_dir + 1 }, { 00444, AID_ROOT, AID_ROOT, 0, odm_conf_file + 1 }, { 00600, AID_ROOT, AID_ROOT, 0, "system/odm/build.prop" }, { 00600, AID_ROOT, AID_ROOT, 0, "system/odm/default.prop" }, { 00444, AID_ROOT, AID_ROOT, 0, "system/odm/etc/fs_config_dirs" }, { 00444, AID_ROOT, AID_ROOT, 0, "system/odm/etc/fs_config_files" }, { 00444, AID_ROOT, AID_ROOT, 0, oem_conf_dir + 1 }, { 00444, AID_ROOT, AID_ROOT, 0, oem_conf_file + 1 }, { 00444, AID_ROOT, AID_ROOT, 0, "system/oem/etc/fs_config_dirs" }, { 00444, AID_ROOT, AID_ROOT, 0, "system/oem/etc/fs_config_files" }, { 00750, AID_ROOT, AID_SHELL, 0, "sbin/fs_mgr" }, { 00755, AID_ROOT, AID_SHELL, 0, "system/bin/crash_dump32" }, { 00755, AID_ROOT, AID_SHELL, 0, "system/bin/crash_dump64" }, Loading @@ -163,10 +157,6 @@ static const struct fs_path_config android_files[] = { { 00555, AID_ROOT, AID_ROOT, 0, "system/etc/ppp/*" }, { 00555, AID_ROOT, AID_ROOT, 0, "system/etc/rc.*" }, { 00440, AID_ROOT, AID_ROOT, 0, "system/etc/recovery.img" }, { 00600, AID_ROOT, AID_ROOT, 0, "system/vendor/build.prop" }, { 00600, AID_ROOT, AID_ROOT, 0, "system/vendor/default.prop" }, { 00444, AID_ROOT, AID_ROOT, 0, "system/vendor/etc/fs_config_dirs" }, { 00444, AID_ROOT, AID_ROOT, 0, "system/vendor/etc/fs_config_files" }, { 00600, AID_ROOT, AID_ROOT, 0, "vendor/build.prop" }, { 00600, AID_ROOT, AID_ROOT, 0, "vendor/default.prop" }, { 00444, AID_ROOT, AID_ROOT, 0, ven_conf_dir + 1 }, Loading Loading @@ -200,17 +190,11 @@ static const struct fs_path_config android_files[] = { // Support Bluetooth legacy hal accessing /sys/class/rfkill // Support RT scheduling in Bluetooth { 00700, AID_BLUETOOTH, AID_BLUETOOTH, CAP_MASK_LONG(CAP_NET_ADMIN) | CAP_MASK_LONG(CAP_SYS_NICE), "system/vendor/bin/hw/android.hardware.bluetooth@1.0-service" }, { 00700, AID_BLUETOOTH, AID_BLUETOOTH, CAP_MASK_LONG(CAP_NET_ADMIN) | CAP_MASK_LONG(CAP_SYS_NICE), "vendor/bin/hw/android.hardware.bluetooth@1.0-service" }, // Support wifi_hal_legacy administering a network interface. { 00755, AID_WIFI, AID_WIFI, CAP_MASK_LONG(CAP_NET_ADMIN) | CAP_MASK_LONG(CAP_NET_RAW), "system/vendor/bin/hw/android.hardware.wifi@1.0-service" }, { 00755, AID_WIFI, AID_WIFI, CAP_MASK_LONG(CAP_NET_ADMIN) | CAP_MASK_LONG(CAP_NET_RAW), "vendor/bin/hw/android.hardware.wifi@1.0-service" }, Loading @@ -233,8 +217,6 @@ static const struct fs_path_config android_files[] = { { 00755, AID_ROOT, AID_SHELL, 0, "system/bin/*" }, { 00755, AID_ROOT, AID_ROOT, 0, "system/lib/valgrind/*" }, { 00755, AID_ROOT, AID_ROOT, 0, "system/lib64/valgrind/*" }, { 00755, AID_ROOT, AID_SHELL, 0, "system/vendor/bin/*" }, { 00755, AID_ROOT, AID_SHELL, 0, "system/vendor/xbin/*" }, { 00755, AID_ROOT, AID_SHELL, 0, "system/xbin/*" }, { 00755, AID_ROOT, AID_SHELL, 0, "vendor/bin/*" }, { 00755, AID_ROOT, AID_SHELL, 0, "vendor/xbin/*" }, Loading Loading @@ -273,6 +255,36 @@ static int fs_config_open(int dir, int which, const char* target_out_path) { return fd; } // if path is "vendor/<stuff>", "oem/<stuff>" or "odm/<stuff>" static bool is_partition(const char* path, size_t len) { static const char* partitions[] = {"vendor/", "oem/", "odm/"}; for (size_t i = 0; i < (sizeof(partitions) / sizeof(partitions[0])); ++i) { size_t plen = strlen(partitions[i]); if (len <= plen) continue; if (!strncmp(path, partitions[i], plen)) return true; } return false; } // alias prefixes of "<partition>/<stuff>" to "system/<partition>/<stuff>" or // "system/<partition>/<stuff>" to "<partition>/<stuff>" static bool prefix_cmp(const char* prefix, const char* path, size_t len) { if (!strncmp(prefix, path, len)) return true; static const char system[] = "system/"; if (!strncmp(path, system, strlen(system))) { path += strlen(system); } else if (len <= strlen(system)) { return false; } else if (strncmp(prefix, system, strlen(system))) { return false; } else { prefix += strlen(system); len -= strlen(system); } return is_partition(prefix, len) && !strncmp(prefix, path, len); } static bool fs_config_cmp(bool dir, const char* prefix, size_t len, const char* path, size_t plen) { if (dir) { if (plen < len) { Loading @@ -281,13 +293,13 @@ static bool fs_config_cmp(bool dir, const char* prefix, size_t len, const char* } else { // If name ends in * then allow partial matches. if (prefix[len - 1] == '*') { return !strncmp(prefix, path, len - 1); return prefix_cmp(prefix, path, len - 1); } if (plen != len) { return false; } } return !strncmp(prefix, path, len); return prefix_cmp(prefix, path, len); } void fs_config(const char* path, int dir, const char* target_out_path, unsigned* uid, unsigned* gid, Loading libcutils/tests/fs_config.cpp +149 −24 Original line number Diff line number Diff line Loading @@ -14,63 +14,188 @@ * limitations under the License. */ #include <inttypes.h> #include <string> #include <gtest/gtest.h> #include <android-base/file.h> #include <android-base/stringprintf.h> #include <android-base/strings.h> #include <private/android_filesystem_config.h> #include <private/fs_config.h> extern const struct fs_path_config* __for_testing_only__android_dirs; extern const struct fs_path_config* __for_testing_only__android_files; extern const fs_path_config* __for_testing_only__android_dirs; extern const fs_path_config* __for_testing_only__android_files; static void check_one(const struct fs_path_config* paths, const std::string& prefix, const std::string& alternate) { for (size_t idx = 0; paths[idx].prefix; ++idx) { std::string path(paths[idx].prefix); if (android::base::StartsWith(path, prefix.c_str())) { path = alternate + path.substr(prefix.length()); // Maximum entries in system/core/libcutils/fs_config.cpp:android_* before we // hit a nullptr termination, before we declare the list is just too big or // could be missing the nullptr. static constexpr size_t max_idx = 4096; static bool check_unique(std::vector<const char*>& paths, const std::string& config_name, const std::string& prefix) { bool retval = false; std::string alternate = "system/" + prefix; for (size_t idx = 0; idx < paths.size(); ++idx) { size_t second; for (second = 0; paths[second].prefix; ++second) { if (path == paths[second].prefix) break; std::string path(paths[idx]); // check if there are multiple identical paths for (second = idx + 1; second < paths.size(); ++second) { if (path == paths[second]) { GTEST_LOG_(ERROR) << "duplicate paths in " << config_name << ": " << paths[idx]; retval = true; break; } if (!paths[second].prefix) { // guaranteed to fail expectations, trigger test failure with // a message that reports the violation as an inequality. EXPECT_STREQ((prefix + path.substr(alternate.length())).c_str(), path.c_str()); } // check if path is <partition>/ if (android::base::StartsWith(path, prefix.c_str())) { // rebuild path to be system/<partition>/... to check for alias path = alternate + path.substr(prefix.size()); for (second = 0; second < paths.size(); ++second) { if (path == paths[second]) { GTEST_LOG_(ERROR) << "duplicate alias paths in " << config_name << ": " << paths[idx] << " and " << paths[second] << " (remove latter)"; retval = true; break; } } continue; } static void check_two(const struct fs_path_config* paths, const std::string& prefix) { // check if path is system/<partition>/ if (android::base::StartsWith(path, alternate.c_str())) { // rebuild path to be <partition>/... to check for alias path = prefix + path.substr(alternate.size()); for (second = 0; second < paths.size(); ++second) { if (path == paths[second]) break; } if (second >= paths.size()) { GTEST_LOG_(ERROR) << "replace path in " << config_name << ": " << paths[idx] << " with " << path; retval = true; } } } return retval; } static bool check_unique(const fs_path_config* paths, const char* type_name, const std::string& prefix) { std::string config("system/core/libcutils/fs_config.cpp:android_"); config += type_name; config += "[]"; bool retval = false; std::vector<const char*> paths_tmp; for (size_t idx = 0; paths[idx].prefix; ++idx) { if (idx > max_idx) { GTEST_LOG_(WARNING) << config << ": has no end (missing null prefix)"; retval = true; break; } paths_tmp.push_back(paths[idx].prefix); } return check_unique(paths_tmp, config, prefix) || retval; } #define endof(pointer, field) (offsetof(typeof(*(pointer)), field) + sizeof((pointer)->field)) static bool check_unique(const std::string& config, const std::string& prefix) { int retval = false; std::string data; if (!android::base::ReadFileToString(config, &data)) return retval; const fs_path_config_from_file* pc = reinterpret_cast<const fs_path_config_from_file*>(data.c_str()); size_t len = data.size(); std::vector<const char*> paths_tmp; size_t entry_number = 0; while (len > 0) { uint16_t host_len = (len >= endof(pc, len)) ? pc->len : INT16_MAX; if (host_len > len) { GTEST_LOG_(WARNING) << config << ": truncated at entry " << entry_number << " (" << host_len << " > " << len << ")"; const std::string unknown("?"); GTEST_LOG_(WARNING) << config << ": entry[" << entry_number << "]={ " << "len=" << ((len >= endof(pc, len)) ? android::base::StringPrintf("%" PRIu16, pc->len) : unknown) << ", mode=" << ((len >= endof(pc, mode)) ? android::base::StringPrintf("0%" PRIo16, pc->mode) : unknown) << ", uid=" << ((len >= endof(pc, uid)) ? android::base::StringPrintf("%" PRIu16, pc->uid) : unknown) << ", gid=" << ((len >= endof(pc, gid)) ? android::base::StringPrintf("%" PRIu16, pc->gid) : unknown) << ", capabilities=" << ((len >= endof(pc, capabilities)) ? android::base::StringPrintf("0x%" PRIx64, pc->capabilities) : unknown) << ", prefix=" << ((len >= offsetof(fs_path_config_from_file, prefix)) ? android::base::StringPrintf( "\"%.*s...", (int)(len - offsetof(fs_path_config_from_file, prefix)), pc->prefix) : unknown) << " }"; retval = true; break; } paths_tmp.push_back(pc->prefix); pc = reinterpret_cast<const fs_path_config_from_file*>(reinterpret_cast<const char*>(pc) + host_len); len -= host_len; ++entry_number; } return check_unique(paths_tmp, config, prefix) || retval; } void check_two(const fs_path_config* paths, const char* type_name, const char* prefix) { ASSERT_FALSE(paths == nullptr); std::string alternate = "system/" + prefix; check_one(paths, prefix, alternate); check_one(paths, alternate, prefix); ASSERT_FALSE(type_name == nullptr); ASSERT_FALSE(prefix == nullptr); bool check_internal = check_unique(paths, type_name, prefix); EXPECT_FALSE(check_internal); bool check_overrides = check_unique(std::string("/") + prefix + "etc/fs_config_" + type_name, prefix); EXPECT_FALSE(check_overrides); } TEST(fs_config, vendor_dirs_alias) { check_two(__for_testing_only__android_dirs, "vendor/"); check_two(__for_testing_only__android_dirs, "dirs", "vendor/"); } TEST(fs_config, vendor_files_alias) { check_two(__for_testing_only__android_files, "vendor/"); check_two(__for_testing_only__android_files, "files", "vendor/"); } TEST(fs_config, oem_dirs_alias) { check_two(__for_testing_only__android_dirs, "oem/"); check_two(__for_testing_only__android_dirs, "dirs", "oem/"); } TEST(fs_config, oem_files_alias) { check_two(__for_testing_only__android_files, "oem/"); check_two(__for_testing_only__android_files, "files", "oem/"); } TEST(fs_config, odm_dirs_alias) { check_two(__for_testing_only__android_dirs, "odm/"); check_two(__for_testing_only__android_dirs, "dirs", "odm/"); } TEST(fs_config, odm_files_alias) { check_two(__for_testing_only__android_files, "odm/"); check_two(__for_testing_only__android_files, "files", "odm/"); } Loading
libcutils/fs_config.cpp +32 −20 Original line number Diff line number Diff line Loading @@ -139,14 +139,8 @@ static const struct fs_path_config android_files[] = { { 00600, AID_ROOT, AID_ROOT, 0, "odm/default.prop" }, { 00444, AID_ROOT, AID_ROOT, 0, odm_conf_dir + 1 }, { 00444, AID_ROOT, AID_ROOT, 0, odm_conf_file + 1 }, { 00600, AID_ROOT, AID_ROOT, 0, "system/odm/build.prop" }, { 00600, AID_ROOT, AID_ROOT, 0, "system/odm/default.prop" }, { 00444, AID_ROOT, AID_ROOT, 0, "system/odm/etc/fs_config_dirs" }, { 00444, AID_ROOT, AID_ROOT, 0, "system/odm/etc/fs_config_files" }, { 00444, AID_ROOT, AID_ROOT, 0, oem_conf_dir + 1 }, { 00444, AID_ROOT, AID_ROOT, 0, oem_conf_file + 1 }, { 00444, AID_ROOT, AID_ROOT, 0, "system/oem/etc/fs_config_dirs" }, { 00444, AID_ROOT, AID_ROOT, 0, "system/oem/etc/fs_config_files" }, { 00750, AID_ROOT, AID_SHELL, 0, "sbin/fs_mgr" }, { 00755, AID_ROOT, AID_SHELL, 0, "system/bin/crash_dump32" }, { 00755, AID_ROOT, AID_SHELL, 0, "system/bin/crash_dump64" }, Loading @@ -163,10 +157,6 @@ static const struct fs_path_config android_files[] = { { 00555, AID_ROOT, AID_ROOT, 0, "system/etc/ppp/*" }, { 00555, AID_ROOT, AID_ROOT, 0, "system/etc/rc.*" }, { 00440, AID_ROOT, AID_ROOT, 0, "system/etc/recovery.img" }, { 00600, AID_ROOT, AID_ROOT, 0, "system/vendor/build.prop" }, { 00600, AID_ROOT, AID_ROOT, 0, "system/vendor/default.prop" }, { 00444, AID_ROOT, AID_ROOT, 0, "system/vendor/etc/fs_config_dirs" }, { 00444, AID_ROOT, AID_ROOT, 0, "system/vendor/etc/fs_config_files" }, { 00600, AID_ROOT, AID_ROOT, 0, "vendor/build.prop" }, { 00600, AID_ROOT, AID_ROOT, 0, "vendor/default.prop" }, { 00444, AID_ROOT, AID_ROOT, 0, ven_conf_dir + 1 }, Loading Loading @@ -200,17 +190,11 @@ static const struct fs_path_config android_files[] = { // Support Bluetooth legacy hal accessing /sys/class/rfkill // Support RT scheduling in Bluetooth { 00700, AID_BLUETOOTH, AID_BLUETOOTH, CAP_MASK_LONG(CAP_NET_ADMIN) | CAP_MASK_LONG(CAP_SYS_NICE), "system/vendor/bin/hw/android.hardware.bluetooth@1.0-service" }, { 00700, AID_BLUETOOTH, AID_BLUETOOTH, CAP_MASK_LONG(CAP_NET_ADMIN) | CAP_MASK_LONG(CAP_SYS_NICE), "vendor/bin/hw/android.hardware.bluetooth@1.0-service" }, // Support wifi_hal_legacy administering a network interface. { 00755, AID_WIFI, AID_WIFI, CAP_MASK_LONG(CAP_NET_ADMIN) | CAP_MASK_LONG(CAP_NET_RAW), "system/vendor/bin/hw/android.hardware.wifi@1.0-service" }, { 00755, AID_WIFI, AID_WIFI, CAP_MASK_LONG(CAP_NET_ADMIN) | CAP_MASK_LONG(CAP_NET_RAW), "vendor/bin/hw/android.hardware.wifi@1.0-service" }, Loading @@ -233,8 +217,6 @@ static const struct fs_path_config android_files[] = { { 00755, AID_ROOT, AID_SHELL, 0, "system/bin/*" }, { 00755, AID_ROOT, AID_ROOT, 0, "system/lib/valgrind/*" }, { 00755, AID_ROOT, AID_ROOT, 0, "system/lib64/valgrind/*" }, { 00755, AID_ROOT, AID_SHELL, 0, "system/vendor/bin/*" }, { 00755, AID_ROOT, AID_SHELL, 0, "system/vendor/xbin/*" }, { 00755, AID_ROOT, AID_SHELL, 0, "system/xbin/*" }, { 00755, AID_ROOT, AID_SHELL, 0, "vendor/bin/*" }, { 00755, AID_ROOT, AID_SHELL, 0, "vendor/xbin/*" }, Loading Loading @@ -273,6 +255,36 @@ static int fs_config_open(int dir, int which, const char* target_out_path) { return fd; } // if path is "vendor/<stuff>", "oem/<stuff>" or "odm/<stuff>" static bool is_partition(const char* path, size_t len) { static const char* partitions[] = {"vendor/", "oem/", "odm/"}; for (size_t i = 0; i < (sizeof(partitions) / sizeof(partitions[0])); ++i) { size_t plen = strlen(partitions[i]); if (len <= plen) continue; if (!strncmp(path, partitions[i], plen)) return true; } return false; } // alias prefixes of "<partition>/<stuff>" to "system/<partition>/<stuff>" or // "system/<partition>/<stuff>" to "<partition>/<stuff>" static bool prefix_cmp(const char* prefix, const char* path, size_t len) { if (!strncmp(prefix, path, len)) return true; static const char system[] = "system/"; if (!strncmp(path, system, strlen(system))) { path += strlen(system); } else if (len <= strlen(system)) { return false; } else if (strncmp(prefix, system, strlen(system))) { return false; } else { prefix += strlen(system); len -= strlen(system); } return is_partition(prefix, len) && !strncmp(prefix, path, len); } static bool fs_config_cmp(bool dir, const char* prefix, size_t len, const char* path, size_t plen) { if (dir) { if (plen < len) { Loading @@ -281,13 +293,13 @@ static bool fs_config_cmp(bool dir, const char* prefix, size_t len, const char* } else { // If name ends in * then allow partial matches. if (prefix[len - 1] == '*') { return !strncmp(prefix, path, len - 1); return prefix_cmp(prefix, path, len - 1); } if (plen != len) { return false; } } return !strncmp(prefix, path, len); return prefix_cmp(prefix, path, len); } void fs_config(const char* path, int dir, const char* target_out_path, unsigned* uid, unsigned* gid, Loading
libcutils/tests/fs_config.cpp +149 −24 Original line number Diff line number Diff line Loading @@ -14,63 +14,188 @@ * limitations under the License. */ #include <inttypes.h> #include <string> #include <gtest/gtest.h> #include <android-base/file.h> #include <android-base/stringprintf.h> #include <android-base/strings.h> #include <private/android_filesystem_config.h> #include <private/fs_config.h> extern const struct fs_path_config* __for_testing_only__android_dirs; extern const struct fs_path_config* __for_testing_only__android_files; extern const fs_path_config* __for_testing_only__android_dirs; extern const fs_path_config* __for_testing_only__android_files; static void check_one(const struct fs_path_config* paths, const std::string& prefix, const std::string& alternate) { for (size_t idx = 0; paths[idx].prefix; ++idx) { std::string path(paths[idx].prefix); if (android::base::StartsWith(path, prefix.c_str())) { path = alternate + path.substr(prefix.length()); // Maximum entries in system/core/libcutils/fs_config.cpp:android_* before we // hit a nullptr termination, before we declare the list is just too big or // could be missing the nullptr. static constexpr size_t max_idx = 4096; static bool check_unique(std::vector<const char*>& paths, const std::string& config_name, const std::string& prefix) { bool retval = false; std::string alternate = "system/" + prefix; for (size_t idx = 0; idx < paths.size(); ++idx) { size_t second; for (second = 0; paths[second].prefix; ++second) { if (path == paths[second].prefix) break; std::string path(paths[idx]); // check if there are multiple identical paths for (second = idx + 1; second < paths.size(); ++second) { if (path == paths[second]) { GTEST_LOG_(ERROR) << "duplicate paths in " << config_name << ": " << paths[idx]; retval = true; break; } if (!paths[second].prefix) { // guaranteed to fail expectations, trigger test failure with // a message that reports the violation as an inequality. EXPECT_STREQ((prefix + path.substr(alternate.length())).c_str(), path.c_str()); } // check if path is <partition>/ if (android::base::StartsWith(path, prefix.c_str())) { // rebuild path to be system/<partition>/... to check for alias path = alternate + path.substr(prefix.size()); for (second = 0; second < paths.size(); ++second) { if (path == paths[second]) { GTEST_LOG_(ERROR) << "duplicate alias paths in " << config_name << ": " << paths[idx] << " and " << paths[second] << " (remove latter)"; retval = true; break; } } continue; } static void check_two(const struct fs_path_config* paths, const std::string& prefix) { // check if path is system/<partition>/ if (android::base::StartsWith(path, alternate.c_str())) { // rebuild path to be <partition>/... to check for alias path = prefix + path.substr(alternate.size()); for (second = 0; second < paths.size(); ++second) { if (path == paths[second]) break; } if (second >= paths.size()) { GTEST_LOG_(ERROR) << "replace path in " << config_name << ": " << paths[idx] << " with " << path; retval = true; } } } return retval; } static bool check_unique(const fs_path_config* paths, const char* type_name, const std::string& prefix) { std::string config("system/core/libcutils/fs_config.cpp:android_"); config += type_name; config += "[]"; bool retval = false; std::vector<const char*> paths_tmp; for (size_t idx = 0; paths[idx].prefix; ++idx) { if (idx > max_idx) { GTEST_LOG_(WARNING) << config << ": has no end (missing null prefix)"; retval = true; break; } paths_tmp.push_back(paths[idx].prefix); } return check_unique(paths_tmp, config, prefix) || retval; } #define endof(pointer, field) (offsetof(typeof(*(pointer)), field) + sizeof((pointer)->field)) static bool check_unique(const std::string& config, const std::string& prefix) { int retval = false; std::string data; if (!android::base::ReadFileToString(config, &data)) return retval; const fs_path_config_from_file* pc = reinterpret_cast<const fs_path_config_from_file*>(data.c_str()); size_t len = data.size(); std::vector<const char*> paths_tmp; size_t entry_number = 0; while (len > 0) { uint16_t host_len = (len >= endof(pc, len)) ? pc->len : INT16_MAX; if (host_len > len) { GTEST_LOG_(WARNING) << config << ": truncated at entry " << entry_number << " (" << host_len << " > " << len << ")"; const std::string unknown("?"); GTEST_LOG_(WARNING) << config << ": entry[" << entry_number << "]={ " << "len=" << ((len >= endof(pc, len)) ? android::base::StringPrintf("%" PRIu16, pc->len) : unknown) << ", mode=" << ((len >= endof(pc, mode)) ? android::base::StringPrintf("0%" PRIo16, pc->mode) : unknown) << ", uid=" << ((len >= endof(pc, uid)) ? android::base::StringPrintf("%" PRIu16, pc->uid) : unknown) << ", gid=" << ((len >= endof(pc, gid)) ? android::base::StringPrintf("%" PRIu16, pc->gid) : unknown) << ", capabilities=" << ((len >= endof(pc, capabilities)) ? android::base::StringPrintf("0x%" PRIx64, pc->capabilities) : unknown) << ", prefix=" << ((len >= offsetof(fs_path_config_from_file, prefix)) ? android::base::StringPrintf( "\"%.*s...", (int)(len - offsetof(fs_path_config_from_file, prefix)), pc->prefix) : unknown) << " }"; retval = true; break; } paths_tmp.push_back(pc->prefix); pc = reinterpret_cast<const fs_path_config_from_file*>(reinterpret_cast<const char*>(pc) + host_len); len -= host_len; ++entry_number; } return check_unique(paths_tmp, config, prefix) || retval; } void check_two(const fs_path_config* paths, const char* type_name, const char* prefix) { ASSERT_FALSE(paths == nullptr); std::string alternate = "system/" + prefix; check_one(paths, prefix, alternate); check_one(paths, alternate, prefix); ASSERT_FALSE(type_name == nullptr); ASSERT_FALSE(prefix == nullptr); bool check_internal = check_unique(paths, type_name, prefix); EXPECT_FALSE(check_internal); bool check_overrides = check_unique(std::string("/") + prefix + "etc/fs_config_" + type_name, prefix); EXPECT_FALSE(check_overrides); } TEST(fs_config, vendor_dirs_alias) { check_two(__for_testing_only__android_dirs, "vendor/"); check_two(__for_testing_only__android_dirs, "dirs", "vendor/"); } TEST(fs_config, vendor_files_alias) { check_two(__for_testing_only__android_files, "vendor/"); check_two(__for_testing_only__android_files, "files", "vendor/"); } TEST(fs_config, oem_dirs_alias) { check_two(__for_testing_only__android_dirs, "oem/"); check_two(__for_testing_only__android_dirs, "dirs", "oem/"); } TEST(fs_config, oem_files_alias) { check_two(__for_testing_only__android_files, "oem/"); check_two(__for_testing_only__android_files, "files", "oem/"); } TEST(fs_config, odm_dirs_alias) { check_two(__for_testing_only__android_dirs, "odm/"); check_two(__for_testing_only__android_dirs, "dirs", "odm/"); } TEST(fs_config, odm_files_alias) { check_two(__for_testing_only__android_files, "odm/"); check_two(__for_testing_only__android_files, "files", "odm/"); }