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

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

Issue 492008: AU: Try delta updates first, then full updates (Closed)
Patch Set: use mkstemp Created 11 years 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) 2009 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2009 The Chromium 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_diff_generator.h" 5 #include "update_engine/delta_diff_generator.h"
6 #include <dirent.h> 6 #include <dirent.h>
7 #include <endian.h> 7 #include <endian.h>
8 #include <errno.h> 8 #include <errno.h>
9 #include <stdio.h> 9 #include <stdio.h>
10 #include <unistd.h> 10 #include <unistd.h>
11 #include <algorithm> 11 #include <algorithm>
12 #include <map>
13 #include <set>
14 #include <string>
12 #include <vector> 15 #include <vector>
13 #include <tr1/memory> 16 #include <tr1/memory>
14 #include <zlib.h> 17 #include <zlib.h>
15 #include "chromeos/obsolete_logging.h" 18 #include "chromeos/obsolete_logging.h"
16 #include "base/scoped_ptr.h" 19 #include "base/scoped_ptr.h"
17 #include "update_engine/delta_diff_parser.h" 20 #include "update_engine/delta_diff_parser.h"
18 #include "update_engine/gzip.h" 21 #include "update_engine/gzip.h"
19 #include "update_engine/subprocess.h" 22 #include "update_engine/subprocess.h"
20 #include "update_engine/utils.h" 23 #include "update_engine/utils.h"
21 24
25 using std::map;
26 using std::set;
27 using std::string;
22 using std::vector; 28 using std::vector;
23 using std::tr1::shared_ptr; 29 using std::tr1::shared_ptr;
24 using chromeos_update_engine::DeltaArchiveManifest; 30 using chromeos_update_engine::DeltaArchiveManifest;
25 31
26 namespace chromeos_update_engine { 32 namespace chromeos_update_engine {
27 33
28 namespace { 34 namespace {
35
36 const char* kBsdiffPath = "/usr/bin/bsdiff";
37
29 // These structs and methods are helpers for EncodeDataToDeltaFile() 38 // These structs and methods are helpers for EncodeDataToDeltaFile()
30 39
31 // Before moving the data into a proto buffer, the data is stored in 40 // Before moving the data into a proto buffer, the data is stored in
32 // memory in these Node and Child structures. 41 // memory in these Node and Child structures.
33 42
34 // Each Node struct represents a file on disk (which can be regular file, 43 // Each Node struct represents a file on disk (which can be regular file,
35 // directory, fifo, socket, symlink, etc). Nodes that contain children 44 // directory, fifo, socket, symlink, etc). Nodes that contain children
36 // (just directories) will have a vector of Child objects. Each child 45 // (just directories) will have a vector of Child objects. Each child
37 // object has a filename and a pointer to the associated Node. Thus, 46 // object has a filename and a pointer to the associated Node. Thus,
38 // filenames for files are stored with their parents, not as part of 47 // filenames for files are stored with their parents, not as part of
(...skipping 154 matching lines...) Expand 10 before | Expand all | Expand 10 after
193 } 202 }
194 203
195 } // namespace {} 204 } // namespace {}
196 205
197 // For each file in archive, write a delta for it into out_file 206 // For each file in archive, write a delta for it into out_file
198 // and update 'file' to refer to the delta. 207 // and update 'file' to refer to the delta.
199 // This is a recursive function. Returns true on success. 208 // This is a recursive function. Returns true on success.
200 bool DeltaDiffGenerator::WriteFileDiffsToDeltaFile( 209 bool DeltaDiffGenerator::WriteFileDiffsToDeltaFile(
201 DeltaArchiveManifest* archive, 210 DeltaArchiveManifest* archive,
202 DeltaArchiveManifest_File* file, 211 DeltaArchiveManifest_File* file,
203 const std::string& file_name, 212 const string& file_name,
204 const std::string& old_path, 213 const string& old_path,
205 const std::string& new_path, 214 const string& new_path,
206 FileWriter* out_file_writer, 215 FileWriter* out_file_writer,
207 int* out_file_length, 216 int* out_file_length,
208 const std::string& force_compress_dev_path) { 217 set<string> always_full_target_paths,
218 const string& force_compress_dev_path) {
209 TEST_AND_RETURN_FALSE(file->has_mode()); 219 TEST_AND_RETURN_FALSE(file->has_mode());
210 220
211 // Stat the actual file, too 221 // Stat the actual file, too
212 struct stat stbuf; 222 struct stat stbuf;
213 TEST_AND_RETURN_FALSE_ERRNO(lstat((new_path + "/" + file_name).c_str(), 223 TEST_AND_RETURN_FALSE_ERRNO(lstat((new_path + "/" + file_name).c_str(),
214 &stbuf) == 0); 224 &stbuf) == 0);
215 TEST_AND_RETURN_FALSE(stbuf.st_mode == file->mode()); 225 TEST_AND_RETURN_FALSE(stbuf.st_mode == file->mode());
216 226
217 // See if we're a directory or not 227 // See if we're a directory or not
218 if (S_ISDIR(file->mode())) { 228 if (S_ISDIR(file->mode())) {
219 for (int i = 0; i < file->children_size(); i++) { 229 for (int i = 0; i < file->children_size(); i++) {
220 DeltaArchiveManifest_File_Child* child = file->mutable_children(i); 230 DeltaArchiveManifest_File_Child* child = file->mutable_children(i);
221 DeltaArchiveManifest_File* child_file = 231 DeltaArchiveManifest_File* child_file =
222 archive->mutable_files(child->index()); 232 archive->mutable_files(child->index());
233 string recurse_old_path = old_path;
234 string recurse_new_path = new_path;
235 if (!file_name.empty()) {
236 recurse_new_path += "/" + file_name;
237 recurse_old_path += "/" + file_name;
238 }
223 TEST_AND_RETURN_FALSE(WriteFileDiffsToDeltaFile( 239 TEST_AND_RETURN_FALSE(WriteFileDiffsToDeltaFile(
224 archive, 240 archive,
225 child_file, 241 child_file,
226 child->name(), 242 child->name(),
227 old_path + "/" + file_name, 243 recurse_old_path,
228 new_path + "/" + file_name, 244 recurse_new_path,
229 out_file_writer, 245 out_file_writer,
230 out_file_length, 246 out_file_length,
247 always_full_target_paths,
231 force_compress_dev_path)); 248 force_compress_dev_path));
232 } 249 }
233 return true; 250 return true;
234 } 251 }
235 252
236 if (S_ISFIFO(file->mode()) || S_ISSOCK(file->mode()) || 253 if (S_ISFIFO(file->mode()) || S_ISSOCK(file->mode()) ||
237 file->has_hardlink_path()) { 254 file->has_hardlink_path()) {
238 // These don't store any additional data 255 // These don't store any additional data
239 return true; 256 return true;
240 } 257 }
241 258
242 vector<char> data; 259 vector<char> data;
243 bool should_compress = true; 260 bool should_compress = true;
244 bool format_set = false; 261 bool format_set = false;
245 DeltaArchiveManifest_File_DataFormat format; 262 DeltaArchiveManifest_File_DataFormat format;
246 if (S_ISLNK(file->mode())) { 263 if (S_ISLNK(file->mode())) {
247 TEST_AND_RETURN_FALSE(EncodeLink(new_path + "/" + file_name, &data)); 264 TEST_AND_RETURN_FALSE(EncodeLink(new_path + "/" + file_name, &data));
248 } else if (S_ISCHR(file->mode()) || S_ISBLK(file->mode())) { 265 } else if (S_ISCHR(file->mode()) || S_ISBLK(file->mode())) {
249 TEST_AND_RETURN_FALSE(EncodeDev(stbuf, &data, &format, 266 TEST_AND_RETURN_FALSE(EncodeDev(stbuf, &data, &format,
250 new_path + "/" + file_name == 267 new_path + "/" + file_name ==
251 force_compress_dev_path)); 268 force_compress_dev_path));
252 format_set = true; 269 format_set = true;
253 } else if (S_ISREG(file->mode())) { 270 } else if (S_ISREG(file->mode())) {
254 // regular file. We may use a delta here. 271 // regular file. We may use a delta here.
255 TEST_AND_RETURN_FALSE(EncodeFile(old_path, new_path, file_name, &format, 272 const bool avoid_diff = utils::SetContainsKey(always_full_target_paths,
256 &data)); 273 new_path + "/" + file_name);
274 bool no_change = false;
275 TEST_AND_RETURN_FALSE(EncodeFile(old_path, new_path, file_name,
276 avoid_diff, &format, &data, &no_change));
277 if (no_change) {
278 // No data change. We're done!
279 return true;
280 }
257 should_compress = false; 281 should_compress = false;
258 format_set = true; 282 format_set = true;
259 if ((format == DeltaArchiveManifest_File_DataFormat_BSDIFF) || 283 if ((format == DeltaArchiveManifest_File_DataFormat_BSDIFF) ||
260 (format == DeltaArchiveManifest_File_DataFormat_FULL_GZ)) 284 (format == DeltaArchiveManifest_File_DataFormat_FULL_GZ))
261 TEST_AND_RETURN_FALSE(!data.empty()); 285 TEST_AND_RETURN_FALSE(!data.empty());
262 } else { 286 } else {
263 // Should never get here; unhandled mode type. 287 // Should never get here; unhandled mode type.
264 LOG(ERROR) << "Unhandled mode type: " << file->mode(); 288 LOG(ERROR) << "Unhandled mode type: " << file->mode();
265 return false; 289 return false;
266 } 290 }
267 291
268 if (!format_set) { 292 if (!format_set) {
269 // Pick a format now 293 // Pick a format now
270 vector<char> compressed_data; 294 vector<char> compressed_data;
271 TEST_AND_RETURN_FALSE(GzipCompress(data, &compressed_data)); 295 TEST_AND_RETURN_FALSE(GzipCompress(data, &compressed_data));
272 if (compressed_data.size() < data.size()) { 296 if (compressed_data.size() < data.size()) {
273 format = DeltaArchiveManifest_File_DataFormat_FULL_GZ; 297 format = DeltaArchiveManifest_File_DataFormat_FULL_GZ;
274 data.swap(compressed_data); 298 data.swap(compressed_data);
275 } else { 299 } else {
276 format = DeltaArchiveManifest_File_DataFormat_FULL; 300 format = DeltaArchiveManifest_File_DataFormat_FULL;
277 } 301 }
278 format_set = true; 302 format_set = true;
279 } 303 }
280 304
281 if (!data.empty()) { 305 TEST_AND_RETURN_FALSE(format_set);
282 TEST_AND_RETURN_FALSE(format_set); 306 file->set_data_format(format);
283 file->set_data_format(format); 307 file->set_data_offset(*out_file_length);
284 file->set_data_offset(*out_file_length); 308 TEST_AND_RETURN_FALSE(static_cast<ssize_t>(data.size()) ==
285 TEST_AND_RETURN_FALSE(static_cast<ssize_t>(data.size()) == 309 out_file_writer->Write(&data[0], data.size()));
286 out_file_writer->Write(&data[0], data.size())); 310 file->set_data_length(data.size());
287 file->set_data_length(data.size()); 311 *out_file_length += data.size();
288 *out_file_length += data.size();
289 }
290 return true; 312 return true;
291 } 313 }
292 314
293 bool DeltaDiffGenerator::EncodeLink(const std::string& path, 315 bool DeltaDiffGenerator::EncodeLink(const string& path, vector<char>* out) {
294 std::vector<char>* out) {
295 // Store symlink path as file data 316 // Store symlink path as file data
296 vector<char> link_data(4096); 317 vector<char> link_data(4096);
297 int rc = readlink(path.c_str(), &link_data[0], link_data.size()); 318 int rc = readlink(path.c_str(), &link_data[0], link_data.size());
298 TEST_AND_RETURN_FALSE_ERRNO(rc >= 0); 319 TEST_AND_RETURN_FALSE_ERRNO(rc >= 0);
299 link_data.resize(rc); 320 link_data.resize(rc);
300 out->swap(link_data); 321 out->swap(link_data);
301 return true; 322 return true;
302 } 323 }
303 324
304 bool DeltaDiffGenerator::EncodeDev( 325 bool DeltaDiffGenerator::EncodeDev(
(...skipping 17 matching lines...) Expand all
322 return true; 343 return true;
323 } 344 }
324 345
325 // Encode the file at new_path + "/" + file_name. It may be a binary diff 346 // Encode the file at new_path + "/" + file_name. It may be a binary diff
326 // based on old_path + "/" + file_name. out_data_format will be set to 347 // based on old_path + "/" + file_name. out_data_format will be set to
327 // the format used. out_data_format may not be NULL. 348 // the format used. out_data_format may not be NULL.
328 bool DeltaDiffGenerator::EncodeFile( 349 bool DeltaDiffGenerator::EncodeFile(
329 const string& old_dir, 350 const string& old_dir,
330 const string& new_dir, 351 const string& new_dir,
331 const string& file_name, 352 const string& file_name,
353 const bool avoid_diff,
332 DeltaArchiveManifest_File_DataFormat* out_data_format, 354 DeltaArchiveManifest_File_DataFormat* out_data_format,
333 vector<char>* out) { 355 vector<char>* out,
356 bool* no_change) {
334 TEST_AND_RETURN_FALSE(out_data_format); 357 TEST_AND_RETURN_FALSE(out_data_format);
335 // First, see the full length: 358 vector<char> ret;
336 vector<char> full_data; 359 vector<char> full_data;
337 TEST_AND_RETURN_FALSE(utils::ReadFile(new_dir + "/" + file_name, &full_data)); 360 {
338 vector<char> gz_data; 361 // First, see the full length:
339 if (!full_data.empty()) { 362 TEST_AND_RETURN_FALSE(utils::ReadFile(new_dir + "/" + file_name,
340 TEST_AND_RETURN_FALSE(GzipCompress(full_data, &gz_data)); 363 &full_data));
364 vector<char> gz_data;
365 if (!full_data.empty()) {
366 TEST_AND_RETURN_FALSE(GzipCompress(full_data, &gz_data));
367 }
368
369 if (gz_data.size() < full_data.size()) {
370 *out_data_format = DeltaArchiveManifest_File_DataFormat_FULL_GZ;
371 ret.swap(gz_data);
372 } else {
373 *out_data_format = DeltaArchiveManifest_File_DataFormat_FULL;
374 ret = full_data;
375 }
341 } 376 }
342 vector<char> *ret = NULL;
343 377
344 if (gz_data.size() < full_data.size()) { 378 if (avoid_diff) {
345 *out_data_format = DeltaArchiveManifest_File_DataFormat_FULL_GZ; 379 out->swap(ret);
346 ret = &gz_data; 380 return true;
347 } else {
348 *out_data_format = DeltaArchiveManifest_File_DataFormat_FULL;
349 ret = &full_data;
350 } 381 }
351 382
352 struct stat old_stbuf; 383 struct stat old_stbuf;
353 if ((stat((old_dir + "/" + file_name).c_str(), &old_stbuf) < 0) || 384 if ((stat((old_dir + "/" + file_name).c_str(), &old_stbuf) < 0) ||
354 (!S_ISREG(old_stbuf.st_mode))) { 385 (!S_ISREG(old_stbuf.st_mode))) {
355 // stat() failed or old file is not a regular file. Just send back the full 386 // stat() failed or old file is not a regular file. Just send back
356 // contents 387 // the full contents
357 *out = *ret; 388 out->swap(ret);
358 return true; 389 return true;
359 } 390 }
360 // We have an old file. Do a binary diff. For now use bsdiff. 391 // We have an old file.
361 const string kPatchFile = "/tmp/delta.patch"; 392 // First see if the data is _exactly_ the same
393 {
394 vector<char> original_data;
395 TEST_AND_RETURN_FALSE(utils::ReadFile(old_dir + "/" + file_name,
396 &original_data));
397 if (original_data == full_data) {
398 // Original data unchanged in new file.
399 *no_change = true;
400 return true;
401 }
402 }
403
404 // Do a binary diff. For now use bsdiff.
405 const string kPatchFile = "/tmp/delta.patchXXXXXX";
406 vector<char> patch_file_path(kPatchFile.begin(), kPatchFile.end());
407 patch_file_path.push_back('\0');
408
409 int fd = mkstemp(&patch_file_path[0]);
410 if (fd >= 0)
411 close(fd);
412 TEST_AND_RETURN_FALSE(fd != -1);
362 413
363 vector<string> cmd; 414 vector<string> cmd;
364 cmd.push_back("/usr/bin/bsdiff"); 415 cmd.push_back(kBsdiffPath);
365 cmd.push_back(old_dir + "/" + file_name); 416 cmd.push_back(old_dir + "/" + file_name);
366 cmd.push_back(new_dir + "/" + file_name); 417 cmd.push_back(new_dir + "/" + file_name);
367 cmd.push_back(kPatchFile); 418 cmd.push_back(&patch_file_path[0]);
368 419
369 int rc = 1; 420 int rc = 1;
421 vector<char> patch_file;
370 TEST_AND_RETURN_FALSE(Subprocess::SynchronousExec(cmd, &rc)); 422 TEST_AND_RETURN_FALSE(Subprocess::SynchronousExec(cmd, &rc));
371 TEST_AND_RETURN_FALSE(rc == 0); 423 TEST_AND_RETURN_FALSE(rc == 0);
372 vector<char> patch_file; 424 TEST_AND_RETURN_FALSE(utils::ReadFile(&patch_file_path[0], &patch_file));
373 TEST_AND_RETURN_FALSE(utils::ReadFile(kPatchFile, &patch_file)); 425 unlink(&patch_file_path[0]);
374 unlink(kPatchFile.c_str());
375 426
376 if (patch_file.size() < ret->size()) { 427 if (patch_file.size() < ret.size()) {
377 *out_data_format = DeltaArchiveManifest_File_DataFormat_BSDIFF; 428 *out_data_format = DeltaArchiveManifest_File_DataFormat_BSDIFF;
378 ret = &patch_file; 429 ret.swap(patch_file);
379 } 430 }
380 431 out->swap(ret);
381 *out = *ret;
382 return true; 432 return true;
383 } 433 }
384 434
385 DeltaArchiveManifest* DeltaDiffGenerator::EncodeMetadataToProtoBuffer( 435 DeltaArchiveManifest* DeltaDiffGenerator::EncodeMetadataToProtoBuffer(
386 const char* new_path) { 436 const char* new_path) {
387 Node node; 437 Node node;
388 if (!UpdateNodeFromPath(new_path, &node)) 438 if (!UpdateNodeFromPath(new_path, &node))
389 return NULL; 439 return NULL;
390 int index = 0; 440 int index = 0;
391 PopulateChildIndexes(&node, &index); 441 PopulateChildIndexes(&node, &index);
392 DeltaArchiveManifest *ret = new DeltaArchiveManifest; 442 DeltaArchiveManifest *ret = new DeltaArchiveManifest;
393 map<ino_t, string> hard_links; // inode -> first found path for inode 443 map<ino_t, string> hard_links; // inode -> first found path for inode
394 NodeToDeltaArchiveManifest(&node, ret, &hard_links, ""); 444 NodeToDeltaArchiveManifest(&node, ret, &hard_links, "");
395 return ret; 445 return ret;
396 } 446 }
397 447
398 bool DeltaDiffGenerator::EncodeDataToDeltaFile( 448 bool DeltaDiffGenerator::EncodeDataToDeltaFile(
399 DeltaArchiveManifest* archive, 449 DeltaArchiveManifest* archive,
400 const std::string& old_path, 450 const string& old_path,
401 const std::string& new_path, 451 const string& new_path,
402 const std::string& out_file, 452 const string& out_file,
403 const std::string& force_compress_dev_path) { 453 const set<string>& nondiff_paths,
454 const string& force_compress_dev_path) {
404 DirectFileWriter out_writer; 455 DirectFileWriter out_writer;
405 int r = out_writer.Open(out_file.c_str(), O_WRONLY | O_CREAT | O_TRUNC, 0666); 456 int r = out_writer.Open(out_file.c_str(), O_WRONLY | O_CREAT | O_TRUNC, 0666);
406 TEST_AND_RETURN_FALSE_ERRNO(r >= 0); 457 TEST_AND_RETURN_FALSE_ERRNO(r >= 0);
407 ScopedFileWriterCloser closer(&out_writer); 458 ScopedFileWriterCloser closer(&out_writer);
408 TEST_AND_RETURN_FALSE(out_writer.Write(DeltaDiffParser::kFileMagic, 459 TEST_AND_RETURN_FALSE(out_writer.Write(DeltaDiffParser::kFileMagic,
409 strlen(DeltaDiffParser::kFileMagic)) 460 strlen(DeltaDiffParser::kFileMagic))
410 == static_cast<ssize_t>( 461 == static_cast<ssize_t>(
411 strlen(DeltaDiffParser::kFileMagic))); 462 strlen(DeltaDiffParser::kFileMagic)));
412 // Write 8 null bytes. This will be filled in w/ the offset of 463 // Write 8 null bytes. This will be filled in w/ the offset of
413 // the protobuf. 464 // the protobuf.
414 TEST_AND_RETURN_FALSE(out_writer.Write("\0\0\0\0\0\0\0\0", 8) == 8); 465 TEST_AND_RETURN_FALSE(out_writer.Write("\0\0\0\0\0\0\0\0", 8) == 8);
415 // 8 more bytes will be filled w/ the protobuf length. 466 // 8 more bytes will be filled w/ the protobuf length.
416 TEST_AND_RETURN_FALSE(out_writer.Write("\0\0\0\0\0\0\0\0", 8) == 8); 467 TEST_AND_RETURN_FALSE(out_writer.Write("\0\0\0\0\0\0\0\0", 8) == 8);
417 int out_file_length = strlen(DeltaDiffParser::kFileMagic) + 16; 468 int out_file_length = strlen(DeltaDiffParser::kFileMagic) + 16;
418 469
419 TEST_AND_RETURN_FALSE(archive->files_size() > 0); 470 TEST_AND_RETURN_FALSE(archive->files_size() > 0);
420 DeltaArchiveManifest_File* file = archive->mutable_files(0); 471 DeltaArchiveManifest_File* file = archive->mutable_files(0);
421 472
473 // nondiff_paths is passed in w/ paths relative to the installed
474 // system (e.g. /etc/fstab), but WriteFileDiffsToDeltaFile requires them
475 // to be the entire path of the new file. We create a new set
476 // here with nondiff_paths expanded.
477 set<string> always_full_target_paths;
478 for (set<string>::const_iterator it = nondiff_paths.begin();
479 it != nondiff_paths.end(); ++it) {
480 always_full_target_paths.insert(new_path + *it);
481 }
482
422 TEST_AND_RETURN_FALSE(WriteFileDiffsToDeltaFile(archive, 483 TEST_AND_RETURN_FALSE(WriteFileDiffsToDeltaFile(archive,
423 file, 484 file,
424 "", 485 "",
425 old_path, 486 old_path,
426 new_path, 487 new_path,
427 &out_writer, 488 &out_writer,
428 &out_file_length, 489 &out_file_length,
490 always_full_target_paths,
429 force_compress_dev_path)); 491 force_compress_dev_path));
430 492
431 // Finally, write the protobuf to the end of the file 493 // Finally, write the protobuf to the end of the file
432 string encoded_archive; 494 string encoded_archive;
433 TEST_AND_RETURN_FALSE(archive->SerializeToString(&encoded_archive)); 495 TEST_AND_RETURN_FALSE(archive->SerializeToString(&encoded_archive));
434 496
435 // Compress the protobuf (which contains filenames) 497 // Compress the protobuf (which contains filenames)
436 vector<char> compressed_encoded_archive; 498 vector<char> compressed_encoded_archive;
437 TEST_AND_RETURN_FALSE(GzipCompressString(encoded_archive, 499 TEST_AND_RETURN_FALSE(GzipCompressString(encoded_archive,
438 &compressed_encoded_archive)); 500 &compressed_encoded_archive));
(...skipping 15 matching lines...) Expand all
454 TEST_AND_RETURN_FALSE(pwrite(out_writer.fd(), 516 TEST_AND_RETURN_FALSE(pwrite(out_writer.fd(),
455 &pb_length, 517 &pb_length,
456 sizeof(pb_length), 518 sizeof(pb_length),
457 strlen(DeltaDiffParser::kFileMagic) + 519 strlen(DeltaDiffParser::kFileMagic) +
458 sizeof(big_endian_protobuf_offset)) == 520 sizeof(big_endian_protobuf_offset)) ==
459 sizeof(pb_length)); 521 sizeof(pb_length));
460 return true; 522 return true;
461 } 523 }
462 524
463 } // namespace chromeos_update_engine 525 } // namespace chromeos_update_engine
OLDNEW
« no previous file with comments | « src/platform/update_engine/delta_diff_generator.h ('k') | src/platform/update_engine/delta_diff_generator_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698