OLD | NEW |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 |
OLD | NEW |