recovery代碼分析(六)

前面分析了move命令的實現,這裏在簡單的分析一下diff命令:

static int PerformCommandDiff(CommandParameters &params) {
    // <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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章