summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--applypatch/applypatch.cpp4
-rw-r--r--install.cpp8
-rw-r--r--otafault/ota_io.cpp28
-rw-r--r--otafault/ota_io.h20
-rw-r--r--tests/component/applypatch_test.cpp175
-rw-r--r--updater/install.cpp142
6 files changed, 259 insertions, 118 deletions
diff --git a/applypatch/applypatch.cpp b/applypatch/applypatch.cpp
index 9b84fa104..95389da6e 100644
--- a/applypatch/applypatch.cpp
+++ b/applypatch/applypatch.cpp
@@ -66,7 +66,7 @@ int LoadFileContents(const char* filename, FileContents* file) {
}
std::vector<unsigned char> data(file->st.st_size);
- std::unique_ptr<FILE, decltype(&ota_fclose)> f(ota_fopen(filename, "rb"), ota_fclose);
+ unique_file f(ota_fopen(filename, "rb"));
if (!f) {
printf("failed to open \"%s\": %s\n", filename, strerror(errno));
return -1;
@@ -118,7 +118,7 @@ static int LoadPartitionContents(const std::string& filename, FileContents* file
std::sort(pairs.begin(), pairs.end());
const char* partition = pieces[1].c_str();
- std::unique_ptr<FILE, decltype(&ota_fclose)> dev(ota_fopen(partition, "rb"), ota_fclose);
+ unique_file dev(ota_fopen(partition, "rb"));
if (!dev) {
printf("failed to open emmc partition \"%s\": %s\n", partition, strerror(errno));
return -1;
diff --git a/install.cpp b/install.cpp
index 98f1e3f36..f124a2688 100644
--- a/install.cpp
+++ b/install.cpp
@@ -373,6 +373,14 @@ try_update_binary(const char* path, ZipArchiveHandle zip, bool* wipe_cache,
}
pid_t pid = fork();
+
+ if (pid == -1) {
+ close(pipefd[0]);
+ close(pipefd[1]);
+ PLOG(ERROR) << "Failed to fork update binary";
+ return INSTALL_ERROR;
+ }
+
if (pid == 0) {
umask(022);
close(pipefd[0]);
diff --git a/otafault/ota_io.cpp b/otafault/ota_io.cpp
index 2efd3004a..f5b01136f 100644
--- a/otafault/ota_io.cpp
+++ b/otafault/ota_io.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include <map>
+#include "ota_io.h"
#include <errno.h>
#include <fcntl.h>
@@ -22,8 +22,10 @@
#include <sys/stat.h>
#include <unistd.h>
+#include <map>
+#include <memory>
+
#include "config.h"
-#include "ota_io.h"
static std::map<intptr_t, const char*> filename_cache;
static std::string read_fault_file_name = "";
@@ -68,17 +70,33 @@ FILE* ota_fopen(const char* path, const char* mode) {
return fh;
}
-int ota_close(int fd) {
+static int __ota_close(int fd) {
// descriptors can be reused, so make sure not to leave them in the cache
filename_cache.erase(fd);
return close(fd);
}
-int ota_fclose(FILE* fh) {
- filename_cache.erase((intptr_t)fh);
+void OtaCloser::Close(int fd) {
+ __ota_close(fd);
+}
+
+int ota_close(unique_fd& fd) {
+ return __ota_close(fd.release());
+}
+
+static int __ota_fclose(FILE* fh) {
+ filename_cache.erase(reinterpret_cast<intptr_t>(fh));
return fclose(fh);
}
+void OtaFcloser::operator()(FILE* f) {
+ __ota_fclose(f);
+};
+
+int ota_fclose(unique_file& fh) {
+ return __ota_fclose(fh.release());
+}
+
size_t ota_fread(void* ptr, size_t size, size_t nitems, FILE* stream) {
if (should_fault_inject(OTAIO_READ)) {
auto cached = filename_cache.find((intptr_t)stream);
diff --git a/otafault/ota_io.h b/otafault/ota_io.h
index e119eef08..395b4230e 100644
--- a/otafault/ota_io.h
+++ b/otafault/ota_io.h
@@ -26,6 +26,8 @@
#include <stdio.h>
#include <sys/stat.h>
+#include <memory>
+
#include <android-base/unique_fd.h>
#define OTAIO_CACHE_FNAME "/cache/saved.file"
@@ -38,10 +40,6 @@ int ota_open(const char* path, int oflags, mode_t mode);
FILE* ota_fopen(const char* filename, const char* mode);
-int ota_close(int fd);
-
-int ota_fclose(FILE* fh);
-
size_t ota_fread(void* ptr, size_t size, size_t nitems, FILE* stream);
ssize_t ota_read(int fd, void* buf, size_t nbyte);
@@ -53,11 +51,19 @@ ssize_t ota_write(int fd, const void* buf, size_t nbyte);
int ota_fsync(int fd);
struct OtaCloser {
- static void Close(int fd) {
- ota_close(fd);
- }
+ static void Close(int);
};
using unique_fd = android::base::unique_fd_impl<OtaCloser>;
+int ota_close(unique_fd& fd);
+
+struct OtaFcloser {
+ void operator()(FILE*);
+};
+
+using unique_file = std::unique_ptr<FILE, OtaFcloser>;
+
+int ota_fclose(unique_file& fh);
+
#endif
diff --git a/tests/component/applypatch_test.cpp b/tests/component/applypatch_test.cpp
index 1a0b19113..d178303aa 100644
--- a/tests/component/applypatch_test.cpp
+++ b/tests/component/applypatch_test.cpp
@@ -83,15 +83,11 @@ class ApplyPatchTest : public ::testing::Test {
ASSERT_TRUE(android::base::WriteStringToFile("hello", rand_file));
// set up SHA constants
- sha1sum(old_file, &old_sha1);
- sha1sum(new_file, &new_sha1);
+ sha1sum(old_file, &old_sha1, &old_size);
+ sha1sum(new_file, &new_sha1, &new_size);
srand(time(nullptr));
bad_sha1_a = android::base::StringPrintf("%040x", rand());
bad_sha1_b = android::base::StringPrintf("%040x", rand());
-
- struct stat st;
- stat(&new_file[0], &st);
- new_size = st.st_size;
}
static std::string old_file;
@@ -105,6 +101,7 @@ class ApplyPatchTest : public ::testing::Test {
static std::string bad_sha1_a;
static std::string bad_sha1_b;
+ static size_t old_size;
static size_t new_size;
};
@@ -184,7 +181,7 @@ std::string ApplyPatchTest::old_sha1;
std::string ApplyPatchTest::new_sha1;
std::string ApplyPatchTest::bad_sha1_a;
std::string ApplyPatchTest::bad_sha1_b;
-
+size_t ApplyPatchTest::old_size;
size_t ApplyPatchTest::new_size;
std::vector<std::unique_ptr<Value>> ApplyPatchFullTest::patches;
@@ -211,6 +208,42 @@ TEST_F(ApplyPatchTest, CheckModeFailure) {
ASSERT_NE(0, applypatch_check(&old_file[0], sha1s));
}
+TEST_F(ApplyPatchTest, CheckModeEmmcTarget) {
+ // EMMC:old_file:size:sha1 should pass the check.
+ std::string src_file =
+ "EMMC:" + old_file + ":" + std::to_string(old_size) + ":" + old_sha1;
+ std::vector<std::string> sha1s;
+ ASSERT_EQ(0, applypatch_check(src_file.c_str(), sha1s));
+
+ // EMMC:old_file:(size-1):sha1:(size+1):sha1 should fail the check.
+ src_file = "EMMC:" + old_file + ":" + std::to_string(old_size - 1) + ":" + old_sha1 + ":" +
+ std::to_string(old_size + 1) + ":" + old_sha1;
+ ASSERT_EQ(1, applypatch_check(src_file.c_str(), sha1s));
+
+ // EMMC:old_file:(size-1):sha1:size:sha1:(size+1):sha1 should pass the check.
+ src_file = "EMMC:" + old_file + ":" +
+ std::to_string(old_size - 1) + ":" + old_sha1 + ":" +
+ std::to_string(old_size) + ":" + old_sha1 + ":" +
+ std::to_string(old_size + 1) + ":" + old_sha1;
+ ASSERT_EQ(0, applypatch_check(src_file.c_str(), sha1s));
+
+ // EMMC:old_file:(size+1):sha1:(size-1):sha1:size:sha1 should pass the check.
+ src_file = "EMMC:" + old_file + ":" +
+ std::to_string(old_size + 1) + ":" + old_sha1 + ":" +
+ std::to_string(old_size - 1) + ":" + old_sha1 + ":" +
+ std::to_string(old_size) + ":" + old_sha1;
+ ASSERT_EQ(0, applypatch_check(src_file.c_str(), sha1s));
+
+ // EMMC:new_file:(size+1):old_sha1:(size-1):old_sha1:size:old_sha1:size:new_sha1
+ // should pass the check.
+ src_file = "EMMC:" + new_file + ":" +
+ std::to_string(old_size + 1) + ":" + old_sha1 + ":" +
+ std::to_string(old_size - 1) + ":" + old_sha1 + ":" +
+ std::to_string(old_size) + ":" + old_sha1 + ":" +
+ std::to_string(new_size) + ":" + new_sha1;
+ ASSERT_EQ(0, applypatch_check(src_file.c_str(), sha1s));
+}
+
TEST_F(ApplyPatchCacheTest, CheckCacheCorruptedSingle) {
mangle_file(old_file);
std::vector<std::string> sha1s = { old_sha1 };
@@ -307,7 +340,7 @@ TEST_F(ApplyPatchDoubleCacheTest, ApplyDoubleCorruptedInNewLocation) {
ASSERT_FALSE(file_cmp(output_loc, new_file));
}
-TEST(ApplyPatchModes, InvalidArgs) {
+TEST(ApplyPatchModesTest, InvalidArgs) {
// At least two args (including the filename).
ASSERT_EQ(2, applypatch_modes(1, (const char* []){ "applypatch" }));
@@ -315,21 +348,22 @@ TEST(ApplyPatchModes, InvalidArgs) {
ASSERT_EQ(2, applypatch_modes(2, (const char* []){ "applypatch", "-x" }));
}
-TEST(ApplyPatchModes, PatchMode) {
+TEST(ApplyPatchModesTest, PatchMode) {
std::string boot_img = from_testdata_base("boot.img");
size_t boot_img_size;
std::string boot_img_sha1;
sha1sum(boot_img, &boot_img_sha1, &boot_img_size);
std::string recovery_img = from_testdata_base("recovery.img");
- size_t recovery_img_size;
std::string recovery_img_sha1;
- sha1sum(recovery_img, &recovery_img_sha1, &recovery_img_size);
-
+ size_t size;
+ sha1sum(recovery_img, &recovery_img_sha1, &size);
+ std::string recovery_img_size = std::to_string(size);
std::string bonus_file = from_testdata_base("bonus.file");
// applypatch -b <bonus-file> <src-file> <tgt-file> <tgt-sha1> <tgt-size> <src-sha1>:<patch>
TemporaryFile tmp1;
+ std::string patch = boot_img_sha1 + ":" + from_testdata_base("recovery-from-boot.p");
std::vector<const char*> args = {
"applypatch",
"-b",
@@ -337,28 +371,32 @@ TEST(ApplyPatchModes, PatchMode) {
boot_img.c_str(),
tmp1.path,
recovery_img_sha1.c_str(),
- std::to_string(recovery_img_size).c_str(),
- (boot_img_sha1 + ":" + from_testdata_base("recovery-from-boot.p")).c_str()
+ recovery_img_size.c_str(),
+ patch.c_str()
};
ASSERT_EQ(0, applypatch_modes(args.size(), args.data()));
// applypatch <src-file> <tgt-file> <tgt-sha1> <tgt-size> <src-sha1>:<patch>
TemporaryFile tmp2;
+ patch = boot_img_sha1 + ":" + from_testdata_base("recovery-from-boot-with-bonus.p");
std::vector<const char*> args2 = {
"applypatch",
boot_img.c_str(),
tmp2.path,
recovery_img_sha1.c_str(),
- std::to_string(recovery_img_size).c_str(),
- (boot_img_sha1 + ":" + from_testdata_base("recovery-from-boot-with-bonus.p")).c_str()
+ recovery_img_size.c_str(),
+ patch.c_str()
};
ASSERT_EQ(0, applypatch_modes(args2.size(), args2.data()));
// applypatch -b <bonus-file> <src-file> <tgt-file> <tgt-sha1> <tgt-size> \
- // <src-sha1-fake>:<patch1> <src-sha1>:<patch2>
+ // <src-sha1-fake>:<patch1> <src-sha1>:<patch2>
TemporaryFile tmp3;
std::string bad_sha1_a = android::base::StringPrintf("%040x", rand());
std::string bad_sha1_b = android::base::StringPrintf("%040x", rand());
+ std::string patch1 = bad_sha1_a + ":" + from_testdata_base("recovery-from-boot.p");
+ std::string patch2 = boot_img_sha1 + ":" + from_testdata_base("recovery-from-boot.p");
+ std::string patch3 = bad_sha1_b + ":" + from_testdata_base("recovery-from-boot.p");
std::vector<const char*> args3 = {
"applypatch",
"-b",
@@ -366,15 +404,85 @@ TEST(ApplyPatchModes, PatchMode) {
boot_img.c_str(),
tmp3.path,
recovery_img_sha1.c_str(),
- std::to_string(recovery_img_size).c_str(),
- (bad_sha1_a + ":" + from_testdata_base("recovery-from-boot.p")).c_str(),
- (boot_img_sha1 + ":" + from_testdata_base("recovery-from-boot.p")).c_str(),
- (bad_sha1_b + ":" + from_testdata_base("recovery-from-boot.p")).c_str(),
+ recovery_img_size.c_str(),
+ patch1.c_str(),
+ patch2.c_str(),
+ patch3.c_str()
+ };
+ ASSERT_EQ(0, applypatch_modes(args3.size(), args3.data()));
+}
+
+TEST(ApplyPatchModesTest, PatchModeEmmcTarget) {
+ std::string boot_img = from_testdata_base("boot.img");
+ size_t boot_img_size;
+ std::string boot_img_sha1;
+ sha1sum(boot_img, &boot_img_sha1, &boot_img_size);
+
+ std::string recovery_img = from_testdata_base("recovery.img");
+ size_t size;
+ std::string recovery_img_sha1;
+ sha1sum(recovery_img, &recovery_img_sha1, &size);
+ std::string recovery_img_size = std::to_string(size);
+
+ std::string bonus_file = from_testdata_base("bonus.file");
+
+ // applypatch -b <bonus-file> <src-file> <tgt-file> <tgt-sha1> <tgt-size> <src-sha1>:<patch>
+ TemporaryFile tmp1;
+ std::string src_file =
+ "EMMC:" + boot_img + ":" + std::to_string(boot_img_size) + ":" + boot_img_sha1;
+ std::string tgt_file = "EMMC:" + std::string(tmp1.path);
+ std::string patch = boot_img_sha1 + ":" + from_testdata_base("recovery-from-boot.p");
+ std::vector<const char*> args = {
+ "applypatch",
+ "-b",
+ bonus_file.c_str(),
+ src_file.c_str(),
+ tgt_file.c_str(),
+ recovery_img_sha1.c_str(),
+ recovery_img_size.c_str(),
+ patch.c_str()
+ };
+ ASSERT_EQ(0, applypatch_modes(args.size(), args.data()));
+
+ // applypatch <src-file> <tgt-file> <tgt-sha1> <tgt-size> <src-sha1>:<patch>
+ TemporaryFile tmp2;
+ patch = boot_img_sha1 + ":" + from_testdata_base("recovery-from-boot-with-bonus.p");
+ tgt_file = "EMMC:" + std::string(tmp2.path);
+ std::vector<const char*> args2 = {
+ "applypatch",
+ src_file.c_str(),
+ tgt_file.c_str(),
+ recovery_img_sha1.c_str(),
+ recovery_img_size.c_str(),
+ patch.c_str()
+ };
+ ASSERT_EQ(0, applypatch_modes(args2.size(), args2.data()));
+
+ // applypatch -b <bonus-file> <src-file> <tgt-file> <tgt-sha1> <tgt-size> \
+ // <src-sha1-fake>:<patch1> <src-sha1>:<patch2>
+ TemporaryFile tmp3;
+ tgt_file = "EMMC:" + std::string(tmp3.path);
+ std::string bad_sha1_a = android::base::StringPrintf("%040x", rand());
+ std::string bad_sha1_b = android::base::StringPrintf("%040x", rand());
+ std::string patch1 = bad_sha1_a + ":" + from_testdata_base("recovery-from-boot.p");
+ std::string patch2 = boot_img_sha1 + ":" + from_testdata_base("recovery-from-boot.p");
+ std::string patch3 = bad_sha1_b + ":" + from_testdata_base("recovery-from-boot.p");
+ std::vector<const char*> args3 = {
+ "applypatch",
+ "-b",
+ bonus_file.c_str(),
+ src_file.c_str(),
+ tgt_file.c_str(),
+ recovery_img_sha1.c_str(),
+ recovery_img_size.c_str(),
+ patch1.c_str(),
+ patch2.c_str(),
+ patch3.c_str()
};
ASSERT_EQ(0, applypatch_modes(args3.size(), args3.data()));
}
-TEST(ApplyPatchModes, PatchModeInvalidArgs) {
+TEST(ApplyPatchModesTest, PatchModeInvalidArgs) {
// Invalid bonus file.
ASSERT_NE(0, applypatch_modes(3, (const char* []){ "applypatch", "-b", "/doesntexist" }));
@@ -388,9 +496,10 @@ TEST(ApplyPatchModes, PatchModeInvalidArgs) {
sha1sum(boot_img, &boot_img_sha1, &boot_img_size);
std::string recovery_img = from_testdata_base("recovery.img");
- size_t recovery_img_size;
+ size_t size;
std::string recovery_img_sha1;
- sha1sum(recovery_img, &recovery_img_sha1, &recovery_img_size);
+ sha1sum(recovery_img, &recovery_img_sha1, &size);
+ std::string recovery_img_size = std::to_string(size);
// Bonus file is not supported in flash mode.
// applypatch -b <bonus-file> <src-file> <tgt-file> <tgt-sha1> <tgt-size>
@@ -402,40 +511,44 @@ TEST(ApplyPatchModes, PatchModeInvalidArgs) {
boot_img.c_str(),
tmp4.path,
recovery_img_sha1.c_str(),
- std::to_string(recovery_img_size).c_str() };
+ recovery_img_size.c_str()
+ };
ASSERT_NE(0, applypatch_modes(args4.size(), args4.data()));
// Failed to parse patch args.
TemporaryFile tmp5;
+ std::string bad_arg1 =
+ "invalid-sha1:filename" + from_testdata_base("recovery-from-boot-with-bonus.p");
std::vector<const char*> args5 = {
"applypatch",
boot_img.c_str(),
tmp5.path,
recovery_img_sha1.c_str(),
- std::to_string(recovery_img_size).c_str(),
- ("invalid-sha1:filename" + from_testdata_base("recovery-from-boot-with-bonus.p")).c_str(),
+ recovery_img_size.c_str(),
+ bad_arg1.c_str()
};
ASSERT_NE(0, applypatch_modes(args5.size(), args5.data()));
// Target size cannot be zero.
TemporaryFile tmp6;
+ std::string patch = boot_img_sha1 + ":" + from_testdata_base("recovery-from-boot-with-bonus.p");
std::vector<const char*> args6 = {
"applypatch",
boot_img.c_str(),
tmp6.path,
recovery_img_sha1.c_str(),
"0", // target size
- (boot_img_sha1 + ":" + from_testdata_base("recovery-from-boot-with-bonus.p")).c_str()
+ patch.c_str()
};
ASSERT_NE(0, applypatch_modes(args6.size(), args6.data()));
}
-TEST(ApplyPatchModes, CheckModeInvalidArgs) {
+TEST(ApplyPatchModesTest, CheckModeInvalidArgs) {
// Insufficient args.
ASSERT_EQ(2, applypatch_modes(2, (const char* []){ "applypatch", "-c" }));
}
-TEST(ApplyPatchModes, SpaceModeInvalidArgs) {
+TEST(ApplyPatchModesTest, SpaceModeInvalidArgs) {
// Insufficient args.
ASSERT_EQ(2, applypatch_modes(2, (const char* []){ "applypatch", "-s" }));
@@ -449,6 +562,6 @@ TEST(ApplyPatchModes, SpaceModeInvalidArgs) {
ASSERT_EQ(0, applypatch_modes(3, (const char* []){ "applypatch", "-s", "0x10" }));
}
-TEST(ApplyPatchModes, ShowLicenses) {
+TEST(ApplyPatchModesTest, ShowLicenses) {
ASSERT_EQ(0, applypatch_modes(2, (const char* []){ "applypatch", "-l" }));
}
diff --git a/updater/install.cpp b/updater/install.cpp
index b9bc19e2c..8db5c1fe0 100644
--- a/updater/install.cpp
+++ b/updater/install.cpp
@@ -509,8 +509,8 @@ Value* PackageExtractFileFn(const char* name, State* state, int argc, Expr* argv
return StringValue("");
}
- int fd = TEMP_FAILURE_RETRY(
- ota_open(dest_path.c_str(), O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR));
+ unique_fd fd(TEMP_FAILURE_RETRY(
+ ota_open(dest_path.c_str(), O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR)));
if (fd == -1) {
printf("%s: can't open %s for write: %s\n", name, dest_path.c_str(), strerror(errno));
return StringValue("");
@@ -872,68 +872,67 @@ Value* GetPropFn(const char* name, State* state, int argc, Expr* argv[]) {
// per line. # comment lines, blank lines, lines without '=' ignored),
// and returns the value for 'key' (or "" if it isn't defined).
Value* FileGetPropFn(const char* name, State* state, int argc, Expr* argv[]) {
- if (argc != 2) {
- return ErrorAbort(state, kArgsParsingFailure, "%s() expects 2 args, got %d", name, argc);
- }
+ if (argc != 2) {
+ return ErrorAbort(state, kArgsParsingFailure, "%s() expects 2 args, got %d", name, argc);
+ }
- std::vector<std::string> args;
- if (!ReadArgs(state, 2, argv, &args)) {
- return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name);
- }
- const std::string& filename = args[0];
- const std::string& key = args[1];
+ std::vector<std::string> args;
+ if (!ReadArgs(state, 2, argv, &args)) {
+ return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name);
+ }
+ const std::string& filename = args[0];
+ const std::string& key = args[1];
- struct stat st;
- if (stat(filename.c_str(), &st) < 0) {
- return ErrorAbort(state, kFileGetPropFailure, "%s: failed to stat \"%s\": %s", name,
- filename.c_str(), strerror(errno));
- }
+ struct stat st;
+ if (stat(filename.c_str(), &st) < 0) {
+ return ErrorAbort(state, kFileGetPropFailure, "%s: failed to stat \"%s\": %s", name,
+ filename.c_str(), strerror(errno));
+ }
- constexpr off_t MAX_FILE_GETPROP_SIZE = 65536;
- if (st.st_size > MAX_FILE_GETPROP_SIZE) {
- return ErrorAbort(state, kFileGetPropFailure, "%s too large for %s (max %lld)",
- filename.c_str(), name, static_cast<long long>(MAX_FILE_GETPROP_SIZE));
- }
+ constexpr off_t MAX_FILE_GETPROP_SIZE = 65536;
+ if (st.st_size > MAX_FILE_GETPROP_SIZE) {
+ return ErrorAbort(state, kFileGetPropFailure, "%s too large for %s (max %lld)",
+ filename.c_str(), name, static_cast<long long>(MAX_FILE_GETPROP_SIZE));
+ }
- std::string buffer(st.st_size, '\0');
- FILE* f = ota_fopen(filename.c_str(), "rb");
- if (f == nullptr) {
- return ErrorAbort(state, kFileOpenFailure, "%s: failed to open %s: %s", name,
- filename.c_str(), strerror(errno));
- }
+ std::string buffer(st.st_size, '\0');
+ unique_file f(ota_fopen(filename.c_str(), "rb"));
+ if (f == nullptr) {
+ return ErrorAbort(state, kFileOpenFailure, "%s: failed to open %s: %s", name, filename.c_str(),
+ strerror(errno));
+ }
- if (ota_fread(&buffer[0], 1, st.st_size, f) != static_cast<size_t>(st.st_size)) {
- ErrorAbort(state, kFreadFailure, "%s: failed to read %zu bytes from %s",
- name, static_cast<size_t>(st.st_size), filename.c_str());
- ota_fclose(f);
- return nullptr;
- }
+ if (ota_fread(&buffer[0], 1, st.st_size, f.get()) != static_cast<size_t>(st.st_size)) {
+ ErrorAbort(state, kFreadFailure, "%s: failed to read %zu bytes from %s", name,
+ static_cast<size_t>(st.st_size), filename.c_str());
+ return nullptr;
+ }
- ota_fclose(f);
+ ota_fclose(f);
- std::vector<std::string> lines = android::base::Split(buffer, "\n");
- for (size_t i = 0; i < lines.size(); i++) {
- std::string line = android::base::Trim(lines[i]);
+ std::vector<std::string> lines = android::base::Split(buffer, "\n");
+ for (size_t i = 0; i < lines.size(); i++) {
+ std::string line = android::base::Trim(lines[i]);
- // comment or blank line: skip to next line
- if (line.empty() || line[0] == '#') {
- continue;
- }
- size_t equal_pos = line.find('=');
- if (equal_pos == std::string::npos) {
- continue;
- }
+ // comment or blank line: skip to next line
+ if (line.empty() || line[0] == '#') {
+ continue;
+ }
+ size_t equal_pos = line.find('=');
+ if (equal_pos == std::string::npos) {
+ continue;
+ }
- // trim whitespace between key and '='
- std::string str = android::base::Trim(line.substr(0, equal_pos));
+ // trim whitespace between key and '='
+ std::string str = android::base::Trim(line.substr(0, equal_pos));
- // not the key we're looking for
- if (key != str) continue;
+ // not the key we're looking for
+ if (key != str) continue;
- return StringValue(android::base::Trim(line.substr(equal_pos + 1)));
- }
+ return StringValue(android::base::Trim(line.substr(equal_pos + 1)));
+ }
- return StringValue("");
+ return StringValue("");
}
// apply_patch_space(bytes)
@@ -1292,29 +1291,26 @@ Value* GetStageFn(const char* name, State* state, int argc, Expr* argv[]) {
}
Value* WipeBlockDeviceFn(const char* name, State* state, int argc, Expr* argv[]) {
- if (argc != 2) {
- return ErrorAbort(state, kArgsParsingFailure, "%s() expects 2 args, got %d", name, argc);
- }
-
- std::vector<std::string> args;
- if (!ReadArgs(state, 2, argv, &args)) {
- return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name);
- }
- const std::string& filename = args[0];
- const std::string& len_str = args[1];
-
- size_t len;
- if (!android::base::ParseUint(len_str.c_str(), &len)) {
- return nullptr;
- }
- int fd = ota_open(filename.c_str(), O_WRONLY, 0644);
- // The wipe_block_device function in ext4_utils returns 0 on success and 1
- // for failure.
- int status = wipe_block_device(fd, len);
+ if (argc != 2) {
+ return ErrorAbort(state, kArgsParsingFailure, "%s() expects 2 args, got %d", name, argc);
+ }
- ota_close(fd);
+ std::vector<std::string> args;
+ if (!ReadArgs(state, 2, argv, &args)) {
+ return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name);
+ }
+ const std::string& filename = args[0];
+ const std::string& len_str = args[1];
- return StringValue((status == 0) ? "t" : "");
+ size_t len;
+ if (!android::base::ParseUint(len_str.c_str(), &len)) {
+ return nullptr;
+ }
+ unique_fd fd(ota_open(filename.c_str(), O_WRONLY, 0644));
+ // The wipe_block_device function in ext4_utils returns 0 on success and 1
+ // for failure.
+ int status = wipe_block_device(fd, len);
+ return StringValue((status == 0) ? "t" : "");
}
Value* EnableRebootFn(const char* name, State* state, int argc, Expr* argv[]) {