Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(359)

Side by Side Diff: src/platform/update_engine/delta_performer.cc

Issue 1819002: AU: delta compress the kernel partition (Closed) Base URL: ssh://git@chromiumos-git/chromeos
Patch Set: fixes for review Created 10 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2010 The Chromium OS Authors. All rights reserved. 1 // Copyright (c) 2010 The Chromium OS Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "update_engine/delta_performer.h" 5 #include "update_engine/delta_performer.h"
6 #include <endian.h> 6 #include <endian.h>
7 #include <errno.h> 7 #include <errno.h>
8 #include <algorithm> 8 #include <algorithm>
9 #include <cstring> 9 #include <cstring>
10 #include <string> 10 #include <string>
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
52 if (!ret.empty()) { 52 if (!ret.empty()) {
53 DCHECK_GT(ret.size(), static_cast<size_t>(1)); 53 DCHECK_GT(ret.size(), static_cast<size_t>(1));
54 ret.resize(ret.size() - 2); 54 ret.resize(ret.size() - 2);
55 } 55 }
56 return ret; 56 return ret;
57 } 57 }
58 58
59 // LOGs a DeltaArchiveManifest object. Useful for debugging. 59 // LOGs a DeltaArchiveManifest object. Useful for debugging.
60 void DumpUpdateProto(const DeltaArchiveManifest& manifest) { 60 void DumpUpdateProto(const DeltaArchiveManifest& manifest) {
61 LOG(INFO) << "Update Proto:"; 61 LOG(INFO) << "Update Proto:";
62 LOG(INFO) << " src_checksum: " << manifest.src_checksum();
63 LOG(INFO) << " dst_checksum: " << manifest.dst_checksum();
64 LOG(INFO) << " block_size: " << manifest.block_size(); 62 LOG(INFO) << " block_size: " << manifest.block_size();
65 for (int i = 0; i < manifest.install_operations_size(); i++) { 63 for (int i = 0; i < (manifest.install_operations_size() +
64 manifest.kernel_install_operations_size()); i++) {
66 const DeltaArchiveManifest_InstallOperation& op = 65 const DeltaArchiveManifest_InstallOperation& op =
67 manifest.install_operations(i); 66 i < manifest.install_operations_size() ?
67 manifest.install_operations(i) :
68 manifest.kernel_install_operations(
69 i - manifest.install_operations_size());
70 if (i == 0)
71 LOG(INFO) << " Rootfs ops:";
72 else if (i == manifest.install_operations_size())
73 LOG(INFO) << " Kernel ops:";
68 LOG(INFO) << " operation(" << i << ")"; 74 LOG(INFO) << " operation(" << i << ")";
69 LOG(INFO) << " type: " 75 LOG(INFO) << " type: "
70 << DeltaArchiveManifest_InstallOperation_Type_Name(op.type()); 76 << DeltaArchiveManifest_InstallOperation_Type_Name(op.type());
71 if (op.has_data_offset()) 77 if (op.has_data_offset())
72 LOG(INFO) << " data_offset: " << op.data_offset(); 78 LOG(INFO) << " data_offset: " << op.data_offset();
73 if (op.has_data_length()) 79 if (op.has_data_length())
74 LOG(INFO) << " data_length: " << op.data_length(); 80 LOG(INFO) << " data_length: " << op.data_length();
75 LOG(INFO) << " src_extents: " << ExtentsToString(op.src_extents()); 81 LOG(INFO) << " src_extents: " << ExtentsToString(op.src_extents());
76 if (op.has_src_length()) 82 if (op.has_src_length())
77 LOG(INFO) << " src_length: " << op.src_length(); 83 LOG(INFO) << " src_length: " << op.src_length();
78 LOG(INFO) << " dst_extents: " << ExtentsToString(op.dst_extents()); 84 LOG(INFO) << " dst_extents: " << ExtentsToString(op.dst_extents());
79 if (op.has_dst_length()) 85 if (op.has_dst_length())
80 LOG(INFO) << " dst_length: " << op.dst_length(); 86 LOG(INFO) << " dst_length: " << op.dst_length();
81 } 87 }
82 } 88 }
89
90 // Opens path for read/write, put the fd into *fd. On success returns true
91 // and sets *err to 0. On failure, returns false and sets *err to errno.
92 bool OpenFile(const char* path, int* fd, int* err) {
93 if (*fd != -1) {
94 LOG(ERROR) << "Can't open(" << path << "), *fd != -1 (it's " << *fd << ")";
95 *err = EINVAL;
96 return false;
97 }
98 *fd = open(path, O_RDWR, 000);
99 if (*fd < 0) {
100 *err = errno;
101 PLOG(ERROR) << "Unable to open file " << path;
102 return false;
103 }
104 *err = 0;
105 return true;
106 }
107
83 } // namespace {} 108 } // namespace {}
84 109
85 int DeltaPerformer::Open(const char* path, int flags, mode_t mode) { 110 int DeltaPerformer::Open(const char* path, int flags, mode_t mode) {
86 if (fd_ != -1) { 111 int err;
87 LOG(ERROR) << "Can't Open(), fd_ != -1 (it's " << fd_ << ")"; 112 if (OpenFile(path, &fd_, &err))
88 return -EINVAL; 113 path_ = path;
89 } 114 return -err;
90 path_ = path; 115 }
91 fd_ = open(path, O_RDWR, 000); 116
92 if (fd_ < 0) 117 bool DeltaPerformer::OpenKernel(const char* kernel_path) {
93 return -errno; 118 int err;
94 return 0; 119 bool success = OpenFile(kernel_path, &kernel_fd_, &err);
120 if (success)
121 kernel_path_ = kernel_path;
122 return success;
95 } 123 }
96 124
97 int DeltaPerformer::Close() { 125 int DeltaPerformer::Close() {
98 if (!buffer_.empty()) { 126 if (!buffer_.empty()) {
99 LOG(ERROR) << "Called Close() while buffer not empty!"; 127 LOG(ERROR) << "Called Close() while buffer not empty!";
100 return -1; 128 return -1;
101 } 129 }
102 if (close(fd_) == -1) 130 int err = 0;
103 return -errno; 131 if (close(kernel_fd_) == -1) {
132 err = errno;
133 PLOG(ERROR) << "Unable to close kernel fd:";
134 }
135 if (close(fd_) == -1) {
136 err = errno;
137 PLOG(ERROR) << "Unable to close rootfs fd:";
138 }
104 fd_ = -2; // Set so that isn't not valid AND calls to Open() will fail. 139 fd_ = -2; // Set so that isn't not valid AND calls to Open() will fail.
105 path_ = ""; 140 path_ = "";
106 return 0; 141 return -err;
107 } 142 }
108 143
109 // Wrapper around write. Returns bytes written on success or 144 // Wrapper around write. Returns bytes written on success or
110 // -errno on error. 145 // -errno on error.
111 // This function performs as many actions as it can, given the amount of 146 // This function performs as many actions as it can, given the amount of
112 // data received thus far. 147 // data received thus far.
113 ssize_t DeltaPerformer::Write(const void* bytes, size_t count) { 148 ssize_t DeltaPerformer::Write(const void* bytes, size_t count) {
114 const char* c_bytes = reinterpret_cast<const char*>(bytes); 149 const char* c_bytes = reinterpret_cast<const char*>(bytes);
115 buffer_.insert(buffer_.end(), c_bytes, c_bytes + count); 150 buffer_.insert(buffer_.end(), c_bytes, c_bytes + count);
116 151
(...skipping 24 matching lines...) Expand all
141 } 176 }
142 // Remove protobuf and header info from buffer_, so buffer_ contains 177 // Remove protobuf and header info from buffer_, so buffer_ contains
143 // just data blobs 178 // just data blobs
144 RemoveBufferHeadBytes(&buffer_, 179 RemoveBufferHeadBytes(&buffer_,
145 strlen(kDeltaMagic) + 180 strlen(kDeltaMagic) +
146 kDeltaVersionLength + 181 kDeltaVersionLength +
147 kDeltaProtobufLengthLength + protobuf_length); 182 kDeltaProtobufLengthLength + protobuf_length);
148 manifest_valid_ = true; 183 manifest_valid_ = true;
149 block_size_ = manifest_.block_size(); 184 block_size_ = manifest_.block_size();
150 } 185 }
151 while (next_operation_ < manifest_.install_operations_size() && 186 ssize_t total_operations = manifest_.install_operations_size() +
152 CanPerformInstallOperation( 187 manifest_.kernel_install_operations_size();
153 manifest_.install_operations(next_operation_))) { 188 while (next_operation_num_ < total_operations) {
154 const DeltaArchiveManifest_InstallOperation &op = 189 const DeltaArchiveManifest_InstallOperation &op =
155 manifest_.install_operations(next_operation_); 190 next_operation_num_ < manifest_.install_operations_size() ?
191 manifest_.install_operations(next_operation_num_) :
192 manifest_.kernel_install_operations(
193 next_operation_num_ - manifest_.install_operations_size());
194 if (!CanPerformInstallOperation(op))
195 break;
196 bool is_kernel_partition =
197 (next_operation_num_ >= manifest_.install_operations_size());
156 if (op.type() == DeltaArchiveManifest_InstallOperation_Type_REPLACE || 198 if (op.type() == DeltaArchiveManifest_InstallOperation_Type_REPLACE ||
157 op.type() == DeltaArchiveManifest_InstallOperation_Type_REPLACE_BZ) { 199 op.type() == DeltaArchiveManifest_InstallOperation_Type_REPLACE_BZ) {
158 if (!PerformReplaceOperation(op)) { 200 if (!PerformReplaceOperation(op, is_kernel_partition)) {
159 LOG(ERROR) << "Failed to perform replace operation " << next_operation_; 201 LOG(ERROR) << "Failed to perform replace operation "
202 << next_operation_num_;
160 return -EINVAL; 203 return -EINVAL;
161 } 204 }
162 } else if (op.type() == DeltaArchiveManifest_InstallOperation_Type_MOVE) { 205 } else if (op.type() == DeltaArchiveManifest_InstallOperation_Type_MOVE) {
163 if (!PerformMoveOperation(op)) { 206 if (!PerformMoveOperation(op, is_kernel_partition)) {
164 LOG(ERROR) << "Failed to perform move operation " << next_operation_; 207 LOG(ERROR) << "Failed to perform move operation "
208 << next_operation_num_;
165 return -EINVAL; 209 return -EINVAL;
166 } 210 }
167 } else if (op.type() == DeltaArchiveManifest_InstallOperation_Type_BSDIFF) { 211 } else if (op.type() == DeltaArchiveManifest_InstallOperation_Type_BSDIFF) {
168 if (!PerformBsdiffOperation(op)) { 212 if (!PerformBsdiffOperation(op, is_kernel_partition)) {
169 LOG(ERROR) << "Failed to perform bsdiff operation " << next_operation_; 213 LOG(ERROR) << "Failed to perform bsdiff operation "
214 << next_operation_num_;
170 return -EINVAL; 215 return -EINVAL;
171 } 216 }
172 } 217 }
173 next_operation_++; 218 next_operation_num_++;
174 } 219 }
175 return count; 220 return count;
176 } 221 }
177 222
178 bool DeltaPerformer::CanPerformInstallOperation( 223 bool DeltaPerformer::CanPerformInstallOperation(
179 const chromeos_update_engine::DeltaArchiveManifest_InstallOperation& 224 const chromeos_update_engine::DeltaArchiveManifest_InstallOperation&
180 operation) { 225 operation) {
181 // Move operations don't require any data blob, so they can always 226 // Move operations don't require any data blob, so they can always
182 // be performed 227 // be performed
183 if (operation.type() == DeltaArchiveManifest_InstallOperation_Type_MOVE) 228 if (operation.type() == DeltaArchiveManifest_InstallOperation_Type_MOVE)
184 return true; 229 return true;
185 230
186 // See if we have the entire data blob in the buffer 231 // See if we have the entire data blob in the buffer
187 if (operation.data_offset() < buffer_offset_) { 232 if (operation.data_offset() < buffer_offset_) {
188 LOG(ERROR) << "we threw away data it seems?"; 233 LOG(ERROR) << "we threw away data it seems?";
189 return false; 234 return false;
190 } 235 }
191 236
192 return (operation.data_offset() + operation.data_length()) <= 237 return (operation.data_offset() + operation.data_length()) <=
193 (buffer_offset_ + buffer_.size()); 238 (buffer_offset_ + buffer_.size());
194 } 239 }
195 240
196 bool DeltaPerformer::PerformReplaceOperation( 241 bool DeltaPerformer::PerformReplaceOperation(
197 const DeltaArchiveManifest_InstallOperation& operation) { 242 const DeltaArchiveManifest_InstallOperation& operation,
243 bool is_kernel_partition) {
198 CHECK(operation.type() == \ 244 CHECK(operation.type() == \
199 DeltaArchiveManifest_InstallOperation_Type_REPLACE || \ 245 DeltaArchiveManifest_InstallOperation_Type_REPLACE || \
200 operation.type() == \ 246 operation.type() == \
201 DeltaArchiveManifest_InstallOperation_Type_REPLACE_BZ); 247 DeltaArchiveManifest_InstallOperation_Type_REPLACE_BZ);
202 248
203 // Since we delete data off the beginning of the buffer as we use it, 249 // Since we delete data off the beginning of the buffer as we use it,
204 // the data we need should be exactly at the beginning of the buffer. 250 // the data we need should be exactly at the beginning of the buffer.
205 CHECK_EQ(buffer_offset_, operation.data_offset()); 251 CHECK_EQ(buffer_offset_, operation.data_offset());
206 CHECK_GE(buffer_.size(), operation.data_length()); 252 CHECK_GE(buffer_.size(), operation.data_length());
207 253
(...skipping 13 matching lines...) Expand all
221 } else { 267 } else {
222 NOTREACHED(); 268 NOTREACHED();
223 } 269 }
224 270
225 // Create a vector of extents to pass to the ExtentWriter. 271 // Create a vector of extents to pass to the ExtentWriter.
226 vector<Extent> extents; 272 vector<Extent> extents;
227 for (int i = 0; i < operation.dst_extents_size(); i++) { 273 for (int i = 0; i < operation.dst_extents_size(); i++) {
228 extents.push_back(operation.dst_extents(i)); 274 extents.push_back(operation.dst_extents(i));
229 } 275 }
230 276
231 TEST_AND_RETURN_FALSE(writer->Init(fd_, extents, block_size_)); 277 int fd = is_kernel_partition ? kernel_fd_ : fd_;
278
279 TEST_AND_RETURN_FALSE(writer->Init(fd, extents, block_size_));
232 TEST_AND_RETURN_FALSE(writer->Write(&buffer_[0], operation.data_length())); 280 TEST_AND_RETURN_FALSE(writer->Write(&buffer_[0], operation.data_length()));
233 TEST_AND_RETURN_FALSE(writer->End()); 281 TEST_AND_RETURN_FALSE(writer->End());
234 282
235 // Update buffer 283 // Update buffer
236 buffer_offset_ += operation.data_length(); 284 buffer_offset_ += operation.data_length();
237 RemoveBufferHeadBytes(&buffer_, operation.data_length()); 285 RemoveBufferHeadBytes(&buffer_, operation.data_length());
238 return true; 286 return true;
239 } 287 }
240 288
241 bool DeltaPerformer::PerformMoveOperation( 289 bool DeltaPerformer::PerformMoveOperation(
242 const DeltaArchiveManifest_InstallOperation& operation) { 290 const DeltaArchiveManifest_InstallOperation& operation,
291 bool is_kernel_partition) {
243 // Calculate buffer size. Note, this function doesn't do a sliding 292 // Calculate buffer size. Note, this function doesn't do a sliding
244 // window to copy in case the source and destination blocks overlap. 293 // window to copy in case the source and destination blocks overlap.
245 // If we wanted to do a sliding window, we could program the server 294 // If we wanted to do a sliding window, we could program the server
246 // to generate deltas that effectively did a sliding window. 295 // to generate deltas that effectively did a sliding window.
247 296
248 uint64_t blocks_to_read = 0; 297 uint64_t blocks_to_read = 0;
249 for (int i = 0; i < operation.src_extents_size(); i++) 298 for (int i = 0; i < operation.src_extents_size(); i++)
250 blocks_to_read += operation.src_extents(i).num_blocks(); 299 blocks_to_read += operation.src_extents(i).num_blocks();
251 300
252 uint64_t blocks_to_write = 0; 301 uint64_t blocks_to_write = 0;
253 for (int i = 0; i < operation.dst_extents_size(); i++) 302 for (int i = 0; i < operation.dst_extents_size(); i++)
254 blocks_to_write += operation.dst_extents(i).num_blocks(); 303 blocks_to_write += operation.dst_extents(i).num_blocks();
255 304
256 DCHECK_EQ(blocks_to_write, blocks_to_read); 305 DCHECK_EQ(blocks_to_write, blocks_to_read);
257 vector<char> buf(blocks_to_write * block_size_); 306 vector<char> buf(blocks_to_write * block_size_);
258 307
308 int fd = is_kernel_partition ? kernel_fd_ : fd_;
309
259 // Read in bytes. 310 // Read in bytes.
260 ssize_t bytes_read = 0; 311 ssize_t bytes_read = 0;
261 for (int i = 0; i < operation.src_extents_size(); i++) { 312 for (int i = 0; i < operation.src_extents_size(); i++) {
262 ssize_t bytes_read_this_iteration = 0; 313 ssize_t bytes_read_this_iteration = 0;
263 const Extent& extent = operation.src_extents(i); 314 const Extent& extent = operation.src_extents(i);
264 TEST_AND_RETURN_FALSE(utils::PReadAll(fd_, 315 TEST_AND_RETURN_FALSE(utils::PReadAll(fd,
265 &buf[bytes_read], 316 &buf[bytes_read],
266 extent.num_blocks() * block_size_, 317 extent.num_blocks() * block_size_,
267 extent.start_block() * block_size_, 318 extent.start_block() * block_size_,
268 &bytes_read_this_iteration)); 319 &bytes_read_this_iteration));
269 TEST_AND_RETURN_FALSE( 320 TEST_AND_RETURN_FALSE(
270 bytes_read_this_iteration == 321 bytes_read_this_iteration ==
271 static_cast<ssize_t>(extent.num_blocks() * block_size_)); 322 static_cast<ssize_t>(extent.num_blocks() * block_size_));
272 bytes_read += bytes_read_this_iteration; 323 bytes_read += bytes_read_this_iteration;
273 } 324 }
274 325
275 // Write bytes out. 326 // Write bytes out.
276 ssize_t bytes_written = 0; 327 ssize_t bytes_written = 0;
277 for (int i = 0; i < operation.dst_extents_size(); i++) { 328 for (int i = 0; i < operation.dst_extents_size(); i++) {
278 const Extent& extent = operation.dst_extents(i); 329 const Extent& extent = operation.dst_extents(i);
279 TEST_AND_RETURN_FALSE(utils::PWriteAll(fd_, 330 TEST_AND_RETURN_FALSE(utils::PWriteAll(fd,
280 &buf[bytes_written], 331 &buf[bytes_written],
281 extent.num_blocks() * block_size_, 332 extent.num_blocks() * block_size_,
282 extent.start_block() * block_size_)); 333 extent.start_block() * block_size_));
283 bytes_written += extent.num_blocks() * block_size_; 334 bytes_written += extent.num_blocks() * block_size_;
284 } 335 }
285 DCHECK_EQ(bytes_written, bytes_read); 336 DCHECK_EQ(bytes_written, bytes_read);
286 DCHECK_EQ(bytes_written, static_cast<ssize_t>(buf.size())); 337 DCHECK_EQ(bytes_written, static_cast<ssize_t>(buf.size()));
287 return true; 338 return true;
288 } 339 }
289 340
(...skipping 17 matching lines...) Expand all
307 length += this_length; 358 length += this_length;
308 } 359 }
309 TEST_AND_RETURN_FALSE(length == full_length); 360 TEST_AND_RETURN_FALSE(length == full_length);
310 if (!ret.empty()) 361 if (!ret.empty())
311 ret.resize(ret.size() - 1); // Strip trailing comma off 362 ret.resize(ret.size() - 1); // Strip trailing comma off
312 *positions_string = ret; 363 *positions_string = ret;
313 return true; 364 return true;
314 } 365 }
315 366
316 bool DeltaPerformer::PerformBsdiffOperation( 367 bool DeltaPerformer::PerformBsdiffOperation(
317 const DeltaArchiveManifest_InstallOperation& operation) { 368 const DeltaArchiveManifest_InstallOperation& operation,
369 bool is_kernel_partition) {
318 // Since we delete data off the beginning of the buffer as we use it, 370 // Since we delete data off the beginning of the buffer as we use it,
319 // the data we need should be exactly at the beginning of the buffer. 371 // the data we need should be exactly at the beginning of the buffer.
320 CHECK_EQ(buffer_offset_, operation.data_offset()); 372 CHECK_EQ(buffer_offset_, operation.data_offset());
321 CHECK_GE(buffer_.size(), operation.data_length()); 373 CHECK_GE(buffer_.size(), operation.data_length());
322 374
323 string input_positions; 375 string input_positions;
324 TEST_AND_RETURN_FALSE(ExtentsToBsdiffPositionsString(operation.src_extents(), 376 TEST_AND_RETURN_FALSE(ExtentsToBsdiffPositionsString(operation.src_extents(),
325 block_size_, 377 block_size_,
326 operation.src_length(), 378 operation.src_length(),
327 &input_positions)); 379 &input_positions));
328 string output_positions; 380 string output_positions;
329 TEST_AND_RETURN_FALSE(ExtentsToBsdiffPositionsString(operation.dst_extents(), 381 TEST_AND_RETURN_FALSE(ExtentsToBsdiffPositionsString(operation.dst_extents(),
330 block_size_, 382 block_size_,
331 operation.dst_length(), 383 operation.dst_length(),
332 &output_positions)); 384 &output_positions));
333 385
334 string temp_filename; 386 string temp_filename;
335 TEST_AND_RETURN_FALSE(utils::MakeTempFile("/tmp/au_patch.XXXXXX", 387 TEST_AND_RETURN_FALSE(utils::MakeTempFile("/tmp/au_patch.XXXXXX",
336 &temp_filename, 388 &temp_filename,
337 NULL)); 389 NULL));
338 ScopedPathUnlinker path_unlinker(temp_filename); 390 ScopedPathUnlinker path_unlinker(temp_filename);
339 { 391 {
340 int fd = open(temp_filename.c_str(), O_WRONLY | O_CREAT | O_TRUNC, 0644); 392 int fd = open(temp_filename.c_str(), O_WRONLY | O_CREAT | O_TRUNC, 0644);
341 ScopedFdCloser fd_closer(&fd); 393 ScopedFdCloser fd_closer(&fd);
342 TEST_AND_RETURN_FALSE( 394 TEST_AND_RETURN_FALSE(
343 utils::WriteAll(fd, &buffer_[0], operation.data_length())); 395 utils::WriteAll(fd, &buffer_[0], operation.data_length()));
344 } 396 }
397
398 int fd = is_kernel_partition ? kernel_fd_ : fd_;
399 const string& path = is_kernel_partition ? kernel_path_ : path_;
400
345 vector<string> cmd; 401 vector<string> cmd;
346 cmd.push_back(kBspatchPath); 402 cmd.push_back(kBspatchPath);
347 cmd.push_back(path_); 403 cmd.push_back(path);
348 cmd.push_back(path_); 404 cmd.push_back(path);
349 cmd.push_back(temp_filename); 405 cmd.push_back(temp_filename);
350 cmd.push_back(input_positions); 406 cmd.push_back(input_positions);
351 cmd.push_back(output_positions); 407 cmd.push_back(output_positions);
352 int return_code = 0; 408 int return_code = 0;
353 TEST_AND_RETURN_FALSE(Subprocess::SynchronousExec(cmd, &return_code)); 409 TEST_AND_RETURN_FALSE(Subprocess::SynchronousExec(cmd, &return_code));
354 TEST_AND_RETURN_FALSE(return_code == 0); 410 TEST_AND_RETURN_FALSE(return_code == 0);
355 411
356 if (operation.dst_length() % block_size_) { 412 if (operation.dst_length() % block_size_) {
357 // Zero out rest of final block. 413 // Zero out rest of final block.
358 // TODO(adlr): build this into bspatch; it's more efficient that way. 414 // TODO(adlr): build this into bspatch; it's more efficient that way.
359 const Extent& last_extent = 415 const Extent& last_extent =
360 operation.dst_extents(operation.dst_extents_size() - 1); 416 operation.dst_extents(operation.dst_extents_size() - 1);
361 const uint64_t end_byte = 417 const uint64_t end_byte =
362 (last_extent.start_block() + last_extent.num_blocks()) * block_size_; 418 (last_extent.start_block() + last_extent.num_blocks()) * block_size_;
363 const uint64_t begin_byte = 419 const uint64_t begin_byte =
364 end_byte - (block_size_ - operation.dst_length() % block_size_); 420 end_byte - (block_size_ - operation.dst_length() % block_size_);
365 vector<char> zeros(end_byte - begin_byte); 421 vector<char> zeros(end_byte - begin_byte);
366 TEST_AND_RETURN_FALSE( 422 TEST_AND_RETURN_FALSE(
367 utils::PWriteAll(fd_, &zeros[0], end_byte - begin_byte, begin_byte)); 423 utils::PWriteAll(fd, &zeros[0], end_byte - begin_byte, begin_byte));
368 } 424 }
369 425
370 // Update buffer. 426 // Update buffer.
371 buffer_offset_ += operation.data_length(); 427 buffer_offset_ += operation.data_length();
372 RemoveBufferHeadBytes(&buffer_, operation.data_length()); 428 RemoveBufferHeadBytes(&buffer_, operation.data_length());
373 return true; 429 return true;
374 } 430 }
375 431
376 } // namespace chromeos_update_engine 432 } // namespace chromeos_update_engine
OLDNEW
« no previous file with comments | « src/platform/update_engine/delta_performer.h ('k') | src/platform/update_engine/delta_performer_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698