| 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_diff_generator.h" | 5 #include "update_engine/delta_diff_generator.h" |
| 6 | 6 |
| 7 #include <errno.h> | 7 #include <errno.h> |
| 8 #include <fcntl.h> | 8 #include <fcntl.h> |
| 9 #include <inttypes.h> | 9 #include <inttypes.h> |
| 10 #include <sys/stat.h> | 10 #include <sys/stat.h> |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 48 using std::vector; | 48 using std::vector; |
| 49 | 49 |
| 50 namespace chromeos_update_engine { | 50 namespace chromeos_update_engine { |
| 51 | 51 |
| 52 typedef DeltaDiffGenerator::Block Block; | 52 typedef DeltaDiffGenerator::Block Block; |
| 53 typedef map<const DeltaArchiveManifest_InstallOperation*, | 53 typedef map<const DeltaArchiveManifest_InstallOperation*, |
| 54 const string*> OperationNameMap; | 54 const string*> OperationNameMap; |
| 55 | 55 |
| 56 namespace { | 56 namespace { |
| 57 const size_t kBlockSize = 4096; // bytes | 57 const size_t kBlockSize = 4096; // bytes |
| 58 const string kNonexistentPath = ""; |
| 58 | 59 |
| 59 // TODO(adlr): switch from 1GiB to 2GiB when we no longer care about old | 60 // TODO(adlr): switch from 1GiB to 2GiB when we no longer care about old |
| 60 // clients: | 61 // clients: |
| 61 const size_t kRootFSPartitionSize = 1 * 1024 * 1024 * 1024; // bytes | 62 const size_t kRootFSPartitionSize = 1 * 1024 * 1024 * 1024; // bytes |
| 62 const uint64_t kVersionNumber = 1; | 63 const uint64_t kVersionNumber = 1; |
| 63 const uint64_t kFullUpdateChunkSize = 1024 * 1024; // bytes | 64 const uint64_t kFullUpdateChunkSize = 1024 * 1024; // bytes |
| 64 | 65 |
| 65 static const char* kInstallOperationTypes[] = { | 66 static const char* kInstallOperationTypes[] = { |
| 66 "REPLACE", | 67 "REPLACE", |
| 67 "REPLACE_BZ", | 68 "REPLACE_BZ", |
| (...skipping 22 matching lines...) Expand all Loading... |
| 90 Vertex::Index existing_vertex, | 91 Vertex::Index existing_vertex, |
| 91 vector<Block>* blocks, | 92 vector<Block>* blocks, |
| 92 const string& old_root, | 93 const string& old_root, |
| 93 const string& new_root, | 94 const string& new_root, |
| 94 const string& path, // within new_root | 95 const string& path, // within new_root |
| 95 int data_fd, | 96 int data_fd, |
| 96 off_t* data_file_size) { | 97 off_t* data_file_size) { |
| 97 vector<char> data; | 98 vector<char> data; |
| 98 DeltaArchiveManifest_InstallOperation operation; | 99 DeltaArchiveManifest_InstallOperation operation; |
| 99 | 100 |
| 100 TEST_AND_RETURN_FALSE(DeltaDiffGenerator::ReadFileToDiff(old_root + path, | 101 string old_path = (old_root == kNonexistentPath) ? kNonexistentPath : |
| 102 old_root + path; |
| 103 |
| 104 TEST_AND_RETURN_FALSE(DeltaDiffGenerator::ReadFileToDiff(old_path, |
| 101 new_root + path, | 105 new_root + path, |
| 102 &data, | 106 &data, |
| 103 &operation, | 107 &operation, |
| 104 true)); | 108 true)); |
| 105 | 109 |
| 106 // Write the data | 110 // Write the data |
| 107 if (operation.type() != DeltaArchiveManifest_InstallOperation_Type_MOVE) { | 111 if (operation.type() != DeltaArchiveManifest_InstallOperation_Type_MOVE) { |
| 108 operation.set_data_offset(*data_file_size); | 112 operation.set_data_offset(*data_file_size); |
| 109 operation.set_data_length(data.size()); | 113 operation.set_data_length(data.size()); |
| 110 } | 114 } |
| (...skipping 23 matching lines...) Expand all Loading... |
| 134 // For each regular file within new_root, creates a node in the graph, | 138 // For each regular file within new_root, creates a node in the graph, |
| 135 // determines the best way to compress it (REPLACE, REPLACE_BZ, COPY, BSDIFF), | 139 // determines the best way to compress it (REPLACE, REPLACE_BZ, COPY, BSDIFF), |
| 136 // and writes any necessary data to the end of data_fd. | 140 // and writes any necessary data to the end of data_fd. |
| 137 bool DeltaReadFiles(Graph* graph, | 141 bool DeltaReadFiles(Graph* graph, |
| 138 vector<Block>* blocks, | 142 vector<Block>* blocks, |
| 139 const string& old_root, | 143 const string& old_root, |
| 140 const string& new_root, | 144 const string& new_root, |
| 141 int data_fd, | 145 int data_fd, |
| 142 off_t* data_file_size) { | 146 off_t* data_file_size) { |
| 143 set<ino_t> visited_inodes; | 147 set<ino_t> visited_inodes; |
| 148 set<ino_t> visited_src_inodes; |
| 144 for (FilesystemIterator fs_iter(new_root, | 149 for (FilesystemIterator fs_iter(new_root, |
| 145 utils::SetWithValue<string>("/lost+found")); | 150 utils::SetWithValue<string>("/lost+found")); |
| 146 !fs_iter.IsEnd(); fs_iter.Increment()) { | 151 !fs_iter.IsEnd(); fs_iter.Increment()) { |
| 147 if (!S_ISREG(fs_iter.GetStat().st_mode)) | 152 if (!S_ISREG(fs_iter.GetStat().st_mode)) |
| 148 continue; | 153 continue; |
| 149 | 154 |
| 150 // Make sure we visit each inode only once. | 155 // Make sure we visit each inode only once. |
| 151 if (utils::SetContainsKey(visited_inodes, fs_iter.GetStat().st_ino)) | 156 if (utils::SetContainsKey(visited_inodes, fs_iter.GetStat().st_ino)) |
| 152 continue; | 157 continue; |
| 153 visited_inodes.insert(fs_iter.GetStat().st_ino); | 158 visited_inodes.insert(fs_iter.GetStat().st_ino); |
| 154 if (fs_iter.GetStat().st_size == 0) | 159 if (fs_iter.GetStat().st_size == 0) |
| 155 continue; | 160 continue; |
| 156 | 161 |
| 157 LOG(INFO) << "Encoding file " << fs_iter.GetPartialPath(); | 162 LOG(INFO) << "Encoding file " << fs_iter.GetPartialPath(); |
| 158 | 163 |
| 164 // We can't visit each dst image inode more than once, as that would |
| 165 // duplicate work. Here, we avoid visiting each source image inode |
| 166 // more than once. Technically, we could have multiple operations |
| 167 // that read the same blocks from the source image for diffing, but |
| 168 // we choose not to to avoid complexity. Eventually we will move away |
| 169 // from using a graph/cycle detection/etc to generate diffs, and at that |
| 170 // time, it will be easy (non-complex) to have many operations read |
| 171 // from the same source blocks. At that time, this code can die. -adlr |
| 172 bool should_diff_from_source = true; |
| 173 string src_path = old_root + fs_iter.GetPartialPath(); |
| 174 if (utils::FileExists(src_path.c_str())) { |
| 175 struct stat src_stbuf; |
| 176 TEST_AND_RETURN_FALSE_ERRNO(0 == stat(src_path.c_str(), &src_stbuf)); |
| 177 should_diff_from_source = !utils::SetContainsKey(visited_src_inodes, |
| 178 src_stbuf.st_ino); |
| 179 visited_src_inodes.insert(src_stbuf.st_ino); |
| 180 } |
| 181 |
| 159 TEST_AND_RETURN_FALSE(DeltaReadFile(graph, | 182 TEST_AND_RETURN_FALSE(DeltaReadFile(graph, |
| 160 Vertex::kInvalidIndex, | 183 Vertex::kInvalidIndex, |
| 161 blocks, | 184 blocks, |
| 162 old_root, | 185 (should_diff_from_source ? |
| 186 old_root : |
| 187 kNonexistentPath), |
| 163 new_root, | 188 new_root, |
| 164 fs_iter.GetPartialPath(), | 189 fs_iter.GetPartialPath(), |
| 165 data_fd, | 190 data_fd, |
| 166 data_file_size)); | 191 data_file_size)); |
| 167 } | 192 } |
| 168 return true; | 193 return true; |
| 169 } | 194 } |
| 170 | 195 |
| 171 // This class allocates non-existent temp blocks, starting from | 196 // This class allocates non-existent temp blocks, starting from |
| 172 // kTempBlockStart. Other code is responsible for converting these | 197 // kTempBlockStart. Other code is responsible for converting these |
| (...skipping 980 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1153 if ((*graph)[cut.old_dst].op.type() != | 1178 if ((*graph)[cut.old_dst].op.type() != |
| 1154 DeltaArchiveManifest_InstallOperation_Type_REPLACE_BZ && | 1179 DeltaArchiveManifest_InstallOperation_Type_REPLACE_BZ && |
| 1155 (*graph)[cut.old_dst].op.type() != | 1180 (*graph)[cut.old_dst].op.type() != |
| 1156 DeltaArchiveManifest_InstallOperation_Type_REPLACE) { | 1181 DeltaArchiveManifest_InstallOperation_Type_REPLACE) { |
| 1157 Vertex::EdgeMap out_edges = (*graph)[cut.old_dst].out_edges; | 1182 Vertex::EdgeMap out_edges = (*graph)[cut.old_dst].out_edges; |
| 1158 graph_utils::DropWriteBeforeDeps(&out_edges); | 1183 graph_utils::DropWriteBeforeDeps(&out_edges); |
| 1159 | 1184 |
| 1160 TEST_AND_RETURN_FALSE(DeltaReadFile(graph, | 1185 TEST_AND_RETURN_FALSE(DeltaReadFile(graph, |
| 1161 cut.old_dst, | 1186 cut.old_dst, |
| 1162 NULL, | 1187 NULL, |
| 1163 "/-!@:&*nonexistent_path", | 1188 kNonexistentPath, |
| 1164 new_root, | 1189 new_root, |
| 1165 (*graph)[cut.old_dst].file_name, | 1190 (*graph)[cut.old_dst].file_name, |
| 1166 data_fd, | 1191 data_fd, |
| 1167 data_file_size)); | 1192 data_file_size)); |
| 1168 | 1193 |
| 1169 (*graph)[cut.old_dst].out_edges = out_edges; | 1194 (*graph)[cut.old_dst].out_edges = out_edges; |
| 1170 | 1195 |
| 1171 // Right now we don't have doubly-linked edges, so we have to scan | 1196 // Right now we don't have doubly-linked edges, so we have to scan |
| 1172 // the whole graph. | 1197 // the whole graph. |
| 1173 graph_utils::DropIncomingEdgesTo(graph, cut.old_dst); | 1198 graph_utils::DropIncomingEdgesTo(graph, cut.old_dst); |
| (...skipping 427 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1601 dummy_extent->set_start_block(kSparseHole); | 1626 dummy_extent->set_start_block(kSparseHole); |
| 1602 dummy_extent->set_num_blocks((signature_blob_length + kBlockSize - 1) / | 1627 dummy_extent->set_num_blocks((signature_blob_length + kBlockSize - 1) / |
| 1603 kBlockSize); | 1628 kBlockSize); |
| 1604 } | 1629 } |
| 1605 | 1630 |
| 1606 const char* const kBsdiffPath = "bsdiff"; | 1631 const char* const kBsdiffPath = "bsdiff"; |
| 1607 const char* const kBspatchPath = "bspatch"; | 1632 const char* const kBspatchPath = "bspatch"; |
| 1608 const char* const kDeltaMagic = "CrAU"; | 1633 const char* const kDeltaMagic = "CrAU"; |
| 1609 | 1634 |
| 1610 }; // namespace chromeos_update_engine | 1635 }; // namespace chromeos_update_engine |
| OLD | NEW |