Loading updater/blockimg.cpp +143 −146 Original line number Diff line number Diff line Loading @@ -883,43 +883,36 @@ static void MoveRange(std::vector<uint8_t>& dest, const RangeSet& locs, } } // Do a source/target load for move/bsdiff/imgdiff in version 2. // We expect to parse the remainder of the parameter tokens as one of: // // <tgt_range> <src_block_count> <src_range> // (loads data from source image only) // // <tgt_range> <src_block_count> - <[stash_id:stash_range] ...> // (loads data from stashes only) // // <tgt_range> <src_block_count> <src_range> <src_loc> <[stash_id:stash_range] ...> // (loads data from both source image and stashes) // // On return, params.buffer is filled with the loaded source data (rearranged and combined with // stashed data as necessary). buffer may be reallocated if needed to accommodate the source data. // *tgt is the target RangeSet. Any stashes required are loaded using LoadStash. static int LoadSrcTgtVersion2(CommandParameters& params, RangeSet& tgt, size_t& src_blocks, /** * We expect to parse the remainder of the parameter tokens as one of: * * <src_block_count> <src_range> * (loads data from source image only) * * <src_block_count> - <[stash_id:stash_range] ...> * (loads data from stashes only) * * <src_block_count> <src_range> <src_loc> <[stash_id:stash_range] ...> * (loads data from both source image and stashes) * * On return, params.buffer is filled with the loaded source data (rearranged and combined with * stashed data as necessary). buffer may be reallocated if needed to accommodate the source data. * tgt is the target RangeSet for detecting overlaps. Any stashes required are loaded using * LoadStash. */ static int LoadSourceBlocks(CommandParameters& params, const RangeSet& tgt, size_t* src_blocks, bool* overlap) { // At least it needs to provide three parameters: <tgt_range>, // <src_block_count> and "-"/<src_range>. if (params.cpos + 2 >= params.tokens.size()) { LOG(ERROR) << "invalid parameters"; return -1; } // <tgt_range> tgt = parse_range(params.tokens[params.cpos++]); CHECK(src_blocks != nullptr); CHECK(overlap != nullptr); // <src_block_count> const std::string& token = params.tokens[params.cpos++]; if (!android::base::ParseUint(token.c_str(), &src_blocks)) { if (!android::base::ParseUint(token, src_blocks)) { LOG(ERROR) << "invalid src_block_count \"" << token << "\""; return -1; } allocate(src_blocks * BLOCKSIZE, params.buffer); allocate(*src_blocks * BLOCKSIZE, params.buffer); // "-" or <src_range> [<src_loc>] if (params.tokens[params.cpos] == "-") { Loading @@ -927,13 +920,9 @@ static int LoadSrcTgtVersion2(CommandParameters& params, RangeSet& tgt, size_t& params.cpos++; } else { RangeSet src = parse_range(params.tokens[params.cpos++]); int res = ReadBlocks(src, params.buffer, params.fd); if (overlap) { *overlap = range_overlaps(src, tgt); } if (res == -1) { if (ReadBlocks(src, params.buffer, params.fd) == -1) { return -1; } Loading @@ -948,9 +937,8 @@ static int LoadSrcTgtVersion2(CommandParameters& params, RangeSet& tgt, size_t& // <[stash_id:stash_range]> while (params.cpos < params.tokens.size()) { // Each word is a an index into the stash table, a colon, and // then a rangeset describing where in the source block that // stashed data should go. // Each word is a an index into the stash table, a colon, and then a RangeSet describing where // in the source block that stashed data should go. std::vector<std::string> tokens = android::base::Split(params.tokens[params.cpos++], ":"); if (tokens.size() != 2) { LOG(ERROR) << "invalid parameter"; Loading @@ -958,9 +946,7 @@ static int LoadSrcTgtVersion2(CommandParameters& params, RangeSet& tgt, size_t& } std::vector<uint8_t> stash; int res = LoadStash(params, tokens[0], false, nullptr, stash, true); if (res == -1) { if (LoadStash(params, tokens[0], false, nullptr, stash, true) == -1) { // These source blocks will fail verification if used later, but we // will let the caller decide if this is a fatal failure LOG(ERROR) << "failed to load stash " << tokens[0]; Loading @@ -968,7 +954,6 @@ static int LoadSrcTgtVersion2(CommandParameters& params, RangeSet& tgt, size_t& } RangeSet locs = parse_range(tokens[1]); MoveRange(params.buffer, locs, stash); } Loading @@ -989,9 +974,8 @@ static int LoadSrcTgtVersion2(CommandParameters& params, RangeSet& tgt, size_t& * <tgt_range> <src_block_count> <src_range> <src_loc> <[stash_id:stash_range] ...> * (loads data from both source image and stashes) * * Parameters are the same as for LoadSrcTgtVersion2, except for 'onehash', which tells the function * whether to expect separate source and targe block hashes, or if they are both the same and only * one hash should be expected, and 'isunresumable', which receives a non-zero value if block * 'onehash' tells whether to expect separate source and targe block hashes, or if they are both the * same and only one hash should be expected. params.isunresumable will be set to true if block * verification fails in a way that the update cannot be resumed anymore. * * If the function is unable to load the necessary blocks or their contents don't match the hashes, Loading @@ -1002,8 +986,11 @@ static int LoadSrcTgtVersion2(CommandParameters& params, RangeSet& tgt, size_t& * * If the return value is 0, source blocks have expected content and the command can be performed. */ static int LoadSrcTgtVersion3(CommandParameters& params, RangeSet& tgt, size_t& src_blocks, bool onehash, bool& overlap) { static int LoadSrcTgtVersion3(CommandParameters& params, RangeSet& tgt, size_t* src_blocks, bool onehash, bool* overlap) { CHECK(src_blocks != nullptr); CHECK(overlap != nullptr); if (params.cpos >= params.tokens.size()) { LOG(ERROR) << "missing source hash"; return -1; Loading @@ -1022,36 +1009,46 @@ static int LoadSrcTgtVersion3(CommandParameters& params, RangeSet& tgt, size_t& tgthash = params.tokens[params.cpos++]; } if (LoadSrcTgtVersion2(params, tgt, src_blocks, &overlap) == -1) { // At least it needs to provide three parameters: <tgt_range>, <src_block_count> and // "-"/<src_range>. if (params.cpos + 2 >= params.tokens.size()) { LOG(ERROR) << "invalid parameters"; return -1; } std::vector<uint8_t> tgtbuffer(tgt.size * BLOCKSIZE); // <tgt_range> tgt = parse_range(params.tokens[params.cpos++]); std::vector<uint8_t> tgtbuffer(tgt.size * BLOCKSIZE); if (ReadBlocks(tgt, tgtbuffer, params.fd) == -1) { return -1; } // Return now if target blocks already have expected content. if (VerifyBlocks(tgthash, tgtbuffer, tgt.size, false) == 0) { // Target blocks already have expected content, command should be skipped. return 1; } if (VerifyBlocks(srchash, params.buffer, src_blocks, true) == 0) { // Load source blocks. if (LoadSourceBlocks(params, tgt, src_blocks, overlap) == -1) { return -1; } if (VerifyBlocks(srchash, params.buffer, *src_blocks, true) == 0) { // If source and target blocks overlap, stash the source blocks so we can // resume from possible write errors. In verify mode, we can skip stashing // because the source blocks won't be overwritten. if (overlap && params.canwrite) { LOG(INFO) << "stashing " << src_blocks << " overlapping blocks to " << srchash; if (*overlap && params.canwrite) { LOG(INFO) << "stashing " << *src_blocks << " overlapping blocks to " << srchash; bool stash_exists = false; if (WriteStash(params.stashbase, srchash, src_blocks, params.buffer, true, if (WriteStash(params.stashbase, srchash, *src_blocks, params.buffer, true, &stash_exists) != 0) { LOG(ERROR) << "failed to stash overlapping source blocks"; return -1; } params.stashed += src_blocks; params.stashed += *src_blocks; // Can be deleted when the write has completed. if (!stash_exists) { params.freestash = srchash; Loading @@ -1062,10 +1059,10 @@ static int LoadSrcTgtVersion3(CommandParameters& params, RangeSet& tgt, size_t& return 0; } if (overlap && LoadStash(params, srchash, true, nullptr, params.buffer, true) == 0) { // Overlapping source blocks were previously stashed, command can proceed. // We are recovering from an interrupted command, so we don't know if the // stash can safely be deleted after this command. if (*overlap && LoadStash(params, srchash, true, nullptr, params.buffer, true) == 0) { // Overlapping source blocks were previously stashed, command can proceed. We are recovering // from an interrupted command, so we don't know if the stash can safely be deleted after this // command. return 0; } Loading @@ -1082,7 +1079,7 @@ static int PerformCommandMove(CommandParameters& params) { size_t blocks = 0; bool overlap = false; RangeSet tgt; int status = LoadSrcTgtVersion3(params, tgt, blocks, true, overlap); int status = LoadSrcTgtVersion3(params, tgt, &blocks, true, &overlap); if (status == -1) { LOG(ERROR) << "failed to read blocks for move"; Loading Loading @@ -1270,13 +1267,13 @@ static int PerformCommandDiff(CommandParameters& params) { } size_t offset; if (!android::base::ParseUint(params.tokens[params.cpos++].c_str(), &offset)) { if (!android::base::ParseUint(params.tokens[params.cpos++], &offset)) { LOG(ERROR) << "invalid patch offset"; return -1; } size_t len; if (!android::base::ParseUint(params.tokens[params.cpos++].c_str(), &len)) { if (!android::base::ParseUint(params.tokens[params.cpos++], &len)) { LOG(ERROR) << "invalid patch len"; return -1; } Loading @@ -1284,7 +1281,7 @@ static int PerformCommandDiff(CommandParameters& params) { RangeSet tgt; size_t blocks = 0; bool overlap = false; int status = LoadSrcTgtVersion3(params, tgt, blocks, false, overlap); int status = LoadSrcTgtVersion3(params, tgt, &blocks, false, &overlap); if (status == -1) { LOG(ERROR) << "failed to read blocks for diff"; Loading Loading @@ -1871,7 +1868,7 @@ Value* BlockImageRecoverFn(const char* name, State* state, LOG(INFO) << filename->data << " image corrupted, attempting to recover..."; // When opened with O_RDWR, libfec rewrites corrupted blocks when they are read fec::io fh(filename->data.c_str(), O_RDWR); fec::io fh(filename->data, O_RDWR); if (!fh) { ErrorAbort(state, kLibfecFailure, "fec_open \"%s\" failed: %s", filename->data.c_str(), Loading Loading
updater/blockimg.cpp +143 −146 Original line number Diff line number Diff line Loading @@ -883,43 +883,36 @@ static void MoveRange(std::vector<uint8_t>& dest, const RangeSet& locs, } } // Do a source/target load for move/bsdiff/imgdiff in version 2. // We expect to parse the remainder of the parameter tokens as one of: // // <tgt_range> <src_block_count> <src_range> // (loads data from source image only) // // <tgt_range> <src_block_count> - <[stash_id:stash_range] ...> // (loads data from stashes only) // // <tgt_range> <src_block_count> <src_range> <src_loc> <[stash_id:stash_range] ...> // (loads data from both source image and stashes) // // On return, params.buffer is filled with the loaded source data (rearranged and combined with // stashed data as necessary). buffer may be reallocated if needed to accommodate the source data. // *tgt is the target RangeSet. Any stashes required are loaded using LoadStash. static int LoadSrcTgtVersion2(CommandParameters& params, RangeSet& tgt, size_t& src_blocks, /** * We expect to parse the remainder of the parameter tokens as one of: * * <src_block_count> <src_range> * (loads data from source image only) * * <src_block_count> - <[stash_id:stash_range] ...> * (loads data from stashes only) * * <src_block_count> <src_range> <src_loc> <[stash_id:stash_range] ...> * (loads data from both source image and stashes) * * On return, params.buffer is filled with the loaded source data (rearranged and combined with * stashed data as necessary). buffer may be reallocated if needed to accommodate the source data. * tgt is the target RangeSet for detecting overlaps. Any stashes required are loaded using * LoadStash. */ static int LoadSourceBlocks(CommandParameters& params, const RangeSet& tgt, size_t* src_blocks, bool* overlap) { // At least it needs to provide three parameters: <tgt_range>, // <src_block_count> and "-"/<src_range>. if (params.cpos + 2 >= params.tokens.size()) { LOG(ERROR) << "invalid parameters"; return -1; } // <tgt_range> tgt = parse_range(params.tokens[params.cpos++]); CHECK(src_blocks != nullptr); CHECK(overlap != nullptr); // <src_block_count> const std::string& token = params.tokens[params.cpos++]; if (!android::base::ParseUint(token.c_str(), &src_blocks)) { if (!android::base::ParseUint(token, src_blocks)) { LOG(ERROR) << "invalid src_block_count \"" << token << "\""; return -1; } allocate(src_blocks * BLOCKSIZE, params.buffer); allocate(*src_blocks * BLOCKSIZE, params.buffer); // "-" or <src_range> [<src_loc>] if (params.tokens[params.cpos] == "-") { Loading @@ -927,13 +920,9 @@ static int LoadSrcTgtVersion2(CommandParameters& params, RangeSet& tgt, size_t& params.cpos++; } else { RangeSet src = parse_range(params.tokens[params.cpos++]); int res = ReadBlocks(src, params.buffer, params.fd); if (overlap) { *overlap = range_overlaps(src, tgt); } if (res == -1) { if (ReadBlocks(src, params.buffer, params.fd) == -1) { return -1; } Loading @@ -948,9 +937,8 @@ static int LoadSrcTgtVersion2(CommandParameters& params, RangeSet& tgt, size_t& // <[stash_id:stash_range]> while (params.cpos < params.tokens.size()) { // Each word is a an index into the stash table, a colon, and // then a rangeset describing where in the source block that // stashed data should go. // Each word is a an index into the stash table, a colon, and then a RangeSet describing where // in the source block that stashed data should go. std::vector<std::string> tokens = android::base::Split(params.tokens[params.cpos++], ":"); if (tokens.size() != 2) { LOG(ERROR) << "invalid parameter"; Loading @@ -958,9 +946,7 @@ static int LoadSrcTgtVersion2(CommandParameters& params, RangeSet& tgt, size_t& } std::vector<uint8_t> stash; int res = LoadStash(params, tokens[0], false, nullptr, stash, true); if (res == -1) { if (LoadStash(params, tokens[0], false, nullptr, stash, true) == -1) { // These source blocks will fail verification if used later, but we // will let the caller decide if this is a fatal failure LOG(ERROR) << "failed to load stash " << tokens[0]; Loading @@ -968,7 +954,6 @@ static int LoadSrcTgtVersion2(CommandParameters& params, RangeSet& tgt, size_t& } RangeSet locs = parse_range(tokens[1]); MoveRange(params.buffer, locs, stash); } Loading @@ -989,9 +974,8 @@ static int LoadSrcTgtVersion2(CommandParameters& params, RangeSet& tgt, size_t& * <tgt_range> <src_block_count> <src_range> <src_loc> <[stash_id:stash_range] ...> * (loads data from both source image and stashes) * * Parameters are the same as for LoadSrcTgtVersion2, except for 'onehash', which tells the function * whether to expect separate source and targe block hashes, or if they are both the same and only * one hash should be expected, and 'isunresumable', which receives a non-zero value if block * 'onehash' tells whether to expect separate source and targe block hashes, or if they are both the * same and only one hash should be expected. params.isunresumable will be set to true if block * verification fails in a way that the update cannot be resumed anymore. * * If the function is unable to load the necessary blocks or their contents don't match the hashes, Loading @@ -1002,8 +986,11 @@ static int LoadSrcTgtVersion2(CommandParameters& params, RangeSet& tgt, size_t& * * If the return value is 0, source blocks have expected content and the command can be performed. */ static int LoadSrcTgtVersion3(CommandParameters& params, RangeSet& tgt, size_t& src_blocks, bool onehash, bool& overlap) { static int LoadSrcTgtVersion3(CommandParameters& params, RangeSet& tgt, size_t* src_blocks, bool onehash, bool* overlap) { CHECK(src_blocks != nullptr); CHECK(overlap != nullptr); if (params.cpos >= params.tokens.size()) { LOG(ERROR) << "missing source hash"; return -1; Loading @@ -1022,36 +1009,46 @@ static int LoadSrcTgtVersion3(CommandParameters& params, RangeSet& tgt, size_t& tgthash = params.tokens[params.cpos++]; } if (LoadSrcTgtVersion2(params, tgt, src_blocks, &overlap) == -1) { // At least it needs to provide three parameters: <tgt_range>, <src_block_count> and // "-"/<src_range>. if (params.cpos + 2 >= params.tokens.size()) { LOG(ERROR) << "invalid parameters"; return -1; } std::vector<uint8_t> tgtbuffer(tgt.size * BLOCKSIZE); // <tgt_range> tgt = parse_range(params.tokens[params.cpos++]); std::vector<uint8_t> tgtbuffer(tgt.size * BLOCKSIZE); if (ReadBlocks(tgt, tgtbuffer, params.fd) == -1) { return -1; } // Return now if target blocks already have expected content. if (VerifyBlocks(tgthash, tgtbuffer, tgt.size, false) == 0) { // Target blocks already have expected content, command should be skipped. return 1; } if (VerifyBlocks(srchash, params.buffer, src_blocks, true) == 0) { // Load source blocks. if (LoadSourceBlocks(params, tgt, src_blocks, overlap) == -1) { return -1; } if (VerifyBlocks(srchash, params.buffer, *src_blocks, true) == 0) { // If source and target blocks overlap, stash the source blocks so we can // resume from possible write errors. In verify mode, we can skip stashing // because the source blocks won't be overwritten. if (overlap && params.canwrite) { LOG(INFO) << "stashing " << src_blocks << " overlapping blocks to " << srchash; if (*overlap && params.canwrite) { LOG(INFO) << "stashing " << *src_blocks << " overlapping blocks to " << srchash; bool stash_exists = false; if (WriteStash(params.stashbase, srchash, src_blocks, params.buffer, true, if (WriteStash(params.stashbase, srchash, *src_blocks, params.buffer, true, &stash_exists) != 0) { LOG(ERROR) << "failed to stash overlapping source blocks"; return -1; } params.stashed += src_blocks; params.stashed += *src_blocks; // Can be deleted when the write has completed. if (!stash_exists) { params.freestash = srchash; Loading @@ -1062,10 +1059,10 @@ static int LoadSrcTgtVersion3(CommandParameters& params, RangeSet& tgt, size_t& return 0; } if (overlap && LoadStash(params, srchash, true, nullptr, params.buffer, true) == 0) { // Overlapping source blocks were previously stashed, command can proceed. // We are recovering from an interrupted command, so we don't know if the // stash can safely be deleted after this command. if (*overlap && LoadStash(params, srchash, true, nullptr, params.buffer, true) == 0) { // Overlapping source blocks were previously stashed, command can proceed. We are recovering // from an interrupted command, so we don't know if the stash can safely be deleted after this // command. return 0; } Loading @@ -1082,7 +1079,7 @@ static int PerformCommandMove(CommandParameters& params) { size_t blocks = 0; bool overlap = false; RangeSet tgt; int status = LoadSrcTgtVersion3(params, tgt, blocks, true, overlap); int status = LoadSrcTgtVersion3(params, tgt, &blocks, true, &overlap); if (status == -1) { LOG(ERROR) << "failed to read blocks for move"; Loading Loading @@ -1270,13 +1267,13 @@ static int PerformCommandDiff(CommandParameters& params) { } size_t offset; if (!android::base::ParseUint(params.tokens[params.cpos++].c_str(), &offset)) { if (!android::base::ParseUint(params.tokens[params.cpos++], &offset)) { LOG(ERROR) << "invalid patch offset"; return -1; } size_t len; if (!android::base::ParseUint(params.tokens[params.cpos++].c_str(), &len)) { if (!android::base::ParseUint(params.tokens[params.cpos++], &len)) { LOG(ERROR) << "invalid patch len"; return -1; } Loading @@ -1284,7 +1281,7 @@ static int PerformCommandDiff(CommandParameters& params) { RangeSet tgt; size_t blocks = 0; bool overlap = false; int status = LoadSrcTgtVersion3(params, tgt, blocks, false, overlap); int status = LoadSrcTgtVersion3(params, tgt, &blocks, false, &overlap); if (status == -1) { LOG(ERROR) << "failed to read blocks for diff"; Loading Loading @@ -1871,7 +1868,7 @@ Value* BlockImageRecoverFn(const char* name, State* state, LOG(INFO) << filename->data << " image corrupted, attempting to recover..."; // When opened with O_RDWR, libfec rewrites corrupted blocks when they are read fec::io fh(filename->data.c_str(), O_RDWR); fec::io fh(filename->data, O_RDWR); if (!fh) { ErrorAbort(state, kLibfecFailure, "fec_open \"%s\" failed: %s", filename->data.c_str(), Loading