AU: Class to perform delta updates.

A class to perform delta updates and the associated unittests. Also,
change the delta diff generator executable to be able to apply a
delta, which is handy for debugging.

TEST=Attached unit test, hand-tested on real build images
BUG=552

Review URL: http://codereview.chromium.org/1718001
diff --git a/delta_performer.h b/delta_performer.h
new file mode 100644
index 0000000..1356bae
--- /dev/null
+++ b/delta_performer.h
@@ -0,0 +1,98 @@
+// Copyright (c) 2010 The Chromium OS Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROMEOS_PLATFORM_UPDATE_ENGINE_DELTA_PERFORMER_H__
+#define CHROMEOS_PLATFORM_UPDATE_ENGINE_DELTA_PERFORMER_H__
+
+#include <inttypes.h>
+#include <vector>
+#include <google/protobuf/repeated_field.h>
+#include "update_engine/file_writer.h"
+#include "update_engine/update_metadata.pb.h"
+
+namespace chromeos_update_engine {
+
+// This class performs the actions in a delta update synchronously. The delta
+// update itself should be passed in in chunks as it is received.
+
+class DeltaPerformer : public FileWriter {
+ public:
+  DeltaPerformer()
+      : fd_(-1),
+        manifest_valid_(false),
+        next_operation_(0),
+        buffer_offset_(0),
+        block_size_(0) {}
+  // flags and mode ignored. Once Close()d, a DeltaPerformer can't be
+  // Open()ed again.
+  int Open(const char* path, int flags, mode_t mode);
+
+  // Wrapper around write. Returns bytes written on success or
+  // -errno on error.
+  int Write(const void* bytes, size_t count);
+
+  // Wrapper around close. Returns 0 on success or -errno on error.
+  int Close();
+  
+  // Converts an ordered collection of Extent objects which contain data of
+  // length full_length to a comma-separated string. For each Extent, the
+  // string will have the start offset and then the length in bytes.
+  // The length value of the last extent in the string may be short, since
+  // the full length of all extents in the string is capped to full_length.
+  // Also, an extent starting at kSparseHole, appears as -1 in the string.
+  // For example, if the Extents are {1, 1}, {4, 2}, {kSparseHole, 1},
+  // {0, 1}, block_size is 4096, and full_length is 5 * block_size - 13,
+  // the resulting string will be: "4096:4096,16384:8192,-1:4096,0:4083"
+  static bool ExtentsToBsdiffPositionsString(
+      const google::protobuf::RepeatedPtrField<Extent>& extents,
+      uint64_t block_size,
+      uint64_t full_length,
+      std::string* positions_string);
+
+ private:
+  // Returns true if enough of the delta file has been passed via Write()
+  // to be able to perform a given install operation.
+  bool CanPerformInstallOperation(
+      const DeltaArchiveManifest_InstallOperation& operation);
+  
+  // Returns true on success.
+  bool PerformInstallOperation(
+      const DeltaArchiveManifest_InstallOperation& operation);
+  
+  // These perform a specific type of operation and return true on success.
+  bool PerformReplaceOperation(
+      const DeltaArchiveManifest_InstallOperation& operation);
+  bool PerformMoveOperation(
+      const DeltaArchiveManifest_InstallOperation& operation);
+  bool PerformBsdiffOperation(
+      const DeltaArchiveManifest_InstallOperation& operation);
+
+  // File descriptor of open device.
+  int fd_;
+  
+  std::string path_;  // Path that fd_ refers to
+  
+  DeltaArchiveManifest manifest_;
+  bool manifest_valid_;
+  
+  // Index of the next operation to perform in the manifest.
+  int next_operation_;
+
+  // buffer_ is a window of the data that's been downloaded. At first,
+  // it contains the beginning of the download, but after the protobuf
+  // has been downloaded and parsed, it contains a sliding window of
+  // data blobs.
+  std::vector<char> buffer_;
+  // Offset of buffer_ in the binary blobs section of the update.
+  uint64_t buffer_offset_;
+  
+  // The block size (parsed from the manifest).
+  uint32_t block_size_;
+  
+  DISALLOW_COPY_AND_ASSIGN(DeltaPerformer);
+};
+
+}  // namespace chromeos_update_engine
+
+#endif  // CHROMEOS_PLATFORM_UPDATE_ENGINE_DELTA_PERFORMER_H__