| Index: delta_diff_generator.cc
|
| diff --git a/delta_diff_generator.cc b/delta_diff_generator.cc
|
| index 21a4c03ad84b98decd39afa9c7a94bfd6e4f29d1..4f71c498283a2d170ffaa57b6d7fa1b29cfd1413 100644
|
| --- a/delta_diff_generator.cc
|
| +++ b/delta_diff_generator.cc
|
| @@ -30,6 +30,7 @@
|
| #include "update_engine/full_update_generator.h"
|
| #include "update_engine/graph_types.h"
|
| #include "update_engine/graph_utils.h"
|
| +#include "update_engine/metadata.h"
|
| #include "update_engine/omaha_hash_calculator.h"
|
| #include "update_engine/payload_signer.h"
|
| #include "update_engine/subprocess.h"
|
| @@ -77,81 +78,6 @@ bool GatherExtents(const string& path,
|
| return true;
|
| }
|
|
|
| -// Runs the bsdiff tool on two files and returns the resulting delta in
|
| -// 'out'. Returns true on success.
|
| -bool BsdiffFiles(const string& old_file,
|
| - const string& new_file,
|
| - vector<char>* out) {
|
| - const string kPatchFile = "/tmp/delta.patchXXXXXX";
|
| - string patch_file_path;
|
| -
|
| - TEST_AND_RETURN_FALSE(
|
| - utils::MakeTempFile(kPatchFile, &patch_file_path, NULL));
|
| -
|
| - vector<string> cmd;
|
| - cmd.push_back(kBsdiffPath);
|
| - cmd.push_back(old_file);
|
| - cmd.push_back(new_file);
|
| - cmd.push_back(patch_file_path);
|
| -
|
| - int rc = 1;
|
| - vector<char> patch_file;
|
| - TEST_AND_RETURN_FALSE(Subprocess::SynchronousExec(cmd, &rc));
|
| - TEST_AND_RETURN_FALSE(rc == 0);
|
| - TEST_AND_RETURN_FALSE(utils::ReadFile(patch_file_path, out));
|
| - unlink(patch_file_path.c_str());
|
| - return true;
|
| -}
|
| -
|
| -// The blocks vector contains a reader and writer for each block on the
|
| -// filesystem that's being in-place updated. We populate the reader/writer
|
| -// fields of blocks by calling this function.
|
| -// For each block in 'operation' that is read or written, find that block
|
| -// in 'blocks' and set the reader/writer field to the vertex passed.
|
| -// 'graph' is not strictly necessary, but useful for printing out
|
| -// error messages.
|
| -bool AddInstallOpToBlocksVector(
|
| - const DeltaArchiveManifest_InstallOperation& operation,
|
| - vector<Block>* blocks,
|
| - const Graph& graph,
|
| - Vertex::Index vertex) {
|
| - // See if this is already present.
|
| - TEST_AND_RETURN_FALSE(operation.dst_extents_size() > 0);
|
| -
|
| - enum BlockField { READER = 0, WRITER, BLOCK_FIELD_COUNT };
|
| - for (int field = READER; field < BLOCK_FIELD_COUNT; field++) {
|
| - const int extents_size =
|
| - (field == READER) ? operation.src_extents_size() :
|
| - operation.dst_extents_size();
|
| - const char* past_participle = (field == READER) ? "read" : "written";
|
| - const google::protobuf::RepeatedPtrField<Extent>& extents =
|
| - (field == READER) ? operation.src_extents() : operation.dst_extents();
|
| - Vertex::Index Block::*access_type =
|
| - (field == READER) ? &Block::reader : &Block::writer;
|
| -
|
| - for (int i = 0; i < extents_size; i++) {
|
| - const Extent& extent = extents.Get(i);
|
| - if (extent.start_block() == kSparseHole) {
|
| - // Hole in sparse file. skip
|
| - continue;
|
| - }
|
| - for (uint64_t block = extent.start_block();
|
| - block < (extent.start_block() + extent.num_blocks()); block++) {
|
| - if ((*blocks)[block].*access_type != Vertex::kInvalidIndex) {
|
| - LOG(FATAL) << "Block " << block << " is already "
|
| - << past_participle << " by "
|
| - << (*blocks)[block].*access_type << "("
|
| - << graph[(*blocks)[block].*access_type].file_name
|
| - << ") and also " << vertex << "("
|
| - << graph[vertex].file_name << ")";
|
| - }
|
| - (*blocks)[block].*access_type = vertex;
|
| - }
|
| - }
|
| - }
|
| - return true;
|
| -}
|
| -
|
| // For a given regular file which must exist at new_root + path, and
|
| // may exist at old_root + path, creates a new InstallOperation and
|
| // adds it to the graph. Also, populates the |blocks| array as
|
| @@ -197,10 +123,11 @@ bool DeltaReadFile(Graph* graph,
|
| (*graph)[vertex].file_name = path;
|
|
|
| if (blocks)
|
| - TEST_AND_RETURN_FALSE(AddInstallOpToBlocksVector((*graph)[vertex].op,
|
| - blocks,
|
| - *graph,
|
| - vertex));
|
| + TEST_AND_RETURN_FALSE(DeltaDiffGenerator::AddInstallOpToBlocksVector(
|
| + (*graph)[vertex].op,
|
| + *graph,
|
| + vertex,
|
| + blocks));
|
| return true;
|
| }
|
|
|
| @@ -1390,6 +1317,16 @@ bool DeltaDiffGenerator::GenerateDeltaUpdateFile(
|
| LOG(INFO) << "done reading normal files";
|
| CheckGraph(graph);
|
|
|
| + LOG(INFO) << "Starting metadata processing";
|
| + TEST_AND_RETURN_FALSE(Metadata::DeltaReadMetadata(&graph,
|
| + &blocks,
|
| + old_image,
|
| + new_image,
|
| + fd,
|
| + &data_file_size));
|
| + LOG(INFO) << "Done metadata processing";
|
| + CheckGraph(graph);
|
| +
|
| graph.resize(graph.size() + 1);
|
| TEST_AND_RETURN_FALSE(ReadUnwrittenBlocks(blocks,
|
| fd,
|
| @@ -1585,6 +1522,81 @@ bool DeltaDiffGenerator::GenerateDeltaUpdateFile(
|
| return true;
|
| }
|
|
|
| +// Runs the bsdiff tool on two files and returns the resulting delta in
|
| +// 'out'. Returns true on success.
|
| +bool DeltaDiffGenerator::BsdiffFiles(const string& old_file,
|
| + const string& new_file,
|
| + vector<char>* out) {
|
| + const string kPatchFile = "/tmp/delta.patchXXXXXX";
|
| + string patch_file_path;
|
| +
|
| + TEST_AND_RETURN_FALSE(
|
| + utils::MakeTempFile(kPatchFile, &patch_file_path, NULL));
|
| +
|
| + vector<string> cmd;
|
| + cmd.push_back(kBsdiffPath);
|
| + cmd.push_back(old_file);
|
| + cmd.push_back(new_file);
|
| + cmd.push_back(patch_file_path);
|
| +
|
| + int rc = 1;
|
| + vector<char> patch_file;
|
| + TEST_AND_RETURN_FALSE(Subprocess::SynchronousExec(cmd, &rc));
|
| + TEST_AND_RETURN_FALSE(rc == 0);
|
| + TEST_AND_RETURN_FALSE(utils::ReadFile(patch_file_path, out));
|
| + unlink(patch_file_path.c_str());
|
| + return true;
|
| +}
|
| +
|
| +// The |blocks| vector contains a reader and writer for each block on the
|
| +// filesystem that's being in-place updated. We populate the reader/writer
|
| +// fields of |blocks| by calling this function.
|
| +// For each block in |operation| that is read or written, find that block
|
| +// in |blocks| and set the reader/writer field to the vertex passed.
|
| +// |graph| is not strictly necessary, but useful for printing out
|
| +// error messages.
|
| +bool DeltaDiffGenerator::AddInstallOpToBlocksVector(
|
| + const DeltaArchiveManifest_InstallOperation& operation,
|
| + const Graph& graph,
|
| + Vertex::Index vertex,
|
| + vector<Block>* blocks) {
|
| + // See if this is already present.
|
| + TEST_AND_RETURN_FALSE(operation.dst_extents_size() > 0);
|
| +
|
| + enum BlockField { READER = 0, WRITER, BLOCK_FIELD_COUNT };
|
| + for (int field = READER; field < BLOCK_FIELD_COUNT; field++) {
|
| + const int extents_size =
|
| + (field == READER) ? operation.src_extents_size() :
|
| + operation.dst_extents_size();
|
| + const char* past_participle = (field == READER) ? "read" : "written";
|
| + const google::protobuf::RepeatedPtrField<Extent>& extents =
|
| + (field == READER) ? operation.src_extents() : operation.dst_extents();
|
| + Vertex::Index Block::*access_type =
|
| + (field == READER) ? &Block::reader : &Block::writer;
|
| +
|
| + for (int i = 0; i < extents_size; i++) {
|
| + const Extent& extent = extents.Get(i);
|
| + if (extent.start_block() == kSparseHole) {
|
| + // Hole in sparse file. skip
|
| + continue;
|
| + }
|
| + for (uint64_t block = extent.start_block();
|
| + block < (extent.start_block() + extent.num_blocks()); block++) {
|
| + if ((*blocks)[block].*access_type != Vertex::kInvalidIndex) {
|
| + LOG(FATAL) << "Block " << block << " is already "
|
| + << past_participle << " by "
|
| + << (*blocks)[block].*access_type << "("
|
| + << graph[(*blocks)[block].*access_type].file_name
|
| + << ") and also " << vertex << "("
|
| + << graph[vertex].file_name << ")";
|
| + }
|
| + (*blocks)[block].*access_type = vertex;
|
| + }
|
| + }
|
| + }
|
| + return true;
|
| +}
|
| +
|
| const char* const kBsdiffPath = "bsdiff";
|
| const char* const kBspatchPath = "bspatch";
|
| const char* const kDeltaMagic = "CrAU";
|
|
|