From 2d9ffb62a307ca6eabc5c0c8a297b3cc89de7850 Mon Sep 17 00:00:00 2001 From: Zhomart Mukhamejanov Date: Thu, 14 Jun 2018 16:42:05 -0700 Subject: updater_sample: run as a systemp app Android.mk: remove local tags, make privileged module AndroidManifest.xml: add access cache filesystem Test: on device Test: junit4 Change-Id: I611970747b7b630520249dd53105b9a2f7f76355 Signed-off-by: Zhomart Mukhamejanov --- updater_sample/Android.mk | 2 +- updater_sample/AndroidManifest.xml | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/updater_sample/Android.mk b/updater_sample/Android.mk index 463dbb32d..cff5b0c1f 100644 --- a/updater_sample/Android.mk +++ b/updater_sample/Android.mk @@ -18,8 +18,8 @@ LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_PACKAGE_NAME := SystemUpdaterSample -LOCAL_MODULE_TAGS := samples LOCAL_SDK_VERSION := system_current +LOCAL_PRIVILEGED_MODULE := true LOCAL_PROGUARD_FLAG_FILES := proguard.flags diff --git a/updater_sample/AndroidManifest.xml b/updater_sample/AndroidManifest.xml index 4b4448438..18d8425e1 100644 --- a/updater_sample/AndroidManifest.xml +++ b/updater_sample/AndroidManifest.xml @@ -19,6 +19,8 @@ + + Date: Wed, 13 Jun 2018 16:14:18 -0700 Subject: updater_sample: add privileged system app docs README.md: add instructions Test: on device Bug: 80250430 Change-Id: I2e04fdefda2b73d01dfa0a8e684542feb2ed6c61 Signed-off-by: Zhomart Mukhamejanov --- updater_sample/README.md | 82 +++++++++++++++------- .../tests/res/raw/update_config_002_stream.json | 2 +- .../tests/res/raw/update_config_003_nonstream.json | 2 +- 3 files changed, 57 insertions(+), 29 deletions(-) diff --git a/updater_sample/README.md b/updater_sample/README.md index 11b55eb91..f6a2a044b 100644 --- a/updater_sample/README.md +++ b/updater_sample/README.md @@ -31,7 +31,7 @@ The directory can be found in logs or on the UI. In most cases it should be loca `/data/user/0/com.example.android.systemupdatersample/files/configs/`. SystemUpdaterSample app downloads OTA package from `url`. In this sample app -`url` is expected to point to file system, e.g. `file:///data/sample-builds/ota-002.zip`. +`url` is expected to point to file system, e.g. `file:///data/my-sample-ota-builds-dir/ota-002.zip`. If `ab_install_type` is `NON_STREAMING` then app checks if `url` starts with `file://` and passes `url` to the `update_engine`. @@ -52,19 +52,6 @@ Config files can be generated using `tools/gen_update_config.py`. Running `./tools/gen_update_config.py --help` shows usage of the script. -## Running on a device - -The commands expected to be run from `$ANDROID_BUILD_TOP` and for demo -purpose only. - -1. Compile the app `$ mmma bootable/recovery/updater_sample`. -2. Install the app to the device using `$ adb install `. -3. Change permissions on `/data/ota_package/` to `0777` on the device. -4. Set SELinux mode to permissive. See instructions below. -5. Add update config files. -6. Push OTA packages to the device. - - ## Sample App State vs UpdateEngine Status UpdateEngine provides status for different stages of update application @@ -165,7 +152,54 @@ except when update_engine fails to initialize. ### Callback: onPayloadApplicationComplete -Called whenever an update attempt is completed. +Called whenever an update attempt is completed or failed. + + +## Running on a device + +The commands are expected to be run from `$ANDROID_BUILD_TOP` and for demo +purpose only. + +### Without the privileged system permissions + +1. Compile the app `mmma -j bootable/recovery/updater_sample`. +2. Install the app to the device using `adb install `. +3. Change permissions on `/data/ota_package/` to `0777` on the device. +4. Set SELinux mode to permissive. See instructions below. +5. Add update config files; look above at [Update Config file](#Update-Config-file). +6. Push OTA packages to the device. +7. Run the sample app. + +### With the privileged system permissions + +To run sample app as a privileged system app, it needs to be installed in `/system/priv-app/`. +This directory is expected to be read-only, unless explicitly remounted. + +The recommended way to run the app is to build and install it as a +privileged system app, so it's granted the required permissions to access +`update_engine` service as well as OTA package files. Detailed steps are as follows: + +1. [Prepare to build](https://source.android.com/setup/build/building) +2. Add the module (SystemUpdaterSample) to the `PRODUCT_PACKAGES` list for the lunch target. + e.g. add a line containing `PRODUCT_PACKAGES += SystemUpdaterSample` + to `device/google/marlin/device-common.mk`. +3. [Whitelist the sample app](https://source.android.com/devices/tech/config/perms-whitelist) + * Add + ``` + + + + ``` + to `frameworks/base/data/etc/privapp-permissions-platform.xml` +5. Build sample app `mmma -j bootable/recovery/updater_sample`. +6. Build Android `make -j` +7. [Flash the device](https://source.android.com/setup/build/running) +8. Add update config files; look above at `## Update Config file`; + `adb root` might be required. +9. Push OTA packages to the device if there is no server to stream packages from; + changing of SELinux labels of OTA packages directory might be required + `chcon -R u:object_r:ota_package_file:s0 /data/my-sample-ota-builds-dir` +10. Run the sample app. ## Development @@ -192,16 +226,16 @@ Called whenever an update attempt is completed. ## Running tests -1. Build `$ mmma bootable/recovery/updater_sample/` +1. Build `mmma bootable/recovery/updater_sample/` 2. Install app - `$ adb install $OUT/system/app/SystemUpdaterSample/SystemUpdaterSample.apk` + `adb install $OUT/system/app/SystemUpdaterSample/SystemUpdaterSample.apk` 3. Install tests - `$ adb install $OUT/testcases/SystemUpdaterSampleTests/SystemUpdaterSampleTests.apk` + `adb install $OUT/testcases/SystemUpdaterSampleTests/SystemUpdaterSampleTests.apk` 4. Run tests - `$ adb shell am instrument -w com.example.android.systemupdatersample.tests/android.support.test.runner.AndroidJUnitRunner` + `adb shell am instrument -w com.example.android.systemupdatersample.tests/android.support.test.runner.AndroidJUnitRunner` 5. Run a test file ``` - $ adb shell am instrument \ + adb shell am instrument \ -w com.example.android.systemupdatersample.tests/android.support.test.runner.AndroidJUnitRunner \ -c com.example.android.systemupdatersample.util.PayloadSpecsTest ``` @@ -214,13 +248,7 @@ Called whenever an update attempt is completed. ## Getting read/write access to `/data/ota_package/` -Following must be included in `AndroidManifest.xml`: - -```xml - -``` - -Note: access to cache filesystem is granted only to system apps. +Access to cache filesystem is granted only to system apps. ## Setting SELinux mode to permissive (0) diff --git a/updater_sample/tests/res/raw/update_config_002_stream.json b/updater_sample/tests/res/raw/update_config_002_stream.json index 5d7874cdb..40c8fe1c1 100644 --- a/updater_sample/tests/res/raw/update_config_002_stream.json +++ b/updater_sample/tests/res/raw/update_config_002_stream.json @@ -39,5 +39,5 @@ ] }, "name": "S ota_002_package", - "url": "file:///data/sample-ota-packages/ota_002_package.zip" + "url": "file:///data/my-sample-ota-builds-dir/ota_002_package.zip" } \ No newline at end of file diff --git a/updater_sample/tests/res/raw/update_config_003_nonstream.json b/updater_sample/tests/res/raw/update_config_003_nonstream.json index 4175c35ea..7c78b9d21 100644 --- a/updater_sample/tests/res/raw/update_config_003_nonstream.json +++ b/updater_sample/tests/res/raw/update_config_003_nonstream.json @@ -5,5 +5,5 @@ }, "ab_install_type": "NON_STREAMING", "name": "S ota_002_package", - "url": "file:///data/sample-ota-packages/ota_003_package.zip" + "url": "file:///data/my-sample-ota-builds-dir/ota_003_package.zip" } \ No newline at end of file -- cgit v1.2.3 From 0a883c18f6063ba088e7eca327e330ae07b539a7 Mon Sep 17 00:00:00 2001 From: Tao Bao Date: Mon, 18 Jun 2018 12:49:06 -0700 Subject: updater: Defer the creation of the new data writer. This avoids leaving the created new data writer thread unjoined, in the presence of transfer list parsing errors, or the early exit case on `total_blocks == 0`. Also fix a minor issue when dumping the errno on pthread_create error (pthread_create returns the error number, as opposed to setting errno). Test: Run recovery_component_test on marlin. Change-Id: Icfac27fef0c64736eb8c76264da73c223b4960cb --- updater/blockimg.cpp | 48 ++++++++++++++++++++++++------------------------ 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/updater/blockimg.cpp b/updater/blockimg.cpp index ff1d20a78..cdf24f8b1 100644 --- a/updater/blockimg.cpp +++ b/updater/blockimg.cpp @@ -1603,29 +1603,6 @@ static Value* PerformBlockImageUpdate(const char* name, State* state, } } - if (params.canwrite) { - params.nti.za = za; - params.nti.entry = new_entry; - params.nti.brotli_compressed = android::base::EndsWith(new_data_fn->data, ".br"); - if (params.nti.brotli_compressed) { - // Initialize brotli decoder state. - params.nti.brotli_decoder_state = BrotliDecoderCreateInstance(nullptr, nullptr, nullptr); - } - params.nti.receiver_available = true; - - pthread_mutex_init(¶ms.nti.mu, nullptr); - pthread_cond_init(¶ms.nti.cv, nullptr); - pthread_attr_t attr; - pthread_attr_init(&attr); - pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); - - int error = pthread_create(¶ms.thread, &attr, unzip_new_data, ¶ms.nti); - if (error != 0) { - PLOG(ERROR) << "pthread_create failed"; - return StringValue(""); - } - } - static constexpr size_t kTransferListHeaderLines = 4; std::vector lines = android::base::Split(transfer_list_value->data, "\n"); if (lines.size() < kTransferListHeaderLines) { @@ -1668,9 +1645,32 @@ static Value* PerformBlockImageUpdate(const char* name, State* state, if (res == -1) { return StringValue(""); } - params.createdstash = res; + // Set up the new data writer. + if (params.canwrite) { + params.nti.za = za; + params.nti.entry = new_entry; + params.nti.brotli_compressed = android::base::EndsWith(new_data_fn->data, ".br"); + if (params.nti.brotli_compressed) { + // Initialize brotli decoder state. + params.nti.brotli_decoder_state = BrotliDecoderCreateInstance(nullptr, nullptr, nullptr); + } + params.nti.receiver_available = true; + + pthread_mutex_init(¶ms.nti.mu, nullptr); + pthread_cond_init(¶ms.nti.cv, nullptr); + pthread_attr_t attr; + pthread_attr_init(&attr); + pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); + + int error = pthread_create(¶ms.thread, &attr, unzip_new_data, ¶ms.nti); + if (error != 0) { + LOG(ERROR) << "pthread_create failed: " << strerror(error); + return StringValue(""); + } + } + // When performing an update, save the index and cmdline of the current command into the // last_command_file. // Upon resuming an update, read the saved index first; then -- cgit v1.2.3 From cf60a44bd497599363c0efcab23eb6be376c741f Mon Sep 17 00:00:00 2001 From: Tao Bao Date: Mon, 18 Jun 2018 14:56:20 -0700 Subject: Drop the dependency on AB_OTA_UPDATER flag. This shortens the gap between A/B and non-A/B builds, by replacing the dependency on build-time flag with runtime detection instead. It also allows building and testing both paths regardless of the target OTA type. The size increase to /sbin/recovery looks negligible (< 0.01%). - marlin: increased from 2084928 to 2085024; - angler: increased from 2084776 to 2084896. Test: Run recovery_component_test on angler and marlin. Test: Sideload an A/B OTA package on marlin. Test: Sideload a non-A/B OTA package on angler. Change-Id: I1d927d1ede9713fb42f73b4fe324aa5705ee6f99 --- Android.mk | 4 - install.cpp | 39 ++++----- otautil/include/otautil/paths.h | 10 +++ otautil/paths.cpp | 4 +- private/install.h | 18 ++-- tests/Android.mk | 4 - tests/component/install_test.cpp | 174 +++++++++++++++++++-------------------- 7 files changed, 126 insertions(+), 127 deletions(-) diff --git a/Android.mk b/Android.mk index 24da8b28a..257564058 100644 --- a/Android.mk +++ b/Android.mk @@ -143,10 +143,6 @@ LOCAL_C_INCLUDES := \ LOCAL_CFLAGS := $(recovery_common_cflags) -ifeq ($(AB_OTA_UPDATER),true) - LOCAL_CFLAGS += -DAB_OTA_UPDATER=1 -endif - LOCAL_MODULE := librecovery LOCAL_STATIC_LIBRARIES := \ diff --git a/install.cpp b/install.cpp index a4c6986a6..800847fdb 100644 --- a/install.cpp +++ b/install.cpp @@ -45,6 +45,7 @@ #include #include #include +#include #include #include @@ -124,11 +125,9 @@ static void read_source_target_build(ZipArchiveHandle zip, std::vector* cmd) { CHECK(cmd != nullptr); int ret = check_newer_ab_build(zip); @@ -250,7 +248,7 @@ int update_binary_command(const std::string& package, ZipArchiveHandle zip, } long payload_offset = payload_entry.offset; *cmd = { - binary_path, + "/sbin/update_engine_sideload", "--payload=file://" + package, android::base::StringPrintf("--offset=%ld", payload_offset), "--headers=" + std::string(payload_properties.begin(), payload_properties.end()), @@ -259,14 +257,11 @@ int update_binary_command(const std::string& package, ZipArchiveHandle zip, return 0; } -#else // !AB_OTA_UPDATER - -int update_binary_command(const std::string& package, ZipArchiveHandle zip, - const std::string& binary_path, int retry_count, int status_fd, - std::vector* cmd) { +int SetUpNonAbUpdateCommands(const std::string& package, ZipArchiveHandle zip, int retry_count, + int status_fd, std::vector* cmd) { CHECK(cmd != nullptr); - // On traditional updates we extract the update binary from the package. + // In non-A/B updates we extract the update binary from the package. static constexpr const char* UPDATE_BINARY_NAME = "META-INF/com/google/android/update-binary"; ZipString binary_name(UPDATE_BINARY_NAME); ZipEntry binary_entry; @@ -275,15 +270,16 @@ int update_binary_command(const std::string& package, ZipArchiveHandle zip, return INSTALL_CORRUPT; } + const std::string binary_path = Paths::Get().temporary_update_binary(); unlink(binary_path.c_str()); - int fd = open(binary_path.c_str(), O_CREAT | O_WRONLY | O_TRUNC | O_CLOEXEC, 0755); + android::base::unique_fd fd( + open(binary_path.c_str(), O_CREAT | O_WRONLY | O_TRUNC | O_CLOEXEC, 0755)); if (fd == -1) { PLOG(ERROR) << "Failed to create " << binary_path; return INSTALL_ERROR; } int32_t error = ExtractEntryToFile(zip, &binary_entry, fd); - close(fd); if (error != 0) { LOG(ERROR) << "Failed to extract " << UPDATE_BINARY_NAME << ": " << ErrorCodeString(error); return INSTALL_ERROR; @@ -300,7 +296,6 @@ int update_binary_command(const std::string& package, ZipArchiveHandle zip, } return 0; } -#endif // !AB_OTA_UPDATER static void log_max_temperature(int* max_temperature, const std::atomic& logger_finished) { CHECK(max_temperature != nullptr); @@ -321,14 +316,10 @@ static int try_update_binary(const std::string& package, ZipArchiveHandle zip, b int pipefd[2]; pipe(pipefd); + bool is_ab = android::base::GetBoolProperty("ro.build.ab_update", false); std::vector args; -#ifdef AB_OTA_UPDATER - int ret = update_binary_command(package, zip, "/sbin/update_engine_sideload", retry_count, - pipefd[1], &args); -#else - int ret = update_binary_command(package, zip, "/tmp/update-binary", retry_count, pipefd[1], - &args); -#endif + int ret = is_ab ? SetUpAbUpdateCommands(package, zip, pipefd[1], &args) + : SetUpNonAbUpdateCommands(package, zip, retry_count, pipefd[1], &args); if (ret) { close(pipefd[0]); close(pipefd[1]); diff --git a/otautil/include/otautil/paths.h b/otautil/include/otautil/paths.h index 39088f100..f95741a24 100644 --- a/otautil/include/otautil/paths.h +++ b/otautil/include/otautil/paths.h @@ -76,6 +76,13 @@ class Paths { temporary_log_file_ = log_file; } + std::string temporary_update_binary() const { + return temporary_update_binary_; + } + void set_temporary_update_binary(const std::string& update_binary) { + temporary_update_binary_ = update_binary; + } + private: Paths(); DISALLOW_COPY_AND_ASSIGN(Paths); @@ -103,6 +110,9 @@ class Paths { // Path to the temporary log file while under recovery. std::string temporary_log_file_; + + // Path to the temporary update binary while installing a non-A/B package. + std::string temporary_update_binary_; }; #endif // _OTAUTIL_PATHS_H_ diff --git a/otautil/paths.cpp b/otautil/paths.cpp index f08e51c7a..33ab4a5d4 100644 --- a/otautil/paths.cpp +++ b/otautil/paths.cpp @@ -23,6 +23,7 @@ constexpr const char kDefaultResourceDirectory[] = "/res/images"; constexpr const char kDefaultStashDirectoryBase[] = "/cache/recovery"; constexpr const char kDefaultTemporaryInstallFile[] = "/tmp/last_install"; constexpr const char kDefaultTemporaryLogFile[] = "/tmp/recovery.log"; +constexpr const char kDefaultTemporaryUpdateBinary[] = "/tmp/update-binary"; Paths& Paths::Get() { static Paths paths; @@ -36,4 +37,5 @@ Paths::Paths() resource_dir_(kDefaultResourceDirectory), stash_directory_base_(kDefaultStashDirectoryBase), temporary_install_file_(kDefaultTemporaryInstallFile), - temporary_log_file_(kDefaultTemporaryLogFile) {} + temporary_log_file_(kDefaultTemporaryLogFile), + temporary_update_binary_(kDefaultTemporaryUpdateBinary) {} diff --git a/private/install.h b/private/install.h index ef64bd41d..7fdc741d6 100644 --- a/private/install.h +++ b/private/install.h @@ -23,9 +23,17 @@ #include -// Extract the update binary from the open zip archive |zip| located at |package| to |binary_path|. -// Store the command line that should be called into |cmd|. The |status_fd| is the file descriptor -// the child process should use to report back the progress of the update. -int update_binary_command(const std::string& package, ZipArchiveHandle zip, - const std::string& binary_path, int retry_count, int status_fd, +// Sets up the commands for a non-A/B update. Extracts the updater binary from the open zip archive +// |zip| located at |package|. Stores the command line that should be called into |cmd|. The +// |status_fd| is the file descriptor the child process should use to report back the progress of +// the update. +int SetUpNonAbUpdateCommands(const std::string& package, ZipArchiveHandle zip, int retry_count, + int status_fd, std::vector* cmd); + +// Sets up the commands for an A/B update. Extracts the needed entries from the open zip archive +// |zip| located at |package|. Stores the command line that should be called into |cmd|. The +// |status_fd| is the file descriptor the child process should use to report back the progress of +// the update. Note that since this applies to the sideloading flow only, it takes one less +// parameter |retry_count| than the non-A/B version. +int SetUpAbUpdateCommands(const std::string& package, ZipArchiveHandle zip, int status_fd, std::vector* cmd); diff --git a/tests/Android.mk b/tests/Android.mk index ff420668a..a9e64916f 100644 --- a/tests/Android.mk +++ b/tests/Android.mk @@ -72,10 +72,6 @@ LOCAL_CFLAGS := \ -Werror \ -D_FILE_OFFSET_BITS=64 -ifeq ($(AB_OTA_UPDATER),true) -LOCAL_CFLAGS += -DAB_OTA_UPDATER=1 -endif - LOCAL_MODULE := recovery_component_test LOCAL_COMPATIBILITY_SUITE := device-tests LOCAL_C_INCLUDES := bootable/recovery diff --git a/tests/component/install_test.cpp b/tests/component/install_test.cpp index d19d788e4..b9af0b18b 100644 --- a/tests/component/install_test.cpp +++ b/tests/component/install_test.cpp @@ -33,6 +33,7 @@ #include #include "install.h" +#include "otautil/paths.h" #include "private/install.h" TEST(InstallTest, verify_package_compatibility_no_entry) { @@ -199,8 +200,73 @@ TEST(InstallTest, verify_package_compatibility_with_libvintf_system_manifest_xml CloseArchive(zip); } -#ifdef AB_OTA_UPDATER -static void VerifyAbUpdateBinaryCommand(const std::string& serialno, bool success = true) { +TEST(InstallTest, SetUpNonAbUpdateCommands) { + TemporaryFile temp_file; + FILE* zip_file = fdopen(temp_file.release(), "w"); + ZipWriter writer(zip_file); + static constexpr const char* UPDATE_BINARY_NAME = "META-INF/com/google/android/update-binary"; + ASSERT_EQ(0, writer.StartEntry(UPDATE_BINARY_NAME, kCompressStored)); + ASSERT_EQ(0, writer.FinishEntry()); + ASSERT_EQ(0, writer.Finish()); + ASSERT_EQ(0, fclose(zip_file)); + + ZipArchiveHandle zip; + ASSERT_EQ(0, OpenArchive(temp_file.path, &zip)); + int status_fd = 10; + std::string package = "/path/to/update.zip"; + TemporaryDir td; + std::string binary_path = std::string(td.path) + "/update_binary"; + Paths::Get().set_temporary_update_binary(binary_path); + std::vector cmd; + ASSERT_EQ(0, SetUpNonAbUpdateCommands(package, zip, 0, status_fd, &cmd)); + ASSERT_EQ(4U, cmd.size()); + ASSERT_EQ(binary_path, cmd[0]); + ASSERT_EQ("3", cmd[1]); // RECOVERY_API_VERSION + ASSERT_EQ(std::to_string(status_fd), cmd[2]); + ASSERT_EQ(package, cmd[3]); + struct stat sb; + ASSERT_EQ(0, stat(binary_path.c_str(), &sb)); + ASSERT_EQ(static_cast(0755), sb.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO)); + + // With non-zero retry count. update_binary will be removed automatically. + cmd.clear(); + ASSERT_EQ(0, SetUpNonAbUpdateCommands(package, zip, 2, status_fd, &cmd)); + ASSERT_EQ(5U, cmd.size()); + ASSERT_EQ(binary_path, cmd[0]); + ASSERT_EQ("3", cmd[1]); // RECOVERY_API_VERSION + ASSERT_EQ(std::to_string(status_fd), cmd[2]); + ASSERT_EQ(package, cmd[3]); + ASSERT_EQ("retry", cmd[4]); + sb = {}; + ASSERT_EQ(0, stat(binary_path.c_str(), &sb)); + ASSERT_EQ(static_cast(0755), sb.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO)); + + CloseArchive(zip); +} + +TEST(InstallTest, SetUpNonAbUpdateCommands_MissingUpdateBinary) { + TemporaryFile temp_file; + FILE* zip_file = fdopen(temp_file.release(), "w"); + ZipWriter writer(zip_file); + // The archive must have something to be opened correctly. + ASSERT_EQ(0, writer.StartEntry("dummy_entry", 0)); + ASSERT_EQ(0, writer.FinishEntry()); + ASSERT_EQ(0, writer.Finish()); + ASSERT_EQ(0, fclose(zip_file)); + + // Missing update binary. + ZipArchiveHandle zip; + ASSERT_EQ(0, OpenArchive(temp_file.path, &zip)); + int status_fd = 10; + std::string package = "/path/to/update.zip"; + TemporaryDir td; + Paths::Get().set_temporary_update_binary(std::string(td.path) + "/update_binary"); + std::vector cmd; + ASSERT_EQ(INSTALL_CORRUPT, SetUpNonAbUpdateCommands(package, zip, 0, status_fd, &cmd)); + CloseArchive(zip); +} + +static void VerifyAbUpdateCommands(const std::string& serialno, bool success = true) { TemporaryFile temp_file; FILE* zip_file = fdopen(temp_file.release(), "w"); ZipWriter writer(zip_file); @@ -235,73 +301,27 @@ static void VerifyAbUpdateBinaryCommand(const std::string& serialno, bool succes ASSERT_EQ(0, FindEntry(zip, payload_name, &payload_entry)); int status_fd = 10; std::string package = "/path/to/update.zip"; - std::string binary_path = "/sbin/update_engine_sideload"; std::vector cmd; if (success) { - ASSERT_EQ(0, update_binary_command(package, zip, binary_path, 0, status_fd, &cmd)); + ASSERT_EQ(0, SetUpAbUpdateCommands(package, zip, status_fd, &cmd)); ASSERT_EQ(5U, cmd.size()); - ASSERT_EQ(binary_path, cmd[0]); + ASSERT_EQ("/sbin/update_engine_sideload", cmd[0]); ASSERT_EQ("--payload=file://" + package, cmd[1]); ASSERT_EQ("--offset=" + std::to_string(payload_entry.offset), cmd[2]); ASSERT_EQ("--headers=" + properties, cmd[3]); ASSERT_EQ("--status_fd=" + std::to_string(status_fd), cmd[4]); } else { - ASSERT_EQ(INSTALL_ERROR, update_binary_command(package, zip, binary_path, 0, status_fd, &cmd)); + ASSERT_EQ(INSTALL_ERROR, SetUpAbUpdateCommands(package, zip, status_fd, &cmd)); } CloseArchive(zip); } -#endif // AB_OTA_UPDATER -TEST(InstallTest, update_binary_command_smoke) { -#ifdef AB_OTA_UPDATER +TEST(InstallTest, SetUpAbUpdateCommands) { // Empty serialno will pass the verification. - VerifyAbUpdateBinaryCommand({}); -#else - TemporaryFile temp_file; - FILE* zip_file = fdopen(temp_file.release(), "w"); - ZipWriter writer(zip_file); - static constexpr const char* UPDATE_BINARY_NAME = "META-INF/com/google/android/update-binary"; - ASSERT_EQ(0, writer.StartEntry(UPDATE_BINARY_NAME, kCompressStored)); - ASSERT_EQ(0, writer.FinishEntry()); - ASSERT_EQ(0, writer.Finish()); - ASSERT_EQ(0, fclose(zip_file)); - - ZipArchiveHandle zip; - ASSERT_EQ(0, OpenArchive(temp_file.path, &zip)); - int status_fd = 10; - std::string package = "/path/to/update.zip"; - TemporaryDir td; - std::string binary_path = std::string(td.path) + "/update_binary"; - std::vector cmd; - ASSERT_EQ(0, update_binary_command(package, zip, binary_path, 0, status_fd, &cmd)); - ASSERT_EQ(4U, cmd.size()); - ASSERT_EQ(binary_path, cmd[0]); - ASSERT_EQ("3", cmd[1]); // RECOVERY_API_VERSION - ASSERT_EQ(std::to_string(status_fd), cmd[2]); - ASSERT_EQ(package, cmd[3]); - struct stat sb; - ASSERT_EQ(0, stat(binary_path.c_str(), &sb)); - ASSERT_EQ(static_cast(0755), sb.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO)); - - // With non-zero retry count. update_binary will be removed automatically. - cmd.clear(); - ASSERT_EQ(0, update_binary_command(package, zip, binary_path, 2, status_fd, &cmd)); - ASSERT_EQ(5U, cmd.size()); - ASSERT_EQ(binary_path, cmd[0]); - ASSERT_EQ("3", cmd[1]); // RECOVERY_API_VERSION - ASSERT_EQ(std::to_string(status_fd), cmd[2]); - ASSERT_EQ(package, cmd[3]); - ASSERT_EQ("retry", cmd[4]); - sb = {}; - ASSERT_EQ(0, stat(binary_path.c_str(), &sb)); - ASSERT_EQ(static_cast(0755), sb.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO)); - - CloseArchive(zip); -#endif // AB_OTA_UPDATER + VerifyAbUpdateCommands({}); } -TEST(InstallTest, update_binary_command_invalid) { -#ifdef AB_OTA_UPDATER +TEST(InstallTest, SetUpAbUpdateCommands_MissingPayloadPropertiesTxt) { TemporaryFile temp_file; FILE* zip_file = fdopen(temp_file.release(), "w"); ZipWriter writer(zip_file); @@ -328,60 +348,36 @@ TEST(InstallTest, update_binary_command_invalid) { ASSERT_EQ(0, OpenArchive(temp_file.path, &zip)); int status_fd = 10; std::string package = "/path/to/update.zip"; - std::string binary_path = "/sbin/update_engine_sideload"; - std::vector cmd; - ASSERT_EQ(INSTALL_CORRUPT, update_binary_command(package, zip, binary_path, 0, status_fd, &cmd)); - CloseArchive(zip); -#else - TemporaryFile temp_file; - FILE* zip_file = fdopen(temp_file.release(), "w"); - ZipWriter writer(zip_file); - // The archive must have something to be opened correctly. - ASSERT_EQ(0, writer.StartEntry("dummy_entry", 0)); - ASSERT_EQ(0, writer.FinishEntry()); - ASSERT_EQ(0, writer.Finish()); - ASSERT_EQ(0, fclose(zip_file)); - - // Missing update binary. - ZipArchiveHandle zip; - ASSERT_EQ(0, OpenArchive(temp_file.path, &zip)); - int status_fd = 10; - std::string package = "/path/to/update.zip"; - TemporaryDir td; - std::string binary_path = std::string(td.path) + "/update_binary"; std::vector cmd; - ASSERT_EQ(INSTALL_CORRUPT, update_binary_command(package, zip, binary_path, 0, status_fd, &cmd)); + ASSERT_EQ(INSTALL_CORRUPT, SetUpAbUpdateCommands(package, zip, status_fd, &cmd)); CloseArchive(zip); -#endif // AB_OTA_UPDATER } -#ifdef AB_OTA_UPDATER -TEST(InstallTest, update_binary_command_multiple_serialno) { +TEST(InstallTest, SetUpAbUpdateCommands_MultipleSerialnos) { std::string serialno = android::base::GetProperty("ro.serialno", ""); ASSERT_NE("", serialno); // Single matching serialno will pass the verification. - VerifyAbUpdateBinaryCommand(serialno); + VerifyAbUpdateCommands(serialno); static constexpr char alphabet[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; auto generator = []() { return alphabet[rand() % (sizeof(alphabet) - 1)]; }; // Generate 900 random serial numbers. - std::string random_serial; + std::string random_serialno; for (size_t i = 0; i < 900; i++) { - generate_n(back_inserter(random_serial), serialno.size(), generator); - random_serial.append("|"); + generate_n(back_inserter(random_serialno), serialno.size(), generator); + random_serialno.append("|"); } // Random serialnos should fail the verification. - VerifyAbUpdateBinaryCommand(random_serial, false); + VerifyAbUpdateCommands(random_serialno, false); - std::string long_serial = random_serial + serialno + "|"; + std::string long_serialno = random_serialno + serialno + "|"; for (size_t i = 0; i < 99; i++) { - generate_n(back_inserter(long_serial), serialno.size(), generator); - long_serial.append("|"); + generate_n(back_inserter(long_serialno), serialno.size(), generator); + long_serialno.append("|"); } // String with the matching serialno should pass the verification. - VerifyAbUpdateBinaryCommand(long_serial); + VerifyAbUpdateCommands(long_serialno); } -#endif // AB_OTA_UPDATER -- cgit v1.2.3 From 155771bafa347a1bcba982c6d846240975ea91ef Mon Sep 17 00:00:00 2001 From: Tao Bao Date: Tue, 5 Jun 2018 11:26:01 -0700 Subject: applypatch: Clean up the function comments. Also two minor changes (other than renaming some parameters): - Added constness to the first parameter of FindMatchingPatch(); - Declared WriteToPartition() as static. Bug: 110106408 Test: mmma -j bootable/recovery Change-Id: I388958c944a23ce4a38a757ce2249f6a89dd4f03 --- applypatch/applypatch.cpp | 163 ++++++++++------------------- applypatch/include/applypatch/applypatch.h | 58 ++++++++-- 2 files changed, 105 insertions(+), 116 deletions(-) diff --git a/applypatch/applypatch.cpp b/applypatch/applypatch.cpp index 14137de96..ce7702636 100644 --- a/applypatch/applypatch.cpp +++ b/applypatch/applypatch.cpp @@ -49,8 +49,6 @@ static int GenerateTarget(const FileContents& source_file, const std::unique_ptr const std::string& target_filename, const uint8_t target_sha1[SHA_DIGEST_LENGTH], const Value* bonus_data); -// Read a file into memory; store the file contents and associated metadata in *file. -// Return 0 on success. int LoadFileContents(const char* filename, FileContents* file) { // A special 'filename' beginning with "EMMC:" means to load the contents of a partition. if (strncmp(filename, "EMMC:", 5) == 0) { @@ -80,20 +78,16 @@ int LoadFileContents(const char* filename, FileContents* file) { return 0; } -// Load the contents of an EMMC partition into the provided -// FileContents. filename should be a string of the form -// "EMMC::...". The smallest size_n bytes for -// which that prefix of the partition contents has the corresponding -// sha1 hash will be loaded. It is acceptable for a size value to be -// repeated with different sha1s. Will return 0 on success. +// Loads the contents of an EMMC partition into the provided FileContents. filename should be a +// string of the form "EMMC::...". The smallest size_n bytes for which that prefix +// of the partition contents has the corresponding sha1 hash will be loaded. It is acceptable for a +// size value to be repeated with different sha1s. Returns 0 on success. // -// This complexity is needed because if an OTA installation is -// interrupted, the partition might contain either the source or the -// target data, which might be of different lengths. We need to know -// the length in order to read from a partition (there is no -// "end-of-file" marker), so the caller must specify the possible -// lengths and the hash of the data, and we'll do the load expecting -// to find one of those hashes. +// This complexity is needed because if an OTA installation is interrupted, the partition might +// contain either the source or the target data, which might be of different lengths. We need to +// know the length in order to read from a partition (there is no "end-of-file" marker), so the +// caller must specify the possible lengths and the hash of the data, and we'll do the load +// expecting to find one of those hashes. static int LoadPartitionContents(const std::string& filename, FileContents* file) { std::vector pieces = android::base::Split(filename, ":"); if (pieces.size() < 4 || pieces.size() % 2 != 0 || pieces[0] != "EMMC") { @@ -184,8 +178,6 @@ static int LoadPartitionContents(const std::string& filename, FileContents* file return 0; } -// Save the contents of the given FileContents object under the given -// filename. Return 0 on success. int SaveFileContents(const char* filename, const FileContents* file) { unique_fd fd(ota_open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_SYNC, S_IRUSR | S_IWUSR)); if (fd == -1) { @@ -211,11 +203,10 @@ int SaveFileContents(const char* filename, const FileContents* file) { return 0; } -// Write a memory buffer to 'target' partition, a string of the form -// "EMMC:[:...]". The target name -// might contain multiple colons, but WriteToPartition() only uses the first -// two and ignores the rest. Return 0 on success. -int WriteToPartition(const unsigned char* data, size_t len, const std::string& target) { +// Writes a memory buffer to 'target' partition, a string of the form +// "EMMC:[:...]". The target name might contain multiple colons, but +// WriteToPartition() only uses the first two and ignores the rest. Returns 0 on success. +static int WriteToPartition(const unsigned char* data, size_t len, const std::string& target) { std::vector pieces = android::base::Split(target, ":"); if (pieces.size() < 2 || pieces[0] != "EMMC") { printf("WriteToPartition called with bad target (%s)\n", target.c_str()); @@ -343,42 +334,37 @@ int WriteToPartition(const unsigned char* data, size_t len, const std::string& t return 0; } -// Take a string 'str' of 40 hex digits and parse it into the 20 -// byte array 'digest'. 'str' may contain only the digest or be of -// the form ":". Return 0 on success, -1 on any -// error. int ParseSha1(const char* str, uint8_t* digest) { - const char* ps = str; - uint8_t* pd = digest; - for (int i = 0; i < SHA_DIGEST_LENGTH * 2; ++i, ++ps) { - int digit; - if (*ps >= '0' && *ps <= '9') { - digit = *ps - '0'; - } else if (*ps >= 'a' && *ps <= 'f') { - digit = *ps - 'a' + 10; - } else if (*ps >= 'A' && *ps <= 'F') { - digit = *ps - 'A' + 10; - } else { - return -1; - } - if (i % 2 == 0) { - *pd = digit << 4; - } else { - *pd |= digit; - ++pd; - } + const char* ps = str; + uint8_t* pd = digest; + for (int i = 0; i < SHA_DIGEST_LENGTH * 2; ++i, ++ps) { + int digit; + if (*ps >= '0' && *ps <= '9') { + digit = *ps - '0'; + } else if (*ps >= 'a' && *ps <= 'f') { + digit = *ps - 'a' + 10; + } else if (*ps >= 'A' && *ps <= 'F') { + digit = *ps - 'A' + 10; + } else { + return -1; } - if (*ps != '\0') return -1; - return 0; + if (i % 2 == 0) { + *pd = digit << 4; + } else { + *pd |= digit; + ++pd; + } + } + if (*ps != '\0') return -1; + return 0; } -// Search an array of sha1 strings for one matching the given sha1. -// Return the index of the match on success, or -1 if no match is -// found. -static int FindMatchingPatch(uint8_t* sha1, const std::vector& patch_sha1_str) { - for (size_t i = 0; i < patch_sha1_str.size(); ++i) { +// Searches a vector of SHA-1 strings for one matching the given SHA-1. Returns the index of the +// match on success, or -1 if no match is found. +static int FindMatchingPatch(const uint8_t* sha1, const std::vector& patch_sha1s) { + for (size_t i = 0; i < patch_sha1s.size(); ++i) { uint8_t patch_sha1[SHA_DIGEST_LENGTH]; - if (ParseSha1(patch_sha1_str[i].c_str(), patch_sha1) == 0 && + if (ParseSha1(patch_sha1s[i].c_str(), patch_sha1) == 0 && memcmp(patch_sha1, sha1, SHA_DIGEST_LENGTH) == 0) { return i; } @@ -386,29 +372,24 @@ static int FindMatchingPatch(uint8_t* sha1, const std::vector& patc return -1; } -// Returns 0 if the contents of the file (argv[2]) or the cached file -// match any of the sha1's on the command line (argv[3:]). Returns -// nonzero otherwise. -int applypatch_check(const char* filename, const std::vector& patch_sha1_str) { +int applypatch_check(const char* filename, const std::vector& patch_sha1s) { + // It's okay to specify no SHA-1s; the check will pass if the LoadFileContents is successful. + // (Useful for reading partitions, where the filename encodes the SHA-1s; no need to check them + // twice.) FileContents file; - - // It's okay to specify no sha1s; the check will pass if the - // LoadFileContents is successful. (Useful for reading - // partitions, where the filename encodes the sha1s; no need to - // check them twice.) if (LoadFileContents(filename, &file) != 0 || - (!patch_sha1_str.empty() && FindMatchingPatch(file.sha1, patch_sha1_str) < 0)) { + (!patch_sha1s.empty() && FindMatchingPatch(file.sha1, patch_sha1s) < 0)) { printf("file \"%s\" doesn't have any of expected sha1 sums; checking cache\n", filename); // If the source file is missing or corrupted, it might be because we were killed in the middle - // of patching it. A copy of it should have been made in cache_temp_source. If that file - // exists and matches the sha1 we're looking for, the check still passes. + // of patching it. A copy should have been made in cache_temp_source. If that file exists and + // matches the SHA-1 we're looking for, the check still passes. if (LoadFileContents(Paths::Get().cache_temp_source().c_str(), &file) != 0) { printf("failed to load cache file\n"); return 1; } - if (FindMatchingPatch(file.sha1, patch_sha1_str) < 0) { + if (FindMatchingPatch(file.sha1, patch_sha1s) < 0) { printf("cache bits don't match any sha1 for \"%s\"\n", filename); return 1; } @@ -417,8 +398,8 @@ int applypatch_check(const char* filename, const std::vector& patch } int ShowLicenses() { - ShowBSDiffLicense(); - return 0; + ShowBSDiffLicense(); + return 0; } static size_t FileSink(const unsigned char* data, size_t len, int fd) { @@ -434,8 +415,6 @@ static size_t FileSink(const unsigned char* data, size_t len, int fd) { return done; } -// Return the amount of free space (in bytes) on the filesystem -// containing filename. filename must exist. Return -1 on error. size_t FreeSpaceForFile(const std::string& filename) { struct statfs sf; if (statfs(filename.c_str(), &sf) != 0) { @@ -446,37 +425,16 @@ size_t FreeSpaceForFile(const std::string& filename) { } int CacheSizeCheck(size_t bytes) { - if (MakeFreeSpaceOnCache(bytes) < 0) { - printf("unable to make %zu bytes available on /cache\n", bytes); - return 1; - } - return 0; + if (MakeFreeSpaceOnCache(bytes) < 0) { + printf("unable to make %zu bytes available on /cache\n", bytes); + return 1; + } + return 0; } -// This function applies binary patches to EMMC target files in a way that is safe (the original -// file is not touched until we have the desired replacement for it) and idempotent (it's okay to -// run this program multiple times). -// -// - If the SHA-1 hash of is , does nothing and exits -// successfully. -// -// - Otherwise, if the SHA-1 hash of is one of the entries in , -// the corresponding patch from (which must be a VAL_BLOB) is applied to produce a -// new file (the type of patch is automatically detected from the blob data). If that new file -// has SHA-1 hash , moves it to replace , and exits -// successfully. Note that if and are not the same, -// is NOT deleted on success. may be the string "-" to mean -// "the same as ". -// -// - Otherwise, or if any error is encountered, exits with non-zero status. -// -// must refer to an EMMC partition to read the source data. See the comments for -// the LoadPartitionContents() function above for the format of such a filename. has -// become obsolete since we have dropped the support for patching non-EMMC targets (EMMC targets -// have the size embedded in the filename). int applypatch(const char* source_filename, const char* target_filename, const char* target_sha1_str, size_t /* target_size */, - const std::vector& patch_sha1_str, + const std::vector& patch_sha1s, const std::vector>& patch_data, const Value* bonus_data) { printf("patch %s: ", source_filename); @@ -515,7 +473,7 @@ int applypatch(const char* source_filename, const char* target_filename, } if (!source_file.data.empty()) { - int to_use = FindMatchingPatch(source_file.sha1, patch_sha1_str); + int to_use = FindMatchingPatch(source_file.sha1, patch_sha1s); if (to_use != -1) { return GenerateTarget(source_file, patch_data[to_use], target_filename, target_sha1, bonus_data); @@ -530,7 +488,7 @@ int applypatch(const char* source_filename, const char* target_filename, return 1; } - int to_use = FindMatchingPatch(copy_file.sha1, patch_sha1_str); + int to_use = FindMatchingPatch(copy_file.sha1, patch_sha1s); if (to_use == -1) { printf("copy file doesn't match source SHA-1s either\n"); return 1; @@ -539,13 +497,6 @@ int applypatch(const char* source_filename, const char* target_filename, return GenerateTarget(copy_file, patch_data[to_use], target_filename, target_sha1, bonus_data); } -/* - * This function flashes a given image to the target partition. It verifies - * the target cheksum first, and will return if target has the desired hash. - * It checks the checksum of the given source image before flashing, and - * verifies the target partition afterwards. The function is idempotent. - * Returns zero on success. - */ int applypatch_flash(const char* source_filename, const char* target_filename, const char* target_sha1_str, size_t target_size) { printf("flash %s: ", target_filename); diff --git a/applypatch/include/applypatch/applypatch.h b/applypatch/include/applypatch/applypatch.h index 77125f9de..ef133f290 100644 --- a/applypatch/include/applypatch/applypatch.h +++ b/applypatch/include/applypatch/applypatch.h @@ -39,23 +39,61 @@ using SinkFn = std::function; // applypatch.cpp int ShowLicenses(); + +// Returns the amount of free space (in bytes) on the filesystem containing filename, or -1 on +// error. filename must exist. size_t FreeSpaceForFile(const std::string& filename); + +// Checks whether /cache partition has at least 'bytes'-byte free space. Returns 0 on having +// sufficient space. int CacheSizeCheck(size_t bytes); + +// Parses a given string of 40 hex digits into 20-byte array 'digest'. 'str' may contain only the +// digest or be of the form ":". Returns 0 on success, or -1 on any error. int ParseSha1(const char* str, uint8_t* digest); -int applypatch(const char* source_filename, - const char* target_filename, - const char* target_sha1_str, - size_t target_size, - const std::vector& patch_sha1_str, - const std::vector>& patch_data, - const Value* bonus_data); -int applypatch_check(const char* filename, - const std::vector& patch_sha1_str); +// Applies binary patches to eMMC target files in a way that is safe (the original file is not +// touched until we have the desired replacement for it) and idempotent (it's okay to run this +// program multiple times). +// +// - If the SHA-1 hash of 'target_filename' is 'target_sha1_string', does nothing and returns +// successfully. +// +// - Otherwise, if the SHA-1 hash of 'source_filename' is one of the entries in 'patch_sha1s', the +// corresponding patch from 'patch_data' (which must be a VAL_BLOB) is applied to produce a new +// file (the type of patch is automatically detected from the blob data). If that new file has +// SHA-1 hash 'target_sha1_str', moves it to replace 'target_filename', and exits successfully. +// Note that if 'source_filename' and 'target_filename' are not the same, 'source_filename' is +// NOT deleted on success. 'target_filename' may be the string "-" to mean +// "the same as 'source_filename'". +// +// - Otherwise, or if any error is encountered, exits with non-zero status. +// +// 'source_filename' must refer to an eMMC partition to read the source data. See the comments for +// the LoadPartitionContents() function for the format of such a filename. 'target_size' has become +// obsolete since we have dropped the support for patching non-eMMC targets (eMMC targets have the +// size embedded in the filename). +int applypatch(const char* source_filename, const char* target_filename, + const char* target_sha1_str, size_t target_size, + const std::vector& patch_sha1s, + const std::vector>& patch_data, const Value* bonus_data); + +// Returns 0 if the contents of the file or the cached file match any of the given SHA-1's. Returns +// nonzero otherwise. +int applypatch_check(const char* filename, const std::vector& patch_sha1s); + +// Flashes a given image to the target partition. It verifies the target cheksum first, and will +// return if target already has the desired hash. Otherwise it checks the checksum of the given +// source image before flashing, and verifies the target partition afterwards. The function is +// idempotent. Returns zero on success. int applypatch_flash(const char* source_filename, const char* target_filename, const char* target_sha1_str, size_t target_size); +// Reads a file into memory; stores the file contents and associated metadata in *file. Returns 0 +// on success, or -1 on error. int LoadFileContents(const char* filename, FileContents* file); + +// Saves the given FileContents object to the given filename. Returns 0 on success, or -1 on error. int SaveFileContents(const char* filename, const FileContents* file); // bspatch.cpp @@ -79,9 +117,9 @@ int ApplyImagePatch(const unsigned char* old_data, size_t old_size, const Value& // freecache.cpp int MakeFreeSpaceOnCache(size_t bytes_needed); + // Removes the files in |dirname| until we have at least |bytes_needed| bytes of free space on // the partition. The size of the free space is returned by calling |space_checker|. bool RemoveFilesInDirectory(size_t bytes_needed, const std::string& dirname, const std::function& space_checker); - #endif -- cgit v1.2.3 From 69364fe553c8ceda03b5fa2de7d2459d76da8fb7 Mon Sep 17 00:00:00 2001 From: Jiyong Park Date: Wed, 20 Jun 2018 14:18:18 +0900 Subject: e2fsdroid and mke2fs are dynamic executable in recovery partition The two utilities are now converted to dynamic executables as shared libraries are supported in recovery mode. As part of the conversion, their location has moved from /sbin to /system/bin. Reflect the change in the program 'recovery' Bug: 79146551 Test: adb reboot recovery, and select 'Wipe data/factory reset'. The data partition is formatted and there is no selinux denial. Change-Id: Ie7cfc4c50ab1e6767e4a5170533ccf826ec7d7f3 --- Android.mk | 4 ++-- roots.cpp | 10 ++-------- updater/install.cpp | 8 ++++---- 3 files changed, 8 insertions(+), 14 deletions(-) diff --git a/Android.mk b/Android.mk index 257564058..69490a57e 100644 --- a/Android.mk +++ b/Android.mk @@ -177,8 +177,8 @@ LOCAL_STATIC_LIBRARIES := \ LOCAL_HAL_STATIC_LIBRARIES := libhealthd LOCAL_REQUIRED_MODULES := \ - e2fsdroid_static \ - mke2fs_static \ + e2fsdroid.recovery \ + mke2fs.recovery \ mke2fs.conf ifeq ($(TARGET_USERIMAGES_USE_F2FS),true) diff --git a/roots.cpp b/roots.cpp index 26ebf1fbe..2b26bf43e 100644 --- a/roots.cpp +++ b/roots.cpp @@ -283,7 +283,7 @@ int format_volume(const char* volume, const char* directory) { if (strcmp(v->fs_type, "ext4") == 0) { static constexpr int kBlockSize = 4096; std::vector mke2fs_args = { - "/sbin/mke2fs_static", "-F", "-t", "ext4", "-b", std::to_string(kBlockSize), + "/system/bin/mke2fs", "-F", "-t", "ext4", "-b", std::to_string(kBlockSize), }; int raid_stride = v->logical_blk_size / kBlockSize; @@ -305,13 +305,7 @@ int format_volume(const char* volume, const char* directory) { int result = exec_cmd(mke2fs_args); if (result == 0 && directory != nullptr) { std::vector e2fsdroid_args = { - "/sbin/e2fsdroid_static", - "-e", - "-f", - directory, - "-a", - volume, - v->blk_device, + "/system/bin/e2fsdroid", "-e", "-f", directory, "-a", volume, v->blk_device, }; result = exec_cmd(e2fsdroid_args); } diff --git a/updater/install.cpp b/updater/install.cpp index bd22467ab..5dbe4a984 100644 --- a/updater/install.cpp +++ b/updater/install.cpp @@ -511,8 +511,8 @@ Value* FormatFn(const char* name, State* state, const std::vector(e2fsdroid_argv)); if (status != 0) { LOG(ERROR) << name << ": e2fsdroid failed (" << status << ") on " << location; -- cgit v1.2.3