前面分析了move命令的實現,這裏在簡單的分析一下diff命令:
static int PerformCommandDiff(CommandParameters ¶ms) {
// <offset> <length>
if (params.cpos + 1 >= params.tokens.size()) {
LOG(ERROR) << "missing patch offset or length for " << params.cmdname;
return -1;
}
size_t 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++], &len)) {
LOG(ERROR) << "invalid patch len";
return -1;
}
RangeSet tgt;
size_t blocks = 0;
bool overlap = false;
// Timothy:和move指令一樣,這裏調用LoadSrcTgtVersion3函數來載入source和target。
int status = LoadSrcTgtVersion3(params, tgt, &blocks, false, &overlap);
if (status == -1) {
LOG(ERROR) << "failed to read blocks for diff";
return -1;
}
if (status == 0) {
params.foundwrites = true;
} else if (params.foundwrites) {
LOG(WARNING) << "warning: commands executed out of order [" << params.cmdname << "]";
}
// Timothy:這個字段在veriry階段爲false,在install階段爲true。
if (params.canwrite) {
if (status == 0) {
LOG(INFO) << "patching " << blocks << " blocks to " << tgt.blocks();
Value patch_value(
VAL_BLOB, std::string(reinterpret_cast<const char *>(params.patch_start + offset), len));
RangeSinkWriter writer(params.fd, tgt);
// Timothy:這裏是兩種做差分的方式,imgdiff和bsdiff。
if (params.cmdname[0] == 'i') { // imgdiff
if (ApplyImagePatch(params.buffer.data(), blocks * BLOCKSIZE, &patch_value,
std::bind(&RangeSinkWriter::Write, &writer, std::placeholders::_1,
std::placeholders::_2),
nullptr, nullptr) != 0) {
LOG(ERROR) << "Failed to apply image patch.";
failure_type = kPatchApplicationFailure;
return -1;
}
} else {
if (ApplyBSDiffPatch(params.buffer.data(), blocks * BLOCKSIZE, &patch_value, 0,
std::bind(&RangeSinkWriter::Write, &writer, std::placeholders::_1,
std::placeholders::_2),
nullptr) != 0) {
LOG(ERROR) << "Failed to apply bsdiff patch.";
failure_type = kPatchApplicationFailure;
return -1;
}
}
// We expect the output of the patcher to fill the tgt ranges exactly.
if (!writer.Finished()) {
LOG(ERROR) << "range sink underrun?";
}
} else {
LOG(INFO) << "skipping " << blocks << " blocks already patched to " << tgt.blocks() << " ["
<< params.cmdline << "]";
}
}
if (!params.freestash.empty()) {
FreeStash(params.stashbase, params.freestash);
params.freestash.clear();
}
params.written += tgt.blocks();
return 0;
}