| Index: src/platform/update_engine/split_file_writer.cc
|
| diff --git a/src/platform/update_engine/split_file_writer.cc b/src/platform/update_engine/split_file_writer.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..e86894754b35f85a3ebec4d80bc41414db685dcc
|
| --- /dev/null
|
| +++ b/src/platform/update_engine/split_file_writer.cc
|
| @@ -0,0 +1,113 @@
|
| +// 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.
|
| +
|
| +#include "update_engine/split_file_writer.h"
|
| +#include <algorithm>
|
| +
|
| +using std::min;
|
| +
|
| +namespace chromeos_update_engine {
|
| +
|
| +int SplitFileWriter::Open(const char* path, int flags, mode_t mode) {
|
| + int first_result = first_file_writer_->Open(first_path_,
|
| + first_flags_,
|
| + first_mode_);
|
| + if (first_result < 0) {
|
| + LOG(ERROR) << "Error opening first file " << first_path_;
|
| + return first_result;
|
| + }
|
| + int second_result = second_file_writer_->Open(path, flags, mode);
|
| + if (second_result < 0) {
|
| + LOG(ERROR) << "Error opening second file " << path;
|
| + first_file_writer_->Close();
|
| + return second_result;
|
| + }
|
| + return second_result;
|
| +}
|
| +
|
| +namespace {
|
| +ssize_t PerformWrite(FileWriter* writer, const void* bytes, size_t count) {
|
| + int rc = writer->Write(bytes, count);
|
| + if (rc < 0) {
|
| + LOG(ERROR) << "Write failed to file.";
|
| + return rc;
|
| + }
|
| + if (rc != static_cast<int>(count)) {
|
| + LOG(ERROR) << "Not all bytes successfully written to file.";
|
| + return -EIO;
|
| + }
|
| + return rc;
|
| +}
|
| +}
|
| +
|
| +ssize_t SplitFileWriter::Write(const void* bytes, size_t count) {
|
| + const size_t original_count = count;
|
| +
|
| + // This first block is trying to read the first sizeof(uint64_t)
|
| + // bytes, which are the number of bytes that should be written
|
| + // to the first FileWriter.
|
| + if (bytes_received_ < static_cast<off_t>(sizeof(uint64_t))) {
|
| + // Write more to the initial buffer
|
| + size_t bytes_to_copy = min(count,
|
| + sizeof(first_length_buf_) - bytes_received_);
|
| + memcpy(&first_length_buf_[bytes_received_], bytes, bytes_to_copy);
|
| + bytes_received_ += bytes_to_copy;
|
| + count -= bytes_to_copy;
|
| + bytes = static_cast<const void*>(
|
| + static_cast<const char*>(bytes) + bytes_to_copy);
|
| +
|
| + // See if we have all we need
|
| + if (bytes_received_ == sizeof(first_length_buf_)) {
|
| + // Parse first number
|
| + uint64_t big_endian_first_length;
|
| + memcpy(&big_endian_first_length, first_length_buf_,
|
| + sizeof(big_endian_first_length));
|
| + first_length_ = be64toh(big_endian_first_length);
|
| + }
|
| + if (count == 0)
|
| + return original_count;
|
| + }
|
| + CHECK_GE(bytes_received_, static_cast<off_t>(sizeof(uint64_t)));
|
| +
|
| + // This block of code is writing to the first FileWriter.
|
| + if (bytes_received_ - static_cast<off_t>(sizeof(uint64_t)) < first_length_) {
|
| + // Write to first FileWriter
|
| + size_t bytes_to_write = min(
|
| + first_length_ -
|
| + (bytes_received_ - static_cast<off_t>(sizeof(uint64_t))),
|
| + static_cast<off_t>(count));
|
| +
|
| + int rc = PerformWrite(first_file_writer_, bytes, bytes_to_write);
|
| + if (rc != static_cast<int>(bytes_to_write))
|
| + return rc;
|
| +
|
| + bytes_received_ += bytes_to_write;
|
| + count -= bytes_to_write;
|
| + bytes = static_cast<const void*>(
|
| + static_cast<const char*>(bytes) + bytes_to_write);
|
| + if (count == 0)
|
| + return original_count;
|
| + }
|
| +
|
| + CHECK_GE(static_cast<off_t>(bytes_received_),
|
| + first_length_ + static_cast<off_t>(sizeof(uint64_t)));
|
| + // Write to second FileWriter
|
| + int rc = PerformWrite(second_file_writer_, bytes, count);
|
| + if (rc != static_cast<int>(count))
|
| + return rc;
|
| + return original_count;
|
| +}
|
| +
|
| +int SplitFileWriter::Close() {
|
| + int first_result = first_file_writer_->Close();
|
| + if (first_result < 0)
|
| + LOG(ERROR) << "Error Close()ing first file.";
|
| + int second_result = second_file_writer_->Close();
|
| + if (second_result < 0)
|
| + LOG(ERROR) << "Error Close()ing second file.";
|
| + // Return error if either had returned error.
|
| + return second_result < 0 ? second_result : first_result;
|
| +}
|
| +
|
| +} // namespace chromeos_update_engine
|
|
|