blob: 765bff65866c5857d27be961659a8c4b5dc819c5 [file] [log] [blame]
Andrew de los Reyes80061062010-02-04 14:25:00 -08001// Copyright (c) 2009 The Chromium OS Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
Gilad Arnoldcf175a02014-07-10 16:48:47 -07005#ifndef UPDATE_ENGINE_EXTENT_WRITER_H_
6#define UPDATE_ENGINE_EXTENT_WRITER_H_
Andrew de los Reyes80061062010-02-04 14:25:00 -08007
8#include <vector>
Alex Deymo8427b4a2014-11-05 14:00:32 -08009
10#include <base/logging.h>
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -080011#include <chromeos/secure_blob.h>
Alex Deymo8427b4a2014-11-05 14:00:32 -080012
Nam T. Nguyenf1d582e2014-12-08 15:07:17 -080013#include "update_engine/file_descriptor.h"
Andrew de los Reyes80061062010-02-04 14:25:00 -080014#include "update_engine/update_metadata.pb.h"
15#include "update_engine/utils.h"
16
17// ExtentWriter is an abstract class which synchronously writes to a given
18// file descriptor at the extents given.
19
20namespace chromeos_update_engine {
21
Andrew de los Reyes80061062010-02-04 14:25:00 -080022class ExtentWriter {
23 public:
24 ExtentWriter() : end_called_(false) {}
25 virtual ~ExtentWriter() {
26 LOG_IF(ERROR, !end_called_) << "End() not called on ExtentWriter.";
27 }
28
29 // Returns true on success.
Nam T. Nguyenf1d582e2014-12-08 15:07:17 -080030 virtual bool Init(FileDescriptorPtr fd,
Andrew de los Reyes80061062010-02-04 14:25:00 -080031 const std::vector<Extent>& extents,
Andrew de los Reyes08c4e272010-04-15 14:02:17 -070032 uint32_t block_size) = 0;
Andrew de los Reyes80061062010-02-04 14:25:00 -080033
34 // Returns true on success.
35 virtual bool Write(const void* bytes, size_t count) = 0;
36
37 // Should be called when all writing is complete. Returns true on success.
38 // The fd is not closed. Caller is responsible for closing it.
39 bool End() {
40 end_called_ = true;
41 return EndImpl();
42 }
43 virtual bool EndImpl() = 0;
44 private:
45 bool end_called_;
46};
47
48// DirectExtentWriter is probably the simplest ExtentWriter implementation.
49// It writes the data directly into the extents.
50
51class DirectExtentWriter : public ExtentWriter {
52 public:
53 DirectExtentWriter()
Nam T. Nguyenf1d582e2014-12-08 15:07:17 -080054 : fd_(nullptr),
Andrew de los Reyes80061062010-02-04 14:25:00 -080055 block_size_(0),
56 extent_bytes_written_(0),
57 next_extent_index_(0) {}
58 ~DirectExtentWriter() {}
59
Nam T. Nguyenf1d582e2014-12-08 15:07:17 -080060 bool Init(FileDescriptorPtr fd,
61 const std::vector<Extent>& extents,
62 uint32_t block_size) {
Andrew de los Reyes80061062010-02-04 14:25:00 -080063 fd_ = fd;
64 block_size_ = block_size;
65 extents_ = extents;
66 return true;
67 }
68 bool Write(const void* bytes, size_t count);
69 bool EndImpl() {
70 return true;
71 }
72
73 private:
Nam T. Nguyenf1d582e2014-12-08 15:07:17 -080074 FileDescriptorPtr fd_;
Chris Masone4dc2ada2010-09-23 12:43:03 -070075
Andrew de los Reyes80061062010-02-04 14:25:00 -080076 size_t block_size_;
77 // Bytes written into next_extent_index_ thus far
Andrew de los Reyes09e56d62010-04-23 13:45:53 -070078 uint64_t extent_bytes_written_;
Andrew de los Reyes80061062010-02-04 14:25:00 -080079 std::vector<Extent> extents_;
80 // The next call to write should correspond to extents_[next_extent_index_]
81 std::vector<Extent>::size_type next_extent_index_;
82};
83
84// Takes an underlying ExtentWriter to which all operations are delegated.
85// When End() is called, ZeroPadExtentWriter ensures that the total number
86// of bytes written is a multiple of block_size_. If not, it writes zeros
87// to pad as needed.
88
89class ZeroPadExtentWriter : public ExtentWriter {
90 public:
Alex Vakulenkod2779df2014-06-16 13:19:00 -070091 explicit ZeroPadExtentWriter(ExtentWriter* underlying_extent_writer)
Andrew de los Reyes80061062010-02-04 14:25:00 -080092 : underlying_extent_writer_(underlying_extent_writer),
93 block_size_(0),
94 bytes_written_mod_block_size_(0) {}
95 ~ZeroPadExtentWriter() {}
96
Nam T. Nguyenf1d582e2014-12-08 15:07:17 -080097 bool Init(FileDescriptorPtr fd,
98 const std::vector<Extent>& extents,
99 uint32_t block_size) {
Andrew de los Reyes80061062010-02-04 14:25:00 -0800100 block_size_ = block_size;
101 return underlying_extent_writer_->Init(fd, extents, block_size);
102 }
103 bool Write(const void* bytes, size_t count) {
104 if (underlying_extent_writer_->Write(bytes, count)) {
105 bytes_written_mod_block_size_ += count;
106 bytes_written_mod_block_size_ %= block_size_;
107 return true;
108 }
109 return false;
110 }
111 bool EndImpl() {
112 if (bytes_written_mod_block_size_) {
113 const size_t write_size = block_size_ - bytes_written_mod_block_size_;
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -0800114 chromeos::Blob zeros(write_size, 0);
115 TEST_AND_RETURN_FALSE(underlying_extent_writer_->Write(zeros.data(),
Andrew de los Reyes80061062010-02-04 14:25:00 -0800116 write_size));
117 }
118 return underlying_extent_writer_->End();
119 }
120
121 private:
122 ExtentWriter* underlying_extent_writer_; // The underlying ExtentWriter.
123 size_t block_size_;
124 size_t bytes_written_mod_block_size_;
125};
126
127} // namespace chromeos_update_engine
128
Gilad Arnoldcf175a02014-07-10 16:48:47 -0700129#endif // UPDATE_ENGINE_EXTENT_WRITER_H_