Merge "Change StringValue to use std::string"

This commit is contained in:
Treehugger Robot
2016-10-18 00:05:12 +00:00
committed by Gerrit Code Review
16 changed files with 507 additions and 530 deletions
+12 -16
View File
@@ -408,11 +408,10 @@ int ParseSha1(const char* str, uint8_t* digest) {
// Search an array of sha1 strings for one matching the given sha1. // 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 // Return the index of the match on success, or -1 if no match is
// found. // found.
int FindMatchingPatch(uint8_t* sha1, char* const * const patch_sha1_str, int FindMatchingPatch(uint8_t* sha1, const std::vector<std::string>& patch_sha1_str) {
int num_patches) { for (size_t i = 0; i < patch_sha1_str.size(); ++i) {
uint8_t patch_sha1[SHA_DIGEST_LENGTH]; uint8_t patch_sha1[SHA_DIGEST_LENGTH];
for (int i = 0; i < num_patches; ++i) { if (ParseSha1(patch_sha1_str[i].c_str(), patch_sha1) == 0 &&
if (ParseSha1(patch_sha1_str[i], patch_sha1) == 0 &&
memcmp(patch_sha1, sha1, SHA_DIGEST_LENGTH) == 0) { memcmp(patch_sha1, sha1, SHA_DIGEST_LENGTH) == 0) {
return i; return i;
} }
@@ -423,8 +422,7 @@ int FindMatchingPatch(uint8_t* sha1, char* const * const patch_sha1_str,
// Returns 0 if the contents of the file (argv[2]) or the cached file // 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 // match any of the sha1's on the command line (argv[3:]). Returns
// nonzero otherwise. // nonzero otherwise.
int applypatch_check(const char* filename, int num_patches, int applypatch_check(const char* filename, const std::vector<std::string>& patch_sha1_str) {
char** const patch_sha1_str) {
FileContents file; FileContents file;
// It's okay to specify no sha1s; the check will pass if the // It's okay to specify no sha1s; the check will pass if the
@@ -432,8 +430,7 @@ int applypatch_check(const char* filename, int num_patches,
// partitions, where the filename encodes the sha1s; no need to // partitions, where the filename encodes the sha1s; no need to
// check them twice.) // check them twice.)
if (LoadFileContents(filename, &file) != 0 || if (LoadFileContents(filename, &file) != 0 ||
(num_patches > 0 && FindMatchingPatch(file.sha1, patch_sha1_str) < 0) {
FindMatchingPatch(file.sha1, patch_sha1_str, num_patches) < 0)) {
printf("file \"%s\" doesn't have any of expected " printf("file \"%s\" doesn't have any of expected "
"sha1 sums; checking cache\n", filename); "sha1 sums; checking cache\n", filename);
@@ -448,7 +445,7 @@ int applypatch_check(const char* filename, int num_patches,
return 1; return 1;
} }
if (FindMatchingPatch(file.sha1, patch_sha1_str, num_patches) < 0) { if (FindMatchingPatch(file.sha1, patch_sha1_str) < 0) {
printf("cache bits don't match any sha1 for \"%s\"\n", filename); printf("cache bits don't match any sha1 for \"%s\"\n", filename);
return 1; return 1;
} }
@@ -532,8 +529,7 @@ int applypatch(const char* source_filename,
const char* target_filename, const char* target_filename,
const char* target_sha1_str, const char* target_sha1_str,
size_t target_size, size_t target_size,
int num_patches, const std::vector<std::string>& patch_sha1_str,
char** const patch_sha1_str,
Value** patch_data, Value** patch_data,
Value* bonus_data) { Value* bonus_data) {
printf("patch %s: ", source_filename); printf("patch %s: ", source_filename);
@@ -573,7 +569,7 @@ int applypatch(const char* source_filename,
} }
if (!source_file.data.empty()) { if (!source_file.data.empty()) {
int to_use = FindMatchingPatch(source_file.sha1, patch_sha1_str, num_patches); int to_use = FindMatchingPatch(source_file.sha1, patch_sha1_str);
if (to_use >= 0) { if (to_use >= 0) {
source_patch_value = patch_data[to_use]; source_patch_value = patch_data[to_use];
} }
@@ -589,7 +585,7 @@ int applypatch(const char* source_filename,
return 1; return 1;
} }
int to_use = FindMatchingPatch(copy_file.sha1, patch_sha1_str, num_patches); int to_use = FindMatchingPatch(copy_file.sha1, patch_sha1_str);
if (to_use >= 0) { if (to_use >= 0) {
copy_patch_value = patch_data[to_use]; copy_patch_value = patch_data[to_use];
} }
@@ -701,8 +697,8 @@ static int GenerateTarget(FileContents* source_file,
printf("patch is not a blob\n"); printf("patch is not a blob\n");
return 1; return 1;
} }
char* header = patch->data; const char* header = &patch->data[0];
ssize_t header_bytes_read = patch->size; size_t header_bytes_read = patch->data.size();
bool use_bsdiff = false; bool use_bsdiff = false;
if (header_bytes_read >= 8 && memcmp(header, "BSDIFF40", 8) == 0) { if (header_bytes_read >= 8 && memcmp(header, "BSDIFF40", 8) == 0) {
use_bsdiff = true; use_bsdiff = true;
+6 -6
View File
@@ -64,7 +64,7 @@ void ShowBSDiffLicense() {
); );
} }
static off_t offtin(u_char *buf) static off_t offtin(const u_char *buf)
{ {
off_t y; off_t y;
@@ -130,7 +130,7 @@ int ApplyBSDiffPatchMem(const unsigned char* old_data, ssize_t old_size,
// from oldfile to x bytes from the diff block; copy y bytes from the // from oldfile to x bytes from the diff block; copy y bytes from the
// extra block; seek forwards in oldfile by z bytes". // extra block; seek forwards in oldfile by z bytes".
unsigned char* header = (unsigned char*) patch->data + patch_offset; const unsigned char* header = reinterpret_cast<const unsigned char*>(&patch->data[patch_offset]);
if (memcmp(header, "BSDIFF40", 8) != 0) { if (memcmp(header, "BSDIFF40", 8) != 0) {
printf("corrupt bsdiff patch file header (magic number)\n"); printf("corrupt bsdiff patch file header (magic number)\n");
return 1; return 1;
@@ -149,7 +149,7 @@ int ApplyBSDiffPatchMem(const unsigned char* old_data, ssize_t old_size,
int bzerr; int bzerr;
bz_stream cstream; bz_stream cstream;
cstream.next_in = patch->data + patch_offset + 32; cstream.next_in = const_cast<char*>(&patch->data[patch_offset + 32]);
cstream.avail_in = ctrl_len; cstream.avail_in = ctrl_len;
cstream.bzalloc = NULL; cstream.bzalloc = NULL;
cstream.bzfree = NULL; cstream.bzfree = NULL;
@@ -159,7 +159,7 @@ int ApplyBSDiffPatchMem(const unsigned char* old_data, ssize_t old_size,
} }
bz_stream dstream; bz_stream dstream;
dstream.next_in = patch->data + patch_offset + 32 + ctrl_len; dstream.next_in = const_cast<char*>(&patch->data[patch_offset + 32 + ctrl_len]);
dstream.avail_in = data_len; dstream.avail_in = data_len;
dstream.bzalloc = NULL; dstream.bzalloc = NULL;
dstream.bzfree = NULL; dstream.bzfree = NULL;
@@ -169,8 +169,8 @@ int ApplyBSDiffPatchMem(const unsigned char* old_data, ssize_t old_size,
} }
bz_stream estream; bz_stream estream;
estream.next_in = patch->data + patch_offset + 32 + ctrl_len + data_len; estream.next_in = const_cast<char*>(&patch->data[patch_offset + 32 + ctrl_len + data_len]);
estream.avail_in = patch->size - (patch_offset + 32 + ctrl_len + data_len); estream.avail_in = patch->data.size() - (patch_offset + 32 + ctrl_len + data_len);
estream.bzalloc = NULL; estream.bzalloc = NULL;
estream.bzfree = NULL; estream.bzfree = NULL;
estream.opaque = NULL; estream.opaque = NULL;
+22 -22
View File
@@ -24,6 +24,7 @@
#include <unistd.h> #include <unistd.h>
#include <string.h> #include <string.h>
#include <string>
#include <vector> #include <vector>
#include "zlib.h" #include "zlib.h"
@@ -35,10 +36,10 @@
int ApplyImagePatch(const unsigned char* old_data, ssize_t old_size, int ApplyImagePatch(const unsigned char* old_data, ssize_t old_size,
const unsigned char* patch_data, ssize_t patch_size, const unsigned char* patch_data, ssize_t patch_size,
SinkFn sink, void* token) { SinkFn sink, void* token) {
Value patch = {VAL_BLOB, patch_size, Value patch(VAL_BLOB, std::string(
reinterpret_cast<char*>(const_cast<unsigned char*>(patch_data))}; reinterpret_cast<const char*>(patch_data), patch_size));
return ApplyImagePatch(
old_data, old_size, &patch, sink, token, nullptr, nullptr); return ApplyImagePatch(old_data, old_size, &patch, sink, token, nullptr, nullptr);
} }
/* /*
@@ -51,9 +52,7 @@ int ApplyImagePatch(const unsigned char* old_data, ssize_t old_size,
const Value* patch, const Value* patch,
SinkFn sink, void* token, SHA_CTX* ctx, SinkFn sink, void* token, SHA_CTX* ctx,
const Value* bonus_data) { const Value* bonus_data) {
ssize_t pos = 12; if (patch->data.size() < 12) {
char* header = patch->data;
if (patch->size < 12) {
printf("patch too short to contain header\n"); printf("patch too short to contain header\n");
return -1; return -1;
} }
@@ -61,6 +60,8 @@ int ApplyImagePatch(const unsigned char* old_data, ssize_t old_size,
// IMGDIFF2 uses CHUNK_NORMAL, CHUNK_DEFLATE, and CHUNK_RAW. // IMGDIFF2 uses CHUNK_NORMAL, CHUNK_DEFLATE, and CHUNK_RAW.
// (IMGDIFF1, which is no longer supported, used CHUNK_NORMAL and // (IMGDIFF1, which is no longer supported, used CHUNK_NORMAL and
// CHUNK_GZIP.) // CHUNK_GZIP.)
size_t pos = 12;
const char* header = &patch->data[0];
if (memcmp(header, "IMGDIFF2", 8) != 0) { if (memcmp(header, "IMGDIFF2", 8) != 0) {
printf("corrupt patch file header (magic number)\n"); printf("corrupt patch file header (magic number)\n");
return -1; return -1;
@@ -68,20 +69,19 @@ int ApplyImagePatch(const unsigned char* old_data, ssize_t old_size,
int num_chunks = Read4(header+8); int num_chunks = Read4(header+8);
int i; for (int i = 0; i < num_chunks; ++i) {
for (i = 0; i < num_chunks; ++i) {
// each chunk's header record starts with 4 bytes. // each chunk's header record starts with 4 bytes.
if (pos + 4 > patch->size) { if (pos + 4 > patch->data.size()) {
printf("failed to read chunk %d record\n", i); printf("failed to read chunk %d record\n", i);
return -1; return -1;
} }
int type = Read4(patch->data + pos); int type = Read4(&patch->data[pos]);
pos += 4; pos += 4;
if (type == CHUNK_NORMAL) { if (type == CHUNK_NORMAL) {
char* normal_header = patch->data + pos; const char* normal_header = &patch->data[pos];
pos += 24; pos += 24;
if (pos > patch->size) { if (pos > patch->data.size()) {
printf("failed to read chunk %d normal header data\n", i); printf("failed to read chunk %d normal header data\n", i);
return -1; return -1;
} }
@@ -97,21 +97,21 @@ int ApplyImagePatch(const unsigned char* old_data, ssize_t old_size,
ApplyBSDiffPatch(old_data + src_start, src_len, ApplyBSDiffPatch(old_data + src_start, src_len,
patch, patch_offset, sink, token, ctx); patch, patch_offset, sink, token, ctx);
} else if (type == CHUNK_RAW) { } else if (type == CHUNK_RAW) {
char* raw_header = patch->data + pos; const char* raw_header = &patch->data[pos];
pos += 4; pos += 4;
if (pos > patch->size) { if (pos > patch->data.size()) {
printf("failed to read chunk %d raw header data\n", i); printf("failed to read chunk %d raw header data\n", i);
return -1; return -1;
} }
ssize_t data_len = Read4(raw_header); ssize_t data_len = Read4(raw_header);
if (pos + data_len > patch->size) { if (pos + data_len > patch->data.size()) {
printf("failed to read chunk %d raw data\n", i); printf("failed to read chunk %d raw data\n", i);
return -1; return -1;
} }
if (ctx) SHA1_Update(ctx, patch->data + pos, data_len); if (ctx) SHA1_Update(ctx, &patch->data[pos], data_len);
if (sink((unsigned char*)patch->data + pos, if (sink(reinterpret_cast<const unsigned char*>(&patch->data[pos]),
data_len, token) != data_len) { data_len, token) != data_len) {
printf("failed to write chunk %d raw data\n", i); printf("failed to write chunk %d raw data\n", i);
return -1; return -1;
@@ -119,9 +119,9 @@ int ApplyImagePatch(const unsigned char* old_data, ssize_t old_size,
pos += data_len; pos += data_len;
} else if (type == CHUNK_DEFLATE) { } else if (type == CHUNK_DEFLATE) {
// deflate chunks have an additional 60 bytes in their chunk header. // deflate chunks have an additional 60 bytes in their chunk header.
char* deflate_header = patch->data + pos; const char* deflate_header = &patch->data[pos];
pos += 60; pos += 60;
if (pos > patch->size) { if (pos > patch->data.size()) {
printf("failed to read chunk %d deflate header data\n", i); printf("failed to read chunk %d deflate header data\n", i);
return -1; return -1;
} }
@@ -149,7 +149,7 @@ int ApplyImagePatch(const unsigned char* old_data, ssize_t old_size,
// the patch was constructed with bonus data. The // the patch was constructed with bonus data. The
// deflation will come up 'bonus_size' bytes short; these // deflation will come up 'bonus_size' bytes short; these
// must be appended from the bonus_data value. // must be appended from the bonus_data value.
size_t bonus_size = (i == 1 && bonus_data != NULL) ? bonus_data->size : 0; size_t bonus_size = (i == 1 && bonus_data != NULL) ? bonus_data->data.size() : 0;
std::vector<unsigned char> expanded_source(expanded_len); std::vector<unsigned char> expanded_source(expanded_len);
@@ -189,7 +189,7 @@ int ApplyImagePatch(const unsigned char* old_data, ssize_t old_size,
if (bonus_size) { if (bonus_size) {
memcpy(expanded_source.data() + (expanded_len - bonus_size), memcpy(expanded_source.data() + (expanded_len - bonus_size),
bonus_data->data, bonus_size); &bonus_data->data[0], bonus_size);
} }
} }
+4 -6
View File
@@ -20,6 +20,7 @@
#include <stdint.h> #include <stdint.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <string>
#include <vector> #include <vector>
#include "openssl/sha.h" #include "openssl/sha.h"
@@ -52,19 +53,16 @@ int applypatch(const char* source_filename,
const char* target_filename, const char* target_filename,
const char* target_sha1_str, const char* target_sha1_str,
size_t target_size, size_t target_size,
int num_patches, const std::vector<std::string>& patch_sha1_str,
char** const patch_sha1_str,
Value** patch_data, Value** patch_data,
Value* bonus_data); Value* bonus_data);
int applypatch_check(const char* filename, int applypatch_check(const char* filename,
int num_patches, const std::vector<std::string>& patch_sha1_str);
char** const patch_sha1_str);
int LoadFileContents(const char* filename, FileContents* file); int LoadFileContents(const char* filename, FileContents* file);
int SaveFileContents(const char* filename, const FileContents* file); int SaveFileContents(const char* filename, const FileContents* file);
void FreeFileContents(FileContents* file); void FreeFileContents(FileContents* file);
int FindMatchingPatch(uint8_t* sha1, char* const * const patch_sha1_str, int FindMatchingPatch(uint8_t* sha1, const std::vector<std::string>& patch_sha1_str);
int num_patches);
// bsdiff.cpp // bsdiff.cpp
void ShowBSDiffLicense(); void ShowBSDiffLicense();
+22 -20
View File
@@ -20,6 +20,7 @@
#include <unistd.h> #include <unistd.h>
#include <memory> #include <memory>
#include <string>
#include <vector> #include <vector>
#include "applypatch/applypatch.h" #include "applypatch/applypatch.h"
@@ -30,7 +31,12 @@ static int CheckMode(int argc, char** argv) {
if (argc < 3) { if (argc < 3) {
return 2; return 2;
} }
return applypatch_check(argv[2], argc-3, argv+3); std::vector<std::string> sha1;
for (int i = 3; i < argc; i++) {
sha1.push_back(argv[i]);
}
return applypatch_check(argv[2], sha1);
} }
static int SpaceMode(int argc, char** argv) { static int SpaceMode(int argc, char** argv) {
@@ -49,11 +55,13 @@ static int SpaceMode(int argc, char** argv) {
// Parse arguments (which should be of the form "<sha1>:<filename>" // Parse arguments (which should be of the form "<sha1>:<filename>"
// into the new parallel arrays *sha1s and *files.Returns true on // into the new parallel arrays *sha1s and *files.Returns true on
// success. // success.
static bool ParsePatchArgs(int argc, char** argv, std::vector<char*>* sha1s, static bool ParsePatchArgs(int argc, char** argv, std::vector<std::string>* sha1s,
std::vector<FileContents>* files) { std::vector<FileContents>* files) {
uint8_t digest[SHA_DIGEST_LENGTH]; if (sha1s == nullptr) {
return false;
}
for (int i = 0; i < argc; ++i) { for (int i = 0; i < argc; ++i) {
uint8_t digest[SHA_DIGEST_LENGTH];
char* colon = strchr(argv[i], ':'); char* colon = strchr(argv[i], ':');
if (colon == nullptr) { if (colon == nullptr) {
printf("no ':' in patch argument \"%s\"\n", argv[i]); printf("no ':' in patch argument \"%s\"\n", argv[i]);
@@ -83,18 +91,15 @@ static int FlashMode(const char* src_filename, const char* tgt_filename,
static int PatchMode(int argc, char** argv) { static int PatchMode(int argc, char** argv) {
FileContents bonusFc; FileContents bonusFc;
Value bonusValue; Value bonus(VAL_INVALID, "");
Value* bonus = nullptr;
if (argc >= 3 && strcmp(argv[1], "-b") == 0) { if (argc >= 3 && strcmp(argv[1], "-b") == 0) {
if (LoadFileContents(argv[2], &bonusFc) != 0) { if (LoadFileContents(argv[2], &bonusFc) != 0) {
printf("failed to load bonus file %s\n", argv[2]); printf("failed to load bonus file %s\n", argv[2]);
return 1; return 1;
} }
bonus = &bonusValue; bonus.type = VAL_BLOB;
bonus->type = VAL_BLOB; bonus.data = reinterpret_cast<const char*>(bonusFc.data.data());
bonus->size = bonusFc.data.size();
bonus->data = reinterpret_cast<char*>(bonusFc.data.data());
argc -= 2; argc -= 2;
argv += 2; argv += 2;
} }
@@ -112,29 +117,26 @@ static int PatchMode(int argc, char** argv) {
// If no <src-sha1>:<patch> is provided, it is in flash mode. // If no <src-sha1>:<patch> is provided, it is in flash mode.
if (argc == 5) { if (argc == 5) {
if (bonus != nullptr) { if (bonus.type != VAL_INVALID) {
printf("bonus file not supported in flash mode\n"); printf("bonus file not supported in flash mode\n");
return 1; return 1;
} }
return FlashMode(argv[1], argv[2], argv[3], target_size); return FlashMode(argv[1], argv[2], argv[3], target_size);
} }
std::vector<char*> sha1s; std::vector<std::string> sha1s;
std::vector<FileContents> files; std::vector<FileContents> files;
if (!ParsePatchArgs(argc-5, argv+5, &sha1s, &files)) { if (!ParsePatchArgs(argc-5, argv+5, &sha1s, &files)) {
printf("failed to parse patch args\n"); printf("failed to parse patch args\n");
return 1; return 1;
} }
std::vector<Value> patches(files.size()); std::vector<Value> patches;
std::vector<Value*> patch_ptrs(files.size()); std::vector<Value*> patch_ptrs;
for (size_t i = 0; i < files.size(); ++i) { for (size_t i = 0; i < files.size(); ++i) {
patches[i].type = VAL_BLOB; patches.push_back(Value(VAL_BLOB, reinterpret_cast<const char*>(files[i].data.data())));
patches[i].size = files[i].data.size(); patch_ptrs.push_back(&patches[i]);
patches[i].data = reinterpret_cast<char*>(files[i].data.data());
patch_ptrs[i] = &patches[i];
} }
return applypatch(argv[1], argv[2], argv[3], target_size, return applypatch(argv[1], argv[2], argv[3], target_size,
patch_ptrs.size(), sha1s.data(), sha1s, patch_ptrs.data(), &bonus);
patch_ptrs.data(), bonus);
} }
// This program applies binary patches to files in a way that is safe // This program applies binary patches to files in a way that is safe
+6 -6
View File
@@ -38,22 +38,22 @@ void Write8(int64_t value, FILE* f) {
fputc((value >> 56) & 0xff, f); fputc((value >> 56) & 0xff, f);
} }
int Read2(void* pv) { int Read2(const void* pv) {
unsigned char* p = reinterpret_cast<unsigned char*>(pv); const unsigned char* p = reinterpret_cast<const unsigned char*>(pv);
return (int)(((unsigned int)p[1] << 8) | return (int)(((unsigned int)p[1] << 8) |
(unsigned int)p[0]); (unsigned int)p[0]);
} }
int Read4(void* pv) { int Read4(const void* pv) {
unsigned char* p = reinterpret_cast<unsigned char*>(pv); const unsigned char* p = reinterpret_cast<const unsigned char*>(pv);
return (int)(((unsigned int)p[3] << 24) | return (int)(((unsigned int)p[3] << 24) |
((unsigned int)p[2] << 16) | ((unsigned int)p[2] << 16) |
((unsigned int)p[1] << 8) | ((unsigned int)p[1] << 8) |
(unsigned int)p[0]); (unsigned int)p[0]);
} }
int64_t Read8(void* pv) { int64_t Read8(const void* pv) {
unsigned char* p = reinterpret_cast<unsigned char*>(pv); const unsigned char* p = reinterpret_cast<const unsigned char*>(pv);
return (int64_t)(((uint64_t)p[7] << 56) | return (int64_t)(((uint64_t)p[7] << 56) |
((uint64_t)p[6] << 48) | ((uint64_t)p[6] << 48) |
((uint64_t)p[5] << 40) | ((uint64_t)p[5] << 40) |
+3 -3
View File
@@ -24,8 +24,8 @@
void Write4(int value, FILE* f); void Write4(int value, FILE* f);
void Write8(int64_t value, FILE* f); void Write8(int64_t value, FILE* f);
int Read2(void* p); int Read2(const void* p);
int Read4(void* p); int Read4(const void* p);
int64_t Read8(void* p); int64_t Read8(const void* p);
#endif // _BUILD_TOOLS_APPLYPATCH_UTILS_H #endif // _BUILD_TOOLS_APPLYPATCH_UTILS_H
+3 -3
View File
@@ -66,12 +66,12 @@ int main(int argc, char** argv) {
ExprDump(0, root, buffer); ExprDump(0, root, buffer);
State state(buffer, nullptr); State state(buffer, nullptr);
char* result = Evaluate(&state, root); std::string result;
if (result == NULL) { if (!Evaluate(&state, root, &result)) {
printf("result was NULL, message is: %s\n", printf("result was NULL, message is: %s\n",
(state.errmsg.empty() ? "(NULL)" : state.errmsg.c_str())); (state.errmsg.empty() ? "(NULL)" : state.errmsg.c_str()));
} else { } else {
printf("result is [%s]\n", result); printf("result is [%s]\n", result.c_str());
} }
} }
return 0; return 0;
+174 -158
View File
@@ -22,184 +22,164 @@
#include <string.h> #include <string.h>
#include <unistd.h> #include <unistd.h>
#include <memory>
#include <string> #include <string>
#include <unordered_map> #include <unordered_map>
#include <vector>
#include <android-base/parseint.h>
#include <android-base/stringprintf.h> #include <android-base/stringprintf.h>
#include <android-base/strings.h> #include <android-base/strings.h>
// Functions should: // Functions should:
// //
// - return a malloc()'d string // - return a malloc()'d string
// - if Evaluate() on any argument returns NULL, return NULL. // - if Evaluate() on any argument returns nullptr, return nullptr.
int BooleanString(const char* s) { static bool BooleanString(const std::string& s) {
return s[0] != '\0'; return !s.empty();
} }
char* Evaluate(State* state, Expr* expr) { bool Evaluate(State* state, Expr* expr, std::string* result) {
Value* v = expr->fn(expr->name, state, expr->argc, expr->argv); if (result == nullptr) {
if (v == NULL) return NULL; return false;
}
std::unique_ptr<Value> v(expr->fn(expr->name, state, expr->argc, expr->argv));
if (!v) {
return false;
}
if (v->type != VAL_STRING) { if (v->type != VAL_STRING) {
ErrorAbort(state, kArgsParsingFailure, "expecting string, got value type %d", v->type); ErrorAbort(state, kArgsParsingFailure, "expecting string, got value type %d", v->type);
FreeValue(v); return false;
return NULL;
} }
char* result = v->data;
free(v); *result = v->data;
return result; return true;
} }
Value* EvaluateValue(State* state, Expr* expr) { Value* EvaluateValue(State* state, Expr* expr) {
return expr->fn(expr->name, state, expr->argc, expr->argv); return expr->fn(expr->name, state, expr->argc, expr->argv);
} }
Value* StringValue(char* str) { Value* StringValue(const char* str) {
if (str == NULL) return NULL; if (str == nullptr) {
Value* v = reinterpret_cast<Value*>(malloc(sizeof(Value))); return nullptr;
v->type = VAL_STRING; }
v->size = strlen(str); return new Value(VAL_STRING, str);
v->data = str;
return v;
} }
void FreeValue(Value* v) { Value* StringValue(const std::string& str) {
if (v == NULL) return; return StringValue(str.c_str());
free(v->data);
free(v);
} }
Value* ConcatFn(const char* name, State* state, int argc, Expr* argv[]) { Value* ConcatFn(const char* name, State* state, int argc, Expr* argv[]) {
if (argc == 0) { if (argc == 0) {
return StringValue(strdup("")); return StringValue("");
} }
char** strings = reinterpret_cast<char**>(malloc(argc * sizeof(char*))); std::string result;
int i; for (int i = 0; i < argc; ++i) {
for (i = 0; i < argc; ++i) { std::string str;
strings[i] = NULL; if (!Evaluate(state, argv[i], &str)) {
} return nullptr;
char* result = NULL;
int length = 0;
for (i = 0; i < argc; ++i) {
strings[i] = Evaluate(state, argv[i]);
if (strings[i] == NULL) {
goto done;
} }
length += strlen(strings[i]); result += str;
} }
result = reinterpret_cast<char*>(malloc(length+1));
int p;
p = 0;
for (i = 0; i < argc; ++i) {
strcpy(result+p, strings[i]);
p += strlen(strings[i]);
}
result[p] = '\0';
done:
for (i = 0; i < argc; ++i) {
free(strings[i]);
}
free(strings);
return StringValue(result); return StringValue(result);
} }
Value* IfElseFn(const char* name, State* state, int argc, Expr* argv[]) { Value* IfElseFn(const char* name, State* state, int argc, Expr* argv[]) {
if (argc != 2 && argc != 3) { if (argc != 2 && argc != 3) {
state->errmsg = "ifelse expects 2 or 3 arguments"; state->errmsg = "ifelse expects 2 or 3 arguments";
return NULL; return nullptr;
}
char* cond = Evaluate(state, argv[0]);
if (cond == NULL) {
return NULL;
} }
if (BooleanString(cond) == true) { std::string cond;
free(cond); if (!Evaluate(state, argv[0], &cond)) {
return EvaluateValue(state, argv[1]); return nullptr;
} else {
if (argc == 3) {
free(cond);
return EvaluateValue(state, argv[2]);
} else {
return StringValue(cond);
}
} }
if (!cond.empty()) {
return EvaluateValue(state, argv[1]);
} else if (argc == 3) {
return EvaluateValue(state, argv[2]);
}
return StringValue("");
} }
Value* AbortFn(const char* name, State* state, int argc, Expr* argv[]) { Value* AbortFn(const char* name, State* state, int argc, Expr* argv[]) {
char* msg = NULL; std::string msg;
if (argc > 0) { if (argc > 0 && Evaluate(state, argv[0], &msg)) {
msg = Evaluate(state, argv[0]);
}
if (msg) {
state->errmsg = msg; state->errmsg = msg;
} else { } else {
state->errmsg = "called abort()"; state->errmsg = "called abort()";
} }
return NULL; return nullptr;
} }
Value* AssertFn(const char* name, State* state, int argc, Expr* argv[]) { Value* AssertFn(const char* name, State* state, int argc, Expr* argv[]) {
int i; for (int i = 0; i < argc; ++i) {
for (i = 0; i < argc; ++i) { std::string result;
char* v = Evaluate(state, argv[i]); if (!Evaluate(state, argv[i], &result)) {
if (v == NULL) { return nullptr;
return NULL;
} }
int b = BooleanString(v); if (result.empty()) {
free(v);
if (!b) {
int len = argv[i]->end - argv[i]->start; int len = argv[i]->end - argv[i]->start;
state->errmsg = "assert failed: " + state->script.substr(argv[i]->start, len); state->errmsg = "assert failed: " + state->script.substr(argv[i]->start, len);
return NULL; return nullptr;
} }
} }
return StringValue(strdup("")); return StringValue("");
} }
Value* SleepFn(const char* name, State* state, int argc, Expr* argv[]) { Value* SleepFn(const char* name, State* state, int argc, Expr* argv[]) {
char* val = Evaluate(state, argv[0]); std::string val;
if (val == NULL) { if (!Evaluate(state, argv[0], &val)) {
return NULL; return nullptr;
}
int v;
if (!android::base::ParseInt(val.c_str(), &v, 0)) {
return nullptr;
} }
int v = strtol(val, NULL, 10);
sleep(v); sleep(v);
return StringValue(val); return StringValue(val);
} }
Value* StdoutFn(const char* name, State* state, int argc, Expr* argv[]) { Value* StdoutFn(const char* name, State* state, int argc, Expr* argv[]) {
int i; for (int i = 0; i < argc; ++i) {
for (i = 0; i < argc; ++i) { std::string v;
char* v = Evaluate(state, argv[i]); if (!Evaluate(state, argv[i], &v)) {
if (v == NULL) { return nullptr;
return NULL;
} }
fputs(v, stdout); fputs(v.c_str(), stdout);
free(v);
} }
return StringValue(strdup("")); return StringValue("");
} }
Value* LogicalAndFn(const char* name, State* state, Value* LogicalAndFn(const char* name, State* state,
int argc, Expr* argv[]) { int argc, Expr* argv[]) {
char* left = Evaluate(state, argv[0]); std::string left;
if (left == NULL) return NULL; if (!Evaluate(state, argv[0], &left)) {
if (BooleanString(left) == true) { return nullptr;
free(left); }
if (BooleanString(left)) {
return EvaluateValue(state, argv[1]); return EvaluateValue(state, argv[1]);
} else { } else {
return StringValue(left); return StringValue("");
} }
} }
Value* LogicalOrFn(const char* name, State* state, Value* LogicalOrFn(const char* name, State* state,
int argc, Expr* argv[]) { int argc, Expr* argv[]) {
char* left = Evaluate(state, argv[0]); std::string left;
if (left == NULL) return NULL; if (!Evaluate(state, argv[0], &left)) {
if (BooleanString(left) == false) { return nullptr;
free(left); }
if (!BooleanString(left)) {
return EvaluateValue(state, argv[1]); return EvaluateValue(state, argv[1]);
} else { } else {
return StringValue(left); return StringValue(left);
@@ -208,75 +188,75 @@ Value* LogicalOrFn(const char* name, State* state,
Value* LogicalNotFn(const char* name, State* state, Value* LogicalNotFn(const char* name, State* state,
int argc, Expr* argv[]) { int argc, Expr* argv[]) {
char* val = Evaluate(state, argv[0]); std::string val;
if (val == NULL) return NULL; if (!Evaluate(state, argv[0], &val)) {
bool bv = BooleanString(val); return nullptr;
free(val); }
return StringValue(strdup(bv ? "" : "t"));
return StringValue(BooleanString(val) ? "" : "t");
} }
Value* SubstringFn(const char* name, State* state, Value* SubstringFn(const char* name, State* state,
int argc, Expr* argv[]) { int argc, Expr* argv[]) {
char* needle = Evaluate(state, argv[0]); std::string needle;
if (needle == NULL) return NULL; if (!Evaluate(state, argv[0], &needle)) {
char* haystack = Evaluate(state, argv[1]); return nullptr;
if (haystack == NULL) {
free(needle);
return NULL;
} }
char* result = strdup(strstr(haystack, needle) ? "t" : ""); std::string haystack;
free(needle); if (!Evaluate(state, argv[1], &haystack)) {
free(haystack); return nullptr;
}
std::string result = (haystack.find(needle) != std::string::npos) ? "t" : "";
return StringValue(result); return StringValue(result);
} }
Value* EqualityFn(const char* name, State* state, int argc, Expr* argv[]) { Value* EqualityFn(const char* name, State* state, int argc, Expr* argv[]) {
char* left = Evaluate(state, argv[0]); std::string left;
if (left == NULL) return NULL; if (!Evaluate(state, argv[0], &left)) {
char* right = Evaluate(state, argv[1]); return nullptr;
if (right == NULL) { }
free(left); std::string right;
return NULL; if (!Evaluate(state, argv[1], &right)) {
return nullptr;
} }
char* result = strdup(strcmp(left, right) == 0 ? "t" : ""); const char* result = (left == right) ? "t" : "";
free(left);
free(right);
return StringValue(result); return StringValue(result);
} }
Value* InequalityFn(const char* name, State* state, int argc, Expr* argv[]) { Value* InequalityFn(const char* name, State* state, int argc, Expr* argv[]) {
char* left = Evaluate(state, argv[0]); std::string left;
if (left == NULL) return NULL; if (!Evaluate(state, argv[0], &left)) {
char* right = Evaluate(state, argv[1]); return nullptr;
if (right == NULL) { }
free(left); std::string right;
return NULL; if (!Evaluate(state, argv[1], &right)) {
return nullptr;
} }
char* result = strdup(strcmp(left, right) != 0 ? "t" : ""); const char* result = (left != right) ? "t" : "";
free(left);
free(right);
return StringValue(result); return StringValue(result);
} }
Value* SequenceFn(const char* name, State* state, int argc, Expr* argv[]) { Value* SequenceFn(const char* name, State* state, int argc, Expr* argv[]) {
Value* left = EvaluateValue(state, argv[0]); std::unique_ptr<Value> left(EvaluateValue(state, argv[0]));
if (left == NULL) return NULL; if (!left) {
FreeValue(left); return nullptr;
}
return EvaluateValue(state, argv[1]); return EvaluateValue(state, argv[1]);
} }
Value* LessThanIntFn(const char* name, State* state, int argc, Expr* argv[]) { Value* LessThanIntFn(const char* name, State* state, int argc, Expr* argv[]) {
if (argc != 2) { if (argc != 2) {
state->errmsg = "less_than_int expects 2 arguments"; state->errmsg = "less_than_int expects 2 arguments";
return NULL; return nullptr;
} }
char* left; char* left;
char* right; char* right;
if (ReadArgs(state, argv, 2, &left, &right) < 0) return NULL; if (ReadArgs(state, argv, 2, &left, &right) < 0) return nullptr;
bool result = false; bool result = false;
char* end; char* end;
@@ -298,14 +278,14 @@ Value* LessThanIntFn(const char* name, State* state, int argc, Expr* argv[]) {
done: done:
free(left); free(left);
free(right); free(right);
return StringValue(strdup(result ? "t" : "")); return StringValue(result ? "t" : "");
} }
Value* GreaterThanIntFn(const char* name, State* state, Value* GreaterThanIntFn(const char* name, State* state,
int argc, Expr* argv[]) { int argc, Expr* argv[]) {
if (argc != 2) { if (argc != 2) {
state->errmsg = "greater_than_int expects 2 arguments"; state->errmsg = "greater_than_int expects 2 arguments";
return NULL; return nullptr;
} }
Expr* temp[2]; Expr* temp[2];
@@ -316,7 +296,7 @@ Value* GreaterThanIntFn(const char* name, State* state,
} }
Value* Literal(const char* name, State* state, int argc, Expr* argv[]) { Value* Literal(const char* name, State* state, int argc, Expr* argv[]) {
return StringValue(strdup(name)); return StringValue(name);
} }
// ----------------------------------------------------------------- // -----------------------------------------------------------------
@@ -355,6 +335,43 @@ void RegisterBuiltins() {
// convenience methods for functions // convenience methods for functions
// ----------------------------------------------------------------- // -----------------------------------------------------------------
// Evaluate the expressions in argv, and put the results of strings in
// args. If any expression evaluates to nullptr, free the rest and return
// false. Return true on success.
bool ReadArgs(State* state, int argc, Expr* argv[], std::vector<std::string>* args) {
if (args == nullptr) {
return false;
}
for (int i = 0; i < argc; ++i) {
std::string var;
if (!Evaluate(state, argv[i], &var)) {
args->clear();
return false;
}
args->push_back(var);
}
return true;
}
// Evaluate the expressions in argv, and put the results of Value* in
// args. If any expression evaluate to nullptr, free the rest and return
// false. Return true on success.
bool ReadValueArgs(State* state, int argc, Expr* argv[],
std::vector<std::unique_ptr<Value>>* args) {
if (args == nullptr) {
return false;
}
for (int i = 0; i < argc; ++i) {
std::unique_ptr<Value> v(EvaluateValue(state, argv[i]));
if (!v) {
args->clear();
return false;
}
args->push_back(std::move(v));
}
return true;
}
// Evaluate the expressions in argv, giving 'count' char* (the ... is // Evaluate the expressions in argv, giving 'count' char* (the ... is
// zero or more char** to put them in). If any expression evaluates // zero or more char** to put them in). If any expression evaluates
// to NULL, free the rest and return -1. Return 0 on success. // to NULL, free the rest and return -1. Return 0 on success.
@@ -364,8 +381,9 @@ int ReadArgs(State* state, Expr* argv[], int count, ...) {
va_start(v, count); va_start(v, count);
int i; int i;
for (i = 0; i < count; ++i) { for (i = 0; i < count; ++i) {
args[i] = Evaluate(state, argv[i]); std::string str;
if (args[i] == NULL) { if (!Evaluate(state, argv[i], &str) ||
(args[i] = strdup(str.c_str())) == nullptr) {
va_end(v); va_end(v);
int j; int j;
for (j = 0; j < i; ++j) { for (j = 0; j < i; ++j) {
@@ -385,25 +403,24 @@ int ReadArgs(State* state, Expr* argv[], int count, ...) {
// zero or more Value** to put them in). If any expression evaluates // zero or more Value** to put them in). If any expression evaluates
// to NULL, free the rest and return -1. Return 0 on success. // to NULL, free the rest and return -1. Return 0 on success.
int ReadValueArgs(State* state, Expr* argv[], int count, ...) { int ReadValueArgs(State* state, Expr* argv[], int count, ...) {
Value** args = reinterpret_cast<Value**>(malloc(count * sizeof(Value*))); Value** args = new Value*[count];
va_list v; va_list v;
va_start(v, count); va_start(v, count);
int i; for (int i = 0; i < count; ++i) {
for (i = 0; i < count; ++i) {
args[i] = EvaluateValue(state, argv[i]); args[i] = EvaluateValue(state, argv[i]);
if (args[i] == NULL) { if (args[i] == NULL) {
va_end(v); va_end(v);
int j; int j;
for (j = 0; j < i; ++j) { for (j = 0; j < i; ++j) {
FreeValue(args[j]); delete args[j];
} }
free(args); delete[] args;
return -1; return -1;
} }
*(va_arg(v, Value**)) = args[i]; *(va_arg(v, Value**)) = args[i];
} }
va_end(v); va_end(v);
free(args); delete[] args;
return 0; return 0;
} }
@@ -413,12 +430,11 @@ int ReadValueArgs(State* state, Expr* argv[], int count, ...) {
// strings it contains. // strings it contains.
char** ReadVarArgs(State* state, int argc, Expr* argv[]) { char** ReadVarArgs(State* state, int argc, Expr* argv[]) {
char** args = (char**)malloc(argc * sizeof(char*)); char** args = (char**)malloc(argc * sizeof(char*));
int i = 0; for (int i = 0; i < argc; ++i) {
for (i = 0; i < argc; ++i) { std::string str;
args[i] = Evaluate(state, argv[i]); if (!Evaluate(state, argv[i], &str) ||
if (args[i] == NULL) { (args[i] = strdup(str.c_str())) == nullptr) {
int j; for (int j = 0; j < i; ++j) {
for (j = 0; j < i; ++j) {
free(args[j]); free(args[j]);
} }
free(args); free(args);
@@ -433,16 +449,16 @@ char** ReadVarArgs(State* state, int argc, Expr* argv[]) {
// The caller is responsible for freeing the returned array and the // The caller is responsible for freeing the returned array and the
// Values it contains. // Values it contains.
Value** ReadValueVarArgs(State* state, int argc, Expr* argv[]) { Value** ReadValueVarArgs(State* state, int argc, Expr* argv[]) {
Value** args = (Value**)malloc(argc * sizeof(Value*)); Value** args = new Value*[argc];
int i = 0; int i = 0;
for (i = 0; i < argc; ++i) { for (i = 0; i < argc; ++i) {
args[i] = EvaluateValue(state, argv[i]); args[i] = EvaluateValue(state, argv[i]);
if (args[i] == NULL) { if (args[i] == NULL) {
int j; int j;
for (j = 0; j < i; ++j) { for (j = 0; j < i; ++j) {
FreeValue(args[j]); delete args[j];
} }
free(args); delete[] args;
return NULL; return NULL;
} }
} }
+30 -14
View File
@@ -48,13 +48,19 @@ struct State {
bool is_retry = false; bool is_retry = false;
}; };
#define VAL_STRING 1 // data will be NULL-terminated; size doesn't count null enum ValueType {
#define VAL_BLOB 2 VAL_INVALID = -1,
VAL_STRING = 1,
VAL_BLOB = 2,
};
struct Value { struct Value {
int type; ValueType type;
ssize_t size; std::string data;
char* data;
Value(ValueType type, const std::string& str) :
type(type),
data(str) {}
}; };
struct Expr; struct Expr;
@@ -75,11 +81,11 @@ struct Expr {
Value* EvaluateValue(State* state, Expr* expr); Value* EvaluateValue(State* state, Expr* expr);
// Take one of the Expr*s passed to the function as an argument, // Take one of the Expr*s passed to the function as an argument,
// evaluate it, assert that it is a string, and return the resulting // evaluate it, assert that it is a string, and update the result
// char*. The caller takes ownership of the returned char*. This is // parameter. This function returns true if the evaluation succeeds.
// a convenience function for older functions that want to deal only // This is a convenience function for older functions that want to
// with strings. // deal only with strings.
char* Evaluate(State* state, Expr* expr); bool Evaluate(State* state, Expr* expr, std::string* result);
// Glue to make an Expr out of a literal. // Glue to make an Expr out of a literal.
Value* Literal(const char* name, State* state, int argc, Expr* argv[]); Value* Literal(const char* name, State* state, int argc, Expr* argv[]);
@@ -114,6 +120,17 @@ Function FindFunction(const std::string& name);
// --- convenience functions for use in functions --- // --- convenience functions for use in functions ---
// Evaluate the expressions in argv, and put the results of strings in
// args. If any expression evaluates to nullptr, free the rest and return
// false. Return true on success.
bool ReadArgs(State* state, int argc, Expr* argv[], std::vector<std::string>* args);
// Evaluate the expressions in argv, and put the results of Value* in
// args. If any expression evaluate to nullptr, free the rest and return
// false. Return true on success.
bool ReadValueArgs(State* state, int argc, Expr* argv[],
std::vector<std::unique_ptr<Value>>* args);
// Evaluate the expressions in argv, giving 'count' char* (the ... is // Evaluate the expressions in argv, giving 'count' char* (the ... is
// zero or more char** to put them in). If any expression evaluates // zero or more char** to put them in). If any expression evaluates
// to NULL, free the rest and return -1. Return 0 on success. // to NULL, free the rest and return -1. Return 0 on success.
@@ -146,11 +163,10 @@ Value* ErrorAbort(State* state, const char* format, ...)
Value* ErrorAbort(State* state, CauseCode cause_code, const char* format, ...) Value* ErrorAbort(State* state, CauseCode cause_code, const char* format, ...)
__attribute__((format(printf, 3, 4))); __attribute__((format(printf, 3, 4)));
// Wrap a string into a Value, taking ownership of the string. // Copying the string into a Value.
Value* StringValue(char* str); Value* StringValue(const char* str);
// Free a Value object. Value* StringValue(const std::string& str);
void FreeValue(Value* v);
int parse_string(const char* str, Expr** root, int* error_count); int parse_string(const char* str, Expr** root, int* error_count);
+59 -73
View File
@@ -153,25 +153,16 @@ class ApplyPatchFullTest : public ApplyPatchCacheTest {
struct FileContents fc; struct FileContents fc;
ASSERT_EQ(0, LoadFileContents(&rand_file[0], &fc)); ASSERT_EQ(0, LoadFileContents(&rand_file[0], &fc));
Value* patch1 = new Value(); Value* patch1 = new Value(VAL_BLOB, std::string(fc.data.begin(), fc.data.end()));
patch1->type = VAL_BLOB;
patch1->size = fc.data.size();
patch1->data = static_cast<char*>(malloc(fc.data.size()));
memcpy(patch1->data, fc.data.data(), fc.data.size());
patches.push_back(patch1); patches.push_back(patch1);
ASSERT_EQ(0, LoadFileContents(&patch_file[0], &fc)); ASSERT_EQ(0, LoadFileContents(&patch_file[0], &fc));
Value* patch2 = new Value(); Value* patch2 = new Value(VAL_BLOB, std::string(fc.data.begin(), fc.data.end()));
patch2->type = VAL_BLOB;
patch2->size = fc.st.st_size;
patch2->data = static_cast<char*>(malloc(fc.data.size()));
memcpy(patch2->data, fc.data.data(), fc.data.size());
patches.push_back(patch2); patches.push_back(patch2);
} }
static void TearDownTestCase() { static void TearDownTestCase() {
delete output_f; delete output_f;
for (auto it = patches.begin(); it != patches.end(); ++it) { for (auto it = patches.begin(); it != patches.end(); ++it) {
free((*it)->data);
delete *it; delete *it;
} }
patches.clear(); patches.clear();
@@ -210,88 +201,87 @@ TemporaryFile* ApplyPatchFullTest::output_f;
std::string ApplyPatchFullTest::output_loc; std::string ApplyPatchFullTest::output_loc;
TEST_F(ApplyPatchTest, CheckModeSingle) { TEST_F(ApplyPatchTest, CheckModeSingle) {
char* s = &old_sha1[0]; std::vector<std::string> sha1s = { old_sha1 };
ASSERT_EQ(0, applypatch_check(&old_file[0], 1, &s)); ASSERT_EQ(0, applypatch_check(&old_file[0], sha1s));
} }
TEST_F(ApplyPatchTest, CheckModeMultiple) { TEST_F(ApplyPatchTest, CheckModeMultiple) {
char* argv[3] = { std::vector<std::string> sha1s = {
&bad_sha1_a[0], bad_sha1_a,
&old_sha1[0], old_sha1,
&bad_sha1_b[0] bad_sha1_b
}; };
ASSERT_EQ(0, applypatch_check(&old_file[0], 3, argv)); ASSERT_EQ(0, applypatch_check(&old_file[0], sha1s));
} }
TEST_F(ApplyPatchTest, CheckModeFailure) { TEST_F(ApplyPatchTest, CheckModeFailure) {
char* argv[2] = { std::vector<std::string> sha1s = {
&bad_sha1_a[0], bad_sha1_a,
&bad_sha1_b[0] bad_sha1_b
}; };
ASSERT_NE(0, applypatch_check(&old_file[0], 2, argv)); ASSERT_NE(0, applypatch_check(&old_file[0], sha1s));
} }
TEST_F(ApplyPatchCacheTest, CheckCacheCorruptedSingle) { TEST_F(ApplyPatchCacheTest, CheckCacheCorruptedSingle) {
mangle_file(old_file); mangle_file(old_file);
char* s = &old_sha1[0]; std::vector<std::string> sha1s = { old_sha1 };
ASSERT_EQ(0, applypatch_check(&old_file[0], 1, &s)); ASSERT_EQ(0, applypatch_check(&old_file[0], sha1s));
} }
TEST_F(ApplyPatchCacheTest, CheckCacheCorruptedMultiple) { TEST_F(ApplyPatchCacheTest, CheckCacheCorruptedMultiple) {
mangle_file(old_file); mangle_file(old_file);
char* argv[3] = { std::vector<std::string> sha1s = {
&bad_sha1_a[0], bad_sha1_a,
&old_sha1[0], old_sha1,
&bad_sha1_b[0] bad_sha1_b
}; };
ASSERT_EQ(0, applypatch_check(&old_file[0], 3, argv)); ASSERT_EQ(0, applypatch_check(&old_file[0], sha1s));
} }
TEST_F(ApplyPatchCacheTest, CheckCacheCorruptedFailure) { TEST_F(ApplyPatchCacheTest, CheckCacheCorruptedFailure) {
mangle_file(old_file); mangle_file(old_file);
char* argv[2] = { std::vector<std::string> sha1s = {
&bad_sha1_a[0], bad_sha1_a,
&bad_sha1_b[0] bad_sha1_b
}; };
ASSERT_NE(0, applypatch_check(&old_file[0], 2, argv)); ASSERT_NE(0, applypatch_check(&old_file[0], sha1s));
} }
TEST_F(ApplyPatchCacheTest, CheckCacheMissingSingle) { TEST_F(ApplyPatchCacheTest, CheckCacheMissingSingle) {
unlink(&old_file[0]); unlink(&old_file[0]);
char* s = &old_sha1[0]; std::vector<std::string> sha1s = { old_sha1 };
ASSERT_EQ(0, applypatch_check(&old_file[0], 1, &s)); ASSERT_EQ(0, applypatch_check(&old_file[0], sha1s));
} }
TEST_F(ApplyPatchCacheTest, CheckCacheMissingMultiple) { TEST_F(ApplyPatchCacheTest, CheckCacheMissingMultiple) {
unlink(&old_file[0]); unlink(&old_file[0]);
char* argv[3] = { std::vector<std::string> sha1s = {
&bad_sha1_a[0], bad_sha1_a,
&old_sha1[0], old_sha1,
&bad_sha1_b[0] bad_sha1_b
}; };
ASSERT_EQ(0, applypatch_check(&old_file[0], 3, argv)); ASSERT_EQ(0, applypatch_check(&old_file[0], sha1s));
} }
TEST_F(ApplyPatchCacheTest, CheckCacheMissingFailure) { TEST_F(ApplyPatchCacheTest, CheckCacheMissingFailure) {
unlink(&old_file[0]); unlink(&old_file[0]);
char* argv[2] = { std::vector<std::string> sha1s = {
&bad_sha1_a[0], bad_sha1_a,
&bad_sha1_b[0] bad_sha1_b
}; };
ASSERT_NE(0, applypatch_check(&old_file[0], 2, argv)); ASSERT_NE(0, applypatch_check(&old_file[0], sha1s));
} }
TEST_F(ApplyPatchFullTest, ApplyInPlace) { TEST_F(ApplyPatchFullTest, ApplyInPlace) {
std::vector<char*> sha1s; std::vector<std::string> sha1s = {
sha1s.push_back(&bad_sha1_a[0]); bad_sha1_a,
sha1s.push_back(&old_sha1[0]); old_sha1
};
int ap_result = applypatch(&old_file[0], int ap_result = applypatch(&old_file[0],
"-", "-",
&new_sha1[0], &new_sha1[0],
new_size, new_size,
2, sha1s,
sha1s.data(),
patches.data(), patches.data(),
nullptr); nullptr);
ASSERT_EQ(0, ap_result); ASSERT_EQ(0, ap_result);
@@ -301,8 +291,7 @@ TEST_F(ApplyPatchFullTest, ApplyInPlace) {
"-", "-",
&new_sha1[0], &new_sha1[0],
new_size, new_size,
2, sha1s,
sha1s.data(),
patches.data(), patches.data(),
nullptr); nullptr);
ASSERT_EQ(0, ap_result); ASSERT_EQ(0, ap_result);
@@ -310,15 +299,15 @@ TEST_F(ApplyPatchFullTest, ApplyInPlace) {
} }
TEST_F(ApplyPatchFullTest, ApplyInNewLocation) { TEST_F(ApplyPatchFullTest, ApplyInNewLocation) {
std::vector<char*> sha1s; std::vector<std::string> sha1s = {
sha1s.push_back(&bad_sha1_a[0]); bad_sha1_a,
sha1s.push_back(&old_sha1[0]); old_sha1
};
int ap_result = applypatch(&old_file[0], int ap_result = applypatch(&old_file[0],
&output_loc[0], &output_loc[0],
&new_sha1[0], &new_sha1[0],
new_size, new_size,
2, sha1s,
sha1s.data(),
patches.data(), patches.data(),
nullptr); nullptr);
ASSERT_EQ(0, ap_result); ASSERT_EQ(0, ap_result);
@@ -327,8 +316,7 @@ TEST_F(ApplyPatchFullTest, ApplyInNewLocation) {
&output_loc[0], &output_loc[0],
&new_sha1[0], &new_sha1[0],
new_size, new_size,
2, sha1s,
sha1s.data(),
patches.data(), patches.data(),
nullptr); nullptr);
ASSERT_EQ(0, ap_result); ASSERT_EQ(0, ap_result);
@@ -337,15 +325,15 @@ TEST_F(ApplyPatchFullTest, ApplyInNewLocation) {
TEST_F(ApplyPatchFullTest, ApplyCorruptedInNewLocation) { TEST_F(ApplyPatchFullTest, ApplyCorruptedInNewLocation) {
mangle_file(old_file); mangle_file(old_file);
std::vector<char*> sha1s; std::vector<std::string> sha1s = {
sha1s.push_back(&bad_sha1_a[0]); bad_sha1_a,
sha1s.push_back(&old_sha1[0]); old_sha1
};
int ap_result = applypatch(&old_file[0], int ap_result = applypatch(&old_file[0],
&output_loc[0], &output_loc[0],
&new_sha1[0], &new_sha1[0],
new_size, new_size,
2, sha1s,
sha1s.data(),
patches.data(), patches.data(),
nullptr); nullptr);
ASSERT_EQ(0, ap_result); ASSERT_EQ(0, ap_result);
@@ -354,8 +342,7 @@ TEST_F(ApplyPatchFullTest, ApplyCorruptedInNewLocation) {
&output_loc[0], &output_loc[0],
&new_sha1[0], &new_sha1[0],
new_size, new_size,
2, sha1s,
sha1s.data(),
patches.data(), patches.data(),
nullptr); nullptr);
ASSERT_EQ(0, ap_result); ASSERT_EQ(0, ap_result);
@@ -366,15 +353,15 @@ TEST_F(ApplyPatchDoubleCacheTest, ApplyDoubleCorruptedInNewLocation) {
mangle_file(old_file); mangle_file(old_file);
mangle_file(cache_file); mangle_file(cache_file);
std::vector<char*> sha1s; std::vector<std::string> sha1s = {
sha1s.push_back(&bad_sha1_a[0]); bad_sha1_a,
sha1s.push_back(&old_sha1[0]); old_sha1
};
int ap_result = applypatch(&old_file[0], int ap_result = applypatch(&old_file[0],
&output_loc[0], &output_loc[0],
&new_sha1[0], &new_sha1[0],
new_size, new_size,
2, sha1s,
sha1s.data(),
patches.data(), patches.data(),
nullptr); nullptr);
ASSERT_NE(0, ap_result); ASSERT_NE(0, ap_result);
@@ -383,8 +370,7 @@ TEST_F(ApplyPatchDoubleCacheTest, ApplyDoubleCorruptedInNewLocation) {
&output_loc[0], &output_loc[0],
&new_sha1[0], &new_sha1[0],
new_size, new_size,
2, sha1s,
sha1s.data(),
patches.data(), patches.data(),
nullptr); nullptr);
ASSERT_NE(0, ap_result); ASSERT_NE(0, ap_result);
+4 -4
View File
@@ -28,15 +28,15 @@ static void expect(const char* expr_str, const char* expected) {
State state(expr_str, nullptr); State state(expr_str, nullptr);
char* result = Evaluate(&state, e); std::string result;
bool status = Evaluate(&state, e, &result);
if (expected == nullptr) { if (expected == nullptr) {
EXPECT_EQ(nullptr, result); EXPECT_FALSE(status);
} else { } else {
EXPECT_STREQ(expected, result); EXPECT_STREQ(expected, result.c_str());
} }
free(result);
} }
class EdifyTest : public ::testing::Test { class EdifyTest : public ::testing::Test {
+4 -4
View File
@@ -32,12 +32,13 @@ static void expect(const char* expected, const char* expr_str, CauseCode cause_c
State state(expr_str, nullptr); State state(expr_str, nullptr);
char* result = Evaluate(&state, e); std::string result;
bool status = Evaluate(&state, e, &result);
if (expected == nullptr) { if (expected == nullptr) {
EXPECT_EQ(nullptr, result); EXPECT_FALSE(status);
} else { } else {
EXPECT_STREQ(expected, result); EXPECT_STREQ(expected, result.c_str());
} }
// Error code is set in updater/updater.cpp only, by parsing State.errmsg. // Error code is set in updater/updater.cpp only, by parsing State.errmsg.
@@ -46,7 +47,6 @@ static void expect(const char* expected, const char* expr_str, CauseCode cause_c
// Cause code should always be available. // Cause code should always be available.
EXPECT_EQ(cause_code, state.cause_code); EXPECT_EQ(cause_code, state.cause_code);
free(result);
} }
class UpdaterTest : public ::testing::Test { class UpdaterTest : public ::testing::Test {
+73 -81
View File
@@ -1216,7 +1216,7 @@ static int PerformCommandDiff(CommandParameters& params) {
size_t len; size_t len;
if (!android::base::ParseUint(params.tokens[params.cpos++].c_str(), &len)) { if (!android::base::ParseUint(params.tokens[params.cpos++].c_str(), &len)) {
fprintf(stderr, "invalid patch offset\n"); fprintf(stderr, "invalid patch len\n");
return -1; return -1;
} }
@@ -1248,10 +1248,8 @@ static int PerformCommandDiff(CommandParameters& params) {
if (status == 0) { if (status == 0) {
fprintf(stderr, "patching %zu blocks to %zu\n", blocks, tgt.size); fprintf(stderr, "patching %zu blocks to %zu\n", blocks, tgt.size);
Value patch_value; Value patch_value(VAL_BLOB,
patch_value.type = VAL_BLOB; std::string(reinterpret_cast<const char*>(params.patch_start + offset), len));
patch_value.size = len;
patch_value.data = (char*) (params.patch_start + offset);
RangeSinkState rss(tgt); RangeSinkState rss(tgt);
rss.fd = params.fd; rss.fd = params.fd;
@@ -1398,64 +1396,62 @@ static Value* PerformBlockImageUpdate(const char* name, State* state, int /* arg
Value* patch_data_fn = nullptr; Value* patch_data_fn = nullptr;
if (ReadValueArgs(state, argv, 4, &blockdev_filename, &transfer_list_value, if (ReadValueArgs(state, argv, 4, &blockdev_filename, &transfer_list_value,
&new_data_fn, &patch_data_fn) < 0) { &new_data_fn, &patch_data_fn) < 0) {
return StringValue(strdup("")); return StringValue("");
} }
std::unique_ptr<Value, decltype(&FreeValue)> blockdev_filename_holder(blockdev_filename, std::unique_ptr<Value> blockdev_filename_holder(blockdev_filename);
FreeValue); std::unique_ptr<Value> transfer_list_value_holder(transfer_list_value);
std::unique_ptr<Value, decltype(&FreeValue)> transfer_list_value_holder(transfer_list_value, std::unique_ptr<Value> new_data_fn_holder(new_data_fn);
FreeValue); std::unique_ptr<Value> patch_data_fn_holder(patch_data_fn);
std::unique_ptr<Value, decltype(&FreeValue)> new_data_fn_holder(new_data_fn, FreeValue);
std::unique_ptr<Value, decltype(&FreeValue)> patch_data_fn_holder(patch_data_fn, FreeValue);
if (blockdev_filename->type != VAL_STRING) { if (blockdev_filename->type != VAL_STRING) {
ErrorAbort(state, kArgsParsingFailure, "blockdev_filename argument to %s must be string", ErrorAbort(state, kArgsParsingFailure, "blockdev_filename argument to %s must be string",
name); name);
return StringValue(strdup("")); return StringValue("");
} }
if (transfer_list_value->type != VAL_BLOB) { if (transfer_list_value->type != VAL_BLOB) {
ErrorAbort(state, kArgsParsingFailure, "transfer_list argument to %s must be blob", name); ErrorAbort(state, kArgsParsingFailure, "transfer_list argument to %s must be blob", name);
return StringValue(strdup("")); return StringValue("");
} }
if (new_data_fn->type != VAL_STRING) { if (new_data_fn->type != VAL_STRING) {
ErrorAbort(state, kArgsParsingFailure, "new_data_fn argument to %s must be string", name); ErrorAbort(state, kArgsParsingFailure, "new_data_fn argument to %s must be string", name);
return StringValue(strdup("")); return StringValue("");
} }
if (patch_data_fn->type != VAL_STRING) { if (patch_data_fn->type != VAL_STRING) {
ErrorAbort(state, kArgsParsingFailure, "patch_data_fn argument to %s must be string", ErrorAbort(state, kArgsParsingFailure, "patch_data_fn argument to %s must be string",
name); name);
return StringValue(strdup("")); return StringValue("");
} }
UpdaterInfo* ui = reinterpret_cast<UpdaterInfo*>(state->cookie); UpdaterInfo* ui = reinterpret_cast<UpdaterInfo*>(state->cookie);
if (ui == nullptr) { if (ui == nullptr) {
return StringValue(strdup("")); return StringValue("");
} }
FILE* cmd_pipe = ui->cmd_pipe; FILE* cmd_pipe = ui->cmd_pipe;
ZipArchive* za = ui->package_zip; ZipArchive* za = ui->package_zip;
if (cmd_pipe == nullptr || za == nullptr) { if (cmd_pipe == nullptr || za == nullptr) {
return StringValue(strdup("")); return StringValue("");
} }
const ZipEntry* patch_entry = mzFindZipEntry(za, patch_data_fn->data); const ZipEntry* patch_entry = mzFindZipEntry(za, patch_data_fn->data.c_str());
if (patch_entry == nullptr) { if (patch_entry == nullptr) {
fprintf(stderr, "%s(): no file \"%s\" in package", name, patch_data_fn->data); fprintf(stderr, "%s(): no file \"%s\" in package", name, patch_data_fn->data.c_str());
return StringValue(strdup("")); return StringValue("");
} }
params.patch_start = ui->package_zip_addr + mzGetZipEntryOffset(patch_entry); params.patch_start = ui->package_zip_addr + mzGetZipEntryOffset(patch_entry);
const ZipEntry* new_entry = mzFindZipEntry(za, new_data_fn->data); const ZipEntry* new_entry = mzFindZipEntry(za, new_data_fn->data.c_str());
if (new_entry == nullptr) { if (new_entry == nullptr) {
fprintf(stderr, "%s(): no file \"%s\" in package", name, new_data_fn->data); fprintf(stderr, "%s(): no file \"%s\" in package", name, new_data_fn->data.c_str());
return StringValue(strdup("")); return StringValue("");
} }
params.fd.reset(TEMP_FAILURE_RETRY(ota_open(blockdev_filename->data, O_RDWR))); params.fd.reset(TEMP_FAILURE_RETRY(ota_open(blockdev_filename->data.c_str(), O_RDWR)));
if (params.fd == -1) { if (params.fd == -1) {
fprintf(stderr, "open \"%s\" failed: %s\n", blockdev_filename->data, strerror(errno)); fprintf(stderr, "open \"%s\" failed: %s\n", blockdev_filename->data.c_str(), strerror(errno));
return StringValue(strdup("")); return StringValue("");
} }
if (params.canwrite) { if (params.canwrite) {
@@ -1471,24 +1467,21 @@ static Value* PerformBlockImageUpdate(const char* name, State* state, int /* arg
int error = pthread_create(&params.thread, &attr, unzip_new_data, &params.nti); int error = pthread_create(&params.thread, &attr, unzip_new_data, &params.nti);
if (error != 0) { if (error != 0) {
fprintf(stderr, "pthread_create failed: %s\n", strerror(error)); fprintf(stderr, "pthread_create failed: %s\n", strerror(error));
return StringValue(strdup("")); return StringValue("");
} }
} }
// Copy all the lines in transfer_list_value into std::string for std::vector<std::string> lines = android::base::Split(transfer_list_value->data, "\n");
// processing.
const std::string transfer_list(transfer_list_value->data, transfer_list_value->size);
std::vector<std::string> lines = android::base::Split(transfer_list, "\n");
if (lines.size() < 2) { if (lines.size() < 2) {
ErrorAbort(state, kArgsParsingFailure, "too few lines in the transfer list [%zd]\n", ErrorAbort(state, kArgsParsingFailure, "too few lines in the transfer list [%zd]\n",
lines.size()); lines.size());
return StringValue(strdup("")); return StringValue("");
} }
// First line in transfer list is the version number // First line in transfer list is the version number
if (!android::base::ParseInt(lines[0].c_str(), &params.version, 1, 4)) { if (!android::base::ParseInt(lines[0].c_str(), &params.version, 1, 4)) {
fprintf(stderr, "unexpected transfer list version [%s]\n", lines[0].c_str()); fprintf(stderr, "unexpected transfer list version [%s]\n", lines[0].c_str());
return StringValue(strdup("")); return StringValue("");
} }
fprintf(stderr, "blockimg version is %d\n", params.version); fprintf(stderr, "blockimg version is %d\n", params.version);
@@ -1497,11 +1490,11 @@ static Value* PerformBlockImageUpdate(const char* name, State* state, int /* arg
int total_blocks; int total_blocks;
if (!android::base::ParseInt(lines[1].c_str(), &total_blocks, 0)) { if (!android::base::ParseInt(lines[1].c_str(), &total_blocks, 0)) {
ErrorAbort(state, kArgsParsingFailure, "unexpected block count [%s]\n", lines[1].c_str()); ErrorAbort(state, kArgsParsingFailure, "unexpected block count [%s]\n", lines[1].c_str());
return StringValue(strdup("")); return StringValue("");
} }
if (total_blocks == 0) { if (total_blocks == 0) {
return StringValue(strdup("t")); return StringValue("t");
} }
size_t start = 2; size_t start = 2;
@@ -1509,7 +1502,7 @@ static Value* PerformBlockImageUpdate(const char* name, State* state, int /* arg
if (lines.size() < 4) { if (lines.size() < 4) {
ErrorAbort(state, kArgsParsingFailure, "too few lines in the transfer list [%zu]\n", ErrorAbort(state, kArgsParsingFailure, "too few lines in the transfer list [%zu]\n",
lines.size()); lines.size());
return StringValue(strdup("")); return StringValue("");
} }
// Third line is how many stash entries are needed simultaneously // Third line is how many stash entries are needed simultaneously
@@ -1520,12 +1513,12 @@ static Value* PerformBlockImageUpdate(const char* name, State* state, int /* arg
if (!android::base::ParseInt(lines[3].c_str(), &stash_max_blocks, 0)) { if (!android::base::ParseInt(lines[3].c_str(), &stash_max_blocks, 0)) {
ErrorAbort(state, kArgsParsingFailure, "unexpected maximum stash blocks [%s]\n", ErrorAbort(state, kArgsParsingFailure, "unexpected maximum stash blocks [%s]\n",
lines[3].c_str()); lines[3].c_str());
return StringValue(strdup("")); return StringValue("");
} }
int res = CreateStash(state, stash_max_blocks, blockdev_filename->data, params.stashbase); int res = CreateStash(state, stash_max_blocks, blockdev_filename->data.c_str(), params.stashbase);
if (res == -1) { if (res == -1) {
return StringValue(strdup("")); return StringValue("");
} }
params.createdstash = res; params.createdstash = res;
@@ -1589,7 +1582,7 @@ static Value* PerformBlockImageUpdate(const char* name, State* state, int /* arg
fprintf(stderr, "stashed %zu blocks\n", params.stashed); fprintf(stderr, "stashed %zu blocks\n", params.stashed);
fprintf(stderr, "max alloc needed was %zu\n", params.buffer.size()); fprintf(stderr, "max alloc needed was %zu\n", params.buffer.size());
const char* partition = strrchr(blockdev_filename->data, '/'); const char* partition = strrchr(blockdev_filename->data.c_str(), '/');
if (partition != nullptr && *(partition+1) != 0) { if (partition != nullptr && *(partition+1) != 0) {
fprintf(cmd_pipe, "log bytes_written_%s: %zu\n", partition + 1, fprintf(cmd_pipe, "log bytes_written_%s: %zu\n", partition + 1,
params.written * BLOCKSIZE); params.written * BLOCKSIZE);
@@ -1623,7 +1616,7 @@ pbiudone:
state->cause_code = failure_type; state->cause_code = failure_type;
} }
return StringValue(rc == 0 ? strdup("t") : strdup("")); return StringValue(rc == 0 ? "t" : "");
} }
// The transfer list is a text file containing commands to // The transfer list is a text file containing commands to
@@ -1721,27 +1714,26 @@ Value* RangeSha1Fn(const char* name, State* state, int /* argc */, Expr* argv[])
Value* ranges; Value* ranges;
if (ReadValueArgs(state, argv, 2, &blockdev_filename, &ranges) < 0) { if (ReadValueArgs(state, argv, 2, &blockdev_filename, &ranges) < 0) {
return StringValue(strdup("")); return StringValue("");
} }
std::unique_ptr<Value, decltype(&FreeValue)> ranges_holder(ranges, FreeValue); std::unique_ptr<Value> ranges_holder(ranges);
std::unique_ptr<Value, decltype(&FreeValue)> blockdev_filename_holder(blockdev_filename, std::unique_ptr<Value> blockdev_filename_holder(blockdev_filename);
FreeValue);
if (blockdev_filename->type != VAL_STRING) { if (blockdev_filename->type != VAL_STRING) {
ErrorAbort(state, kArgsParsingFailure, "blockdev_filename argument to %s must be string", ErrorAbort(state, kArgsParsingFailure, "blockdev_filename argument to %s must be string",
name); name);
return StringValue(strdup("")); return StringValue("");
} }
if (ranges->type != VAL_STRING) { if (ranges->type != VAL_STRING) {
ErrorAbort(state, kArgsParsingFailure, "ranges argument to %s must be string", name); ErrorAbort(state, kArgsParsingFailure, "ranges argument to %s must be string", name);
return StringValue(strdup("")); return StringValue("");
} }
android::base::unique_fd fd(ota_open(blockdev_filename->data, O_RDWR)); android::base::unique_fd fd(ota_open(blockdev_filename->data.c_str(), O_RDWR));
if (fd == -1) { if (fd == -1) {
ErrorAbort(state, kFileOpenFailure, "open \"%s\" failed: %s", blockdev_filename->data, ErrorAbort(state, kFileOpenFailure, "open \"%s\" failed: %s",
strerror(errno)); blockdev_filename->data.c_str(), strerror(errno));
return StringValue(strdup("")); return StringValue("");
} }
RangeSet rs; RangeSet rs;
@@ -1753,16 +1745,16 @@ Value* RangeSha1Fn(const char* name, State* state, int /* argc */, Expr* argv[])
std::vector<uint8_t> buffer(BLOCKSIZE); std::vector<uint8_t> buffer(BLOCKSIZE);
for (size_t i = 0; i < rs.count; ++i) { for (size_t i = 0; i < rs.count; ++i) {
if (!check_lseek(fd, (off64_t)rs.pos[i*2] * BLOCKSIZE, SEEK_SET)) { if (!check_lseek(fd, (off64_t)rs.pos[i*2] * BLOCKSIZE, SEEK_SET)) {
ErrorAbort(state, kLseekFailure, "failed to seek %s: %s", blockdev_filename->data, ErrorAbort(state, kLseekFailure, "failed to seek %s: %s",
strerror(errno)); blockdev_filename->data.c_str(), strerror(errno));
return StringValue(strdup("")); return StringValue("");
} }
for (size_t j = rs.pos[i*2]; j < rs.pos[i*2+1]; ++j) { for (size_t j = rs.pos[i*2]; j < rs.pos[i*2+1]; ++j) {
if (read_all(fd, buffer, BLOCKSIZE) == -1) { if (read_all(fd, buffer, BLOCKSIZE) == -1) {
ErrorAbort(state, kFreadFailure, "failed to read %s: %s", blockdev_filename->data, ErrorAbort(state, kFreadFailure, "failed to read %s: %s",
strerror(errno)); blockdev_filename->data.c_str(), strerror(errno));
return StringValue(strdup("")); return StringValue("");
} }
SHA1_Update(&ctx, buffer.data(), BLOCKSIZE); SHA1_Update(&ctx, buffer.data(), BLOCKSIZE);
@@ -1771,7 +1763,7 @@ Value* RangeSha1Fn(const char* name, State* state, int /* argc */, Expr* argv[])
uint8_t digest[SHA_DIGEST_LENGTH]; uint8_t digest[SHA_DIGEST_LENGTH];
SHA1_Final(digest, &ctx); SHA1_Final(digest, &ctx);
return StringValue(strdup(print_sha1(digest).c_str())); return StringValue(print_sha1(digest));
} }
// This function checks if a device has been remounted R/W prior to an incremental // This function checks if a device has been remounted R/W prior to an incremental
@@ -1785,27 +1777,27 @@ Value* CheckFirstBlockFn(const char* name, State* state, int argc, Expr* argv[])
if (ReadValueArgs(state, argv, 1, &arg_filename) < 0) { if (ReadValueArgs(state, argv, 1, &arg_filename) < 0) {
return nullptr; return nullptr;
} }
std::unique_ptr<Value, decltype(&FreeValue)> filename(arg_filename, FreeValue); std::unique_ptr<Value> filename(arg_filename);
if (filename->type != VAL_STRING) { if (filename->type != VAL_STRING) {
ErrorAbort(state, kArgsParsingFailure, "filename argument to %s must be string", name); ErrorAbort(state, kArgsParsingFailure, "filename argument to %s must be string", name);
return StringValue(strdup("")); return StringValue("");
} }
android::base::unique_fd fd(ota_open(arg_filename->data, O_RDONLY)); android::base::unique_fd fd(ota_open(arg_filename->data.c_str(), O_RDONLY));
if (fd == -1) { if (fd == -1) {
ErrorAbort(state, kFileOpenFailure, "open \"%s\" failed: %s", arg_filename->data, ErrorAbort(state, kFileOpenFailure, "open \"%s\" failed: %s", arg_filename->data.c_str(),
strerror(errno)); strerror(errno));
return StringValue(strdup("")); return StringValue("");
} }
RangeSet blk0 {1 /*count*/, 1/*size*/, std::vector<size_t> {0, 1}/*position*/}; RangeSet blk0 {1 /*count*/, 1/*size*/, std::vector<size_t> {0, 1}/*position*/};
std::vector<uint8_t> block0_buffer(BLOCKSIZE); std::vector<uint8_t> block0_buffer(BLOCKSIZE);
if (ReadBlocks(blk0, block0_buffer, fd) == -1) { if (ReadBlocks(blk0, block0_buffer, fd) == -1) {
ErrorAbort(state, kFreadFailure, "failed to read %s: %s", arg_filename->data, ErrorAbort(state, kFreadFailure, "failed to read %s: %s", arg_filename->data.c_str(),
strerror(errno)); strerror(errno));
return StringValue(strdup("")); return StringValue("");
} }
// https://ext4.wiki.kernel.org/index.php/Ext4_Disk_Layout // https://ext4.wiki.kernel.org/index.php/Ext4_Disk_Layout
@@ -1823,7 +1815,7 @@ Value* CheckFirstBlockFn(const char* name, State* state, int argc, Expr* argv[])
uiPrintf(state, "Last remount happened on %s", ctime(&mount_time)); uiPrintf(state, "Last remount happened on %s", ctime(&mount_time));
} }
return StringValue(strdup("t")); return StringValue("t");
} }
@@ -1835,40 +1827,40 @@ Value* BlockImageRecoverFn(const char* name, State* state, int argc, Expr* argv[
return NULL; return NULL;
} }
std::unique_ptr<Value, decltype(&FreeValue)> filename(arg_filename, FreeValue); std::unique_ptr<Value> filename(arg_filename);
std::unique_ptr<Value, decltype(&FreeValue)> ranges(arg_ranges, FreeValue); std::unique_ptr<Value> ranges(arg_ranges);
if (filename->type != VAL_STRING) { if (filename->type != VAL_STRING) {
ErrorAbort(state, kArgsParsingFailure, "filename argument to %s must be string", name); ErrorAbort(state, kArgsParsingFailure, "filename argument to %s must be string", name);
return StringValue(strdup("")); return StringValue("");
} }
if (ranges->type != VAL_STRING) { if (ranges->type != VAL_STRING) {
ErrorAbort(state, kArgsParsingFailure, "ranges argument to %s must be string", name); ErrorAbort(state, kArgsParsingFailure, "ranges argument to %s must be string", name);
return StringValue(strdup("")); return StringValue("");
} }
// Output notice to log when recover is attempted // Output notice to log when recover is attempted
fprintf(stderr, "%s image corrupted, attempting to recover...\n", filename->data); fprintf(stderr, "%s image corrupted, attempting to recover...\n", filename->data.c_str());
// When opened with O_RDWR, libfec rewrites corrupted blocks when they are read // When opened with O_RDWR, libfec rewrites corrupted blocks when they are read
fec::io fh(filename->data, O_RDWR); fec::io fh(filename->data.c_str(), O_RDWR);
if (!fh) { if (!fh) {
ErrorAbort(state, kLibfecFailure, "fec_open \"%s\" failed: %s", filename->data, ErrorAbort(state, kLibfecFailure, "fec_open \"%s\" failed: %s", filename->data.c_str(),
strerror(errno)); strerror(errno));
return StringValue(strdup("")); return StringValue("");
} }
if (!fh.has_ecc() || !fh.has_verity()) { if (!fh.has_ecc() || !fh.has_verity()) {
ErrorAbort(state, kLibfecFailure, "unable to use metadata to correct errors"); ErrorAbort(state, kLibfecFailure, "unable to use metadata to correct errors");
return StringValue(strdup("")); return StringValue("");
} }
fec_status status; fec_status status;
if (!fh.get_status(status)) { if (!fh.get_status(status)) {
ErrorAbort(state, kLibfecFailure, "failed to read FEC status"); ErrorAbort(state, kLibfecFailure, "failed to read FEC status");
return StringValue(strdup("")); return StringValue("");
} }
RangeSet rs; RangeSet rs;
@@ -1885,8 +1877,8 @@ Value* BlockImageRecoverFn(const char* name, State* state, int argc, Expr* argv[
if (fh.pread(buffer, BLOCKSIZE, (off64_t)j * BLOCKSIZE) != BLOCKSIZE) { if (fh.pread(buffer, BLOCKSIZE, (off64_t)j * BLOCKSIZE) != BLOCKSIZE) {
ErrorAbort(state, kLibfecFailure, "failed to recover %s (block %zu): %s", ErrorAbort(state, kLibfecFailure, "failed to recover %s (block %zu): %s",
filename->data, j, strerror(errno)); filename->data.c_str(), j, strerror(errno));
return StringValue(strdup("")); return StringValue("");
} }
// If we want to be able to recover from a situation where rewriting a corrected // If we want to be able to recover from a situation where rewriting a corrected
@@ -1901,8 +1893,8 @@ Value* BlockImageRecoverFn(const char* name, State* state, int argc, Expr* argv[
// read and check if the errors field value has increased. // read and check if the errors field value has increased.
} }
} }
fprintf(stderr, "...%s image recovered successfully.\n", filename->data); fprintf(stderr, "...%s image recovered successfully.\n", filename->data.c_str());
return StringValue(strdup("t")); return StringValue("t");
} }
void RegisterBlockImageFunctions() { void RegisterBlockImageFunctions() {
+81 -110
View File
@@ -116,7 +116,7 @@ static int make_parents(char* name) {
// //
// fs_type="ext4" partition_type="EMMC" location=device // fs_type="ext4" partition_type="EMMC" location=device
Value* MountFn(const char* name, State* state, int argc, Expr* argv[]) { Value* MountFn(const char* name, State* state, int argc, Expr* argv[]) {
char* result = NULL; char* result = nullptr;
if (argc != 4 && argc != 5) { if (argc != 4 && argc != 5) {
return ErrorAbort(state, kArgsParsingFailure, "%s() expects 4-5 args, got %d", name, argc); return ErrorAbort(state, kArgsParsingFailure, "%s() expects 4-5 args, got %d", name, argc);
} }
@@ -197,7 +197,7 @@ done:
// is_mounted(mount_point) // is_mounted(mount_point)
Value* IsMountedFn(const char* name, State* state, int argc, Expr* argv[]) { Value* IsMountedFn(const char* name, State* state, int argc, Expr* argv[]) {
char* result = NULL; char* result = nullptr;
if (argc != 1) { if (argc != 1) {
return ErrorAbort(state, kArgsParsingFailure, "%s() expects 1 arg, got %d", name, argc); return ErrorAbort(state, kArgsParsingFailure, "%s() expects 1 arg, got %d", name, argc);
} }
@@ -227,7 +227,7 @@ done:
Value* UnmountFn(const char* name, State* state, int argc, Expr* argv[]) { Value* UnmountFn(const char* name, State* state, int argc, Expr* argv[]) {
char* result = NULL; char* result = nullptr;
if (argc != 1) { if (argc != 1) {
return ErrorAbort(state, kArgsParsingFailure, "%s() expects 1 arg, got %d", name, argc); return ErrorAbort(state, kArgsParsingFailure, "%s() expects 1 arg, got %d", name, argc);
} }
@@ -284,7 +284,7 @@ static int exec_cmd(const char* path, char* const argv[]) {
// if fs_size > 0, that is the size to use // if fs_size > 0, that is the size to use
// if fs_size < 0, then reserve that many bytes at the end of the partition (not for "f2fs") // if fs_size < 0, then reserve that many bytes at the end of the partition (not for "f2fs")
Value* FormatFn(const char* name, State* state, int argc, Expr* argv[]) { Value* FormatFn(const char* name, State* state, int argc, Expr* argv[]) {
char* result = NULL; char* result = nullptr;
if (argc != 5) { if (argc != 5) {
return ErrorAbort(state, kArgsParsingFailure, "%s() expects 5 args, got %d", name, argc); return ErrorAbort(state, kArgsParsingFailure, "%s() expects 5 args, got %d", name, argc);
} }
@@ -358,7 +358,7 @@ done:
} }
Value* RenameFn(const char* name, State* state, int argc, Expr* argv[]) { Value* RenameFn(const char* name, State* state, int argc, Expr* argv[]) {
char* result = NULL; char* result = nullptr;
if (argc != 2) { if (argc != 2) {
return ErrorAbort(state, kArgsParsingFailure, "%s() expects 2 args, got %d", name, argc); return ErrorAbort(state, kArgsParsingFailure, "%s() expects 2 args, got %d", name, argc);
} }
@@ -397,15 +397,10 @@ done:
} }
Value* DeleteFn(const char* name, State* state, int argc, Expr* argv[]) { Value* DeleteFn(const char* name, State* state, int argc, Expr* argv[]) {
char** paths = reinterpret_cast<char**>(malloc(argc * sizeof(char*))); std::vector<std::string> paths;
for (int i = 0; i < argc; ++i) { for (int i = 0; i < argc; ++i) {
paths[i] = Evaluate(state, argv[i]); if (!Evaluate(state, argv[i], &paths[i])) {
if (paths[i] == NULL) { return nullptr;
for (int j = 0; j < i; ++j) {
free(paths[j]);
}
free(paths);
return NULL;
} }
} }
@@ -413,15 +408,12 @@ Value* DeleteFn(const char* name, State* state, int argc, Expr* argv[]) {
int success = 0; int success = 0;
for (int i = 0; i < argc; ++i) { for (int i = 0; i < argc; ++i) {
if ((recursive ? dirUnlinkHierarchy(paths[i]) : unlink(paths[i])) == 0) if ((recursive ? dirUnlinkHierarchy(paths[i].c_str()) : unlink(paths[i].c_str())) == 0) {
++success; ++success;
free(paths[i]); }
} }
free(paths);
char buffer[10]; return StringValue(android::base::StringPrintf("%d", success));
sprintf(buffer, "%d", success);
return StringValue(strdup(buffer));
} }
@@ -483,7 +475,7 @@ Value* PackageExtractDirFn(const char* name, State* state,
NULL, NULL, sehandle); NULL, NULL, sehandle);
free(zip_path); free(zip_path);
free(dest_path); free(dest_path);
return StringValue(strdup(success ? "t" : "")); return StringValue(success ? "t" : "");
} }
@@ -536,7 +528,7 @@ Value* PackageExtractFileFn(const char* name, State* state,
done2: done2:
free(zip_path); free(zip_path);
free(dest_path); free(dest_path);
return StringValue(strdup(success ? "t" : "")); return StringValue(success ? "t" : "");
} else { } else {
// The one-argument version returns the contents of the file // The one-argument version returns the contents of the file
// as the result. // as the result.
@@ -544,10 +536,7 @@ Value* PackageExtractFileFn(const char* name, State* state,
char* zip_path; char* zip_path;
if (ReadArgs(state, argv, 1, &zip_path) < 0) return NULL; if (ReadArgs(state, argv, 1, &zip_path) < 0) return NULL;
Value* v = reinterpret_cast<Value*>(malloc(sizeof(Value))); Value* v = new Value(VAL_INVALID, "");
v->type = VAL_BLOB;
v->size = -1;
v->data = NULL;
ZipArchive* za = ((UpdaterInfo*)(state->cookie))->package_zip; ZipArchive* za = ((UpdaterInfo*)(state->cookie))->package_zip;
const ZipEntry* entry = mzFindZipEntry(za, zip_path); const ZipEntry* entry = mzFindZipEntry(za, zip_path);
@@ -556,23 +545,16 @@ Value* PackageExtractFileFn(const char* name, State* state,
goto done1; goto done1;
} }
v->size = mzGetZipEntryUncompLen(entry); v->data.resize(mzGetZipEntryUncompLen(entry));
v->data = reinterpret_cast<char*>(malloc(v->size));
if (v->data == NULL) {
printf("%s: failed to allocate %zd bytes for %s\n",
name, v->size, zip_path);
goto done1;
}
success = mzExtractZipEntryToBuffer(za, entry, success = mzExtractZipEntryToBuffer(za, entry,
(unsigned char *)v->data); reinterpret_cast<unsigned char *>(&v->data[0]));
done1: done1:
free(zip_path); free(zip_path);
if (!success) { if (!success) {
free(v->data); v->data.clear();
v->data = NULL; } else {
v->size = -1; v->type = VAL_BLOB;
} }
return v; return v;
} }
@@ -584,13 +566,13 @@ Value* SymlinkFn(const char* name, State* state, int argc, Expr* argv[]) {
if (argc == 0) { if (argc == 0) {
return ErrorAbort(state, kArgsParsingFailure, "%s() expects 1+ args, got %d", name, argc); return ErrorAbort(state, kArgsParsingFailure, "%s() expects 1+ args, got %d", name, argc);
} }
char* target; std::string target;
target = Evaluate(state, argv[0]); if (!Evaluate(state, argv[0], &target)) {
if (target == NULL) return NULL; return nullptr;
}
char** srcs = ReadVarArgs(state, argc-1, argv+1); char** srcs = ReadVarArgs(state, argc-1, argv+1);
if (srcs == NULL) { if (srcs == NULL) {
free(target);
return NULL; return NULL;
} }
@@ -606,12 +588,12 @@ Value* SymlinkFn(const char* name, State* state, int argc, Expr* argv[]) {
} }
if (make_parents(srcs[i])) { if (make_parents(srcs[i])) {
printf("%s: failed to symlink %s to %s: making parents failed\n", printf("%s: failed to symlink %s to %s: making parents failed\n",
name, srcs[i], target); name, srcs[i], target.c_str());
++bad; ++bad;
} }
if (symlink(target, srcs[i]) < 0) { if (symlink(target.c_str(), srcs[i]) < 0) {
printf("%s: failed to symlink %s to %s: %s\n", printf("%s: failed to symlink %s to %s: %s\n",
name, srcs[i], target, strerror(errno)); name, srcs[i], target.c_str(), strerror(errno));
++bad; ++bad;
} }
free(srcs[i]); free(srcs[i]);
@@ -620,7 +602,7 @@ Value* SymlinkFn(const char* name, State* state, int argc, Expr* argv[]) {
if (bad) { if (bad) {
return ErrorAbort(state, kSymlinkFailure, "%s: some symlinks failed", name); return ErrorAbort(state, kSymlinkFailure, "%s: some symlinks failed", name);
} }
return StringValue(strdup("")); return StringValue("");
} }
struct perm_parsed_args { struct perm_parsed_args {
@@ -883,20 +865,20 @@ done:
return ErrorAbort(state, kSetMetadataFailure, "%s: some changes failed", name); return ErrorAbort(state, kSetMetadataFailure, "%s: some changes failed", name);
} }
return StringValue(strdup("")); return StringValue("");
} }
Value* GetPropFn(const char* name, State* state, int argc, Expr* argv[]) { Value* GetPropFn(const char* name, State* state, int argc, Expr* argv[]) {
if (argc != 1) { if (argc != 1) {
return ErrorAbort(state, kArgsParsingFailure, "%s() expects 1 arg, got %d", name, argc); return ErrorAbort(state, kArgsParsingFailure, "%s() expects 1 arg, got %d", name, argc);
} }
char* key = Evaluate(state, argv[0]); std::string key;
if (key == NULL) return NULL; if (!Evaluate(state, argv[0], &key)) {
return nullptr;
}
std::string value = android::base::GetProperty(key, ""); std::string value = android::base::GetProperty(key, "");
free(key);
return StringValue(strdup(value.c_str())); return StringValue(value);
} }
@@ -1015,7 +997,7 @@ Value* ApplyPatchSpaceFn(const char* name, State* state,
return nullptr; return nullptr;
} }
return StringValue(strdup(CacheSizeCheck(bytes) ? "" : "t")); return StringValue(CacheSizeCheck(bytes) ? "" : "t");
} }
// apply_patch(file, size, init_sha1, tgt_sha1, patch) // apply_patch(file, size, init_sha1, tgt_sha1, patch)
@@ -1047,17 +1029,16 @@ Value* ApplyPatchFn(const char* name, State* state, int argc, Expr* argv[]) {
} }
int patchcount = (argc-4) / 2; int patchcount = (argc-4) / 2;
std::unique_ptr<Value*, decltype(&free)> arg_values(ReadValueVarArgs(state, argc-4, argv+4), std::unique_ptr<Value*> arg_values(ReadValueVarArgs(state, argc-4, argv+4));
free);
if (!arg_values) { if (!arg_values) {
return nullptr; return nullptr;
} }
std::vector<std::unique_ptr<Value, decltype(&FreeValue)>> patch_shas; std::vector<std::unique_ptr<Value>> patch_shas;
std::vector<std::unique_ptr<Value, decltype(&FreeValue)>> patches; std::vector<std::unique_ptr<Value>> patches;
// Protect values by unique_ptrs first to get rid of memory leak. // Protect values by unique_ptrs first to get rid of memory leak.
for (int i = 0; i < patchcount * 2; i += 2) { for (int i = 0; i < patchcount * 2; i += 2) {
patch_shas.emplace_back(arg_values.get()[i], FreeValue); patch_shas.emplace_back(arg_values.get()[i]);
patches.emplace_back(arg_values.get()[i+1], FreeValue); patches.emplace_back(arg_values.get()[i+1]);
} }
for (int i = 0; i < patchcount; ++i) { for (int i = 0; i < patchcount; ++i) {
@@ -1071,7 +1052,7 @@ Value* ApplyPatchFn(const char* name, State* state, int argc, Expr* argv[]) {
} }
} }
std::vector<char*> patch_sha_str; std::vector<std::string> patch_sha_str;
std::vector<Value*> patch_ptrs; std::vector<Value*> patch_ptrs;
for (int i = 0; i < patchcount; ++i) { for (int i = 0; i < patchcount; ++i) {
patch_sha_str.push_back(patch_shas[i]->data); patch_sha_str.push_back(patch_shas[i]->data);
@@ -1080,9 +1061,9 @@ Value* ApplyPatchFn(const char* name, State* state, int argc, Expr* argv[]) {
int result = applypatch(source_filename, target_filename, int result = applypatch(source_filename, target_filename,
target_sha1, target_size, target_sha1, target_size,
patchcount, patch_sha_str.data(), patch_ptrs.data(), NULL); patch_sha_str, patch_ptrs.data(), NULL);
return StringValue(strdup(result == 0 ? "t" : "")); return StringValue(result == 0 ? "t" : "");
} }
// apply_patch_check(file, [sha1_1, ...]) // apply_patch_check(file, [sha1_1, ...])
@@ -1095,21 +1076,17 @@ Value* ApplyPatchCheckFn(const char* name, State* state,
char* filename; char* filename;
if (ReadArgs(state, argv, 1, &filename) < 0) { if (ReadArgs(state, argv, 1, &filename) < 0) {
return NULL; return nullptr;
} }
int patchcount = argc-1; std::vector<std::string> sha1s;
char** sha1s = ReadVarArgs(state, argc-1, argv+1); if (!ReadArgs(state, argc-1, argv+1, &sha1s)) {
return nullptr;
int result = applypatch_check(filename, patchcount, sha1s);
int i;
for (i = 0; i < patchcount; ++i) {
free(sha1s[i]);
} }
free(sha1s);
return StringValue(strdup(result == 0 ? "t" : "")); int result = applypatch_check(filename, sha1s);
return StringValue(result == 0 ? "t" : "");
} }
// This is the updater side handler for ui_print() in edify script. Contents // This is the updater side handler for ui_print() in edify script. Contents
@@ -1129,7 +1106,7 @@ Value* UIPrintFn(const char* name, State* state, int argc, Expr* argv[]) {
buffer += "\n"; buffer += "\n";
uiPrint(state, buffer); uiPrint(state, buffer);
return StringValue(strdup(buffer.c_str())); return StringValue(buffer);
} }
Value* WipeCacheFn(const char* name, State* state, int argc, Expr* argv[]) { Value* WipeCacheFn(const char* name, State* state, int argc, Expr* argv[]) {
@@ -1137,7 +1114,7 @@ Value* WipeCacheFn(const char* name, State* state, int argc, Expr* argv[]) {
return ErrorAbort(state, kArgsParsingFailure, "%s() expects no args, got %d", name, argc); return ErrorAbort(state, kArgsParsingFailure, "%s() expects no args, got %d", name, argc);
} }
fprintf(((UpdaterInfo*)(state->cookie))->cmd_pipe, "wipe_cache\n"); fprintf(((UpdaterInfo*)(state->cookie))->cmd_pipe, "wipe_cache\n");
return StringValue(strdup("t")); return StringValue("t");
} }
Value* RunProgramFn(const char* name, State* state, int argc, Expr* argv[]) { Value* RunProgramFn(const char* name, State* state, int argc, Expr* argv[]) {
@@ -1180,10 +1157,7 @@ Value* RunProgramFn(const char* name, State* state, int argc, Expr* argv[]) {
free(args); free(args);
free(args2); free(args2);
char buffer[20]; return StringValue(android::base::StringPrintf("%d", status));
sprintf(buffer, "%d", status);
return StringValue(strdup(buffer));
} }
// sha1_check(data) // sha1_check(data)
@@ -1199,32 +1173,32 @@ Value* Sha1CheckFn(const char* name, State* state, int argc, Expr* argv[]) {
return ErrorAbort(state, kArgsParsingFailure, "%s() expects at least 1 arg", name); return ErrorAbort(state, kArgsParsingFailure, "%s() expects at least 1 arg", name);
} }
std::unique_ptr<Value*, decltype(&free)> arg_values(ReadValueVarArgs(state, argc, argv), free); std::unique_ptr<Value*> arg_values(ReadValueVarArgs(state, argc, argv));
if (arg_values == nullptr) { if (arg_values == nullptr) {
return nullptr; return nullptr;
} }
std::vector<std::unique_ptr<Value, decltype(&FreeValue)>> args; std::vector<std::unique_ptr<Value>> args;
for (int i = 0; i < argc; ++i) { for (int i = 0; i < argc; ++i) {
args.emplace_back(arg_values.get()[i], FreeValue); args.emplace_back(arg_values.get()[i]);
} }
if (args[0]->size < 0) { if (args[0]->type == VAL_INVALID) {
return StringValue(strdup("")); return StringValue("");
} }
uint8_t digest[SHA_DIGEST_LENGTH]; uint8_t digest[SHA_DIGEST_LENGTH];
SHA1(reinterpret_cast<uint8_t*>(args[0]->data), args[0]->size, digest); SHA1(reinterpret_cast<const uint8_t*>(args[0]->data.c_str()), args[0]->data.size(), digest);
if (argc == 1) { if (argc == 1) {
return StringValue(strdup(print_sha1(digest).c_str())); return StringValue(print_sha1(digest));
} }
for (int i = 1; i < argc; ++i) { for (int i = 1; i < argc; ++i) {
uint8_t arg_digest[SHA_DIGEST_LENGTH]; uint8_t arg_digest[SHA_DIGEST_LENGTH];
if (args[i]->type != VAL_STRING) { if (args[i]->type != VAL_STRING) {
printf("%s(): arg %d is not a string; skipping", name, i); printf("%s(): arg %d is not a string; skipping", name, i);
} else if (ParseSha1(args[i]->data, arg_digest) != 0) { } else if (ParseSha1(args[i]->data.c_str(), arg_digest) != 0) {
// Warn about bad args and skip them. // Warn about bad args and skip them.
printf("%s(): error parsing \"%s\" as sha-1; skipping", name, args[i]->data); printf("%s(): error parsing \"%s\" as sha-1; skipping", name, args[i]->data.c_str());
} else if (memcmp(digest, arg_digest, SHA_DIGEST_LENGTH) == 0) { } else if (memcmp(digest, arg_digest, SHA_DIGEST_LENGTH) == 0) {
// Found a match. // Found a match.
return args[i].release(); return args[i].release();
@@ -1232,7 +1206,7 @@ Value* Sha1CheckFn(const char* name, State* state, int argc, Expr* argv[]) {
} }
// Didn't match any of the hex strings; return false. // Didn't match any of the hex strings; return false.
return StringValue(strdup("")); return StringValue("");
} }
// Read a local file and return its contents (the Value* returned // Read a local file and return its contents (the Value* returned
@@ -1244,21 +1218,12 @@ Value* ReadFileFn(const char* name, State* state, int argc, Expr* argv[]) {
char* filename; char* filename;
if (ReadArgs(state, argv, 1, &filename) < 0) return NULL; if (ReadArgs(state, argv, 1, &filename) < 0) return NULL;
Value* v = static_cast<Value*>(malloc(sizeof(Value))); Value* v = new Value(VAL_INVALID, "");
if (v == nullptr) {
return nullptr;
}
v->type = VAL_BLOB;
v->size = -1;
v->data = nullptr;
FileContents fc; FileContents fc;
if (LoadFileContents(filename, &fc) == 0) { if (LoadFileContents(filename, &fc) == 0) {
v->data = static_cast<char*>(malloc(fc.data.size())); v->type = VAL_BLOB;
if (v->data != nullptr) { v->data = std::string(fc.data.begin(), fc.data.end());
memcpy(v->data, fc.data.data(), fc.data.size());
v->size = fc.data.size();
}
} }
free(filename); free(filename);
return v; return v;
@@ -1326,16 +1291,19 @@ Value* SetStageFn(const char* name, State* state, int argc, Expr* argv[]) {
// package installation. // package installation.
FILE* f = ota_fopen(filename, "r+b"); FILE* f = ota_fopen(filename, "r+b");
fseek(f, offsetof(struct bootloader_message, stage), SEEK_SET); fseek(f, offsetof(struct bootloader_message, stage), SEEK_SET);
int to_write = strlen(stagestr)+1; size_t to_write = strlen(stagestr) + 1;
int max_size = sizeof(((struct bootloader_message*)0)->stage); size_t max_size = sizeof(((struct bootloader_message*)0)->stage);
if (to_write > max_size) { if (to_write > max_size) {
to_write = max_size; to_write = max_size;
stagestr[max_size-1] = 0; stagestr[max_size - 1] = 0;
} }
ota_fwrite(stagestr, to_write, 1, f); size_t status = ota_fwrite(stagestr, to_write, 1, f);
ota_fclose(f); ota_fclose(f);
free(stagestr); free(stagestr);
if (status != to_write) {
return StringValue("");
}
return StringValue(filename); return StringValue(filename);
} }
@@ -1352,11 +1320,14 @@ Value* GetStageFn(const char* name, State* state, int argc, Expr* argv[]) {
char buffer[sizeof(((struct bootloader_message*)0)->stage)]; char buffer[sizeof(((struct bootloader_message*)0)->stage)];
FILE* f = ota_fopen(filename, "rb"); FILE* f = ota_fopen(filename, "rb");
fseek(f, offsetof(struct bootloader_message, stage), SEEK_SET); fseek(f, offsetof(struct bootloader_message, stage), SEEK_SET);
ota_fread(buffer, sizeof(buffer), 1, f); size_t status = ota_fread(buffer, sizeof(buffer), 1, f);
ota_fclose(f); ota_fclose(f);
buffer[sizeof(buffer)-1] = '\0'; if (status != sizeof(buffer)) {
return StringValue("");
}
return StringValue(strdup(buffer)); buffer[sizeof(buffer)-1] = '\0';
return StringValue(buffer);
} }
Value* WipeBlockDeviceFn(const char* name, State* state, int argc, Expr* argv[]) { Value* WipeBlockDeviceFn(const char* name, State* state, int argc, Expr* argv[]) {
@@ -1378,7 +1349,7 @@ Value* WipeBlockDeviceFn(const char* name, State* state, int argc, Expr* argv[])
ota_close(fd); ota_close(fd);
return StringValue(strdup(success ? "t" : "")); return StringValue(success ? "t" : "");
} }
Value* EnableRebootFn(const char* name, State* state, int argc, Expr* argv[]) { Value* EnableRebootFn(const char* name, State* state, int argc, Expr* argv[]) {
@@ -1387,7 +1358,7 @@ Value* EnableRebootFn(const char* name, State* state, int argc, Expr* argv[]) {
} }
UpdaterInfo* ui = (UpdaterInfo*)(state->cookie); UpdaterInfo* ui = (UpdaterInfo*)(state->cookie);
fprintf(ui->cmd_pipe, "enable_reboot\n"); fprintf(ui->cmd_pipe, "enable_reboot\n");
return StringValue(strdup("t")); return StringValue("t");
} }
Value* Tune2FsFn(const char* name, State* state, int argc, Expr* argv[]) { Value* Tune2FsFn(const char* name, State* state, int argc, Expr* argv[]) {
@@ -1418,7 +1389,7 @@ Value* Tune2FsFn(const char* name, State* state, int argc, Expr* argv[]) {
return ErrorAbort(state, kTune2FsFailure, "%s() returned error code %d", return ErrorAbort(state, kTune2FsFailure, "%s() returned error code %d",
name, result); name, result);
} }
return StringValue(strdup("t")); return StringValue("t");
} }
void RegisterInstallFunctions() { void RegisterInstallFunctions() {
+4 -4
View File
@@ -151,13 +151,14 @@ int main(int argc, char** argv) {
} }
} }
char* result = Evaluate(&state, root); std::string result;
bool status = Evaluate(&state, root, &result);
if (have_eio_error) { if (have_eio_error) {
fprintf(cmd_pipe, "retry_update\n"); fprintf(cmd_pipe, "retry_update\n");
} }
if (result == NULL) { if (!status) {
if (state.errmsg.empty()) { if (state.errmsg.empty()) {
printf("script aborted (no error message)\n"); printf("script aborted (no error message)\n");
fprintf(cmd_pipe, "ui_print script aborted (no error message)\n"); fprintf(cmd_pipe, "ui_print script aborted (no error message)\n");
@@ -188,8 +189,7 @@ int main(int argc, char** argv) {
return 7; return 7;
} else { } else {
fprintf(cmd_pipe, "ui_print script succeeded: result was [%s]\n", result); fprintf(cmd_pipe, "ui_print script succeeded: result was [%s]\n", result.c_str());
free(result);
} }
if (updater_info.package_zip) { if (updater_info.package_zip) {