Loading tools/fs_config/Android.mk +145 −2 Original line number Diff line number Diff line Loading @@ -113,6 +113,11 @@ LOCAL_C_INCLUDES := $(dir $(my_fs_config_h)) $(dir $(my_gen_oem_aid)) include $(BUILD_HOST_EXECUTABLE) fs_config_generate_bin := $(LOCAL_INSTALLED_MODULE) # List of all supported vendor, oem and odm Partitions fs_config_generate_extra_partition_list := $(strip \ $(if $(BOARD_USES_VENDORIMAGE)$(BOARD_VENDORIMAGE_FILE_SYSTEM_TYPE),vendor) \ $(if $(BOARD_USES_OEMIMAGE)$(BOARD_OEMIMAGE_FILE_SYSTEM_TYPE),oem) \ $(if $(BOARD_USES_ODMIMAGE)$(BOARD_ODMIMAGE_FILE_SYSTEM_TYPE),odm)) ################################## # Generate the system/etc/fs_config_dirs binary file for the target Loading @@ -121,10 +126,13 @@ include $(CLEAR_VARS) LOCAL_MODULE := fs_config_dirs LOCAL_MODULE_CLASS := ETC LOCAL_REQUIRED_MODULES := $(foreach t,$(fs_config_generate_extra_partion_list),$(LOCAL_MODULE)_$(t)) include $(BUILD_SYSTEM)/base_rules.mk $(LOCAL_BUILT_MODULE): $(fs_config_generate_bin) @mkdir -p $(dir $@) $< -D -o $@ $< -D $(if $(fs_config_generate_extra_partition_list), \ -P '$(subst $(space),$(comma),$(addprefix -,$(fs_config_generate_extra_partition_list)))') \ -o $@ ################################## # Generate the system/etc/fs_config_files binary file for the target Loading @@ -133,10 +141,112 @@ include $(CLEAR_VARS) LOCAL_MODULE := fs_config_files LOCAL_MODULE_CLASS := ETC LOCAL_REQUIRED_MODULES := $(foreach t,$(fs_config_generate_extra_partion_list),$(LOCAL_MODULE)_$(t)) include $(BUILD_SYSTEM)/base_rules.mk $(LOCAL_BUILT_MODULE): $(fs_config_generate_bin) @mkdir -p $(dir $@) $< -F -o $@ $< -F $(if $(fs_config_generate_extra_partition_list), \ -P '$(subst $(space),$(comma),$(addprefix -,$(fs_config_generate_extra_partition_list)))') \ -o $@ ifneq ($(filter vendor,$(fs_config_generate_extra_partition_list)),) ################################## # Generate the vendor/etc/fs_config_dirs binary file for the target # Add fs_config_dirs or fs_config_dirs_vendor to PRODUCT_PACKAGES in # the device make file to enable. include $(CLEAR_VARS) LOCAL_MODULE := fs_config_dirs_vendor LOCAL_MODULE_CLASS := ETC LOCAL_INSTALLED_MODULE_STEM := fs_config_dirs LOCAL_MODULE_PATH := $(TARGET_OUT_VENDOR)/etc include $(BUILD_SYSTEM)/base_rules.mk $(LOCAL_BUILT_MODULE): $(fs_config_generate_bin) @mkdir -p $(dir $@) $< -D -P vendor -o $@ ################################## # Generate the vendor/etc/fs_config_files binary file for the target # Add fs_config_files or fs_config_files_vendor to PRODUCT_PACKAGES in # the device make file to enable include $(CLEAR_VARS) LOCAL_MODULE := fs_config_files_vendor LOCAL_MODULE_CLASS := ETC LOCAL_INSTALLED_MODULE_STEM := fs_config_files LOCAL_MODULE_PATH := $(TARGET_OUT_VENDOR)/etc include $(BUILD_SYSTEM)/base_rules.mk $(LOCAL_BUILT_MODULE): $(fs_config_generate_bin) @mkdir -p $(dir $@) $< -F -P vendor -o $@ endif ifneq ($(filter oem,$(fs_config_generate_extra_partition_list)),) ################################## # Generate the oem/etc/fs_config_dirs binary file for the target # Add fs_config_dirs or fs_config_dirs_oem to PRODUCT_PACKAGES in # the device make file to enable include $(CLEAR_VARS) LOCAL_MODULE := fs_config_dirs_oem LOCAL_MODULE_CLASS := ETC LOCAL_INSTALLED_MODULE_STEM := fs_config_dirs LOCAL_MODULE_PATH := $(TARGET_OUT_OEM)/etc include $(BUILD_SYSTEM)/base_rules.mk $(LOCAL_BUILT_MODULE): $(fs_config_generate_bin) @mkdir -p $(dir $@) $< -D -P oem -o $@ ################################## # Generate the oem/etc/fs_config_files binary file for the target # Add fs_config_files or fs_config_files_oem to PRODUCT_PACKAGES in # the device make file to enable include $(CLEAR_VARS) LOCAL_MODULE := fs_config_files_oem LOCAL_MODULE_CLASS := ETC LOCAL_INSTALLED_MODULE_STEM := fs_config_files LOCAL_MODULE_PATH := $(TARGET_OUT_OEM)/etc include $(BUILD_SYSTEM)/base_rules.mk $(LOCAL_BUILT_MODULE): $(fs_config_generate_bin) @mkdir -p $(dir $@) $< -F -P oem -o $@ endif ifneq ($(filter odm,$(fs_config_generate_extra_partition_list)),) ################################## # Generate the odm/etc/fs_config_dirs binary file for the target # Add fs_config_dirs or fs_config_dirs_odm to PRODUCT_PACKAGES in # the device make file to enable include $(CLEAR_VARS) LOCAL_MODULE := fs_config_dirs_odm LOCAL_MODULE_CLASS := ETC LOCAL_INSTALLED_MODULE_STEM := fs_config_dirs LOCAL_MODULE_PATH := $(TARGET_OUT_ODM)/etc include $(BUILD_SYSTEM)/base_rules.mk $(LOCAL_BUILT_MODULE): $(fs_config_generate_bin) @mkdir -p $(dir $@) $< -D -P odm -o $@ ################################## # Generate the odm/etc/fs_config_files binary file for the target # Add fs_config_files of fs_config_files_odm to PRODUCT_PACKAGES in # the device make file to enable include $(CLEAR_VARS) LOCAL_MODULE := fs_config_files_odm LOCAL_MODULE_CLASS := ETC LOCAL_INSTALLED_MODULE_STEM := fs_config_files LOCAL_MODULE_PATH := $(TARGET_OUT_ODM)/etc include $(BUILD_SYSTEM)/base_rules.mk $(LOCAL_BUILT_MODULE): $(fs_config_generate_bin) @mkdir -p $(dir $@) $< -F -P odm -o $@ endif # The newer passwd/group targets are only generated if you # use the new TARGET_FS_CONFIG_GEN method. Loading Loading @@ -195,3 +305,36 @@ ANDROID_FS_CONFIG_H := my_fs_config_h := fs_config_generate_bin := my_gen_oem_aid := # ----------------------------------------------------------------------------- # Unit tests. # ----------------------------------------------------------------------------- test_c_flags := \ -fstack-protector-all \ -g \ -Wall \ -Wextra \ -Werror \ -fno-builtin \ -DANDROID_FILESYSTEM_CONFIG='"android_filesystem_config_test_data.h"' ################################## # test executable include $(CLEAR_VARS) LOCAL_MODULE := fs_config_generate_test LOCAL_SRC_FILES := fs_config_generate.c LOCAL_SHARED_LIBRARIES := libcutils LOCAL_CFLAGS := $(test_c_flags) LOCAL_MODULE_RELATIVE_PATH := fs_config-unit-tests LOCAL_GTEST := false include $(BUILD_HOST_NATIVE_TEST) ################################## # gTest tool include $(CLEAR_VARS) LOCAL_MODULE := fs_config-unit-tests LOCAL_CFLAGS += $(test_c_flags) -DHOST LOCAL_SHARED_LIBRARIES := liblog libcutils libbase LOCAL_SRC_FILES := fs_config_test.cpp include $(BUILD_HOST_NATIVE_TEST) tools/fs_config/README +21 −2 Original line number Diff line number Diff line Loading @@ -156,9 +156,28 @@ properties are preserved during runtime operations. The host files in the ${OUT} directory are used in the final stages when building the filesystem images to set the file and directory properties. For systems with separate partition images, such as vendor or oem, fs_config_generate can be instructed to filter the specific file references to land in each partition's etc/fs_config_dirs or etc/fs_config_files locations. The filter can be instructed to blacklist a partition's data by providing the comma separated minus sign prefixed partition names. The filter can be instructed to whitelist partition data by providing the partition name. For example: - For system.img, but not vendor, oem or odm file references: -P -vendor,-oem,-odm This makes sure the results only contain content associated with the system, and not vendor, oem or odm, blacklisting their content. - For vendor.img file references: -P vendor - For oem.img file references: -P oem - For odm.img file references: -P odm fs_config_generate --help reports: Generate binary content for fs_config_dirs (-D) and fs_config_files (-F) from device-specific android_filesystem_config.h override from device-specific android_filesystem_config.h override. Filter based on a comma separated partition list (-P) whitelist or prefixed by a minus blacklist. Partitions are identified as path references to <partition>/ or system/<partition> Usage: fs_config_generate -D|-F [-o output-file] Usage: fs_config_generate -D|-F [-P list] [-o output-file] tools/fs_config/android_filesystem_config_test_data.h 0 → 100644 +56 −0 Original line number Diff line number Diff line /* * Copyright (C) 2017 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 <private/android_filesystem_config.h> /* Test Data */ #undef NO_ANDROID_FILESYSTEM_CONFIG_DEVICE_DIRS #undef NO_ANDROID_FILESYSTEM_CONFIG_DEVICE_FILES static const struct fs_path_config android_device_dirs[] = { {00555, AID_ROOT, AID_SYSTEM, 0, "system/etc"}, {00555, AID_ROOT, AID_SYSTEM, 0, "vendor/etc"}, {00555, AID_ROOT, AID_SYSTEM, 0, "oem/etc"}, {00555, AID_ROOT, AID_SYSTEM, 0, "odm/etc"}, {00755, AID_SYSTEM, AID_ROOT, 0, "system/oem/etc"}, {00755, AID_SYSTEM, AID_ROOT, 0, "system/odm/etc"}, {00755, AID_SYSTEM, AID_ROOT, 0, "system/vendor/etc"}, {00755, AID_SYSTEM, AID_ROOT, 0, "data/misc"}, {00755, AID_SYSTEM, AID_ROOT, 0, "oem/data/misc"}, {00755, AID_SYSTEM, AID_ROOT, 0, "odm/data/misc"}, {00755, AID_SYSTEM, AID_ROOT, 0, "vendor/data/misc"}, {00555, AID_SYSTEM, AID_ROOT, 0, "etc"}, }; static const struct fs_path_config android_device_files[] = { {00444, AID_ROOT, AID_SYSTEM, 0, "system/etc/fs_config_dirs"}, {00444, AID_ROOT, AID_SYSTEM, 0, "vendor/etc/fs_config_dirs"}, {00444, AID_ROOT, AID_SYSTEM, 0, "oem/etc/fs_config_dirs"}, {00444, AID_ROOT, AID_SYSTEM, 0, "odm/etc/fs_config_dirs"}, {00444, AID_ROOT, AID_SYSTEM, 0, "system/etc/fs_config_files"}, {00444, AID_ROOT, AID_SYSTEM, 0, "vendor/etc/fs_config_files"}, {00444, AID_ROOT, AID_SYSTEM, 0, "oem/etc/fs_config_files"}, {00444, AID_ROOT, AID_SYSTEM, 0, "odm/etc/fs_config_files"}, {00644, AID_SYSTEM, AID_ROOT, 0, "system/vendor/etc/fs_config_dirs"}, {00644, AID_SYSTEM, AID_ROOT, 0, "system/oem/etc/fs_config_dirs"}, {00644, AID_SYSTEM, AID_ROOT, 0, "system/odm/etc/fs_config_dirs"}, {00644, AID_SYSTEM, AID_ROOT, 0, "system/vendor/etc/fs_config_files"}, {00644, AID_SYSTEM, AID_ROOT, 0, "system/oem/etc/fs_config_files"}, {00644, AID_SYSTEM, AID_ROOT, 0, "system/odm/etc/fs_config_files"}, {00644, AID_SYSTEM, AID_ROOT, 0, "etc/fs_config_files"}, {00666, AID_ROOT, AID_SYSTEM, 0, "data/misc/oem"}, }; tools/fs_config/fs_config_generate.c +111 −15 Original line number Diff line number Diff line Loading @@ -14,9 +14,11 @@ * limitations under the License. */ #include <ctype.h> #include <stdbool.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <private/android_filesystem_config.h> Loading @@ -28,37 +30,56 @@ * the binary format used in the /system/etc/fs_config_dirs and * the /system/etc/fs_config_files to be used by the runtimes. */ #ifdef ANDROID_FILESYSTEM_CONFIG #include ANDROID_FILESYSTEM_CONFIG #else #include "android_filesystem_config.h" #endif #ifdef NO_ANDROID_FILESYSTEM_CONFIG_DEVICE_DIRS static const struct fs_path_config android_device_dirs[] = { }; static const struct fs_path_config android_device_dirs[] = { }; #endif #ifdef NO_ANDROID_FILESYSTEM_CONFIG_DEVICE_FILES static const struct fs_path_config android_device_files[] = { #ifdef NO_ANDROID_FILESYSTEM_CONFIG_DEVICE_DIRS { 0, AID_ROOT, AID_ROOT, 0, "system/etc/fs_config_dirs" }, {0000, AID_ROOT, AID_ROOT, 0, "system/etc/fs_config_dirs"}, {0000, AID_ROOT, AID_ROOT, 0, "vendor/etc/fs_config_dirs"}, {0000, AID_ROOT, AID_ROOT, 0, "oem/etc/fs_config_dirs"}, {0000, AID_ROOT, AID_ROOT, 0, "odm/etc/fs_config_dirs"}, #endif { 0, AID_ROOT, AID_ROOT, 0, "system/etc/fs_config_files" }, {0000, AID_ROOT, AID_ROOT, 0, "system/etc/fs_config_files"}, {0000, AID_ROOT, AID_ROOT, 0, "vendor/etc/fs_config_files"}, {0000, AID_ROOT, AID_ROOT, 0, "oem/etc/fs_config_files"}, {0000, AID_ROOT, AID_ROOT, 0, "odm/etc/fs_config_files"}, }; #endif static void usage() { fprintf(stderr, "Generate binary content for fs_config_dirs (-D) and fs_config_files (-F)\n" "from device-specific android_filesystem_config.h override\n\n" "Usage: fs_config_generate -D|-F [-o output-file]\n"); "from device-specific android_filesystem_config.h override. Filter based\n" "on a comma separated partition list (-P) whitelist or prefixed by a\n" "minus blacklist. Partitions are identified as path references to\n" "<partition>/ or system/<partition>/\n\n" "Usage: fs_config_generate -D|-F [-P list] [-o output-file]\n"); } /* If tool switches to C++, use android-base/macros.h array_size() */ #ifndef ARRAY_SIZE /* popular macro */ #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) #endif int main(int argc, char** argv) { const struct fs_path_config* pc; const struct fs_path_config* end; bool dir = false, file = false; const char* partitions = NULL; FILE* fp = stdout; int opt; static const char optstring[] = "DFP:ho:"; while((opt = getopt(argc, argv, "DFho:")) != -1) { while ((opt = getopt(argc, argv, optstring)) != -1) { switch (opt) { case 'D': if (file) { Loading @@ -76,6 +97,30 @@ int main(int argc, char** argv) { } file = true; break; case 'P': if (partitions) { fprintf(stderr, "Specify only one partition list\n"); usage(); exit(EXIT_FAILURE); } while (*optarg && isspace(*optarg)) ++optarg; if (!optarg[0]) { fprintf(stderr, "Partition list empty\n"); usage(); exit(EXIT_FAILURE); } if (!optarg[1]) { fprintf(stderr, "Partition list too short \"%s\"\n", optarg); usage(); exit(EXIT_FAILURE); } if ((optarg[0] == '-') && strchr(optstring, optarg[1]) && !optarg[2]) { fprintf(stderr, "Partition list is a flag \"%s\"\n", optarg); usage(); exit(EXIT_FAILURE); } partitions = optarg; break; case 'o': if (fp != stdout) { fprintf(stderr, "Specify only one output file\n"); Loading @@ -97,6 +142,12 @@ int main(int argc, char** argv) { } } if (optind < argc) { fprintf(stderr, "Unknown non-argument \"%s\"\n", argv[optind]); usage(); exit(EXIT_FAILURE); } if (!file && !dir) { fprintf(stderr, "Must specify either -F or -D\n"); usage(); Loading @@ -105,19 +156,64 @@ int main(int argc, char** argv) { if (dir) { pc = android_device_dirs; end = &android_device_dirs[sizeof(android_device_dirs) / sizeof(android_device_dirs[0])]; end = &android_device_dirs[ARRAY_SIZE(android_device_dirs)]; } else { pc = android_device_files; end = &android_device_files[sizeof(android_device_files) / sizeof(android_device_files[0])]; end = &android_device_files[ARRAY_SIZE(android_device_files)]; } for (; (pc < end) && pc->prefix; pc++) { bool submit; char buffer[512]; ssize_t len = fs_config_generate(buffer, sizeof(buffer), pc); if (len < 0) { fprintf(stderr, "Entry too large\n"); exit(EXIT_FAILURE); } if (fwrite(buffer, 1, len, fp) != (size_t)len) { submit = true; if (partitions) { char* partitions_copy = strdup(partitions); char* arg = partitions_copy; char* sv = NULL; /* Do not leave uninitialized, NULL is known safe. */ /* Deal with case all iterated partitions are blacklists with no match */ bool all_blacklist_but_no_match = true; submit = false; if (!partitions_copy) { fprintf(stderr, "Failed to allocate a copy of %s\n", partitions); exit(EXIT_FAILURE); } /* iterate through (officially) comma separated list of partitions */ while (!!(arg = strtok_r(arg, ",:; \t\n\r\f", &sv))) { static const char system[] = "system/"; size_t plen; bool blacklist = false; if (*arg == '-') { blacklist = true; ++arg; } else { all_blacklist_but_no_match = false; } plen = strlen(arg); /* deal with evil callers */ while (arg[plen - 1] == '/') { --plen; } /* check if we have <partition>/ or /system/<partition>/ */ if ((!strncmp(pc->prefix, arg, plen) && (pc->prefix[plen] == '/')) || (!strncmp(pc->prefix, system, strlen(system)) && !strncmp(pc->prefix + strlen(system), arg, plen) && (pc->prefix[strlen(system) + plen] == '/'))) { all_blacklist_but_no_match = false; /* we have a match !!! */ if (!blacklist) submit = true; break; } arg = NULL; } free(partitions_copy); if (all_blacklist_but_no_match) submit = true; } if (submit && (fwrite(buffer, 1, len, fp) != (size_t)len)) { fprintf(stderr, "Write failure\n"); exit(EXIT_FAILURE); } Loading tools/fs_config/fs_config_test.cpp 0 → 100644 +223 −0 Original line number Diff line number Diff line /* * Copyright (C) 2017 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 <stdio.h> #include <sys/cdefs.h> #include <string> #include <vector> #include <android-base/file.h> #include <android-base/macros.h> #include <android-base/strings.h> #include <android-base/stringprintf.h> #include <gtest/gtest.h> #include <private/android_filesystem_config.h> #include <private/fs_config.h> #include "android_filesystem_config_test_data.h" // must run test in the test directory const static char fs_config_generate_command[] = "./fs_config_generate_test"; static std::string popenToString(std::string command) { std::string ret; FILE* fp = popen(command.c_str(), "r"); if (fp) { if (!android::base::ReadFdToString(fileno(fp), &ret)) ret = ""; pclose(fp); } return ret; } static void confirm(std::string&& data, const fs_path_config* config, ssize_t num_config) { const struct fs_path_config_from_file* pc = reinterpret_cast<const fs_path_config_from_file*>(data.c_str()); size_t len = data.size(); ASSERT_TRUE(config != NULL); ASSERT_LT(0, num_config); while (len > 0) { uint16_t host_len = pc->len; if (host_len > len) break; EXPECT_EQ(config->mode, pc->mode); EXPECT_EQ(config->uid, pc->uid); EXPECT_EQ(config->gid, pc->gid); EXPECT_EQ(config->capabilities, pc->capabilities); EXPECT_STREQ(config->prefix, pc->prefix); EXPECT_LT(0, num_config); --num_config; if (num_config >= 0) ++config; pc = reinterpret_cast<const fs_path_config_from_file*>( reinterpret_cast<const char*>(pc) + host_len); len -= host_len; } EXPECT_EQ(0, num_config); } /* See local android_filesystem_config.h for test data */ TEST(fs_conf_test, dirs) { confirm(popenToString( android::base::StringPrintf("%s -D", fs_config_generate_command)), android_device_dirs, arraysize(android_device_dirs)); } TEST(fs_conf_test, files) { confirm(popenToString( android::base::StringPrintf("%s -F", fs_config_generate_command)), android_device_files, arraysize(android_device_files)); } static const char vendor_str[] = "vendor/"; static const char vendor_alt_str[] = "system/vendor/"; static const char oem_str[] = "oem/"; static const char oem_alt_str[] = "system/oem/"; static const char odm_str[] = "odm/"; static const char odm_alt_str[] = "system/odm/"; TEST(fs_conf_test, system_dirs) { std::vector<fs_path_config> dirs; const fs_path_config* config = android_device_dirs; for (size_t num = arraysize(android_device_dirs); num; --num) { if (!android::base::StartsWith(config->prefix, vendor_str) && !android::base::StartsWith(config->prefix, vendor_alt_str) && !android::base::StartsWith(config->prefix, oem_str) && !android::base::StartsWith(config->prefix, oem_alt_str) && !android::base::StartsWith(config->prefix, odm_str) && !android::base::StartsWith(config->prefix, odm_alt_str)) { dirs.emplace_back(*config); } ++config; } confirm(popenToString(android::base::StringPrintf( "%s -D -P -vendor,-oem,-odm", fs_config_generate_command)), &dirs[0], dirs.size()); } TEST(fs_conf_test, vendor_dirs) { std::vector<fs_path_config> dirs; const fs_path_config* config = android_device_dirs; for (size_t num = arraysize(android_device_dirs); num; --num) { if (android::base::StartsWith(config->prefix, vendor_str) || android::base::StartsWith(config->prefix, vendor_alt_str)) { dirs.emplace_back(*config); } ++config; } confirm(popenToString(android::base::StringPrintf( "%s -D -P vendor", fs_config_generate_command)), &dirs[0], dirs.size()); } TEST(fs_conf_test, oem_dirs) { std::vector<fs_path_config> dirs; const fs_path_config* config = android_device_dirs; for (size_t num = arraysize(android_device_dirs); num; --num) { if (android::base::StartsWith(config->prefix, oem_str) || android::base::StartsWith(config->prefix, oem_alt_str)) { dirs.emplace_back(*config); } ++config; } confirm(popenToString(android::base::StringPrintf( "%s -D -P oem", fs_config_generate_command)), &dirs[0], dirs.size()); } TEST(fs_conf_test, odm_dirs) { std::vector<fs_path_config> dirs; const fs_path_config* config = android_device_dirs; for (size_t num = arraysize(android_device_dirs); num; --num) { if (android::base::StartsWith(config->prefix, odm_str) || android::base::StartsWith(config->prefix, odm_alt_str)) { dirs.emplace_back(*config); } ++config; } confirm(popenToString(android::base::StringPrintf( "%s -D -P odm", fs_config_generate_command)), &dirs[0], dirs.size()); } TEST(fs_conf_test, system_files) { std::vector<fs_path_config> files; const fs_path_config* config = android_device_files; for (size_t num = arraysize(android_device_files); num; --num) { if (!android::base::StartsWith(config->prefix, vendor_str) && !android::base::StartsWith(config->prefix, vendor_alt_str) && !android::base::StartsWith(config->prefix, oem_str) && !android::base::StartsWith(config->prefix, oem_alt_str) && !android::base::StartsWith(config->prefix, odm_str) && !android::base::StartsWith(config->prefix, odm_alt_str)) { files.emplace_back(*config); } ++config; } confirm(popenToString(android::base::StringPrintf( "%s -F -P -vendor,-oem,-odm", fs_config_generate_command)), &files[0], files.size()); } TEST(fs_conf_test, vendor_files) { std::vector<fs_path_config> files; const fs_path_config* config = android_device_files; for (size_t num = arraysize(android_device_files); num; --num) { if (android::base::StartsWith(config->prefix, vendor_str) || android::base::StartsWith(config->prefix, vendor_alt_str)) { files.emplace_back(*config); } ++config; } confirm(popenToString(android::base::StringPrintf( "%s -F -P vendor", fs_config_generate_command)), &files[0], files.size()); } TEST(fs_conf_test, oem_files) { std::vector<fs_path_config> files; const fs_path_config* config = android_device_files; for (size_t num = arraysize(android_device_files); num; --num) { if (android::base::StartsWith(config->prefix, oem_str) || android::base::StartsWith(config->prefix, oem_alt_str)) { files.emplace_back(*config); } ++config; } confirm(popenToString(android::base::StringPrintf( "%s -F -P oem", fs_config_generate_command)), &files[0], files.size()); } TEST(fs_conf_test, odm_files) { std::vector<fs_path_config> files; const fs_path_config* config = android_device_files; for (size_t num = arraysize(android_device_files); num; --num) { if (android::base::StartsWith(config->prefix, odm_str) || android::base::StartsWith(config->prefix, odm_alt_str)) { files.emplace_back(*config); } ++config; } confirm(popenToString(android::base::StringPrintf( "%s -F -P odm", fs_config_generate_command)), &files[0], files.size()); } Loading
tools/fs_config/Android.mk +145 −2 Original line number Diff line number Diff line Loading @@ -113,6 +113,11 @@ LOCAL_C_INCLUDES := $(dir $(my_fs_config_h)) $(dir $(my_gen_oem_aid)) include $(BUILD_HOST_EXECUTABLE) fs_config_generate_bin := $(LOCAL_INSTALLED_MODULE) # List of all supported vendor, oem and odm Partitions fs_config_generate_extra_partition_list := $(strip \ $(if $(BOARD_USES_VENDORIMAGE)$(BOARD_VENDORIMAGE_FILE_SYSTEM_TYPE),vendor) \ $(if $(BOARD_USES_OEMIMAGE)$(BOARD_OEMIMAGE_FILE_SYSTEM_TYPE),oem) \ $(if $(BOARD_USES_ODMIMAGE)$(BOARD_ODMIMAGE_FILE_SYSTEM_TYPE),odm)) ################################## # Generate the system/etc/fs_config_dirs binary file for the target Loading @@ -121,10 +126,13 @@ include $(CLEAR_VARS) LOCAL_MODULE := fs_config_dirs LOCAL_MODULE_CLASS := ETC LOCAL_REQUIRED_MODULES := $(foreach t,$(fs_config_generate_extra_partion_list),$(LOCAL_MODULE)_$(t)) include $(BUILD_SYSTEM)/base_rules.mk $(LOCAL_BUILT_MODULE): $(fs_config_generate_bin) @mkdir -p $(dir $@) $< -D -o $@ $< -D $(if $(fs_config_generate_extra_partition_list), \ -P '$(subst $(space),$(comma),$(addprefix -,$(fs_config_generate_extra_partition_list)))') \ -o $@ ################################## # Generate the system/etc/fs_config_files binary file for the target Loading @@ -133,10 +141,112 @@ include $(CLEAR_VARS) LOCAL_MODULE := fs_config_files LOCAL_MODULE_CLASS := ETC LOCAL_REQUIRED_MODULES := $(foreach t,$(fs_config_generate_extra_partion_list),$(LOCAL_MODULE)_$(t)) include $(BUILD_SYSTEM)/base_rules.mk $(LOCAL_BUILT_MODULE): $(fs_config_generate_bin) @mkdir -p $(dir $@) $< -F -o $@ $< -F $(if $(fs_config_generate_extra_partition_list), \ -P '$(subst $(space),$(comma),$(addprefix -,$(fs_config_generate_extra_partition_list)))') \ -o $@ ifneq ($(filter vendor,$(fs_config_generate_extra_partition_list)),) ################################## # Generate the vendor/etc/fs_config_dirs binary file for the target # Add fs_config_dirs or fs_config_dirs_vendor to PRODUCT_PACKAGES in # the device make file to enable. include $(CLEAR_VARS) LOCAL_MODULE := fs_config_dirs_vendor LOCAL_MODULE_CLASS := ETC LOCAL_INSTALLED_MODULE_STEM := fs_config_dirs LOCAL_MODULE_PATH := $(TARGET_OUT_VENDOR)/etc include $(BUILD_SYSTEM)/base_rules.mk $(LOCAL_BUILT_MODULE): $(fs_config_generate_bin) @mkdir -p $(dir $@) $< -D -P vendor -o $@ ################################## # Generate the vendor/etc/fs_config_files binary file for the target # Add fs_config_files or fs_config_files_vendor to PRODUCT_PACKAGES in # the device make file to enable include $(CLEAR_VARS) LOCAL_MODULE := fs_config_files_vendor LOCAL_MODULE_CLASS := ETC LOCAL_INSTALLED_MODULE_STEM := fs_config_files LOCAL_MODULE_PATH := $(TARGET_OUT_VENDOR)/etc include $(BUILD_SYSTEM)/base_rules.mk $(LOCAL_BUILT_MODULE): $(fs_config_generate_bin) @mkdir -p $(dir $@) $< -F -P vendor -o $@ endif ifneq ($(filter oem,$(fs_config_generate_extra_partition_list)),) ################################## # Generate the oem/etc/fs_config_dirs binary file for the target # Add fs_config_dirs or fs_config_dirs_oem to PRODUCT_PACKAGES in # the device make file to enable include $(CLEAR_VARS) LOCAL_MODULE := fs_config_dirs_oem LOCAL_MODULE_CLASS := ETC LOCAL_INSTALLED_MODULE_STEM := fs_config_dirs LOCAL_MODULE_PATH := $(TARGET_OUT_OEM)/etc include $(BUILD_SYSTEM)/base_rules.mk $(LOCAL_BUILT_MODULE): $(fs_config_generate_bin) @mkdir -p $(dir $@) $< -D -P oem -o $@ ################################## # Generate the oem/etc/fs_config_files binary file for the target # Add fs_config_files or fs_config_files_oem to PRODUCT_PACKAGES in # the device make file to enable include $(CLEAR_VARS) LOCAL_MODULE := fs_config_files_oem LOCAL_MODULE_CLASS := ETC LOCAL_INSTALLED_MODULE_STEM := fs_config_files LOCAL_MODULE_PATH := $(TARGET_OUT_OEM)/etc include $(BUILD_SYSTEM)/base_rules.mk $(LOCAL_BUILT_MODULE): $(fs_config_generate_bin) @mkdir -p $(dir $@) $< -F -P oem -o $@ endif ifneq ($(filter odm,$(fs_config_generate_extra_partition_list)),) ################################## # Generate the odm/etc/fs_config_dirs binary file for the target # Add fs_config_dirs or fs_config_dirs_odm to PRODUCT_PACKAGES in # the device make file to enable include $(CLEAR_VARS) LOCAL_MODULE := fs_config_dirs_odm LOCAL_MODULE_CLASS := ETC LOCAL_INSTALLED_MODULE_STEM := fs_config_dirs LOCAL_MODULE_PATH := $(TARGET_OUT_ODM)/etc include $(BUILD_SYSTEM)/base_rules.mk $(LOCAL_BUILT_MODULE): $(fs_config_generate_bin) @mkdir -p $(dir $@) $< -D -P odm -o $@ ################################## # Generate the odm/etc/fs_config_files binary file for the target # Add fs_config_files of fs_config_files_odm to PRODUCT_PACKAGES in # the device make file to enable include $(CLEAR_VARS) LOCAL_MODULE := fs_config_files_odm LOCAL_MODULE_CLASS := ETC LOCAL_INSTALLED_MODULE_STEM := fs_config_files LOCAL_MODULE_PATH := $(TARGET_OUT_ODM)/etc include $(BUILD_SYSTEM)/base_rules.mk $(LOCAL_BUILT_MODULE): $(fs_config_generate_bin) @mkdir -p $(dir $@) $< -F -P odm -o $@ endif # The newer passwd/group targets are only generated if you # use the new TARGET_FS_CONFIG_GEN method. Loading Loading @@ -195,3 +305,36 @@ ANDROID_FS_CONFIG_H := my_fs_config_h := fs_config_generate_bin := my_gen_oem_aid := # ----------------------------------------------------------------------------- # Unit tests. # ----------------------------------------------------------------------------- test_c_flags := \ -fstack-protector-all \ -g \ -Wall \ -Wextra \ -Werror \ -fno-builtin \ -DANDROID_FILESYSTEM_CONFIG='"android_filesystem_config_test_data.h"' ################################## # test executable include $(CLEAR_VARS) LOCAL_MODULE := fs_config_generate_test LOCAL_SRC_FILES := fs_config_generate.c LOCAL_SHARED_LIBRARIES := libcutils LOCAL_CFLAGS := $(test_c_flags) LOCAL_MODULE_RELATIVE_PATH := fs_config-unit-tests LOCAL_GTEST := false include $(BUILD_HOST_NATIVE_TEST) ################################## # gTest tool include $(CLEAR_VARS) LOCAL_MODULE := fs_config-unit-tests LOCAL_CFLAGS += $(test_c_flags) -DHOST LOCAL_SHARED_LIBRARIES := liblog libcutils libbase LOCAL_SRC_FILES := fs_config_test.cpp include $(BUILD_HOST_NATIVE_TEST)
tools/fs_config/README +21 −2 Original line number Diff line number Diff line Loading @@ -156,9 +156,28 @@ properties are preserved during runtime operations. The host files in the ${OUT} directory are used in the final stages when building the filesystem images to set the file and directory properties. For systems with separate partition images, such as vendor or oem, fs_config_generate can be instructed to filter the specific file references to land in each partition's etc/fs_config_dirs or etc/fs_config_files locations. The filter can be instructed to blacklist a partition's data by providing the comma separated minus sign prefixed partition names. The filter can be instructed to whitelist partition data by providing the partition name. For example: - For system.img, but not vendor, oem or odm file references: -P -vendor,-oem,-odm This makes sure the results only contain content associated with the system, and not vendor, oem or odm, blacklisting their content. - For vendor.img file references: -P vendor - For oem.img file references: -P oem - For odm.img file references: -P odm fs_config_generate --help reports: Generate binary content for fs_config_dirs (-D) and fs_config_files (-F) from device-specific android_filesystem_config.h override from device-specific android_filesystem_config.h override. Filter based on a comma separated partition list (-P) whitelist or prefixed by a minus blacklist. Partitions are identified as path references to <partition>/ or system/<partition> Usage: fs_config_generate -D|-F [-o output-file] Usage: fs_config_generate -D|-F [-P list] [-o output-file]
tools/fs_config/android_filesystem_config_test_data.h 0 → 100644 +56 −0 Original line number Diff line number Diff line /* * Copyright (C) 2017 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 <private/android_filesystem_config.h> /* Test Data */ #undef NO_ANDROID_FILESYSTEM_CONFIG_DEVICE_DIRS #undef NO_ANDROID_FILESYSTEM_CONFIG_DEVICE_FILES static const struct fs_path_config android_device_dirs[] = { {00555, AID_ROOT, AID_SYSTEM, 0, "system/etc"}, {00555, AID_ROOT, AID_SYSTEM, 0, "vendor/etc"}, {00555, AID_ROOT, AID_SYSTEM, 0, "oem/etc"}, {00555, AID_ROOT, AID_SYSTEM, 0, "odm/etc"}, {00755, AID_SYSTEM, AID_ROOT, 0, "system/oem/etc"}, {00755, AID_SYSTEM, AID_ROOT, 0, "system/odm/etc"}, {00755, AID_SYSTEM, AID_ROOT, 0, "system/vendor/etc"}, {00755, AID_SYSTEM, AID_ROOT, 0, "data/misc"}, {00755, AID_SYSTEM, AID_ROOT, 0, "oem/data/misc"}, {00755, AID_SYSTEM, AID_ROOT, 0, "odm/data/misc"}, {00755, AID_SYSTEM, AID_ROOT, 0, "vendor/data/misc"}, {00555, AID_SYSTEM, AID_ROOT, 0, "etc"}, }; static const struct fs_path_config android_device_files[] = { {00444, AID_ROOT, AID_SYSTEM, 0, "system/etc/fs_config_dirs"}, {00444, AID_ROOT, AID_SYSTEM, 0, "vendor/etc/fs_config_dirs"}, {00444, AID_ROOT, AID_SYSTEM, 0, "oem/etc/fs_config_dirs"}, {00444, AID_ROOT, AID_SYSTEM, 0, "odm/etc/fs_config_dirs"}, {00444, AID_ROOT, AID_SYSTEM, 0, "system/etc/fs_config_files"}, {00444, AID_ROOT, AID_SYSTEM, 0, "vendor/etc/fs_config_files"}, {00444, AID_ROOT, AID_SYSTEM, 0, "oem/etc/fs_config_files"}, {00444, AID_ROOT, AID_SYSTEM, 0, "odm/etc/fs_config_files"}, {00644, AID_SYSTEM, AID_ROOT, 0, "system/vendor/etc/fs_config_dirs"}, {00644, AID_SYSTEM, AID_ROOT, 0, "system/oem/etc/fs_config_dirs"}, {00644, AID_SYSTEM, AID_ROOT, 0, "system/odm/etc/fs_config_dirs"}, {00644, AID_SYSTEM, AID_ROOT, 0, "system/vendor/etc/fs_config_files"}, {00644, AID_SYSTEM, AID_ROOT, 0, "system/oem/etc/fs_config_files"}, {00644, AID_SYSTEM, AID_ROOT, 0, "system/odm/etc/fs_config_files"}, {00644, AID_SYSTEM, AID_ROOT, 0, "etc/fs_config_files"}, {00666, AID_ROOT, AID_SYSTEM, 0, "data/misc/oem"}, };
tools/fs_config/fs_config_generate.c +111 −15 Original line number Diff line number Diff line Loading @@ -14,9 +14,11 @@ * limitations under the License. */ #include <ctype.h> #include <stdbool.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <private/android_filesystem_config.h> Loading @@ -28,37 +30,56 @@ * the binary format used in the /system/etc/fs_config_dirs and * the /system/etc/fs_config_files to be used by the runtimes. */ #ifdef ANDROID_FILESYSTEM_CONFIG #include ANDROID_FILESYSTEM_CONFIG #else #include "android_filesystem_config.h" #endif #ifdef NO_ANDROID_FILESYSTEM_CONFIG_DEVICE_DIRS static const struct fs_path_config android_device_dirs[] = { }; static const struct fs_path_config android_device_dirs[] = { }; #endif #ifdef NO_ANDROID_FILESYSTEM_CONFIG_DEVICE_FILES static const struct fs_path_config android_device_files[] = { #ifdef NO_ANDROID_FILESYSTEM_CONFIG_DEVICE_DIRS { 0, AID_ROOT, AID_ROOT, 0, "system/etc/fs_config_dirs" }, {0000, AID_ROOT, AID_ROOT, 0, "system/etc/fs_config_dirs"}, {0000, AID_ROOT, AID_ROOT, 0, "vendor/etc/fs_config_dirs"}, {0000, AID_ROOT, AID_ROOT, 0, "oem/etc/fs_config_dirs"}, {0000, AID_ROOT, AID_ROOT, 0, "odm/etc/fs_config_dirs"}, #endif { 0, AID_ROOT, AID_ROOT, 0, "system/etc/fs_config_files" }, {0000, AID_ROOT, AID_ROOT, 0, "system/etc/fs_config_files"}, {0000, AID_ROOT, AID_ROOT, 0, "vendor/etc/fs_config_files"}, {0000, AID_ROOT, AID_ROOT, 0, "oem/etc/fs_config_files"}, {0000, AID_ROOT, AID_ROOT, 0, "odm/etc/fs_config_files"}, }; #endif static void usage() { fprintf(stderr, "Generate binary content for fs_config_dirs (-D) and fs_config_files (-F)\n" "from device-specific android_filesystem_config.h override\n\n" "Usage: fs_config_generate -D|-F [-o output-file]\n"); "from device-specific android_filesystem_config.h override. Filter based\n" "on a comma separated partition list (-P) whitelist or prefixed by a\n" "minus blacklist. Partitions are identified as path references to\n" "<partition>/ or system/<partition>/\n\n" "Usage: fs_config_generate -D|-F [-P list] [-o output-file]\n"); } /* If tool switches to C++, use android-base/macros.h array_size() */ #ifndef ARRAY_SIZE /* popular macro */ #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) #endif int main(int argc, char** argv) { const struct fs_path_config* pc; const struct fs_path_config* end; bool dir = false, file = false; const char* partitions = NULL; FILE* fp = stdout; int opt; static const char optstring[] = "DFP:ho:"; while((opt = getopt(argc, argv, "DFho:")) != -1) { while ((opt = getopt(argc, argv, optstring)) != -1) { switch (opt) { case 'D': if (file) { Loading @@ -76,6 +97,30 @@ int main(int argc, char** argv) { } file = true; break; case 'P': if (partitions) { fprintf(stderr, "Specify only one partition list\n"); usage(); exit(EXIT_FAILURE); } while (*optarg && isspace(*optarg)) ++optarg; if (!optarg[0]) { fprintf(stderr, "Partition list empty\n"); usage(); exit(EXIT_FAILURE); } if (!optarg[1]) { fprintf(stderr, "Partition list too short \"%s\"\n", optarg); usage(); exit(EXIT_FAILURE); } if ((optarg[0] == '-') && strchr(optstring, optarg[1]) && !optarg[2]) { fprintf(stderr, "Partition list is a flag \"%s\"\n", optarg); usage(); exit(EXIT_FAILURE); } partitions = optarg; break; case 'o': if (fp != stdout) { fprintf(stderr, "Specify only one output file\n"); Loading @@ -97,6 +142,12 @@ int main(int argc, char** argv) { } } if (optind < argc) { fprintf(stderr, "Unknown non-argument \"%s\"\n", argv[optind]); usage(); exit(EXIT_FAILURE); } if (!file && !dir) { fprintf(stderr, "Must specify either -F or -D\n"); usage(); Loading @@ -105,19 +156,64 @@ int main(int argc, char** argv) { if (dir) { pc = android_device_dirs; end = &android_device_dirs[sizeof(android_device_dirs) / sizeof(android_device_dirs[0])]; end = &android_device_dirs[ARRAY_SIZE(android_device_dirs)]; } else { pc = android_device_files; end = &android_device_files[sizeof(android_device_files) / sizeof(android_device_files[0])]; end = &android_device_files[ARRAY_SIZE(android_device_files)]; } for (; (pc < end) && pc->prefix; pc++) { bool submit; char buffer[512]; ssize_t len = fs_config_generate(buffer, sizeof(buffer), pc); if (len < 0) { fprintf(stderr, "Entry too large\n"); exit(EXIT_FAILURE); } if (fwrite(buffer, 1, len, fp) != (size_t)len) { submit = true; if (partitions) { char* partitions_copy = strdup(partitions); char* arg = partitions_copy; char* sv = NULL; /* Do not leave uninitialized, NULL is known safe. */ /* Deal with case all iterated partitions are blacklists with no match */ bool all_blacklist_but_no_match = true; submit = false; if (!partitions_copy) { fprintf(stderr, "Failed to allocate a copy of %s\n", partitions); exit(EXIT_FAILURE); } /* iterate through (officially) comma separated list of partitions */ while (!!(arg = strtok_r(arg, ",:; \t\n\r\f", &sv))) { static const char system[] = "system/"; size_t plen; bool blacklist = false; if (*arg == '-') { blacklist = true; ++arg; } else { all_blacklist_but_no_match = false; } plen = strlen(arg); /* deal with evil callers */ while (arg[plen - 1] == '/') { --plen; } /* check if we have <partition>/ or /system/<partition>/ */ if ((!strncmp(pc->prefix, arg, plen) && (pc->prefix[plen] == '/')) || (!strncmp(pc->prefix, system, strlen(system)) && !strncmp(pc->prefix + strlen(system), arg, plen) && (pc->prefix[strlen(system) + plen] == '/'))) { all_blacklist_but_no_match = false; /* we have a match !!! */ if (!blacklist) submit = true; break; } arg = NULL; } free(partitions_copy); if (all_blacklist_but_no_match) submit = true; } if (submit && (fwrite(buffer, 1, len, fp) != (size_t)len)) { fprintf(stderr, "Write failure\n"); exit(EXIT_FAILURE); } Loading
tools/fs_config/fs_config_test.cpp 0 → 100644 +223 −0 Original line number Diff line number Diff line /* * Copyright (C) 2017 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 <stdio.h> #include <sys/cdefs.h> #include <string> #include <vector> #include <android-base/file.h> #include <android-base/macros.h> #include <android-base/strings.h> #include <android-base/stringprintf.h> #include <gtest/gtest.h> #include <private/android_filesystem_config.h> #include <private/fs_config.h> #include "android_filesystem_config_test_data.h" // must run test in the test directory const static char fs_config_generate_command[] = "./fs_config_generate_test"; static std::string popenToString(std::string command) { std::string ret; FILE* fp = popen(command.c_str(), "r"); if (fp) { if (!android::base::ReadFdToString(fileno(fp), &ret)) ret = ""; pclose(fp); } return ret; } static void confirm(std::string&& data, const fs_path_config* config, ssize_t num_config) { const struct fs_path_config_from_file* pc = reinterpret_cast<const fs_path_config_from_file*>(data.c_str()); size_t len = data.size(); ASSERT_TRUE(config != NULL); ASSERT_LT(0, num_config); while (len > 0) { uint16_t host_len = pc->len; if (host_len > len) break; EXPECT_EQ(config->mode, pc->mode); EXPECT_EQ(config->uid, pc->uid); EXPECT_EQ(config->gid, pc->gid); EXPECT_EQ(config->capabilities, pc->capabilities); EXPECT_STREQ(config->prefix, pc->prefix); EXPECT_LT(0, num_config); --num_config; if (num_config >= 0) ++config; pc = reinterpret_cast<const fs_path_config_from_file*>( reinterpret_cast<const char*>(pc) + host_len); len -= host_len; } EXPECT_EQ(0, num_config); } /* See local android_filesystem_config.h for test data */ TEST(fs_conf_test, dirs) { confirm(popenToString( android::base::StringPrintf("%s -D", fs_config_generate_command)), android_device_dirs, arraysize(android_device_dirs)); } TEST(fs_conf_test, files) { confirm(popenToString( android::base::StringPrintf("%s -F", fs_config_generate_command)), android_device_files, arraysize(android_device_files)); } static const char vendor_str[] = "vendor/"; static const char vendor_alt_str[] = "system/vendor/"; static const char oem_str[] = "oem/"; static const char oem_alt_str[] = "system/oem/"; static const char odm_str[] = "odm/"; static const char odm_alt_str[] = "system/odm/"; TEST(fs_conf_test, system_dirs) { std::vector<fs_path_config> dirs; const fs_path_config* config = android_device_dirs; for (size_t num = arraysize(android_device_dirs); num; --num) { if (!android::base::StartsWith(config->prefix, vendor_str) && !android::base::StartsWith(config->prefix, vendor_alt_str) && !android::base::StartsWith(config->prefix, oem_str) && !android::base::StartsWith(config->prefix, oem_alt_str) && !android::base::StartsWith(config->prefix, odm_str) && !android::base::StartsWith(config->prefix, odm_alt_str)) { dirs.emplace_back(*config); } ++config; } confirm(popenToString(android::base::StringPrintf( "%s -D -P -vendor,-oem,-odm", fs_config_generate_command)), &dirs[0], dirs.size()); } TEST(fs_conf_test, vendor_dirs) { std::vector<fs_path_config> dirs; const fs_path_config* config = android_device_dirs; for (size_t num = arraysize(android_device_dirs); num; --num) { if (android::base::StartsWith(config->prefix, vendor_str) || android::base::StartsWith(config->prefix, vendor_alt_str)) { dirs.emplace_back(*config); } ++config; } confirm(popenToString(android::base::StringPrintf( "%s -D -P vendor", fs_config_generate_command)), &dirs[0], dirs.size()); } TEST(fs_conf_test, oem_dirs) { std::vector<fs_path_config> dirs; const fs_path_config* config = android_device_dirs; for (size_t num = arraysize(android_device_dirs); num; --num) { if (android::base::StartsWith(config->prefix, oem_str) || android::base::StartsWith(config->prefix, oem_alt_str)) { dirs.emplace_back(*config); } ++config; } confirm(popenToString(android::base::StringPrintf( "%s -D -P oem", fs_config_generate_command)), &dirs[0], dirs.size()); } TEST(fs_conf_test, odm_dirs) { std::vector<fs_path_config> dirs; const fs_path_config* config = android_device_dirs; for (size_t num = arraysize(android_device_dirs); num; --num) { if (android::base::StartsWith(config->prefix, odm_str) || android::base::StartsWith(config->prefix, odm_alt_str)) { dirs.emplace_back(*config); } ++config; } confirm(popenToString(android::base::StringPrintf( "%s -D -P odm", fs_config_generate_command)), &dirs[0], dirs.size()); } TEST(fs_conf_test, system_files) { std::vector<fs_path_config> files; const fs_path_config* config = android_device_files; for (size_t num = arraysize(android_device_files); num; --num) { if (!android::base::StartsWith(config->prefix, vendor_str) && !android::base::StartsWith(config->prefix, vendor_alt_str) && !android::base::StartsWith(config->prefix, oem_str) && !android::base::StartsWith(config->prefix, oem_alt_str) && !android::base::StartsWith(config->prefix, odm_str) && !android::base::StartsWith(config->prefix, odm_alt_str)) { files.emplace_back(*config); } ++config; } confirm(popenToString(android::base::StringPrintf( "%s -F -P -vendor,-oem,-odm", fs_config_generate_command)), &files[0], files.size()); } TEST(fs_conf_test, vendor_files) { std::vector<fs_path_config> files; const fs_path_config* config = android_device_files; for (size_t num = arraysize(android_device_files); num; --num) { if (android::base::StartsWith(config->prefix, vendor_str) || android::base::StartsWith(config->prefix, vendor_alt_str)) { files.emplace_back(*config); } ++config; } confirm(popenToString(android::base::StringPrintf( "%s -F -P vendor", fs_config_generate_command)), &files[0], files.size()); } TEST(fs_conf_test, oem_files) { std::vector<fs_path_config> files; const fs_path_config* config = android_device_files; for (size_t num = arraysize(android_device_files); num; --num) { if (android::base::StartsWith(config->prefix, oem_str) || android::base::StartsWith(config->prefix, oem_alt_str)) { files.emplace_back(*config); } ++config; } confirm(popenToString(android::base::StringPrintf( "%s -F -P oem", fs_config_generate_command)), &files[0], files.size()); } TEST(fs_conf_test, odm_files) { std::vector<fs_path_config> files; const fs_path_config* config = android_device_files; for (size_t num = arraysize(android_device_files); num; --num) { if (android::base::StartsWith(config->prefix, odm_str) || android::base::StartsWith(config->prefix, odm_alt_str)) { files.emplace_back(*config); } ++config; } confirm(popenToString(android::base::StringPrintf( "%s -F -P odm", fs_config_generate_command)), &files[0], files.size()); }