xref: /aosp_15_r20/bootable/deprecated-ota/updater/blockimg.cpp (revision acea8879c968027b49a027136800575dd9783ddf)
1*acea8879SAndroid Build Coastguard Worker /*
2*acea8879SAndroid Build Coastguard Worker  * Copyright (C) 2014 The Android Open Source Project
3*acea8879SAndroid Build Coastguard Worker  *
4*acea8879SAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*acea8879SAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*acea8879SAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*acea8879SAndroid Build Coastguard Worker  *
8*acea8879SAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*acea8879SAndroid Build Coastguard Worker  *
10*acea8879SAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*acea8879SAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*acea8879SAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*acea8879SAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*acea8879SAndroid Build Coastguard Worker  * limitations under the License.
15*acea8879SAndroid Build Coastguard Worker  */
16*acea8879SAndroid Build Coastguard Worker 
17*acea8879SAndroid Build Coastguard Worker #include <ctype.h>
18*acea8879SAndroid Build Coastguard Worker #include <dirent.h>
19*acea8879SAndroid Build Coastguard Worker #include <errno.h>
20*acea8879SAndroid Build Coastguard Worker #include <fcntl.h>
21*acea8879SAndroid Build Coastguard Worker #include <inttypes.h>
22*acea8879SAndroid Build Coastguard Worker #include <linux/fs.h>
23*acea8879SAndroid Build Coastguard Worker #include <pthread.h>
24*acea8879SAndroid Build Coastguard Worker #include <stdarg.h>
25*acea8879SAndroid Build Coastguard Worker #include <stdio.h>
26*acea8879SAndroid Build Coastguard Worker #include <stdlib.h>
27*acea8879SAndroid Build Coastguard Worker #include <string.h>
28*acea8879SAndroid Build Coastguard Worker #include <sys/ioctl.h>
29*acea8879SAndroid Build Coastguard Worker #include <sys/stat.h>
30*acea8879SAndroid Build Coastguard Worker #include <sys/types.h>
31*acea8879SAndroid Build Coastguard Worker #include <sys/wait.h>
32*acea8879SAndroid Build Coastguard Worker #include <time.h>
33*acea8879SAndroid Build Coastguard Worker #include <unistd.h>
34*acea8879SAndroid Build Coastguard Worker 
35*acea8879SAndroid Build Coastguard Worker #include <functional>
36*acea8879SAndroid Build Coastguard Worker #include <limits>
37*acea8879SAndroid Build Coastguard Worker #include <memory>
38*acea8879SAndroid Build Coastguard Worker #include <string>
39*acea8879SAndroid Build Coastguard Worker #include <unordered_map>
40*acea8879SAndroid Build Coastguard Worker #include <vector>
41*acea8879SAndroid Build Coastguard Worker 
42*acea8879SAndroid Build Coastguard Worker #include <android-base/file.h>
43*acea8879SAndroid Build Coastguard Worker #include <android-base/logging.h>
44*acea8879SAndroid Build Coastguard Worker #include <android-base/parseint.h>
45*acea8879SAndroid Build Coastguard Worker #include <android-base/stringprintf.h>
46*acea8879SAndroid Build Coastguard Worker #include <android-base/strings.h>
47*acea8879SAndroid Build Coastguard Worker #include <android-base/unique_fd.h>
48*acea8879SAndroid Build Coastguard Worker #include <applypatch/applypatch.h>
49*acea8879SAndroid Build Coastguard Worker #include <brotli/decode.h>
50*acea8879SAndroid Build Coastguard Worker #include <fec/io.h>
51*acea8879SAndroid Build Coastguard Worker #include <openssl/sha.h>
52*acea8879SAndroid Build Coastguard Worker #include <verity/hash_tree_builder.h>
53*acea8879SAndroid Build Coastguard Worker #include <ziparchive/zip_archive.h>
54*acea8879SAndroid Build Coastguard Worker 
55*acea8879SAndroid Build Coastguard Worker #include "edify/expr.h"
56*acea8879SAndroid Build Coastguard Worker #include "edify/updater_interface.h"
57*acea8879SAndroid Build Coastguard Worker #include "otautil/dirutil.h"
58*acea8879SAndroid Build Coastguard Worker #include "otautil/error_code.h"
59*acea8879SAndroid Build Coastguard Worker #include "otautil/paths.h"
60*acea8879SAndroid Build Coastguard Worker #include "otautil/print_sha1.h"
61*acea8879SAndroid Build Coastguard Worker #include "otautil/rangeset.h"
62*acea8879SAndroid Build Coastguard Worker #include "private/commands.h"
63*acea8879SAndroid Build Coastguard Worker #include "updater/install.h"
64*acea8879SAndroid Build Coastguard Worker 
65*acea8879SAndroid Build Coastguard Worker #ifdef __ANDROID__
66*acea8879SAndroid Build Coastguard Worker #include <private/android_filesystem_config.h>
67*acea8879SAndroid Build Coastguard Worker // Set this to 0 to interpret 'erase' transfers to mean do a BLKDISCARD ioctl (the normal behavior).
68*acea8879SAndroid Build Coastguard Worker // Set to 1 to interpret erase to mean fill the region with zeroes.
69*acea8879SAndroid Build Coastguard Worker #define DEBUG_ERASE  0
70*acea8879SAndroid Build Coastguard Worker #else
71*acea8879SAndroid Build Coastguard Worker #define DEBUG_ERASE 1
72*acea8879SAndroid Build Coastguard Worker #define AID_SYSTEM -1
73*acea8879SAndroid Build Coastguard Worker #endif  // __ANDROID__
74*acea8879SAndroid Build Coastguard Worker 
75*acea8879SAndroid Build Coastguard Worker static constexpr size_t BLOCKSIZE = 4096;
76*acea8879SAndroid Build Coastguard Worker static constexpr mode_t STASH_DIRECTORY_MODE = 0700;
77*acea8879SAndroid Build Coastguard Worker static constexpr mode_t STASH_FILE_MODE = 0600;
78*acea8879SAndroid Build Coastguard Worker static constexpr mode_t MARKER_DIRECTORY_MODE = 0700;
79*acea8879SAndroid Build Coastguard Worker 
80*acea8879SAndroid Build Coastguard Worker static CauseCode failure_type = kNoCause;
81*acea8879SAndroid Build Coastguard Worker static bool is_retry = false;
82*acea8879SAndroid Build Coastguard Worker static std::unordered_map<std::string, RangeSet> stash_map;
83*acea8879SAndroid Build Coastguard Worker 
DeleteLastCommandFile()84*acea8879SAndroid Build Coastguard Worker static void DeleteLastCommandFile() {
85*acea8879SAndroid Build Coastguard Worker   const std::string& last_command_file = Paths::Get().last_command_file();
86*acea8879SAndroid Build Coastguard Worker   if (unlink(last_command_file.c_str()) == -1 && errno != ENOENT) {
87*acea8879SAndroid Build Coastguard Worker     PLOG(ERROR) << "Failed to unlink: " << last_command_file;
88*acea8879SAndroid Build Coastguard Worker   }
89*acea8879SAndroid Build Coastguard Worker }
90*acea8879SAndroid Build Coastguard Worker 
91*acea8879SAndroid Build Coastguard Worker // Parse the last command index of the last update and save the result to |last_command_index|.
92*acea8879SAndroid Build Coastguard Worker // Return true if we successfully read the index.
ParseLastCommandFile(size_t * last_command_index)93*acea8879SAndroid Build Coastguard Worker static bool ParseLastCommandFile(size_t* last_command_index) {
94*acea8879SAndroid Build Coastguard Worker   const std::string& last_command_file = Paths::Get().last_command_file();
95*acea8879SAndroid Build Coastguard Worker   android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(last_command_file.c_str(), O_RDONLY)));
96*acea8879SAndroid Build Coastguard Worker   if (fd == -1) {
97*acea8879SAndroid Build Coastguard Worker     if (errno != ENOENT) {
98*acea8879SAndroid Build Coastguard Worker       PLOG(ERROR) << "Failed to open " << last_command_file;
99*acea8879SAndroid Build Coastguard Worker       return false;
100*acea8879SAndroid Build Coastguard Worker     }
101*acea8879SAndroid Build Coastguard Worker 
102*acea8879SAndroid Build Coastguard Worker     LOG(INFO) << last_command_file << " doesn't exist.";
103*acea8879SAndroid Build Coastguard Worker     return false;
104*acea8879SAndroid Build Coastguard Worker   }
105*acea8879SAndroid Build Coastguard Worker 
106*acea8879SAndroid Build Coastguard Worker   // Now that the last_command file exists, parse the last command index of previous update.
107*acea8879SAndroid Build Coastguard Worker   std::string content;
108*acea8879SAndroid Build Coastguard Worker   if (!android::base::ReadFdToString(fd.get(), &content)) {
109*acea8879SAndroid Build Coastguard Worker     LOG(ERROR) << "Failed to read: " << last_command_file;
110*acea8879SAndroid Build Coastguard Worker     return false;
111*acea8879SAndroid Build Coastguard Worker   }
112*acea8879SAndroid Build Coastguard Worker 
113*acea8879SAndroid Build Coastguard Worker   std::vector<std::string> lines = android::base::Split(android::base::Trim(content), "\n");
114*acea8879SAndroid Build Coastguard Worker   if (lines.size() != 2) {
115*acea8879SAndroid Build Coastguard Worker     LOG(ERROR) << "Unexpected line counts in last command file: " << content;
116*acea8879SAndroid Build Coastguard Worker     return false;
117*acea8879SAndroid Build Coastguard Worker   }
118*acea8879SAndroid Build Coastguard Worker 
119*acea8879SAndroid Build Coastguard Worker   if (!android::base::ParseUint(lines[0], last_command_index)) {
120*acea8879SAndroid Build Coastguard Worker     LOG(ERROR) << "Failed to parse integer in: " << lines[0];
121*acea8879SAndroid Build Coastguard Worker     return false;
122*acea8879SAndroid Build Coastguard Worker   }
123*acea8879SAndroid Build Coastguard Worker 
124*acea8879SAndroid Build Coastguard Worker   return true;
125*acea8879SAndroid Build Coastguard Worker }
126*acea8879SAndroid Build Coastguard Worker 
FsyncDir(const std::string & dirname)127*acea8879SAndroid Build Coastguard Worker static bool FsyncDir(const std::string& dirname) {
128*acea8879SAndroid Build Coastguard Worker   android::base::unique_fd dfd(TEMP_FAILURE_RETRY(open(dirname.c_str(), O_RDONLY | O_DIRECTORY)));
129*acea8879SAndroid Build Coastguard Worker   if (dfd == -1) {
130*acea8879SAndroid Build Coastguard Worker     failure_type = errno == EIO ? kEioFailure : kFileOpenFailure;
131*acea8879SAndroid Build Coastguard Worker     PLOG(ERROR) << "Failed to open " << dirname;
132*acea8879SAndroid Build Coastguard Worker     return false;
133*acea8879SAndroid Build Coastguard Worker   }
134*acea8879SAndroid Build Coastguard Worker   if (fsync(dfd) == -1) {
135*acea8879SAndroid Build Coastguard Worker     failure_type = errno == EIO ? kEioFailure : kFsyncFailure;
136*acea8879SAndroid Build Coastguard Worker     PLOG(ERROR) << "Failed to fsync " << dirname;
137*acea8879SAndroid Build Coastguard Worker     return false;
138*acea8879SAndroid Build Coastguard Worker   }
139*acea8879SAndroid Build Coastguard Worker   return true;
140*acea8879SAndroid Build Coastguard Worker }
141*acea8879SAndroid Build Coastguard Worker 
142*acea8879SAndroid Build Coastguard Worker // Update the last executed command index in the last_command_file.
UpdateLastCommandIndex(size_t command_index,const std::string & command_string)143*acea8879SAndroid Build Coastguard Worker static bool UpdateLastCommandIndex(size_t command_index, const std::string& command_string) {
144*acea8879SAndroid Build Coastguard Worker   const std::string& last_command_file = Paths::Get().last_command_file();
145*acea8879SAndroid Build Coastguard Worker   std::string last_command_tmp = last_command_file + ".tmp";
146*acea8879SAndroid Build Coastguard Worker   std::string content = std::to_string(command_index) + "\n" + command_string;
147*acea8879SAndroid Build Coastguard Worker   android::base::unique_fd wfd(
148*acea8879SAndroid Build Coastguard Worker       TEMP_FAILURE_RETRY(open(last_command_tmp.c_str(), O_WRONLY | O_CREAT | O_TRUNC, 0660)));
149*acea8879SAndroid Build Coastguard Worker   if (wfd == -1 || !android::base::WriteStringToFd(content, wfd)) {
150*acea8879SAndroid Build Coastguard Worker     PLOG(ERROR) << "Failed to update last command";
151*acea8879SAndroid Build Coastguard Worker     return false;
152*acea8879SAndroid Build Coastguard Worker   }
153*acea8879SAndroid Build Coastguard Worker 
154*acea8879SAndroid Build Coastguard Worker   if (fsync(wfd) == -1) {
155*acea8879SAndroid Build Coastguard Worker     PLOG(ERROR) << "Failed to fsync " << last_command_tmp;
156*acea8879SAndroid Build Coastguard Worker     return false;
157*acea8879SAndroid Build Coastguard Worker   }
158*acea8879SAndroid Build Coastguard Worker 
159*acea8879SAndroid Build Coastguard Worker   if (chown(last_command_tmp.c_str(), AID_SYSTEM, AID_SYSTEM) == -1) {
160*acea8879SAndroid Build Coastguard Worker     PLOG(ERROR) << "Failed to change owner for " << last_command_tmp;
161*acea8879SAndroid Build Coastguard Worker     return false;
162*acea8879SAndroid Build Coastguard Worker   }
163*acea8879SAndroid Build Coastguard Worker 
164*acea8879SAndroid Build Coastguard Worker   if (rename(last_command_tmp.c_str(), last_command_file.c_str()) == -1) {
165*acea8879SAndroid Build Coastguard Worker     PLOG(ERROR) << "Failed to rename" << last_command_tmp;
166*acea8879SAndroid Build Coastguard Worker     return false;
167*acea8879SAndroid Build Coastguard Worker   }
168*acea8879SAndroid Build Coastguard Worker 
169*acea8879SAndroid Build Coastguard Worker   if (!FsyncDir(android::base::Dirname(last_command_file))) {
170*acea8879SAndroid Build Coastguard Worker     return false;
171*acea8879SAndroid Build Coastguard Worker   }
172*acea8879SAndroid Build Coastguard Worker 
173*acea8879SAndroid Build Coastguard Worker   return true;
174*acea8879SAndroid Build Coastguard Worker }
175*acea8879SAndroid Build Coastguard Worker 
SetUpdatedMarker(const std::string & marker)176*acea8879SAndroid Build Coastguard Worker bool SetUpdatedMarker(const std::string& marker) {
177*acea8879SAndroid Build Coastguard Worker   auto dirname = android::base::Dirname(marker);
178*acea8879SAndroid Build Coastguard Worker   auto res = mkdir(dirname.c_str(), MARKER_DIRECTORY_MODE);
179*acea8879SAndroid Build Coastguard Worker   if (res == -1 && errno != EEXIST) {
180*acea8879SAndroid Build Coastguard Worker     PLOG(ERROR) << "Failed to create directory for marker: " << dirname;
181*acea8879SAndroid Build Coastguard Worker     return false;
182*acea8879SAndroid Build Coastguard Worker   }
183*acea8879SAndroid Build Coastguard Worker 
184*acea8879SAndroid Build Coastguard Worker   if (!android::base::WriteStringToFile("", marker)) {
185*acea8879SAndroid Build Coastguard Worker     PLOG(ERROR) << "Failed to write to marker file " << marker;
186*acea8879SAndroid Build Coastguard Worker     return false;
187*acea8879SAndroid Build Coastguard Worker   }
188*acea8879SAndroid Build Coastguard Worker   if (!FsyncDir(dirname)) {
189*acea8879SAndroid Build Coastguard Worker     return false;
190*acea8879SAndroid Build Coastguard Worker   }
191*acea8879SAndroid Build Coastguard Worker   LOG(INFO) << "Wrote updated marker to " << marker;
192*acea8879SAndroid Build Coastguard Worker   return true;
193*acea8879SAndroid Build Coastguard Worker }
194*acea8879SAndroid Build Coastguard Worker 
discard_blocks(int fd,off64_t offset,uint64_t size,bool force=false)195*acea8879SAndroid Build Coastguard Worker static bool discard_blocks(int fd, off64_t offset, uint64_t size, bool force = false) {
196*acea8879SAndroid Build Coastguard Worker   // Don't discard blocks unless the update is a retry run or force == true
197*acea8879SAndroid Build Coastguard Worker   if (!is_retry && !force) {
198*acea8879SAndroid Build Coastguard Worker     return true;
199*acea8879SAndroid Build Coastguard Worker   }
200*acea8879SAndroid Build Coastguard Worker 
201*acea8879SAndroid Build Coastguard Worker   uint64_t args[2] = { static_cast<uint64_t>(offset), size };
202*acea8879SAndroid Build Coastguard Worker   if (ioctl(fd, BLKDISCARD, &args) == -1) {
203*acea8879SAndroid Build Coastguard Worker     // On devices that does not support BLKDISCARD, ignore the error.
204*acea8879SAndroid Build Coastguard Worker     if (errno == EOPNOTSUPP) {
205*acea8879SAndroid Build Coastguard Worker       return true;
206*acea8879SAndroid Build Coastguard Worker     }
207*acea8879SAndroid Build Coastguard Worker     PLOG(ERROR) << "BLKDISCARD ioctl failed";
208*acea8879SAndroid Build Coastguard Worker     return false;
209*acea8879SAndroid Build Coastguard Worker   }
210*acea8879SAndroid Build Coastguard Worker   return true;
211*acea8879SAndroid Build Coastguard Worker }
212*acea8879SAndroid Build Coastguard Worker 
check_lseek(int fd,off64_t offset,int whence)213*acea8879SAndroid Build Coastguard Worker static bool check_lseek(int fd, off64_t offset, int whence) {
214*acea8879SAndroid Build Coastguard Worker     off64_t rc = TEMP_FAILURE_RETRY(lseek64(fd, offset, whence));
215*acea8879SAndroid Build Coastguard Worker     if (rc == -1) {
216*acea8879SAndroid Build Coastguard Worker         failure_type = kLseekFailure;
217*acea8879SAndroid Build Coastguard Worker         PLOG(ERROR) << "lseek64 failed";
218*acea8879SAndroid Build Coastguard Worker         return false;
219*acea8879SAndroid Build Coastguard Worker     }
220*acea8879SAndroid Build Coastguard Worker     return true;
221*acea8879SAndroid Build Coastguard Worker }
222*acea8879SAndroid Build Coastguard Worker 
allocate(size_t size,std::vector<uint8_t> * buffer)223*acea8879SAndroid Build Coastguard Worker static void allocate(size_t size, std::vector<uint8_t>* buffer) {
224*acea8879SAndroid Build Coastguard Worker   // If the buffer's big enough, reuse it.
225*acea8879SAndroid Build Coastguard Worker   if (size <= buffer->size()) return;
226*acea8879SAndroid Build Coastguard Worker   buffer->resize(size);
227*acea8879SAndroid Build Coastguard Worker }
228*acea8879SAndroid Build Coastguard Worker 
229*acea8879SAndroid Build Coastguard Worker /**
230*acea8879SAndroid Build Coastguard Worker  * RangeSinkWriter reads data from the given FD, and writes them to the destination specified by the
231*acea8879SAndroid Build Coastguard Worker  * given RangeSet.
232*acea8879SAndroid Build Coastguard Worker  */
233*acea8879SAndroid Build Coastguard Worker class RangeSinkWriter {
234*acea8879SAndroid Build Coastguard Worker  public:
RangeSinkWriter(int fd,const RangeSet & tgt)235*acea8879SAndroid Build Coastguard Worker   RangeSinkWriter(int fd, const RangeSet& tgt)
236*acea8879SAndroid Build Coastguard Worker       : fd_(fd),
237*acea8879SAndroid Build Coastguard Worker         tgt_(tgt),
238*acea8879SAndroid Build Coastguard Worker         next_range_(0),
239*acea8879SAndroid Build Coastguard Worker         current_range_left_(0),
240*acea8879SAndroid Build Coastguard Worker         bytes_written_(0) {
241*acea8879SAndroid Build Coastguard Worker     CHECK_NE(tgt.size(), static_cast<size_t>(0));
242*acea8879SAndroid Build Coastguard Worker   };
243*acea8879SAndroid Build Coastguard Worker 
Finished() const244*acea8879SAndroid Build Coastguard Worker   bool Finished() const {
245*acea8879SAndroid Build Coastguard Worker     return next_range_ == tgt_.size() && current_range_left_ == 0;
246*acea8879SAndroid Build Coastguard Worker   }
247*acea8879SAndroid Build Coastguard Worker 
AvailableSpace() const248*acea8879SAndroid Build Coastguard Worker   size_t AvailableSpace() const {
249*acea8879SAndroid Build Coastguard Worker     return tgt_.blocks() * BLOCKSIZE - bytes_written_;
250*acea8879SAndroid Build Coastguard Worker   }
251*acea8879SAndroid Build Coastguard Worker 
252*acea8879SAndroid Build Coastguard Worker   // Return number of bytes written; and 0 indicates a writing failure.
Write(const uint8_t * data,size_t size)253*acea8879SAndroid Build Coastguard Worker   size_t Write(const uint8_t* data, size_t size) {
254*acea8879SAndroid Build Coastguard Worker     if (Finished()) {
255*acea8879SAndroid Build Coastguard Worker       LOG(ERROR) << "range sink write overrun; can't write " << size << " bytes";
256*acea8879SAndroid Build Coastguard Worker       return 0;
257*acea8879SAndroid Build Coastguard Worker     }
258*acea8879SAndroid Build Coastguard Worker 
259*acea8879SAndroid Build Coastguard Worker     size_t written = 0;
260*acea8879SAndroid Build Coastguard Worker     while (size > 0) {
261*acea8879SAndroid Build Coastguard Worker       // Move to the next range as needed.
262*acea8879SAndroid Build Coastguard Worker       if (!SeekToOutputRange()) {
263*acea8879SAndroid Build Coastguard Worker         break;
264*acea8879SAndroid Build Coastguard Worker       }
265*acea8879SAndroid Build Coastguard Worker 
266*acea8879SAndroid Build Coastguard Worker       size_t write_now = size;
267*acea8879SAndroid Build Coastguard Worker       if (current_range_left_ < write_now) {
268*acea8879SAndroid Build Coastguard Worker         write_now = current_range_left_;
269*acea8879SAndroid Build Coastguard Worker       }
270*acea8879SAndroid Build Coastguard Worker 
271*acea8879SAndroid Build Coastguard Worker       if (!android::base::WriteFully(fd_, data, write_now)) {
272*acea8879SAndroid Build Coastguard Worker         failure_type = errno == EIO ? kEioFailure : kFwriteFailure;
273*acea8879SAndroid Build Coastguard Worker         PLOG(ERROR) << "Failed to write " << write_now << " bytes of data";
274*acea8879SAndroid Build Coastguard Worker         break;
275*acea8879SAndroid Build Coastguard Worker       }
276*acea8879SAndroid Build Coastguard Worker 
277*acea8879SAndroid Build Coastguard Worker       data += write_now;
278*acea8879SAndroid Build Coastguard Worker       size -= write_now;
279*acea8879SAndroid Build Coastguard Worker 
280*acea8879SAndroid Build Coastguard Worker       current_range_left_ -= write_now;
281*acea8879SAndroid Build Coastguard Worker       written += write_now;
282*acea8879SAndroid Build Coastguard Worker     }
283*acea8879SAndroid Build Coastguard Worker 
284*acea8879SAndroid Build Coastguard Worker     bytes_written_ += written;
285*acea8879SAndroid Build Coastguard Worker     return written;
286*acea8879SAndroid Build Coastguard Worker   }
287*acea8879SAndroid Build Coastguard Worker 
BytesWritten() const288*acea8879SAndroid Build Coastguard Worker   size_t BytesWritten() const {
289*acea8879SAndroid Build Coastguard Worker     return bytes_written_;
290*acea8879SAndroid Build Coastguard Worker   }
291*acea8879SAndroid Build Coastguard Worker 
292*acea8879SAndroid Build Coastguard Worker  private:
293*acea8879SAndroid Build Coastguard Worker   // Set up the output cursor, move to next range if needed.
SeekToOutputRange()294*acea8879SAndroid Build Coastguard Worker   bool SeekToOutputRange() {
295*acea8879SAndroid Build Coastguard Worker     // We haven't finished the current range yet.
296*acea8879SAndroid Build Coastguard Worker     if (current_range_left_ != 0) {
297*acea8879SAndroid Build Coastguard Worker       return true;
298*acea8879SAndroid Build Coastguard Worker     }
299*acea8879SAndroid Build Coastguard Worker     // We can't write any more; let the write function return how many bytes have been written
300*acea8879SAndroid Build Coastguard Worker     // so far.
301*acea8879SAndroid Build Coastguard Worker     if (next_range_ >= tgt_.size()) {
302*acea8879SAndroid Build Coastguard Worker       return false;
303*acea8879SAndroid Build Coastguard Worker     }
304*acea8879SAndroid Build Coastguard Worker 
305*acea8879SAndroid Build Coastguard Worker     const Range& range = tgt_[next_range_];
306*acea8879SAndroid Build Coastguard Worker     off64_t offset = static_cast<off64_t>(range.first) * BLOCKSIZE;
307*acea8879SAndroid Build Coastguard Worker     current_range_left_ = (range.second - range.first) * BLOCKSIZE;
308*acea8879SAndroid Build Coastguard Worker     next_range_++;
309*acea8879SAndroid Build Coastguard Worker 
310*acea8879SAndroid Build Coastguard Worker     if (!discard_blocks(fd_, offset, current_range_left_)) {
311*acea8879SAndroid Build Coastguard Worker       return false;
312*acea8879SAndroid Build Coastguard Worker     }
313*acea8879SAndroid Build Coastguard Worker     if (!check_lseek(fd_, offset, SEEK_SET)) {
314*acea8879SAndroid Build Coastguard Worker       return false;
315*acea8879SAndroid Build Coastguard Worker     }
316*acea8879SAndroid Build Coastguard Worker     return true;
317*acea8879SAndroid Build Coastguard Worker   }
318*acea8879SAndroid Build Coastguard Worker 
319*acea8879SAndroid Build Coastguard Worker   // The output file descriptor.
320*acea8879SAndroid Build Coastguard Worker   int fd_;
321*acea8879SAndroid Build Coastguard Worker   // The destination ranges for the data.
322*acea8879SAndroid Build Coastguard Worker   const RangeSet& tgt_;
323*acea8879SAndroid Build Coastguard Worker   // The next range that we should write to.
324*acea8879SAndroid Build Coastguard Worker   size_t next_range_;
325*acea8879SAndroid Build Coastguard Worker   // The number of bytes to write before moving to the next range.
326*acea8879SAndroid Build Coastguard Worker   size_t current_range_left_;
327*acea8879SAndroid Build Coastguard Worker   // Total bytes written by the writer.
328*acea8879SAndroid Build Coastguard Worker   size_t bytes_written_;
329*acea8879SAndroid Build Coastguard Worker };
330*acea8879SAndroid Build Coastguard Worker 
331*acea8879SAndroid Build Coastguard Worker /**
332*acea8879SAndroid Build Coastguard Worker  * All of the data for all the 'new' transfers is contained in one file in the update package,
333*acea8879SAndroid Build Coastguard Worker  * concatenated together in the order in which transfers.list will need it. We want to stream it out
334*acea8879SAndroid Build Coastguard Worker  * of the archive (it's compressed) without writing it to a temp file, but we can't write each
335*acea8879SAndroid Build Coastguard Worker  * section until it's that transfer's turn to go.
336*acea8879SAndroid Build Coastguard Worker  *
337*acea8879SAndroid Build Coastguard Worker  * To achieve this, we expand the new data from the archive in a background thread, and block that
338*acea8879SAndroid Build Coastguard Worker  * threads 'receive uncompressed data' function until the main thread has reached a point where we
339*acea8879SAndroid Build Coastguard Worker  * want some new data to be written. We signal the background thread with the destination for the
340*acea8879SAndroid Build Coastguard Worker  * data and block the main thread, waiting for the background thread to complete writing that
341*acea8879SAndroid Build Coastguard Worker  * section. Then it signals the main thread to wake up and goes back to blocking waiting for a
342*acea8879SAndroid Build Coastguard Worker  * transfer.
343*acea8879SAndroid Build Coastguard Worker  *
344*acea8879SAndroid Build Coastguard Worker  * NewThreadInfo is the struct used to pass information back and forth between the two threads. When
345*acea8879SAndroid Build Coastguard Worker  * the main thread wants some data written, it sets writer to the destination location and signals
346*acea8879SAndroid Build Coastguard Worker  * the condition. When the background thread is done writing, it clears writer and signals the
347*acea8879SAndroid Build Coastguard Worker  * condition again.
348*acea8879SAndroid Build Coastguard Worker  */
349*acea8879SAndroid Build Coastguard Worker struct NewThreadInfo {
350*acea8879SAndroid Build Coastguard Worker   ZipArchiveHandle za;
351*acea8879SAndroid Build Coastguard Worker   ZipEntry64 entry{};
352*acea8879SAndroid Build Coastguard Worker   bool brotli_compressed;
353*acea8879SAndroid Build Coastguard Worker 
354*acea8879SAndroid Build Coastguard Worker   std::unique_ptr<RangeSinkWriter> writer;
355*acea8879SAndroid Build Coastguard Worker   BrotliDecoderState* brotli_decoder_state;
356*acea8879SAndroid Build Coastguard Worker   bool receiver_available;
357*acea8879SAndroid Build Coastguard Worker 
358*acea8879SAndroid Build Coastguard Worker   pthread_mutex_t mu;
359*acea8879SAndroid Build Coastguard Worker   pthread_cond_t cv;
360*acea8879SAndroid Build Coastguard Worker };
361*acea8879SAndroid Build Coastguard Worker 
receive_new_data(const uint8_t * data,size_t size,void * cookie)362*acea8879SAndroid Build Coastguard Worker static bool receive_new_data(const uint8_t* data, size_t size, void* cookie) {
363*acea8879SAndroid Build Coastguard Worker   NewThreadInfo* nti = static_cast<NewThreadInfo*>(cookie);
364*acea8879SAndroid Build Coastguard Worker 
365*acea8879SAndroid Build Coastguard Worker   while (size > 0) {
366*acea8879SAndroid Build Coastguard Worker     // Wait for nti->writer to be non-null, indicating some of this data is wanted.
367*acea8879SAndroid Build Coastguard Worker     pthread_mutex_lock(&nti->mu);
368*acea8879SAndroid Build Coastguard Worker     while (nti->writer == nullptr) {
369*acea8879SAndroid Build Coastguard Worker       // End the new data receiver if we encounter an error when performing block image update.
370*acea8879SAndroid Build Coastguard Worker       if (!nti->receiver_available) {
371*acea8879SAndroid Build Coastguard Worker         pthread_mutex_unlock(&nti->mu);
372*acea8879SAndroid Build Coastguard Worker         return false;
373*acea8879SAndroid Build Coastguard Worker       }
374*acea8879SAndroid Build Coastguard Worker       pthread_cond_wait(&nti->cv, &nti->mu);
375*acea8879SAndroid Build Coastguard Worker     }
376*acea8879SAndroid Build Coastguard Worker     pthread_mutex_unlock(&nti->mu);
377*acea8879SAndroid Build Coastguard Worker 
378*acea8879SAndroid Build Coastguard Worker     // At this point nti->writer is set, and we own it. The main thread is waiting for it to
379*acea8879SAndroid Build Coastguard Worker     // disappear from nti.
380*acea8879SAndroid Build Coastguard Worker     size_t write_now = std::min(size, nti->writer->AvailableSpace());
381*acea8879SAndroid Build Coastguard Worker     if (nti->writer->Write(data, write_now) != write_now) {
382*acea8879SAndroid Build Coastguard Worker       LOG(ERROR) << "Failed to write " << write_now << " bytes.";
383*acea8879SAndroid Build Coastguard Worker       return false;
384*acea8879SAndroid Build Coastguard Worker     }
385*acea8879SAndroid Build Coastguard Worker 
386*acea8879SAndroid Build Coastguard Worker     data += write_now;
387*acea8879SAndroid Build Coastguard Worker     size -= write_now;
388*acea8879SAndroid Build Coastguard Worker 
389*acea8879SAndroid Build Coastguard Worker     if (nti->writer->Finished()) {
390*acea8879SAndroid Build Coastguard Worker       // We have written all the bytes desired by this writer.
391*acea8879SAndroid Build Coastguard Worker 
392*acea8879SAndroid Build Coastguard Worker       pthread_mutex_lock(&nti->mu);
393*acea8879SAndroid Build Coastguard Worker       nti->writer = nullptr;
394*acea8879SAndroid Build Coastguard Worker       pthread_cond_broadcast(&nti->cv);
395*acea8879SAndroid Build Coastguard Worker       pthread_mutex_unlock(&nti->mu);
396*acea8879SAndroid Build Coastguard Worker     }
397*acea8879SAndroid Build Coastguard Worker   }
398*acea8879SAndroid Build Coastguard Worker 
399*acea8879SAndroid Build Coastguard Worker   return true;
400*acea8879SAndroid Build Coastguard Worker }
401*acea8879SAndroid Build Coastguard Worker 
receive_brotli_new_data(const uint8_t * data,size_t size,void * cookie)402*acea8879SAndroid Build Coastguard Worker static bool receive_brotli_new_data(const uint8_t* data, size_t size, void* cookie) {
403*acea8879SAndroid Build Coastguard Worker   NewThreadInfo* nti = static_cast<NewThreadInfo*>(cookie);
404*acea8879SAndroid Build Coastguard Worker 
405*acea8879SAndroid Build Coastguard Worker   while (size > 0 || BrotliDecoderHasMoreOutput(nti->brotli_decoder_state)) {
406*acea8879SAndroid Build Coastguard Worker     // Wait for nti->writer to be non-null, indicating some of this data is wanted.
407*acea8879SAndroid Build Coastguard Worker     pthread_mutex_lock(&nti->mu);
408*acea8879SAndroid Build Coastguard Worker     while (nti->writer == nullptr) {
409*acea8879SAndroid Build Coastguard Worker       // End the receiver if we encounter an error when performing block image update.
410*acea8879SAndroid Build Coastguard Worker       if (!nti->receiver_available) {
411*acea8879SAndroid Build Coastguard Worker         pthread_mutex_unlock(&nti->mu);
412*acea8879SAndroid Build Coastguard Worker         return false;
413*acea8879SAndroid Build Coastguard Worker       }
414*acea8879SAndroid Build Coastguard Worker       pthread_cond_wait(&nti->cv, &nti->mu);
415*acea8879SAndroid Build Coastguard Worker     }
416*acea8879SAndroid Build Coastguard Worker     pthread_mutex_unlock(&nti->mu);
417*acea8879SAndroid Build Coastguard Worker 
418*acea8879SAndroid Build Coastguard Worker     // At this point nti->writer is set, and we own it. The main thread is waiting for it to
419*acea8879SAndroid Build Coastguard Worker     // disappear from nti.
420*acea8879SAndroid Build Coastguard Worker 
421*acea8879SAndroid Build Coastguard Worker     size_t buffer_size = std::min<size_t>(32768, nti->writer->AvailableSpace());
422*acea8879SAndroid Build Coastguard Worker     if (buffer_size == 0) {
423*acea8879SAndroid Build Coastguard Worker       LOG(ERROR) << "No space left in output range";
424*acea8879SAndroid Build Coastguard Worker       return false;
425*acea8879SAndroid Build Coastguard Worker     }
426*acea8879SAndroid Build Coastguard Worker     uint8_t buffer[buffer_size];
427*acea8879SAndroid Build Coastguard Worker     size_t available_in = size;
428*acea8879SAndroid Build Coastguard Worker     size_t available_out = buffer_size;
429*acea8879SAndroid Build Coastguard Worker     uint8_t* next_out = buffer;
430*acea8879SAndroid Build Coastguard Worker 
431*acea8879SAndroid Build Coastguard Worker     // The brotli decoder will update |data|, |available_in|, |next_out| and |available_out|.
432*acea8879SAndroid Build Coastguard Worker     BrotliDecoderResult result = BrotliDecoderDecompressStream(
433*acea8879SAndroid Build Coastguard Worker         nti->brotli_decoder_state, &available_in, &data, &available_out, &next_out, nullptr);
434*acea8879SAndroid Build Coastguard Worker 
435*acea8879SAndroid Build Coastguard Worker     if (result == BROTLI_DECODER_RESULT_ERROR) {
436*acea8879SAndroid Build Coastguard Worker       LOG(ERROR) << "Decompression failed with "
437*acea8879SAndroid Build Coastguard Worker                  << BrotliDecoderErrorString(BrotliDecoderGetErrorCode(nti->brotli_decoder_state));
438*acea8879SAndroid Build Coastguard Worker       return false;
439*acea8879SAndroid Build Coastguard Worker     }
440*acea8879SAndroid Build Coastguard Worker 
441*acea8879SAndroid Build Coastguard Worker     LOG(DEBUG) << "bytes to write: " << buffer_size - available_out << ", bytes consumed "
442*acea8879SAndroid Build Coastguard Worker                << size - available_in << ", decoder status " << result;
443*acea8879SAndroid Build Coastguard Worker 
444*acea8879SAndroid Build Coastguard Worker     size_t write_now = buffer_size - available_out;
445*acea8879SAndroid Build Coastguard Worker     if (nti->writer->Write(buffer, write_now) != write_now) {
446*acea8879SAndroid Build Coastguard Worker       LOG(ERROR) << "Failed to write " << write_now << " bytes.";
447*acea8879SAndroid Build Coastguard Worker       return false;
448*acea8879SAndroid Build Coastguard Worker     }
449*acea8879SAndroid Build Coastguard Worker 
450*acea8879SAndroid Build Coastguard Worker     // Update the remaining size. The input data ptr is already updated by brotli decoder function.
451*acea8879SAndroid Build Coastguard Worker     size = available_in;
452*acea8879SAndroid Build Coastguard Worker 
453*acea8879SAndroid Build Coastguard Worker     if (nti->writer->Finished()) {
454*acea8879SAndroid Build Coastguard Worker       // We have written all the bytes desired by this writer.
455*acea8879SAndroid Build Coastguard Worker 
456*acea8879SAndroid Build Coastguard Worker       pthread_mutex_lock(&nti->mu);
457*acea8879SAndroid Build Coastguard Worker       nti->writer = nullptr;
458*acea8879SAndroid Build Coastguard Worker       pthread_cond_broadcast(&nti->cv);
459*acea8879SAndroid Build Coastguard Worker       pthread_mutex_unlock(&nti->mu);
460*acea8879SAndroid Build Coastguard Worker     }
461*acea8879SAndroid Build Coastguard Worker   }
462*acea8879SAndroid Build Coastguard Worker 
463*acea8879SAndroid Build Coastguard Worker   return true;
464*acea8879SAndroid Build Coastguard Worker }
465*acea8879SAndroid Build Coastguard Worker 
unzip_new_data(void * cookie)466*acea8879SAndroid Build Coastguard Worker static void* unzip_new_data(void* cookie) {
467*acea8879SAndroid Build Coastguard Worker   NewThreadInfo* nti = static_cast<NewThreadInfo*>(cookie);
468*acea8879SAndroid Build Coastguard Worker   if (nti->brotli_compressed) {
469*acea8879SAndroid Build Coastguard Worker     ProcessZipEntryContents(nti->za, &nti->entry, receive_brotli_new_data, nti);
470*acea8879SAndroid Build Coastguard Worker   } else {
471*acea8879SAndroid Build Coastguard Worker     ProcessZipEntryContents(nti->za, &nti->entry, receive_new_data, nti);
472*acea8879SAndroid Build Coastguard Worker   }
473*acea8879SAndroid Build Coastguard Worker   pthread_mutex_lock(&nti->mu);
474*acea8879SAndroid Build Coastguard Worker   nti->receiver_available = false;
475*acea8879SAndroid Build Coastguard Worker   if (nti->writer != nullptr) {
476*acea8879SAndroid Build Coastguard Worker     pthread_cond_broadcast(&nti->cv);
477*acea8879SAndroid Build Coastguard Worker   }
478*acea8879SAndroid Build Coastguard Worker   pthread_mutex_unlock(&nti->mu);
479*acea8879SAndroid Build Coastguard Worker   return nullptr;
480*acea8879SAndroid Build Coastguard Worker }
481*acea8879SAndroid Build Coastguard Worker 
ReadBlocks(const RangeSet & src,std::vector<uint8_t> * buffer,int fd)482*acea8879SAndroid Build Coastguard Worker static int ReadBlocks(const RangeSet& src, std::vector<uint8_t>* buffer, int fd) {
483*acea8879SAndroid Build Coastguard Worker   size_t p = 0;
484*acea8879SAndroid Build Coastguard Worker   for (const auto& [begin, end] : src) {
485*acea8879SAndroid Build Coastguard Worker     if (!check_lseek(fd, static_cast<off64_t>(begin) * BLOCKSIZE, SEEK_SET)) {
486*acea8879SAndroid Build Coastguard Worker       return -1;
487*acea8879SAndroid Build Coastguard Worker     }
488*acea8879SAndroid Build Coastguard Worker 
489*acea8879SAndroid Build Coastguard Worker     size_t size = (end - begin) * BLOCKSIZE;
490*acea8879SAndroid Build Coastguard Worker     if (!android::base::ReadFully(fd, buffer->data() + p, size)) {
491*acea8879SAndroid Build Coastguard Worker       failure_type = errno == EIO ? kEioFailure : kFreadFailure;
492*acea8879SAndroid Build Coastguard Worker       PLOG(ERROR) << "Failed to read " << size << " bytes of data";
493*acea8879SAndroid Build Coastguard Worker       return -1;
494*acea8879SAndroid Build Coastguard Worker     }
495*acea8879SAndroid Build Coastguard Worker 
496*acea8879SAndroid Build Coastguard Worker     p += size;
497*acea8879SAndroid Build Coastguard Worker   }
498*acea8879SAndroid Build Coastguard Worker 
499*acea8879SAndroid Build Coastguard Worker   return 0;
500*acea8879SAndroid Build Coastguard Worker }
501*acea8879SAndroid Build Coastguard Worker 
WriteBlocks(const RangeSet & tgt,const std::vector<uint8_t> & buffer,int fd)502*acea8879SAndroid Build Coastguard Worker static int WriteBlocks(const RangeSet& tgt, const std::vector<uint8_t>& buffer, int fd) {
503*acea8879SAndroid Build Coastguard Worker   size_t written = 0;
504*acea8879SAndroid Build Coastguard Worker   for (const auto& [begin, end] : tgt) {
505*acea8879SAndroid Build Coastguard Worker     off64_t offset = static_cast<off64_t>(begin) * BLOCKSIZE;
506*acea8879SAndroid Build Coastguard Worker     size_t size = (end - begin) * BLOCKSIZE;
507*acea8879SAndroid Build Coastguard Worker     if (!discard_blocks(fd, offset, size)) {
508*acea8879SAndroid Build Coastguard Worker       return -1;
509*acea8879SAndroid Build Coastguard Worker     }
510*acea8879SAndroid Build Coastguard Worker 
511*acea8879SAndroid Build Coastguard Worker     if (!check_lseek(fd, offset, SEEK_SET)) {
512*acea8879SAndroid Build Coastguard Worker       return -1;
513*acea8879SAndroid Build Coastguard Worker     }
514*acea8879SAndroid Build Coastguard Worker 
515*acea8879SAndroid Build Coastguard Worker     if (!android::base::WriteFully(fd, buffer.data() + written, size)) {
516*acea8879SAndroid Build Coastguard Worker       failure_type = errno == EIO ? kEioFailure : kFwriteFailure;
517*acea8879SAndroid Build Coastguard Worker       PLOG(ERROR) << "Failed to write " << size << " bytes of data";
518*acea8879SAndroid Build Coastguard Worker       return -1;
519*acea8879SAndroid Build Coastguard Worker     }
520*acea8879SAndroid Build Coastguard Worker 
521*acea8879SAndroid Build Coastguard Worker     written += size;
522*acea8879SAndroid Build Coastguard Worker   }
523*acea8879SAndroid Build Coastguard Worker 
524*acea8879SAndroid Build Coastguard Worker   return 0;
525*acea8879SAndroid Build Coastguard Worker }
526*acea8879SAndroid Build Coastguard Worker 
527*acea8879SAndroid Build Coastguard Worker // Parameters for transfer list command functions
528*acea8879SAndroid Build Coastguard Worker struct CommandParameters {
529*acea8879SAndroid Build Coastguard Worker     std::vector<std::string> tokens;
530*acea8879SAndroid Build Coastguard Worker     size_t cpos;
531*acea8879SAndroid Build Coastguard Worker     std::string cmdname;
532*acea8879SAndroid Build Coastguard Worker     std::string cmdline;
533*acea8879SAndroid Build Coastguard Worker     std::string freestash;
534*acea8879SAndroid Build Coastguard Worker     std::string stashbase;
535*acea8879SAndroid Build Coastguard Worker     bool canwrite;
536*acea8879SAndroid Build Coastguard Worker     int createdstash;
537*acea8879SAndroid Build Coastguard Worker     android::base::unique_fd fd;
538*acea8879SAndroid Build Coastguard Worker     bool foundwrites;
539*acea8879SAndroid Build Coastguard Worker     bool isunresumable;
540*acea8879SAndroid Build Coastguard Worker     int version;
541*acea8879SAndroid Build Coastguard Worker     size_t written;
542*acea8879SAndroid Build Coastguard Worker     size_t stashed;
543*acea8879SAndroid Build Coastguard Worker     NewThreadInfo nti;
544*acea8879SAndroid Build Coastguard Worker     pthread_t thread;
545*acea8879SAndroid Build Coastguard Worker     std::vector<uint8_t> buffer;
546*acea8879SAndroid Build Coastguard Worker     uint8_t* patch_start;
547*acea8879SAndroid Build Coastguard Worker     bool target_verified;  // The target blocks have expected contents already.
548*acea8879SAndroid Build Coastguard Worker };
549*acea8879SAndroid Build Coastguard Worker 
550*acea8879SAndroid Build Coastguard Worker // Print the hash in hex for corrupted source blocks (excluding the stashed blocks which is
551*acea8879SAndroid Build Coastguard Worker // handled separately).
PrintHashForCorruptedSourceBlocks(const CommandParameters & params,const std::vector<uint8_t> & buffer)552*acea8879SAndroid Build Coastguard Worker static void PrintHashForCorruptedSourceBlocks(const CommandParameters& params,
553*acea8879SAndroid Build Coastguard Worker                                               const std::vector<uint8_t>& buffer) {
554*acea8879SAndroid Build Coastguard Worker   LOG(INFO) << "unexpected contents of source blocks in cmd:\n" << params.cmdline;
555*acea8879SAndroid Build Coastguard Worker   CHECK(params.tokens[0] == "move" || params.tokens[0] == "bsdiff" ||
556*acea8879SAndroid Build Coastguard Worker         params.tokens[0] == "imgdiff");
557*acea8879SAndroid Build Coastguard Worker 
558*acea8879SAndroid Build Coastguard Worker   size_t pos = 0;
559*acea8879SAndroid Build Coastguard Worker   // Command example:
560*acea8879SAndroid Build Coastguard Worker   // move <onehash> <tgt_range> <src_blk_count> <src_range> [<loc_range> <stashed_blocks>]
561*acea8879SAndroid Build Coastguard Worker   // bsdiff <offset> <len> <src_hash> <tgt_hash> <tgt_range> <src_blk_count> <src_range>
562*acea8879SAndroid Build Coastguard Worker   //        [<loc_range> <stashed_blocks>]
563*acea8879SAndroid Build Coastguard Worker   if (params.tokens[0] == "move") {
564*acea8879SAndroid Build Coastguard Worker     // src_range for move starts at the 4th position.
565*acea8879SAndroid Build Coastguard Worker     if (params.tokens.size() < 5) {
566*acea8879SAndroid Build Coastguard Worker       LOG(ERROR) << "failed to parse source range in cmd:\n" << params.cmdline;
567*acea8879SAndroid Build Coastguard Worker       return;
568*acea8879SAndroid Build Coastguard Worker     }
569*acea8879SAndroid Build Coastguard Worker     pos = 4;
570*acea8879SAndroid Build Coastguard Worker   } else {
571*acea8879SAndroid Build Coastguard Worker     // src_range for diff starts at the 7th position.
572*acea8879SAndroid Build Coastguard Worker     if (params.tokens.size() < 8) {
573*acea8879SAndroid Build Coastguard Worker       LOG(ERROR) << "failed to parse source range in cmd:\n" << params.cmdline;
574*acea8879SAndroid Build Coastguard Worker       return;
575*acea8879SAndroid Build Coastguard Worker     }
576*acea8879SAndroid Build Coastguard Worker     pos = 7;
577*acea8879SAndroid Build Coastguard Worker   }
578*acea8879SAndroid Build Coastguard Worker 
579*acea8879SAndroid Build Coastguard Worker   // Source blocks in stash only, no work to do.
580*acea8879SAndroid Build Coastguard Worker   if (params.tokens[pos] == "-") {
581*acea8879SAndroid Build Coastguard Worker     return;
582*acea8879SAndroid Build Coastguard Worker   }
583*acea8879SAndroid Build Coastguard Worker 
584*acea8879SAndroid Build Coastguard Worker   RangeSet src = RangeSet::Parse(params.tokens[pos++]);
585*acea8879SAndroid Build Coastguard Worker   if (!src) {
586*acea8879SAndroid Build Coastguard Worker     LOG(ERROR) << "Failed to parse range in " << params.cmdline;
587*acea8879SAndroid Build Coastguard Worker     return;
588*acea8879SAndroid Build Coastguard Worker   }
589*acea8879SAndroid Build Coastguard Worker 
590*acea8879SAndroid Build Coastguard Worker   RangeSet locs;
591*acea8879SAndroid Build Coastguard Worker   // If there's no stashed blocks, content in the buffer is consecutive and has the same
592*acea8879SAndroid Build Coastguard Worker   // order as the source blocks.
593*acea8879SAndroid Build Coastguard Worker   if (pos == params.tokens.size()) {
594*acea8879SAndroid Build Coastguard Worker     locs = RangeSet(std::vector<Range>{ Range{ 0, src.blocks() } });
595*acea8879SAndroid Build Coastguard Worker   } else {
596*acea8879SAndroid Build Coastguard Worker     // Otherwise, the next token is the offset of the source blocks in the target range.
597*acea8879SAndroid Build Coastguard Worker     // Example: for the tokens <4,63946,63947,63948,63979> <4,6,7,8,39> <stashed_blocks>;
598*acea8879SAndroid Build Coastguard Worker     // We want to print SHA-1 for the data in buffer[6], buffer[8], buffer[9] ... buffer[38];
599*acea8879SAndroid Build Coastguard Worker     // this corresponds to the 32 src blocks #63946, #63948, #63949 ... #63978.
600*acea8879SAndroid Build Coastguard Worker     locs = RangeSet::Parse(params.tokens[pos++]);
601*acea8879SAndroid Build Coastguard Worker     CHECK_EQ(src.blocks(), locs.blocks());
602*acea8879SAndroid Build Coastguard Worker   }
603*acea8879SAndroid Build Coastguard Worker 
604*acea8879SAndroid Build Coastguard Worker   LOG(INFO) << "printing hash in hex for " << src.blocks() << " source blocks";
605*acea8879SAndroid Build Coastguard Worker   for (size_t i = 0; i < src.blocks(); i++) {
606*acea8879SAndroid Build Coastguard Worker     size_t block_num = src.GetBlockNumber(i);
607*acea8879SAndroid Build Coastguard Worker     size_t buffer_index = locs.GetBlockNumber(i);
608*acea8879SAndroid Build Coastguard Worker     CHECK_LE((buffer_index + 1) * BLOCKSIZE, buffer.size());
609*acea8879SAndroid Build Coastguard Worker 
610*acea8879SAndroid Build Coastguard Worker     uint8_t digest[SHA_DIGEST_LENGTH];
611*acea8879SAndroid Build Coastguard Worker     SHA1(buffer.data() + buffer_index * BLOCKSIZE, BLOCKSIZE, digest);
612*acea8879SAndroid Build Coastguard Worker     std::string hexdigest = print_sha1(digest);
613*acea8879SAndroid Build Coastguard Worker     LOG(INFO) << "  block number: " << block_num << ", SHA-1: " << hexdigest;
614*acea8879SAndroid Build Coastguard Worker   }
615*acea8879SAndroid Build Coastguard Worker }
616*acea8879SAndroid Build Coastguard Worker 
617*acea8879SAndroid Build Coastguard Worker // If the calculated hash for the whole stash doesn't match the stash id, print the SHA-1
618*acea8879SAndroid Build Coastguard Worker // in hex for each block.
PrintHashForCorruptedStashedBlocks(const std::string & id,const std::vector<uint8_t> & buffer,const RangeSet & src)619*acea8879SAndroid Build Coastguard Worker static void PrintHashForCorruptedStashedBlocks(const std::string& id,
620*acea8879SAndroid Build Coastguard Worker                                                const std::vector<uint8_t>& buffer,
621*acea8879SAndroid Build Coastguard Worker                                                const RangeSet& src) {
622*acea8879SAndroid Build Coastguard Worker   LOG(INFO) << "printing hash in hex for stash_id: " << id;
623*acea8879SAndroid Build Coastguard Worker   CHECK_EQ(src.blocks() * BLOCKSIZE, buffer.size());
624*acea8879SAndroid Build Coastguard Worker 
625*acea8879SAndroid Build Coastguard Worker   for (size_t i = 0; i < src.blocks(); i++) {
626*acea8879SAndroid Build Coastguard Worker     size_t block_num = src.GetBlockNumber(i);
627*acea8879SAndroid Build Coastguard Worker 
628*acea8879SAndroid Build Coastguard Worker     uint8_t digest[SHA_DIGEST_LENGTH];
629*acea8879SAndroid Build Coastguard Worker     SHA1(buffer.data() + i * BLOCKSIZE, BLOCKSIZE, digest);
630*acea8879SAndroid Build Coastguard Worker     std::string hexdigest = print_sha1(digest);
631*acea8879SAndroid Build Coastguard Worker     LOG(INFO) << "  block number: " << block_num << ", SHA-1: " << hexdigest;
632*acea8879SAndroid Build Coastguard Worker   }
633*acea8879SAndroid Build Coastguard Worker }
634*acea8879SAndroid Build Coastguard Worker 
635*acea8879SAndroid Build Coastguard Worker // If the stash file doesn't exist, read the source blocks this stash contains and print the
636*acea8879SAndroid Build Coastguard Worker // SHA-1 for these blocks.
PrintHashForMissingStashedBlocks(const std::string & id,int fd)637*acea8879SAndroid Build Coastguard Worker static void PrintHashForMissingStashedBlocks(const std::string& id, int fd) {
638*acea8879SAndroid Build Coastguard Worker   if (stash_map.find(id) == stash_map.end()) {
639*acea8879SAndroid Build Coastguard Worker     LOG(ERROR) << "No stash saved for id: " << id;
640*acea8879SAndroid Build Coastguard Worker     return;
641*acea8879SAndroid Build Coastguard Worker   }
642*acea8879SAndroid Build Coastguard Worker 
643*acea8879SAndroid Build Coastguard Worker   LOG(INFO) << "print hash in hex for source blocks in missing stash: " << id;
644*acea8879SAndroid Build Coastguard Worker   const RangeSet& src = stash_map[id];
645*acea8879SAndroid Build Coastguard Worker   std::vector<uint8_t> buffer(src.blocks() * BLOCKSIZE);
646*acea8879SAndroid Build Coastguard Worker   if (ReadBlocks(src, &buffer, fd) == -1) {
647*acea8879SAndroid Build Coastguard Worker     LOG(ERROR) << "failed to read source blocks for stash: " << id;
648*acea8879SAndroid Build Coastguard Worker     return;
649*acea8879SAndroid Build Coastguard Worker   }
650*acea8879SAndroid Build Coastguard Worker   PrintHashForCorruptedStashedBlocks(id, buffer, src);
651*acea8879SAndroid Build Coastguard Worker }
652*acea8879SAndroid Build Coastguard Worker 
VerifyBlocks(const std::string & expected,const std::vector<uint8_t> & buffer,const size_t blocks,bool printerror)653*acea8879SAndroid Build Coastguard Worker static int VerifyBlocks(const std::string& expected, const std::vector<uint8_t>& buffer,
654*acea8879SAndroid Build Coastguard Worker                         const size_t blocks, bool printerror) {
655*acea8879SAndroid Build Coastguard Worker   uint8_t digest[SHA_DIGEST_LENGTH];
656*acea8879SAndroid Build Coastguard Worker   const uint8_t* data = buffer.data();
657*acea8879SAndroid Build Coastguard Worker 
658*acea8879SAndroid Build Coastguard Worker   SHA1(data, blocks * BLOCKSIZE, digest);
659*acea8879SAndroid Build Coastguard Worker 
660*acea8879SAndroid Build Coastguard Worker   std::string hexdigest = print_sha1(digest);
661*acea8879SAndroid Build Coastguard Worker 
662*acea8879SAndroid Build Coastguard Worker   if (hexdigest != expected) {
663*acea8879SAndroid Build Coastguard Worker     if (printerror) {
664*acea8879SAndroid Build Coastguard Worker       LOG(ERROR) << "failed to verify blocks (expected " << expected << ", read " << hexdigest
665*acea8879SAndroid Build Coastguard Worker                  << ")";
666*acea8879SAndroid Build Coastguard Worker     }
667*acea8879SAndroid Build Coastguard Worker     return -1;
668*acea8879SAndroid Build Coastguard Worker   }
669*acea8879SAndroid Build Coastguard Worker 
670*acea8879SAndroid Build Coastguard Worker   return 0;
671*acea8879SAndroid Build Coastguard Worker }
672*acea8879SAndroid Build Coastguard Worker 
GetStashFileName(const std::string & base,const std::string & id,const std::string & postfix)673*acea8879SAndroid Build Coastguard Worker static std::string GetStashFileName(const std::string& base, const std::string& id,
674*acea8879SAndroid Build Coastguard Worker                                     const std::string& postfix) {
675*acea8879SAndroid Build Coastguard Worker   if (base.empty()) {
676*acea8879SAndroid Build Coastguard Worker     return "";
677*acea8879SAndroid Build Coastguard Worker   }
678*acea8879SAndroid Build Coastguard Worker   std::string filename = Paths::Get().stash_directory_base() + "/" + base;
679*acea8879SAndroid Build Coastguard Worker   if (id.empty() && postfix.empty()) {
680*acea8879SAndroid Build Coastguard Worker     return filename;
681*acea8879SAndroid Build Coastguard Worker   }
682*acea8879SAndroid Build Coastguard Worker   return filename + "/" + id + postfix;
683*acea8879SAndroid Build Coastguard Worker }
684*acea8879SAndroid Build Coastguard Worker 
685*acea8879SAndroid Build Coastguard Worker // Does a best effort enumeration of stash files. Ignores possible non-file items in the stash
686*acea8879SAndroid Build Coastguard Worker // directory and continues despite of errors. Calls the 'callback' function for each file.
EnumerateStash(const std::string & dirname,const std::function<void (const std::string &)> & callback)687*acea8879SAndroid Build Coastguard Worker static void EnumerateStash(const std::string& dirname,
688*acea8879SAndroid Build Coastguard Worker                            const std::function<void(const std::string&)>& callback) {
689*acea8879SAndroid Build Coastguard Worker   if (dirname.empty()) return;
690*acea8879SAndroid Build Coastguard Worker 
691*acea8879SAndroid Build Coastguard Worker   std::unique_ptr<DIR, decltype(&closedir)> directory(opendir(dirname.c_str()), closedir);
692*acea8879SAndroid Build Coastguard Worker 
693*acea8879SAndroid Build Coastguard Worker   if (directory == nullptr) {
694*acea8879SAndroid Build Coastguard Worker     if (errno != ENOENT) {
695*acea8879SAndroid Build Coastguard Worker       PLOG(ERROR) << "opendir \"" << dirname << "\" failed";
696*acea8879SAndroid Build Coastguard Worker     }
697*acea8879SAndroid Build Coastguard Worker     return;
698*acea8879SAndroid Build Coastguard Worker   }
699*acea8879SAndroid Build Coastguard Worker 
700*acea8879SAndroid Build Coastguard Worker   dirent* item;
701*acea8879SAndroid Build Coastguard Worker   while ((item = readdir(directory.get())) != nullptr) {
702*acea8879SAndroid Build Coastguard Worker     if (item->d_type != DT_REG) continue;
703*acea8879SAndroid Build Coastguard Worker     callback(dirname + "/" + item->d_name);
704*acea8879SAndroid Build Coastguard Worker   }
705*acea8879SAndroid Build Coastguard Worker }
706*acea8879SAndroid Build Coastguard Worker 
707*acea8879SAndroid Build Coastguard Worker // Deletes the stash directory and all files in it. Assumes that it only
708*acea8879SAndroid Build Coastguard Worker // contains files. There is nothing we can do about unlikely, but possible
709*acea8879SAndroid Build Coastguard Worker // errors, so they are merely logged.
DeleteFile(const std::string & fn)710*acea8879SAndroid Build Coastguard Worker static void DeleteFile(const std::string& fn) {
711*acea8879SAndroid Build Coastguard Worker   if (fn.empty()) return;
712*acea8879SAndroid Build Coastguard Worker 
713*acea8879SAndroid Build Coastguard Worker   LOG(INFO) << "deleting " << fn;
714*acea8879SAndroid Build Coastguard Worker 
715*acea8879SAndroid Build Coastguard Worker   if (unlink(fn.c_str()) == -1 && errno != ENOENT) {
716*acea8879SAndroid Build Coastguard Worker     PLOG(ERROR) << "unlink \"" << fn << "\" failed";
717*acea8879SAndroid Build Coastguard Worker   }
718*acea8879SAndroid Build Coastguard Worker }
719*acea8879SAndroid Build Coastguard Worker 
DeleteStash(const std::string & base)720*acea8879SAndroid Build Coastguard Worker static void DeleteStash(const std::string& base) {
721*acea8879SAndroid Build Coastguard Worker   if (base.empty()) return;
722*acea8879SAndroid Build Coastguard Worker 
723*acea8879SAndroid Build Coastguard Worker   LOG(INFO) << "deleting stash " << base;
724*acea8879SAndroid Build Coastguard Worker 
725*acea8879SAndroid Build Coastguard Worker   std::string dirname = GetStashFileName(base, "", "");
726*acea8879SAndroid Build Coastguard Worker   EnumerateStash(dirname, DeleteFile);
727*acea8879SAndroid Build Coastguard Worker 
728*acea8879SAndroid Build Coastguard Worker   if (rmdir(dirname.c_str()) == -1) {
729*acea8879SAndroid Build Coastguard Worker     if (errno != ENOENT && errno != ENOTDIR) {
730*acea8879SAndroid Build Coastguard Worker       PLOG(ERROR) << "rmdir \"" << dirname << "\" failed";
731*acea8879SAndroid Build Coastguard Worker     }
732*acea8879SAndroid Build Coastguard Worker   }
733*acea8879SAndroid Build Coastguard Worker }
734*acea8879SAndroid Build Coastguard Worker 
LoadStash(const CommandParameters & params,const std::string & id,bool verify,std::vector<uint8_t> * buffer,bool printnoent)735*acea8879SAndroid Build Coastguard Worker static int LoadStash(const CommandParameters& params, const std::string& id, bool verify,
736*acea8879SAndroid Build Coastguard Worker                      std::vector<uint8_t>* buffer, bool printnoent) {
737*acea8879SAndroid Build Coastguard Worker   // In verify mode, if source range_set was saved for the given hash, check contents in the source
738*acea8879SAndroid Build Coastguard Worker   // blocks first. If the check fails, search for the stashed files on /cache as usual.
739*acea8879SAndroid Build Coastguard Worker   if (!params.canwrite) {
740*acea8879SAndroid Build Coastguard Worker     if (stash_map.find(id) != stash_map.end()) {
741*acea8879SAndroid Build Coastguard Worker       const RangeSet& src = stash_map[id];
742*acea8879SAndroid Build Coastguard Worker       allocate(src.blocks() * BLOCKSIZE, buffer);
743*acea8879SAndroid Build Coastguard Worker 
744*acea8879SAndroid Build Coastguard Worker       if (ReadBlocks(src, buffer, params.fd) == -1) {
745*acea8879SAndroid Build Coastguard Worker         LOG(ERROR) << "failed to read source blocks in stash map.";
746*acea8879SAndroid Build Coastguard Worker         return -1;
747*acea8879SAndroid Build Coastguard Worker       }
748*acea8879SAndroid Build Coastguard Worker       if (VerifyBlocks(id, *buffer, src.blocks(), true) != 0) {
749*acea8879SAndroid Build Coastguard Worker         LOG(ERROR) << "failed to verify loaded source blocks in stash map.";
750*acea8879SAndroid Build Coastguard Worker         if (!is_retry) {
751*acea8879SAndroid Build Coastguard Worker           PrintHashForCorruptedStashedBlocks(id, *buffer, src);
752*acea8879SAndroid Build Coastguard Worker         }
753*acea8879SAndroid Build Coastguard Worker         return -1;
754*acea8879SAndroid Build Coastguard Worker       }
755*acea8879SAndroid Build Coastguard Worker       return 0;
756*acea8879SAndroid Build Coastguard Worker     }
757*acea8879SAndroid Build Coastguard Worker   }
758*acea8879SAndroid Build Coastguard Worker 
759*acea8879SAndroid Build Coastguard Worker   std::string fn = GetStashFileName(params.stashbase, id, "");
760*acea8879SAndroid Build Coastguard Worker 
761*acea8879SAndroid Build Coastguard Worker   struct stat sb;
762*acea8879SAndroid Build Coastguard Worker   if (stat(fn.c_str(), &sb) == -1) {
763*acea8879SAndroid Build Coastguard Worker     if (errno != ENOENT || printnoent) {
764*acea8879SAndroid Build Coastguard Worker       PLOG(ERROR) << "stat \"" << fn << "\" failed";
765*acea8879SAndroid Build Coastguard Worker       PrintHashForMissingStashedBlocks(id, params.fd);
766*acea8879SAndroid Build Coastguard Worker     }
767*acea8879SAndroid Build Coastguard Worker     return -1;
768*acea8879SAndroid Build Coastguard Worker   }
769*acea8879SAndroid Build Coastguard Worker 
770*acea8879SAndroid Build Coastguard Worker   LOG(INFO) << " loading " << fn;
771*acea8879SAndroid Build Coastguard Worker 
772*acea8879SAndroid Build Coastguard Worker   if ((sb.st_size % BLOCKSIZE) != 0) {
773*acea8879SAndroid Build Coastguard Worker     LOG(ERROR) << fn << " size " << sb.st_size << " not multiple of block size " << BLOCKSIZE;
774*acea8879SAndroid Build Coastguard Worker     return -1;
775*acea8879SAndroid Build Coastguard Worker   }
776*acea8879SAndroid Build Coastguard Worker 
777*acea8879SAndroid Build Coastguard Worker   android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(fn.c_str(), O_RDONLY)));
778*acea8879SAndroid Build Coastguard Worker   if (fd == -1) {
779*acea8879SAndroid Build Coastguard Worker     failure_type = errno == EIO ? kEioFailure : kFileOpenFailure;
780*acea8879SAndroid Build Coastguard Worker     PLOG(ERROR) << "open \"" << fn << "\" failed";
781*acea8879SAndroid Build Coastguard Worker     return -1;
782*acea8879SAndroid Build Coastguard Worker   }
783*acea8879SAndroid Build Coastguard Worker 
784*acea8879SAndroid Build Coastguard Worker   allocate(sb.st_size, buffer);
785*acea8879SAndroid Build Coastguard Worker 
786*acea8879SAndroid Build Coastguard Worker   if (!android::base::ReadFully(fd, buffer->data(), sb.st_size)) {
787*acea8879SAndroid Build Coastguard Worker     failure_type = errno == EIO ? kEioFailure : kFreadFailure;
788*acea8879SAndroid Build Coastguard Worker     PLOG(ERROR) << "Failed to read " << sb.st_size << " bytes of data";
789*acea8879SAndroid Build Coastguard Worker     return -1;
790*acea8879SAndroid Build Coastguard Worker   }
791*acea8879SAndroid Build Coastguard Worker 
792*acea8879SAndroid Build Coastguard Worker   size_t blocks = sb.st_size / BLOCKSIZE;
793*acea8879SAndroid Build Coastguard Worker   if (verify && VerifyBlocks(id, *buffer, blocks, true) != 0) {
794*acea8879SAndroid Build Coastguard Worker     LOG(ERROR) << "unexpected contents in " << fn;
795*acea8879SAndroid Build Coastguard Worker     if (stash_map.find(id) == stash_map.end()) {
796*acea8879SAndroid Build Coastguard Worker       LOG(ERROR) << "failed to find source blocks number for stash " << id
797*acea8879SAndroid Build Coastguard Worker                  << " when executing command: " << params.cmdname;
798*acea8879SAndroid Build Coastguard Worker     } else {
799*acea8879SAndroid Build Coastguard Worker       const RangeSet& src = stash_map[id];
800*acea8879SAndroid Build Coastguard Worker       PrintHashForCorruptedStashedBlocks(id, *buffer, src);
801*acea8879SAndroid Build Coastguard Worker     }
802*acea8879SAndroid Build Coastguard Worker     DeleteFile(fn);
803*acea8879SAndroid Build Coastguard Worker     return -1;
804*acea8879SAndroid Build Coastguard Worker   }
805*acea8879SAndroid Build Coastguard Worker 
806*acea8879SAndroid Build Coastguard Worker   return 0;
807*acea8879SAndroid Build Coastguard Worker }
808*acea8879SAndroid Build Coastguard Worker 
WriteStash(const std::string & base,const std::string & id,int blocks,const std::vector<uint8_t> & buffer,bool checkspace,bool * exists)809*acea8879SAndroid Build Coastguard Worker static int WriteStash(const std::string& base, const std::string& id, int blocks,
810*acea8879SAndroid Build Coastguard Worker                       const std::vector<uint8_t>& buffer, bool checkspace, bool* exists) {
811*acea8879SAndroid Build Coastguard Worker   if (base.empty()) {
812*acea8879SAndroid Build Coastguard Worker     return -1;
813*acea8879SAndroid Build Coastguard Worker   }
814*acea8879SAndroid Build Coastguard Worker 
815*acea8879SAndroid Build Coastguard Worker   if (checkspace && !CheckAndFreeSpaceOnCache(blocks * BLOCKSIZE)) {
816*acea8879SAndroid Build Coastguard Worker     LOG(ERROR) << "not enough space to write stash";
817*acea8879SAndroid Build Coastguard Worker     return -1;
818*acea8879SAndroid Build Coastguard Worker   }
819*acea8879SAndroid Build Coastguard Worker 
820*acea8879SAndroid Build Coastguard Worker   std::string fn = GetStashFileName(base, id, ".partial");
821*acea8879SAndroid Build Coastguard Worker   std::string cn = GetStashFileName(base, id, "");
822*acea8879SAndroid Build Coastguard Worker 
823*acea8879SAndroid Build Coastguard Worker   if (exists) {
824*acea8879SAndroid Build Coastguard Worker     struct stat sb;
825*acea8879SAndroid Build Coastguard Worker     int res = stat(cn.c_str(), &sb);
826*acea8879SAndroid Build Coastguard Worker 
827*acea8879SAndroid Build Coastguard Worker     if (res == 0) {
828*acea8879SAndroid Build Coastguard Worker       // The file already exists and since the name is the hash of the contents,
829*acea8879SAndroid Build Coastguard Worker       // it's safe to assume the contents are identical (accidental hash collisions
830*acea8879SAndroid Build Coastguard Worker       // are unlikely)
831*acea8879SAndroid Build Coastguard Worker       LOG(INFO) << " skipping " << blocks << " existing blocks in " << cn;
832*acea8879SAndroid Build Coastguard Worker       *exists = true;
833*acea8879SAndroid Build Coastguard Worker       return 0;
834*acea8879SAndroid Build Coastguard Worker     }
835*acea8879SAndroid Build Coastguard Worker 
836*acea8879SAndroid Build Coastguard Worker     *exists = false;
837*acea8879SAndroid Build Coastguard Worker   }
838*acea8879SAndroid Build Coastguard Worker 
839*acea8879SAndroid Build Coastguard Worker   LOG(INFO) << " writing " << blocks << " blocks to " << cn;
840*acea8879SAndroid Build Coastguard Worker 
841*acea8879SAndroid Build Coastguard Worker   android::base::unique_fd fd(
842*acea8879SAndroid Build Coastguard Worker       TEMP_FAILURE_RETRY(open(fn.c_str(), O_WRONLY | O_CREAT | O_TRUNC, STASH_FILE_MODE)));
843*acea8879SAndroid Build Coastguard Worker   if (fd == -1) {
844*acea8879SAndroid Build Coastguard Worker     failure_type = errno == EIO ? kEioFailure : kFileOpenFailure;
845*acea8879SAndroid Build Coastguard Worker     PLOG(ERROR) << "failed to create \"" << fn << "\"";
846*acea8879SAndroid Build Coastguard Worker     return -1;
847*acea8879SAndroid Build Coastguard Worker   }
848*acea8879SAndroid Build Coastguard Worker 
849*acea8879SAndroid Build Coastguard Worker   if (fchown(fd, AID_SYSTEM, AID_SYSTEM) != 0) {  // system user
850*acea8879SAndroid Build Coastguard Worker     PLOG(ERROR) << "failed to chown \"" << fn << "\"";
851*acea8879SAndroid Build Coastguard Worker     return -1;
852*acea8879SAndroid Build Coastguard Worker   }
853*acea8879SAndroid Build Coastguard Worker 
854*acea8879SAndroid Build Coastguard Worker   if (!android::base::WriteFully(fd, buffer.data(), blocks * BLOCKSIZE)) {
855*acea8879SAndroid Build Coastguard Worker     failure_type = errno == EIO ? kEioFailure : kFwriteFailure;
856*acea8879SAndroid Build Coastguard Worker     PLOG(ERROR) << "Failed to write " << blocks * BLOCKSIZE << " bytes of data";
857*acea8879SAndroid Build Coastguard Worker     return -1;
858*acea8879SAndroid Build Coastguard Worker   }
859*acea8879SAndroid Build Coastguard Worker 
860*acea8879SAndroid Build Coastguard Worker   if (fsync(fd) == -1) {
861*acea8879SAndroid Build Coastguard Worker     failure_type = errno == EIO ? kEioFailure : kFsyncFailure;
862*acea8879SAndroid Build Coastguard Worker     PLOG(ERROR) << "fsync \"" << fn << "\" failed";
863*acea8879SAndroid Build Coastguard Worker     return -1;
864*acea8879SAndroid Build Coastguard Worker   }
865*acea8879SAndroid Build Coastguard Worker 
866*acea8879SAndroid Build Coastguard Worker   if (rename(fn.c_str(), cn.c_str()) == -1) {
867*acea8879SAndroid Build Coastguard Worker     PLOG(ERROR) << "rename(\"" << fn << "\", \"" << cn << "\") failed";
868*acea8879SAndroid Build Coastguard Worker     return -1;
869*acea8879SAndroid Build Coastguard Worker   }
870*acea8879SAndroid Build Coastguard Worker 
871*acea8879SAndroid Build Coastguard Worker   std::string dname = GetStashFileName(base, "", "");
872*acea8879SAndroid Build Coastguard Worker   if (!FsyncDir(dname)) {
873*acea8879SAndroid Build Coastguard Worker     return -1;
874*acea8879SAndroid Build Coastguard Worker   }
875*acea8879SAndroid Build Coastguard Worker 
876*acea8879SAndroid Build Coastguard Worker   return 0;
877*acea8879SAndroid Build Coastguard Worker }
878*acea8879SAndroid Build Coastguard Worker 
879*acea8879SAndroid Build Coastguard Worker // Creates a directory for storing stash files and checks if the /cache partition
880*acea8879SAndroid Build Coastguard Worker // hash enough space for the expected amount of blocks we need to store. Returns
881*acea8879SAndroid Build Coastguard Worker // >0 if we created the directory, zero if it existed already, and <0 of failure.
CreateStash(State * state,size_t maxblocks,const std::string & base)882*acea8879SAndroid Build Coastguard Worker static int CreateStash(State* state, size_t maxblocks, const std::string& base) {
883*acea8879SAndroid Build Coastguard Worker   std::string dirname = GetStashFileName(base, "", "");
884*acea8879SAndroid Build Coastguard Worker   struct stat sb;
885*acea8879SAndroid Build Coastguard Worker   int res = stat(dirname.c_str(), &sb);
886*acea8879SAndroid Build Coastguard Worker   if (res == -1 && errno != ENOENT) {
887*acea8879SAndroid Build Coastguard Worker     ErrorAbort(state, kStashCreationFailure, "stat \"%s\" failed: %s", dirname.c_str(),
888*acea8879SAndroid Build Coastguard Worker                strerror(errno));
889*acea8879SAndroid Build Coastguard Worker     return -1;
890*acea8879SAndroid Build Coastguard Worker   }
891*acea8879SAndroid Build Coastguard Worker 
892*acea8879SAndroid Build Coastguard Worker   size_t max_stash_size = maxblocks * BLOCKSIZE;
893*acea8879SAndroid Build Coastguard Worker   if (res == -1) {
894*acea8879SAndroid Build Coastguard Worker     LOG(INFO) << "creating stash " << dirname;
895*acea8879SAndroid Build Coastguard Worker     res = mkdir_recursively(dirname, STASH_DIRECTORY_MODE, false, nullptr);
896*acea8879SAndroid Build Coastguard Worker 
897*acea8879SAndroid Build Coastguard Worker     if (res != 0) {
898*acea8879SAndroid Build Coastguard Worker       ErrorAbort(state, kStashCreationFailure, "mkdir \"%s\" failed: %s", dirname.c_str(),
899*acea8879SAndroid Build Coastguard Worker                  strerror(errno));
900*acea8879SAndroid Build Coastguard Worker       return -1;
901*acea8879SAndroid Build Coastguard Worker     }
902*acea8879SAndroid Build Coastguard Worker 
903*acea8879SAndroid Build Coastguard Worker     if (chown(dirname.c_str(), AID_SYSTEM, AID_SYSTEM) != 0) {  // system user
904*acea8879SAndroid Build Coastguard Worker       ErrorAbort(state, kStashCreationFailure, "chown \"%s\" failed: %s", dirname.c_str(),
905*acea8879SAndroid Build Coastguard Worker                  strerror(errno));
906*acea8879SAndroid Build Coastguard Worker       return -1;
907*acea8879SAndroid Build Coastguard Worker     }
908*acea8879SAndroid Build Coastguard Worker 
909*acea8879SAndroid Build Coastguard Worker     if (!CheckAndFreeSpaceOnCache(max_stash_size)) {
910*acea8879SAndroid Build Coastguard Worker       ErrorAbort(state, kStashCreationFailure, "not enough space for stash (%zu needed)",
911*acea8879SAndroid Build Coastguard Worker                  max_stash_size);
912*acea8879SAndroid Build Coastguard Worker       return -1;
913*acea8879SAndroid Build Coastguard Worker     }
914*acea8879SAndroid Build Coastguard Worker 
915*acea8879SAndroid Build Coastguard Worker     return 1;  // Created directory
916*acea8879SAndroid Build Coastguard Worker   }
917*acea8879SAndroid Build Coastguard Worker 
918*acea8879SAndroid Build Coastguard Worker   LOG(INFO) << "using existing stash " << dirname;
919*acea8879SAndroid Build Coastguard Worker 
920*acea8879SAndroid Build Coastguard Worker   // If the directory already exists, calculate the space already allocated to stash files and check
921*acea8879SAndroid Build Coastguard Worker   // if there's enough for all required blocks. Delete any partially completed stash files first.
922*acea8879SAndroid Build Coastguard Worker   EnumerateStash(dirname, [](const std::string& fn) {
923*acea8879SAndroid Build Coastguard Worker     if (android::base::EndsWith(fn, ".partial")) {
924*acea8879SAndroid Build Coastguard Worker       DeleteFile(fn);
925*acea8879SAndroid Build Coastguard Worker     }
926*acea8879SAndroid Build Coastguard Worker   });
927*acea8879SAndroid Build Coastguard Worker 
928*acea8879SAndroid Build Coastguard Worker   size_t existing = 0;
929*acea8879SAndroid Build Coastguard Worker   EnumerateStash(dirname, [&existing](const std::string& fn) {
930*acea8879SAndroid Build Coastguard Worker     if (fn.empty()) return;
931*acea8879SAndroid Build Coastguard Worker     struct stat sb;
932*acea8879SAndroid Build Coastguard Worker     if (stat(fn.c_str(), &sb) == -1) {
933*acea8879SAndroid Build Coastguard Worker       PLOG(ERROR) << "stat \"" << fn << "\" failed";
934*acea8879SAndroid Build Coastguard Worker       return;
935*acea8879SAndroid Build Coastguard Worker     }
936*acea8879SAndroid Build Coastguard Worker     existing += static_cast<size_t>(sb.st_size);
937*acea8879SAndroid Build Coastguard Worker   });
938*acea8879SAndroid Build Coastguard Worker 
939*acea8879SAndroid Build Coastguard Worker   if (max_stash_size > existing) {
940*acea8879SAndroid Build Coastguard Worker     size_t needed = max_stash_size - existing;
941*acea8879SAndroid Build Coastguard Worker     if (!CheckAndFreeSpaceOnCache(needed)) {
942*acea8879SAndroid Build Coastguard Worker       ErrorAbort(state, kStashCreationFailure, "not enough space for stash (%zu more needed)",
943*acea8879SAndroid Build Coastguard Worker                  needed);
944*acea8879SAndroid Build Coastguard Worker       return -1;
945*acea8879SAndroid Build Coastguard Worker     }
946*acea8879SAndroid Build Coastguard Worker   }
947*acea8879SAndroid Build Coastguard Worker 
948*acea8879SAndroid Build Coastguard Worker   return 0;  // Using existing directory
949*acea8879SAndroid Build Coastguard Worker }
950*acea8879SAndroid Build Coastguard Worker 
FreeStash(const std::string & base,const std::string & id)951*acea8879SAndroid Build Coastguard Worker static int FreeStash(const std::string& base, const std::string& id) {
952*acea8879SAndroid Build Coastguard Worker   if (base.empty() || id.empty()) {
953*acea8879SAndroid Build Coastguard Worker     return -1;
954*acea8879SAndroid Build Coastguard Worker   }
955*acea8879SAndroid Build Coastguard Worker 
956*acea8879SAndroid Build Coastguard Worker   DeleteFile(GetStashFileName(base, id, ""));
957*acea8879SAndroid Build Coastguard Worker 
958*acea8879SAndroid Build Coastguard Worker   return 0;
959*acea8879SAndroid Build Coastguard Worker }
960*acea8879SAndroid Build Coastguard Worker 
961*acea8879SAndroid Build Coastguard Worker // Source contains packed data, which we want to move to the locations given in locs in the dest
962*acea8879SAndroid Build Coastguard Worker // buffer. source and dest may be the same buffer.
MoveRange(std::vector<uint8_t> & dest,const RangeSet & locs,const std::vector<uint8_t> & source)963*acea8879SAndroid Build Coastguard Worker static void MoveRange(std::vector<uint8_t>& dest, const RangeSet& locs,
964*acea8879SAndroid Build Coastguard Worker                       const std::vector<uint8_t>& source) {
965*acea8879SAndroid Build Coastguard Worker   const uint8_t* from = source.data();
966*acea8879SAndroid Build Coastguard Worker   uint8_t* to = dest.data();
967*acea8879SAndroid Build Coastguard Worker   size_t start = locs.blocks();
968*acea8879SAndroid Build Coastguard Worker   // Must do the movement backward.
969*acea8879SAndroid Build Coastguard Worker   for (auto it = locs.crbegin(); it != locs.crend(); it++) {
970*acea8879SAndroid Build Coastguard Worker     size_t blocks = it->second - it->first;
971*acea8879SAndroid Build Coastguard Worker     start -= blocks;
972*acea8879SAndroid Build Coastguard Worker     memmove(to + (it->first * BLOCKSIZE), from + (start * BLOCKSIZE), blocks * BLOCKSIZE);
973*acea8879SAndroid Build Coastguard Worker   }
974*acea8879SAndroid Build Coastguard Worker }
975*acea8879SAndroid Build Coastguard Worker 
976*acea8879SAndroid Build Coastguard Worker /**
977*acea8879SAndroid Build Coastguard Worker  * We expect to parse the remainder of the parameter tokens as one of:
978*acea8879SAndroid Build Coastguard Worker  *
979*acea8879SAndroid Build Coastguard Worker  *    <src_block_count> <src_range>
980*acea8879SAndroid Build Coastguard Worker  *        (loads data from source image only)
981*acea8879SAndroid Build Coastguard Worker  *
982*acea8879SAndroid Build Coastguard Worker  *    <src_block_count> - <[stash_id:stash_range] ...>
983*acea8879SAndroid Build Coastguard Worker  *        (loads data from stashes only)
984*acea8879SAndroid Build Coastguard Worker  *
985*acea8879SAndroid Build Coastguard Worker  *    <src_block_count> <src_range> <src_loc> <[stash_id:stash_range] ...>
986*acea8879SAndroid Build Coastguard Worker  *        (loads data from both source image and stashes)
987*acea8879SAndroid Build Coastguard Worker  *
988*acea8879SAndroid Build Coastguard Worker  * On return, params.buffer is filled with the loaded source data (rearranged and combined with
989*acea8879SAndroid Build Coastguard Worker  * stashed data as necessary). buffer may be reallocated if needed to accommodate the source data.
990*acea8879SAndroid Build Coastguard Worker  * tgt is the target RangeSet for detecting overlaps. Any stashes required are loaded using
991*acea8879SAndroid Build Coastguard Worker  * LoadStash.
992*acea8879SAndroid Build Coastguard Worker  */
LoadSourceBlocks(CommandParameters & params,const RangeSet & tgt,size_t * src_blocks,bool * overlap)993*acea8879SAndroid Build Coastguard Worker static int LoadSourceBlocks(CommandParameters& params, const RangeSet& tgt, size_t* src_blocks,
994*acea8879SAndroid Build Coastguard Worker                             bool* overlap) {
995*acea8879SAndroid Build Coastguard Worker   CHECK(src_blocks != nullptr);
996*acea8879SAndroid Build Coastguard Worker   CHECK(overlap != nullptr);
997*acea8879SAndroid Build Coastguard Worker 
998*acea8879SAndroid Build Coastguard Worker   // <src_block_count>
999*acea8879SAndroid Build Coastguard Worker   const std::string& token = params.tokens[params.cpos++];
1000*acea8879SAndroid Build Coastguard Worker   if (!android::base::ParseUint(token, src_blocks)) {
1001*acea8879SAndroid Build Coastguard Worker     LOG(ERROR) << "invalid src_block_count \"" << token << "\"";
1002*acea8879SAndroid Build Coastguard Worker     return -1;
1003*acea8879SAndroid Build Coastguard Worker   }
1004*acea8879SAndroid Build Coastguard Worker 
1005*acea8879SAndroid Build Coastguard Worker   allocate(*src_blocks * BLOCKSIZE, &params.buffer);
1006*acea8879SAndroid Build Coastguard Worker 
1007*acea8879SAndroid Build Coastguard Worker   // "-" or <src_range> [<src_loc>]
1008*acea8879SAndroid Build Coastguard Worker   if (params.tokens[params.cpos] == "-") {
1009*acea8879SAndroid Build Coastguard Worker     // no source ranges, only stashes
1010*acea8879SAndroid Build Coastguard Worker     params.cpos++;
1011*acea8879SAndroid Build Coastguard Worker   } else {
1012*acea8879SAndroid Build Coastguard Worker     RangeSet src = RangeSet::Parse(params.tokens[params.cpos++]);
1013*acea8879SAndroid Build Coastguard Worker     CHECK(static_cast<bool>(src));
1014*acea8879SAndroid Build Coastguard Worker     *overlap = src.Overlaps(tgt);
1015*acea8879SAndroid Build Coastguard Worker 
1016*acea8879SAndroid Build Coastguard Worker     if (ReadBlocks(src, &params.buffer, params.fd) == -1) {
1017*acea8879SAndroid Build Coastguard Worker       return -1;
1018*acea8879SAndroid Build Coastguard Worker     }
1019*acea8879SAndroid Build Coastguard Worker 
1020*acea8879SAndroid Build Coastguard Worker     if (params.cpos >= params.tokens.size()) {
1021*acea8879SAndroid Build Coastguard Worker       // no stashes, only source range
1022*acea8879SAndroid Build Coastguard Worker       return 0;
1023*acea8879SAndroid Build Coastguard Worker     }
1024*acea8879SAndroid Build Coastguard Worker 
1025*acea8879SAndroid Build Coastguard Worker     RangeSet locs = RangeSet::Parse(params.tokens[params.cpos++]);
1026*acea8879SAndroid Build Coastguard Worker     CHECK(static_cast<bool>(locs));
1027*acea8879SAndroid Build Coastguard Worker     MoveRange(params.buffer, locs, params.buffer);
1028*acea8879SAndroid Build Coastguard Worker   }
1029*acea8879SAndroid Build Coastguard Worker 
1030*acea8879SAndroid Build Coastguard Worker   // <[stash_id:stash_range]>
1031*acea8879SAndroid Build Coastguard Worker   while (params.cpos < params.tokens.size()) {
1032*acea8879SAndroid Build Coastguard Worker     // Each word is a an index into the stash table, a colon, and then a RangeSet describing where
1033*acea8879SAndroid Build Coastguard Worker     // in the source block that stashed data should go.
1034*acea8879SAndroid Build Coastguard Worker     std::vector<std::string> tokens = android::base::Split(params.tokens[params.cpos++], ":");
1035*acea8879SAndroid Build Coastguard Worker     if (tokens.size() != 2) {
1036*acea8879SAndroid Build Coastguard Worker       LOG(ERROR) << "invalid parameter";
1037*acea8879SAndroid Build Coastguard Worker       return -1;
1038*acea8879SAndroid Build Coastguard Worker     }
1039*acea8879SAndroid Build Coastguard Worker 
1040*acea8879SAndroid Build Coastguard Worker     std::vector<uint8_t> stash;
1041*acea8879SAndroid Build Coastguard Worker     if (LoadStash(params, tokens[0], false, &stash, true) == -1) {
1042*acea8879SAndroid Build Coastguard Worker       // These source blocks will fail verification if used later, but we
1043*acea8879SAndroid Build Coastguard Worker       // will let the caller decide if this is a fatal failure
1044*acea8879SAndroid Build Coastguard Worker       LOG(ERROR) << "failed to load stash " << tokens[0];
1045*acea8879SAndroid Build Coastguard Worker       continue;
1046*acea8879SAndroid Build Coastguard Worker     }
1047*acea8879SAndroid Build Coastguard Worker 
1048*acea8879SAndroid Build Coastguard Worker     RangeSet locs = RangeSet::Parse(tokens[1]);
1049*acea8879SAndroid Build Coastguard Worker     CHECK(static_cast<bool>(locs));
1050*acea8879SAndroid Build Coastguard Worker     MoveRange(params.buffer, locs, stash);
1051*acea8879SAndroid Build Coastguard Worker   }
1052*acea8879SAndroid Build Coastguard Worker 
1053*acea8879SAndroid Build Coastguard Worker   return 0;
1054*acea8879SAndroid Build Coastguard Worker }
1055*acea8879SAndroid Build Coastguard Worker 
1056*acea8879SAndroid Build Coastguard Worker /**
1057*acea8879SAndroid Build Coastguard Worker  * Do a source/target load for move/bsdiff/imgdiff in version 3.
1058*acea8879SAndroid Build Coastguard Worker  *
1059*acea8879SAndroid Build Coastguard Worker  * We expect to parse the remainder of the parameter tokens as one of:
1060*acea8879SAndroid Build Coastguard Worker  *
1061*acea8879SAndroid Build Coastguard Worker  *    <tgt_range> <src_block_count> <src_range>
1062*acea8879SAndroid Build Coastguard Worker  *        (loads data from source image only)
1063*acea8879SAndroid Build Coastguard Worker  *
1064*acea8879SAndroid Build Coastguard Worker  *    <tgt_range> <src_block_count> - <[stash_id:stash_range] ...>
1065*acea8879SAndroid Build Coastguard Worker  *        (loads data from stashes only)
1066*acea8879SAndroid Build Coastguard Worker  *
1067*acea8879SAndroid Build Coastguard Worker  *    <tgt_range> <src_block_count> <src_range> <src_loc> <[stash_id:stash_range] ...>
1068*acea8879SAndroid Build Coastguard Worker  *        (loads data from both source image and stashes)
1069*acea8879SAndroid Build Coastguard Worker  *
1070*acea8879SAndroid Build Coastguard Worker  * 'onehash' tells whether to expect separate source and targe block hashes, or if they are both the
1071*acea8879SAndroid Build Coastguard Worker  * same and only one hash should be expected. params.isunresumable will be set to true if block
1072*acea8879SAndroid Build Coastguard Worker  * verification fails in a way that the update cannot be resumed anymore.
1073*acea8879SAndroid Build Coastguard Worker  *
1074*acea8879SAndroid Build Coastguard Worker  * If the function is unable to load the necessary blocks or their contents don't match the hashes,
1075*acea8879SAndroid Build Coastguard Worker  * the return value is -1 and the command should be aborted.
1076*acea8879SAndroid Build Coastguard Worker  *
1077*acea8879SAndroid Build Coastguard Worker  * If the return value is 1, the command has already been completed according to the contents of the
1078*acea8879SAndroid Build Coastguard Worker  * target blocks, and should not be performed again.
1079*acea8879SAndroid Build Coastguard Worker  *
1080*acea8879SAndroid Build Coastguard Worker  * If the return value is 0, source blocks have expected content and the command can be performed.
1081*acea8879SAndroid Build Coastguard Worker  */
LoadSrcTgtVersion3(CommandParameters & params,RangeSet * tgt,size_t * src_blocks,bool onehash)1082*acea8879SAndroid Build Coastguard Worker static int LoadSrcTgtVersion3(CommandParameters& params, RangeSet* tgt, size_t* src_blocks,
1083*acea8879SAndroid Build Coastguard Worker                               bool onehash) {
1084*acea8879SAndroid Build Coastguard Worker   CHECK(src_blocks != nullptr);
1085*acea8879SAndroid Build Coastguard Worker 
1086*acea8879SAndroid Build Coastguard Worker   if (params.cpos >= params.tokens.size()) {
1087*acea8879SAndroid Build Coastguard Worker     LOG(ERROR) << "missing source hash";
1088*acea8879SAndroid Build Coastguard Worker     return -1;
1089*acea8879SAndroid Build Coastguard Worker   }
1090*acea8879SAndroid Build Coastguard Worker 
1091*acea8879SAndroid Build Coastguard Worker   std::string srchash = params.tokens[params.cpos++];
1092*acea8879SAndroid Build Coastguard Worker   std::string tgthash;
1093*acea8879SAndroid Build Coastguard Worker 
1094*acea8879SAndroid Build Coastguard Worker   if (onehash) {
1095*acea8879SAndroid Build Coastguard Worker     tgthash = srchash;
1096*acea8879SAndroid Build Coastguard Worker   } else {
1097*acea8879SAndroid Build Coastguard Worker     if (params.cpos >= params.tokens.size()) {
1098*acea8879SAndroid Build Coastguard Worker       LOG(ERROR) << "missing target hash";
1099*acea8879SAndroid Build Coastguard Worker       return -1;
1100*acea8879SAndroid Build Coastguard Worker     }
1101*acea8879SAndroid Build Coastguard Worker     tgthash = params.tokens[params.cpos++];
1102*acea8879SAndroid Build Coastguard Worker   }
1103*acea8879SAndroid Build Coastguard Worker 
1104*acea8879SAndroid Build Coastguard Worker   // At least it needs to provide three parameters: <tgt_range>, <src_block_count> and
1105*acea8879SAndroid Build Coastguard Worker   // "-"/<src_range>.
1106*acea8879SAndroid Build Coastguard Worker   if (params.cpos + 2 >= params.tokens.size()) {
1107*acea8879SAndroid Build Coastguard Worker     LOG(ERROR) << "invalid parameters";
1108*acea8879SAndroid Build Coastguard Worker     return -1;
1109*acea8879SAndroid Build Coastguard Worker   }
1110*acea8879SAndroid Build Coastguard Worker 
1111*acea8879SAndroid Build Coastguard Worker   // <tgt_range>
1112*acea8879SAndroid Build Coastguard Worker   *tgt = RangeSet::Parse(params.tokens[params.cpos++]);
1113*acea8879SAndroid Build Coastguard Worker   CHECK(static_cast<bool>(*tgt));
1114*acea8879SAndroid Build Coastguard Worker 
1115*acea8879SAndroid Build Coastguard Worker   std::vector<uint8_t> tgtbuffer(tgt->blocks() * BLOCKSIZE);
1116*acea8879SAndroid Build Coastguard Worker   if (ReadBlocks(*tgt, &tgtbuffer, params.fd) == -1) {
1117*acea8879SAndroid Build Coastguard Worker     return -1;
1118*acea8879SAndroid Build Coastguard Worker   }
1119*acea8879SAndroid Build Coastguard Worker 
1120*acea8879SAndroid Build Coastguard Worker   // Return now if target blocks already have expected content.
1121*acea8879SAndroid Build Coastguard Worker   if (VerifyBlocks(tgthash, tgtbuffer, tgt->blocks(), false) == 0) {
1122*acea8879SAndroid Build Coastguard Worker     return 1;
1123*acea8879SAndroid Build Coastguard Worker   }
1124*acea8879SAndroid Build Coastguard Worker 
1125*acea8879SAndroid Build Coastguard Worker   // Load source blocks.
1126*acea8879SAndroid Build Coastguard Worker   bool overlap = false;
1127*acea8879SAndroid Build Coastguard Worker   if (LoadSourceBlocks(params, *tgt, src_blocks, &overlap) == -1) {
1128*acea8879SAndroid Build Coastguard Worker     return -1;
1129*acea8879SAndroid Build Coastguard Worker   }
1130*acea8879SAndroid Build Coastguard Worker 
1131*acea8879SAndroid Build Coastguard Worker   if (VerifyBlocks(srchash, params.buffer, *src_blocks, true) == 0) {
1132*acea8879SAndroid Build Coastguard Worker     // If source and target blocks overlap, stash the source blocks so we can resume from possible
1133*acea8879SAndroid Build Coastguard Worker     // write errors. In verify mode, we can skip stashing because the source blocks won't be
1134*acea8879SAndroid Build Coastguard Worker     // overwritten.
1135*acea8879SAndroid Build Coastguard Worker     if (overlap && params.canwrite) {
1136*acea8879SAndroid Build Coastguard Worker       LOG(INFO) << "stashing " << *src_blocks << " overlapping blocks to " << srchash;
1137*acea8879SAndroid Build Coastguard Worker 
1138*acea8879SAndroid Build Coastguard Worker       bool stash_exists = false;
1139*acea8879SAndroid Build Coastguard Worker       if (WriteStash(params.stashbase, srchash, *src_blocks, params.buffer, true,
1140*acea8879SAndroid Build Coastguard Worker                      &stash_exists) != 0) {
1141*acea8879SAndroid Build Coastguard Worker         LOG(ERROR) << "failed to stash overlapping source blocks";
1142*acea8879SAndroid Build Coastguard Worker         return -1;
1143*acea8879SAndroid Build Coastguard Worker       }
1144*acea8879SAndroid Build Coastguard Worker 
1145*acea8879SAndroid Build Coastguard Worker       params.stashed += *src_blocks;
1146*acea8879SAndroid Build Coastguard Worker       // Can be deleted when the write has completed.
1147*acea8879SAndroid Build Coastguard Worker       if (!stash_exists) {
1148*acea8879SAndroid Build Coastguard Worker         params.freestash = srchash;
1149*acea8879SAndroid Build Coastguard Worker       }
1150*acea8879SAndroid Build Coastguard Worker     }
1151*acea8879SAndroid Build Coastguard Worker 
1152*acea8879SAndroid Build Coastguard Worker     // Source blocks have expected content, command can proceed.
1153*acea8879SAndroid Build Coastguard Worker     return 0;
1154*acea8879SAndroid Build Coastguard Worker   }
1155*acea8879SAndroid Build Coastguard Worker 
1156*acea8879SAndroid Build Coastguard Worker   if (overlap && LoadStash(params, srchash, true, &params.buffer, true) == 0) {
1157*acea8879SAndroid Build Coastguard Worker     // Overlapping source blocks were previously stashed, command can proceed. We are recovering
1158*acea8879SAndroid Build Coastguard Worker     // from an interrupted command, so we don't know if the stash can safely be deleted after this
1159*acea8879SAndroid Build Coastguard Worker     // command.
1160*acea8879SAndroid Build Coastguard Worker     return 0;
1161*acea8879SAndroid Build Coastguard Worker   }
1162*acea8879SAndroid Build Coastguard Worker 
1163*acea8879SAndroid Build Coastguard Worker   // Valid source data not available, update cannot be resumed.
1164*acea8879SAndroid Build Coastguard Worker   LOG(ERROR) << "partition has unexpected contents";
1165*acea8879SAndroid Build Coastguard Worker   PrintHashForCorruptedSourceBlocks(params, params.buffer);
1166*acea8879SAndroid Build Coastguard Worker 
1167*acea8879SAndroid Build Coastguard Worker   params.isunresumable = true;
1168*acea8879SAndroid Build Coastguard Worker 
1169*acea8879SAndroid Build Coastguard Worker   return -1;
1170*acea8879SAndroid Build Coastguard Worker }
1171*acea8879SAndroid Build Coastguard Worker 
PerformCommandMove(CommandParameters & params)1172*acea8879SAndroid Build Coastguard Worker static int PerformCommandMove(CommandParameters& params) {
1173*acea8879SAndroid Build Coastguard Worker   size_t blocks = 0;
1174*acea8879SAndroid Build Coastguard Worker   RangeSet tgt;
1175*acea8879SAndroid Build Coastguard Worker   int status = LoadSrcTgtVersion3(params, &tgt, &blocks, true);
1176*acea8879SAndroid Build Coastguard Worker 
1177*acea8879SAndroid Build Coastguard Worker   if (status == -1) {
1178*acea8879SAndroid Build Coastguard Worker     LOG(ERROR) << "failed to read blocks for move";
1179*acea8879SAndroid Build Coastguard Worker     return -1;
1180*acea8879SAndroid Build Coastguard Worker   }
1181*acea8879SAndroid Build Coastguard Worker 
1182*acea8879SAndroid Build Coastguard Worker   if (status == 0) {
1183*acea8879SAndroid Build Coastguard Worker     params.foundwrites = true;
1184*acea8879SAndroid Build Coastguard Worker   } else {
1185*acea8879SAndroid Build Coastguard Worker     params.target_verified = true;
1186*acea8879SAndroid Build Coastguard Worker     if (params.foundwrites) {
1187*acea8879SAndroid Build Coastguard Worker       LOG(WARNING) << "warning: commands executed out of order [" << params.cmdname << "]";
1188*acea8879SAndroid Build Coastguard Worker     }
1189*acea8879SAndroid Build Coastguard Worker   }
1190*acea8879SAndroid Build Coastguard Worker 
1191*acea8879SAndroid Build Coastguard Worker   if (params.canwrite) {
1192*acea8879SAndroid Build Coastguard Worker     if (status == 0) {
1193*acea8879SAndroid Build Coastguard Worker       LOG(INFO) << "  moving " << blocks << " blocks";
1194*acea8879SAndroid Build Coastguard Worker 
1195*acea8879SAndroid Build Coastguard Worker       if (WriteBlocks(tgt, params.buffer, params.fd) == -1) {
1196*acea8879SAndroid Build Coastguard Worker         return -1;
1197*acea8879SAndroid Build Coastguard Worker       }
1198*acea8879SAndroid Build Coastguard Worker     } else {
1199*acea8879SAndroid Build Coastguard Worker       LOG(INFO) << "skipping " << blocks << " already moved blocks";
1200*acea8879SAndroid Build Coastguard Worker     }
1201*acea8879SAndroid Build Coastguard Worker   }
1202*acea8879SAndroid Build Coastguard Worker 
1203*acea8879SAndroid Build Coastguard Worker   if (!params.freestash.empty()) {
1204*acea8879SAndroid Build Coastguard Worker     FreeStash(params.stashbase, params.freestash);
1205*acea8879SAndroid Build Coastguard Worker     params.freestash.clear();
1206*acea8879SAndroid Build Coastguard Worker   }
1207*acea8879SAndroid Build Coastguard Worker 
1208*acea8879SAndroid Build Coastguard Worker   params.written += tgt.blocks();
1209*acea8879SAndroid Build Coastguard Worker 
1210*acea8879SAndroid Build Coastguard Worker   return 0;
1211*acea8879SAndroid Build Coastguard Worker }
1212*acea8879SAndroid Build Coastguard Worker 
PerformCommandStash(CommandParameters & params)1213*acea8879SAndroid Build Coastguard Worker static int PerformCommandStash(CommandParameters& params) {
1214*acea8879SAndroid Build Coastguard Worker   // <stash_id> <src_range>
1215*acea8879SAndroid Build Coastguard Worker   if (params.cpos + 1 >= params.tokens.size()) {
1216*acea8879SAndroid Build Coastguard Worker     LOG(ERROR) << "missing id and/or src range fields in stash command";
1217*acea8879SAndroid Build Coastguard Worker     return -1;
1218*acea8879SAndroid Build Coastguard Worker   }
1219*acea8879SAndroid Build Coastguard Worker 
1220*acea8879SAndroid Build Coastguard Worker   const std::string& id = params.tokens[params.cpos++];
1221*acea8879SAndroid Build Coastguard Worker   if (LoadStash(params, id, true, &params.buffer, false) == 0) {
1222*acea8879SAndroid Build Coastguard Worker     // Stash file already exists and has expected contents. Do not read from source again, as the
1223*acea8879SAndroid Build Coastguard Worker     // source may have been already overwritten during a previous attempt.
1224*acea8879SAndroid Build Coastguard Worker     return 0;
1225*acea8879SAndroid Build Coastguard Worker   }
1226*acea8879SAndroid Build Coastguard Worker 
1227*acea8879SAndroid Build Coastguard Worker   RangeSet src = RangeSet::Parse(params.tokens[params.cpos++]);
1228*acea8879SAndroid Build Coastguard Worker   CHECK(static_cast<bool>(src));
1229*acea8879SAndroid Build Coastguard Worker 
1230*acea8879SAndroid Build Coastguard Worker   size_t blocks = src.blocks();
1231*acea8879SAndroid Build Coastguard Worker   allocate(blocks * BLOCKSIZE, &params.buffer);
1232*acea8879SAndroid Build Coastguard Worker   if (ReadBlocks(src, &params.buffer, params.fd) == -1) {
1233*acea8879SAndroid Build Coastguard Worker     return -1;
1234*acea8879SAndroid Build Coastguard Worker   }
1235*acea8879SAndroid Build Coastguard Worker   stash_map[id] = src;
1236*acea8879SAndroid Build Coastguard Worker 
1237*acea8879SAndroid Build Coastguard Worker   if (VerifyBlocks(id, params.buffer, blocks, true) != 0) {
1238*acea8879SAndroid Build Coastguard Worker     // Source blocks have unexpected contents. If we actually need this data later, this is an
1239*acea8879SAndroid Build Coastguard Worker     // unrecoverable error. However, the command that uses the data may have already completed
1240*acea8879SAndroid Build Coastguard Worker     // previously, so the possible failure will occur during source block verification.
1241*acea8879SAndroid Build Coastguard Worker     LOG(ERROR) << "failed to load source blocks for stash " << id;
1242*acea8879SAndroid Build Coastguard Worker     return 0;
1243*acea8879SAndroid Build Coastguard Worker   }
1244*acea8879SAndroid Build Coastguard Worker 
1245*acea8879SAndroid Build Coastguard Worker   // In verify mode, we don't need to stash any blocks.
1246*acea8879SAndroid Build Coastguard Worker   if (!params.canwrite) {
1247*acea8879SAndroid Build Coastguard Worker     return 0;
1248*acea8879SAndroid Build Coastguard Worker   }
1249*acea8879SAndroid Build Coastguard Worker 
1250*acea8879SAndroid Build Coastguard Worker   LOG(INFO) << "stashing " << blocks << " blocks to " << id;
1251*acea8879SAndroid Build Coastguard Worker   int result = WriteStash(params.stashbase, id, blocks, params.buffer, false, nullptr);
1252*acea8879SAndroid Build Coastguard Worker   if (result == 0) {
1253*acea8879SAndroid Build Coastguard Worker     params.stashed += blocks;
1254*acea8879SAndroid Build Coastguard Worker   }
1255*acea8879SAndroid Build Coastguard Worker   return result;
1256*acea8879SAndroid Build Coastguard Worker }
1257*acea8879SAndroid Build Coastguard Worker 
PerformCommandFree(CommandParameters & params)1258*acea8879SAndroid Build Coastguard Worker static int PerformCommandFree(CommandParameters& params) {
1259*acea8879SAndroid Build Coastguard Worker   // <stash_id>
1260*acea8879SAndroid Build Coastguard Worker   if (params.cpos >= params.tokens.size()) {
1261*acea8879SAndroid Build Coastguard Worker     LOG(ERROR) << "missing stash id in free command";
1262*acea8879SAndroid Build Coastguard Worker     return -1;
1263*acea8879SAndroid Build Coastguard Worker   }
1264*acea8879SAndroid Build Coastguard Worker 
1265*acea8879SAndroid Build Coastguard Worker   const std::string& id = params.tokens[params.cpos++];
1266*acea8879SAndroid Build Coastguard Worker   stash_map.erase(id);
1267*acea8879SAndroid Build Coastguard Worker 
1268*acea8879SAndroid Build Coastguard Worker   if (params.createdstash || params.canwrite) {
1269*acea8879SAndroid Build Coastguard Worker     return FreeStash(params.stashbase, id);
1270*acea8879SAndroid Build Coastguard Worker   }
1271*acea8879SAndroid Build Coastguard Worker 
1272*acea8879SAndroid Build Coastguard Worker   return 0;
1273*acea8879SAndroid Build Coastguard Worker }
1274*acea8879SAndroid Build Coastguard Worker 
PerformCommandZero(CommandParameters & params)1275*acea8879SAndroid Build Coastguard Worker static int PerformCommandZero(CommandParameters& params) {
1276*acea8879SAndroid Build Coastguard Worker   if (params.cpos >= params.tokens.size()) {
1277*acea8879SAndroid Build Coastguard Worker     LOG(ERROR) << "missing target blocks for zero";
1278*acea8879SAndroid Build Coastguard Worker     return -1;
1279*acea8879SAndroid Build Coastguard Worker   }
1280*acea8879SAndroid Build Coastguard Worker 
1281*acea8879SAndroid Build Coastguard Worker   RangeSet tgt = RangeSet::Parse(params.tokens[params.cpos++]);
1282*acea8879SAndroid Build Coastguard Worker   CHECK(static_cast<bool>(tgt));
1283*acea8879SAndroid Build Coastguard Worker 
1284*acea8879SAndroid Build Coastguard Worker   LOG(INFO) << "  zeroing " << tgt.blocks() << " blocks";
1285*acea8879SAndroid Build Coastguard Worker 
1286*acea8879SAndroid Build Coastguard Worker   allocate(BLOCKSIZE, &params.buffer);
1287*acea8879SAndroid Build Coastguard Worker   memset(params.buffer.data(), 0, BLOCKSIZE);
1288*acea8879SAndroid Build Coastguard Worker 
1289*acea8879SAndroid Build Coastguard Worker   if (params.canwrite) {
1290*acea8879SAndroid Build Coastguard Worker     for (const auto& [begin, end] : tgt) {
1291*acea8879SAndroid Build Coastguard Worker       off64_t offset = static_cast<off64_t>(begin) * BLOCKSIZE;
1292*acea8879SAndroid Build Coastguard Worker       size_t size = (end - begin) * BLOCKSIZE;
1293*acea8879SAndroid Build Coastguard Worker       if (!discard_blocks(params.fd, offset, size)) {
1294*acea8879SAndroid Build Coastguard Worker         return -1;
1295*acea8879SAndroid Build Coastguard Worker       }
1296*acea8879SAndroid Build Coastguard Worker 
1297*acea8879SAndroid Build Coastguard Worker       if (!check_lseek(params.fd, offset, SEEK_SET)) {
1298*acea8879SAndroid Build Coastguard Worker         return -1;
1299*acea8879SAndroid Build Coastguard Worker       }
1300*acea8879SAndroid Build Coastguard Worker 
1301*acea8879SAndroid Build Coastguard Worker       for (size_t j = begin; j < end; ++j) {
1302*acea8879SAndroid Build Coastguard Worker         if (!android::base::WriteFully(params.fd, params.buffer.data(), BLOCKSIZE)) {
1303*acea8879SAndroid Build Coastguard Worker           failure_type = errno == EIO ? kEioFailure : kFwriteFailure;
1304*acea8879SAndroid Build Coastguard Worker           PLOG(ERROR) << "Failed to write " << BLOCKSIZE << " bytes of data";
1305*acea8879SAndroid Build Coastguard Worker           return -1;
1306*acea8879SAndroid Build Coastguard Worker         }
1307*acea8879SAndroid Build Coastguard Worker       }
1308*acea8879SAndroid Build Coastguard Worker     }
1309*acea8879SAndroid Build Coastguard Worker   }
1310*acea8879SAndroid Build Coastguard Worker 
1311*acea8879SAndroid Build Coastguard Worker   if (params.cmdname[0] == 'z') {
1312*acea8879SAndroid Build Coastguard Worker     // Update only for the zero command, as the erase command will call
1313*acea8879SAndroid Build Coastguard Worker     // this if DEBUG_ERASE is defined.
1314*acea8879SAndroid Build Coastguard Worker     params.written += tgt.blocks();
1315*acea8879SAndroid Build Coastguard Worker   }
1316*acea8879SAndroid Build Coastguard Worker 
1317*acea8879SAndroid Build Coastguard Worker   return 0;
1318*acea8879SAndroid Build Coastguard Worker }
1319*acea8879SAndroid Build Coastguard Worker 
PerformCommandNew(CommandParameters & params)1320*acea8879SAndroid Build Coastguard Worker static int PerformCommandNew(CommandParameters& params) {
1321*acea8879SAndroid Build Coastguard Worker   if (params.cpos >= params.tokens.size()) {
1322*acea8879SAndroid Build Coastguard Worker     LOG(ERROR) << "missing target blocks for new";
1323*acea8879SAndroid Build Coastguard Worker     return -1;
1324*acea8879SAndroid Build Coastguard Worker   }
1325*acea8879SAndroid Build Coastguard Worker 
1326*acea8879SAndroid Build Coastguard Worker   RangeSet tgt = RangeSet::Parse(params.tokens[params.cpos++]);
1327*acea8879SAndroid Build Coastguard Worker   CHECK(static_cast<bool>(tgt));
1328*acea8879SAndroid Build Coastguard Worker 
1329*acea8879SAndroid Build Coastguard Worker   if (params.canwrite) {
1330*acea8879SAndroid Build Coastguard Worker     LOG(INFO) << " writing " << tgt.blocks() << " blocks of new data";
1331*acea8879SAndroid Build Coastguard Worker 
1332*acea8879SAndroid Build Coastguard Worker     pthread_mutex_lock(&params.nti.mu);
1333*acea8879SAndroid Build Coastguard Worker     params.nti.writer = std::make_unique<RangeSinkWriter>(params.fd, tgt);
1334*acea8879SAndroid Build Coastguard Worker     pthread_cond_broadcast(&params.nti.cv);
1335*acea8879SAndroid Build Coastguard Worker 
1336*acea8879SAndroid Build Coastguard Worker     while (params.nti.writer != nullptr) {
1337*acea8879SAndroid Build Coastguard Worker       if (!params.nti.receiver_available) {
1338*acea8879SAndroid Build Coastguard Worker         LOG(ERROR) << "missing " << (tgt.blocks() * BLOCKSIZE - params.nti.writer->BytesWritten())
1339*acea8879SAndroid Build Coastguard Worker                    << " bytes of new data";
1340*acea8879SAndroid Build Coastguard Worker         pthread_mutex_unlock(&params.nti.mu);
1341*acea8879SAndroid Build Coastguard Worker         return -1;
1342*acea8879SAndroid Build Coastguard Worker       }
1343*acea8879SAndroid Build Coastguard Worker       pthread_cond_wait(&params.nti.cv, &params.nti.mu);
1344*acea8879SAndroid Build Coastguard Worker     }
1345*acea8879SAndroid Build Coastguard Worker 
1346*acea8879SAndroid Build Coastguard Worker     pthread_mutex_unlock(&params.nti.mu);
1347*acea8879SAndroid Build Coastguard Worker   }
1348*acea8879SAndroid Build Coastguard Worker 
1349*acea8879SAndroid Build Coastguard Worker   params.written += tgt.blocks();
1350*acea8879SAndroid Build Coastguard Worker 
1351*acea8879SAndroid Build Coastguard Worker   return 0;
1352*acea8879SAndroid Build Coastguard Worker }
1353*acea8879SAndroid Build Coastguard Worker 
PerformCommandDiff(CommandParameters & params)1354*acea8879SAndroid Build Coastguard Worker static int PerformCommandDiff(CommandParameters& params) {
1355*acea8879SAndroid Build Coastguard Worker   // <offset> <length>
1356*acea8879SAndroid Build Coastguard Worker   if (params.cpos + 1 >= params.tokens.size()) {
1357*acea8879SAndroid Build Coastguard Worker     LOG(ERROR) << "missing patch offset or length for " << params.cmdname;
1358*acea8879SAndroid Build Coastguard Worker     return -1;
1359*acea8879SAndroid Build Coastguard Worker   }
1360*acea8879SAndroid Build Coastguard Worker 
1361*acea8879SAndroid Build Coastguard Worker   size_t offset;
1362*acea8879SAndroid Build Coastguard Worker   if (!android::base::ParseUint(params.tokens[params.cpos++], &offset)) {
1363*acea8879SAndroid Build Coastguard Worker     LOG(ERROR) << "invalid patch offset";
1364*acea8879SAndroid Build Coastguard Worker     return -1;
1365*acea8879SAndroid Build Coastguard Worker   }
1366*acea8879SAndroid Build Coastguard Worker 
1367*acea8879SAndroid Build Coastguard Worker   size_t len;
1368*acea8879SAndroid Build Coastguard Worker   if (!android::base::ParseUint(params.tokens[params.cpos++], &len)) {
1369*acea8879SAndroid Build Coastguard Worker     LOG(ERROR) << "invalid patch len";
1370*acea8879SAndroid Build Coastguard Worker     return -1;
1371*acea8879SAndroid Build Coastguard Worker   }
1372*acea8879SAndroid Build Coastguard Worker 
1373*acea8879SAndroid Build Coastguard Worker   RangeSet tgt;
1374*acea8879SAndroid Build Coastguard Worker   size_t blocks = 0;
1375*acea8879SAndroid Build Coastguard Worker   int status = LoadSrcTgtVersion3(params, &tgt, &blocks, false);
1376*acea8879SAndroid Build Coastguard Worker 
1377*acea8879SAndroid Build Coastguard Worker   if (status == -1) {
1378*acea8879SAndroid Build Coastguard Worker     LOG(ERROR) << "failed to read blocks for diff";
1379*acea8879SAndroid Build Coastguard Worker     return -1;
1380*acea8879SAndroid Build Coastguard Worker   }
1381*acea8879SAndroid Build Coastguard Worker 
1382*acea8879SAndroid Build Coastguard Worker   if (status == 0) {
1383*acea8879SAndroid Build Coastguard Worker     params.foundwrites = true;
1384*acea8879SAndroid Build Coastguard Worker   } else {
1385*acea8879SAndroid Build Coastguard Worker     params.target_verified = true;
1386*acea8879SAndroid Build Coastguard Worker     if (params.foundwrites) {
1387*acea8879SAndroid Build Coastguard Worker       LOG(WARNING) << "warning: commands executed out of order [" << params.cmdname << "]";
1388*acea8879SAndroid Build Coastguard Worker     }
1389*acea8879SAndroid Build Coastguard Worker   }
1390*acea8879SAndroid Build Coastguard Worker 
1391*acea8879SAndroid Build Coastguard Worker   if (params.canwrite) {
1392*acea8879SAndroid Build Coastguard Worker     if (status == 0) {
1393*acea8879SAndroid Build Coastguard Worker       LOG(INFO) << "patching " << blocks << " blocks to " << tgt.blocks();
1394*acea8879SAndroid Build Coastguard Worker       Value patch_value(
1395*acea8879SAndroid Build Coastguard Worker           Value::Type::BLOB,
1396*acea8879SAndroid Build Coastguard Worker           std::string(reinterpret_cast<const char*>(params.patch_start + offset), len));
1397*acea8879SAndroid Build Coastguard Worker 
1398*acea8879SAndroid Build Coastguard Worker       RangeSinkWriter writer(params.fd, tgt);
1399*acea8879SAndroid Build Coastguard Worker       if (params.cmdname[0] == 'i') {  // imgdiff
1400*acea8879SAndroid Build Coastguard Worker         if (ApplyImagePatch(params.buffer.data(), blocks * BLOCKSIZE, patch_value,
1401*acea8879SAndroid Build Coastguard Worker                             std::bind(&RangeSinkWriter::Write, &writer, std::placeholders::_1,
1402*acea8879SAndroid Build Coastguard Worker                                       std::placeholders::_2),
1403*acea8879SAndroid Build Coastguard Worker                             nullptr) != 0) {
1404*acea8879SAndroid Build Coastguard Worker           LOG(ERROR) << "Failed to apply image patch.";
1405*acea8879SAndroid Build Coastguard Worker           failure_type = kPatchApplicationFailure;
1406*acea8879SAndroid Build Coastguard Worker           return -1;
1407*acea8879SAndroid Build Coastguard Worker         }
1408*acea8879SAndroid Build Coastguard Worker       } else {
1409*acea8879SAndroid Build Coastguard Worker         if (ApplyBSDiffPatch(params.buffer.data(), blocks * BLOCKSIZE, patch_value, 0,
1410*acea8879SAndroid Build Coastguard Worker                              std::bind(&RangeSinkWriter::Write, &writer, std::placeholders::_1,
1411*acea8879SAndroid Build Coastguard Worker                                        std::placeholders::_2)) != 0) {
1412*acea8879SAndroid Build Coastguard Worker           LOG(ERROR) << "Failed to apply bsdiff patch.";
1413*acea8879SAndroid Build Coastguard Worker           failure_type = kPatchApplicationFailure;
1414*acea8879SAndroid Build Coastguard Worker           return -1;
1415*acea8879SAndroid Build Coastguard Worker         }
1416*acea8879SAndroid Build Coastguard Worker       }
1417*acea8879SAndroid Build Coastguard Worker 
1418*acea8879SAndroid Build Coastguard Worker       // We expect the output of the patcher to fill the tgt ranges exactly.
1419*acea8879SAndroid Build Coastguard Worker       if (!writer.Finished()) {
1420*acea8879SAndroid Build Coastguard Worker         LOG(ERROR) << "Failed to fully write target blocks (range sink underrun): Missing "
1421*acea8879SAndroid Build Coastguard Worker                    << writer.AvailableSpace() << " bytes";
1422*acea8879SAndroid Build Coastguard Worker         failure_type = kPatchApplicationFailure;
1423*acea8879SAndroid Build Coastguard Worker         return -1;
1424*acea8879SAndroid Build Coastguard Worker       }
1425*acea8879SAndroid Build Coastguard Worker     } else {
1426*acea8879SAndroid Build Coastguard Worker       LOG(INFO) << "skipping " << blocks << " blocks already patched to " << tgt.blocks() << " ["
1427*acea8879SAndroid Build Coastguard Worker                 << params.cmdline << "]";
1428*acea8879SAndroid Build Coastguard Worker     }
1429*acea8879SAndroid Build Coastguard Worker   }
1430*acea8879SAndroid Build Coastguard Worker 
1431*acea8879SAndroid Build Coastguard Worker   if (!params.freestash.empty()) {
1432*acea8879SAndroid Build Coastguard Worker     FreeStash(params.stashbase, params.freestash);
1433*acea8879SAndroid Build Coastguard Worker     params.freestash.clear();
1434*acea8879SAndroid Build Coastguard Worker   }
1435*acea8879SAndroid Build Coastguard Worker 
1436*acea8879SAndroid Build Coastguard Worker   params.written += tgt.blocks();
1437*acea8879SAndroid Build Coastguard Worker 
1438*acea8879SAndroid Build Coastguard Worker   return 0;
1439*acea8879SAndroid Build Coastguard Worker }
1440*acea8879SAndroid Build Coastguard Worker 
PerformCommandErase(CommandParameters & params)1441*acea8879SAndroid Build Coastguard Worker static int PerformCommandErase(CommandParameters& params) {
1442*acea8879SAndroid Build Coastguard Worker   if (DEBUG_ERASE) {
1443*acea8879SAndroid Build Coastguard Worker     return PerformCommandZero(params);
1444*acea8879SAndroid Build Coastguard Worker   }
1445*acea8879SAndroid Build Coastguard Worker 
1446*acea8879SAndroid Build Coastguard Worker   struct stat sb;
1447*acea8879SAndroid Build Coastguard Worker   if (fstat(params.fd, &sb) == -1) {
1448*acea8879SAndroid Build Coastguard Worker     PLOG(ERROR) << "failed to fstat device to erase";
1449*acea8879SAndroid Build Coastguard Worker     return -1;
1450*acea8879SAndroid Build Coastguard Worker   }
1451*acea8879SAndroid Build Coastguard Worker 
1452*acea8879SAndroid Build Coastguard Worker   if (!S_ISBLK(sb.st_mode)) {
1453*acea8879SAndroid Build Coastguard Worker     LOG(ERROR) << "not a block device; skipping erase";
1454*acea8879SAndroid Build Coastguard Worker     return -1;
1455*acea8879SAndroid Build Coastguard Worker   }
1456*acea8879SAndroid Build Coastguard Worker 
1457*acea8879SAndroid Build Coastguard Worker   if (params.cpos >= params.tokens.size()) {
1458*acea8879SAndroid Build Coastguard Worker     LOG(ERROR) << "missing target blocks for erase";
1459*acea8879SAndroid Build Coastguard Worker     return -1;
1460*acea8879SAndroid Build Coastguard Worker   }
1461*acea8879SAndroid Build Coastguard Worker 
1462*acea8879SAndroid Build Coastguard Worker   RangeSet tgt = RangeSet::Parse(params.tokens[params.cpos++]);
1463*acea8879SAndroid Build Coastguard Worker   CHECK(static_cast<bool>(tgt));
1464*acea8879SAndroid Build Coastguard Worker 
1465*acea8879SAndroid Build Coastguard Worker   if (params.canwrite) {
1466*acea8879SAndroid Build Coastguard Worker     LOG(INFO) << " erasing " << tgt.blocks() << " blocks";
1467*acea8879SAndroid Build Coastguard Worker 
1468*acea8879SAndroid Build Coastguard Worker     for (const auto& [begin, end] : tgt) {
1469*acea8879SAndroid Build Coastguard Worker       off64_t offset = static_cast<off64_t>(begin) * BLOCKSIZE;
1470*acea8879SAndroid Build Coastguard Worker       size_t size = (end - begin) * BLOCKSIZE;
1471*acea8879SAndroid Build Coastguard Worker       if (!discard_blocks(params.fd, offset, size, true /* force */)) {
1472*acea8879SAndroid Build Coastguard Worker         return -1;
1473*acea8879SAndroid Build Coastguard Worker       }
1474*acea8879SAndroid Build Coastguard Worker     }
1475*acea8879SAndroid Build Coastguard Worker   }
1476*acea8879SAndroid Build Coastguard Worker 
1477*acea8879SAndroid Build Coastguard Worker   return 0;
1478*acea8879SAndroid Build Coastguard Worker }
1479*acea8879SAndroid Build Coastguard Worker 
PerformCommandAbort(CommandParameters &)1480*acea8879SAndroid Build Coastguard Worker static int PerformCommandAbort(CommandParameters&) {
1481*acea8879SAndroid Build Coastguard Worker   LOG(INFO) << "Aborting as instructed";
1482*acea8879SAndroid Build Coastguard Worker   return -1;
1483*acea8879SAndroid Build Coastguard Worker }
1484*acea8879SAndroid Build Coastguard Worker 
1485*acea8879SAndroid Build Coastguard Worker // Computes the hash_tree bytes based on the parameters, checks if the root hash of the tree
1486*acea8879SAndroid Build Coastguard Worker // matches the expected hash and writes the result to the specified range on the block_device.
1487*acea8879SAndroid Build Coastguard Worker // Hash_tree computation arguments:
1488*acea8879SAndroid Build Coastguard Worker //   hash_tree_ranges
1489*acea8879SAndroid Build Coastguard Worker //   source_ranges
1490*acea8879SAndroid Build Coastguard Worker //   hash_algorithm
1491*acea8879SAndroid Build Coastguard Worker //   salt_hex
1492*acea8879SAndroid Build Coastguard Worker //   root_hash
PerformCommandComputeHashTree(CommandParameters & params)1493*acea8879SAndroid Build Coastguard Worker static int PerformCommandComputeHashTree(CommandParameters& params) {
1494*acea8879SAndroid Build Coastguard Worker   if (params.cpos + 5 != params.tokens.size()) {
1495*acea8879SAndroid Build Coastguard Worker     LOG(ERROR) << "Invalid arguments count in hash computation " << params.cmdline;
1496*acea8879SAndroid Build Coastguard Worker     return -1;
1497*acea8879SAndroid Build Coastguard Worker   }
1498*acea8879SAndroid Build Coastguard Worker 
1499*acea8879SAndroid Build Coastguard Worker   // Expects the hash_tree data to be contiguous.
1500*acea8879SAndroid Build Coastguard Worker   RangeSet hash_tree_ranges = RangeSet::Parse(params.tokens[params.cpos++]);
1501*acea8879SAndroid Build Coastguard Worker   if (!hash_tree_ranges || hash_tree_ranges.size() != 1) {
1502*acea8879SAndroid Build Coastguard Worker     LOG(ERROR) << "Invalid hash tree ranges in " << params.cmdline;
1503*acea8879SAndroid Build Coastguard Worker     return -1;
1504*acea8879SAndroid Build Coastguard Worker   }
1505*acea8879SAndroid Build Coastguard Worker 
1506*acea8879SAndroid Build Coastguard Worker   RangeSet source_ranges = RangeSet::Parse(params.tokens[params.cpos++]);
1507*acea8879SAndroid Build Coastguard Worker   if (!source_ranges) {
1508*acea8879SAndroid Build Coastguard Worker     LOG(ERROR) << "Invalid source ranges in " << params.cmdline;
1509*acea8879SAndroid Build Coastguard Worker     return -1;
1510*acea8879SAndroid Build Coastguard Worker   }
1511*acea8879SAndroid Build Coastguard Worker 
1512*acea8879SAndroid Build Coastguard Worker   auto hash_function = HashTreeBuilder::HashFunction(params.tokens[params.cpos++]);
1513*acea8879SAndroid Build Coastguard Worker   if (hash_function == nullptr) {
1514*acea8879SAndroid Build Coastguard Worker     LOG(ERROR) << "Invalid hash algorithm in " << params.cmdline;
1515*acea8879SAndroid Build Coastguard Worker     return -1;
1516*acea8879SAndroid Build Coastguard Worker   }
1517*acea8879SAndroid Build Coastguard Worker 
1518*acea8879SAndroid Build Coastguard Worker   std::vector<unsigned char> salt;
1519*acea8879SAndroid Build Coastguard Worker   std::string salt_hex = params.tokens[params.cpos++];
1520*acea8879SAndroid Build Coastguard Worker   if (salt_hex.empty() || !HashTreeBuilder::ParseBytesArrayFromString(salt_hex, &salt)) {
1521*acea8879SAndroid Build Coastguard Worker     LOG(ERROR) << "Failed to parse salt in " << params.cmdline;
1522*acea8879SAndroid Build Coastguard Worker     return -1;
1523*acea8879SAndroid Build Coastguard Worker   }
1524*acea8879SAndroid Build Coastguard Worker 
1525*acea8879SAndroid Build Coastguard Worker   std::string expected_root_hash = params.tokens[params.cpos++];
1526*acea8879SAndroid Build Coastguard Worker   if (expected_root_hash.empty()) {
1527*acea8879SAndroid Build Coastguard Worker     LOG(ERROR) << "Invalid root hash in " << params.cmdline;
1528*acea8879SAndroid Build Coastguard Worker     return -1;
1529*acea8879SAndroid Build Coastguard Worker   }
1530*acea8879SAndroid Build Coastguard Worker 
1531*acea8879SAndroid Build Coastguard Worker   // Starts the hash_tree computation.
1532*acea8879SAndroid Build Coastguard Worker   HashTreeBuilder builder(BLOCKSIZE, hash_function);
1533*acea8879SAndroid Build Coastguard Worker   if (!builder.Initialize(static_cast<int64_t>(source_ranges.blocks()) * BLOCKSIZE, salt)) {
1534*acea8879SAndroid Build Coastguard Worker     LOG(ERROR) << "Failed to initialize hash tree computation, source " << source_ranges.ToString()
1535*acea8879SAndroid Build Coastguard Worker                << ", salt " << salt_hex;
1536*acea8879SAndroid Build Coastguard Worker     return -1;
1537*acea8879SAndroid Build Coastguard Worker   }
1538*acea8879SAndroid Build Coastguard Worker 
1539*acea8879SAndroid Build Coastguard Worker   // Iterates through every block in the source_ranges and updates the hash tree structure
1540*acea8879SAndroid Build Coastguard Worker   // accordingly.
1541*acea8879SAndroid Build Coastguard Worker   for (const auto& [begin, end] : source_ranges) {
1542*acea8879SAndroid Build Coastguard Worker     uint8_t buffer[BLOCKSIZE];
1543*acea8879SAndroid Build Coastguard Worker     if (!check_lseek(params.fd, static_cast<off64_t>(begin) * BLOCKSIZE, SEEK_SET)) {
1544*acea8879SAndroid Build Coastguard Worker       PLOG(ERROR) << "Failed to seek to block: " << begin;
1545*acea8879SAndroid Build Coastguard Worker       return -1;
1546*acea8879SAndroid Build Coastguard Worker     }
1547*acea8879SAndroid Build Coastguard Worker 
1548*acea8879SAndroid Build Coastguard Worker     for (size_t i = begin; i < end; i++) {
1549*acea8879SAndroid Build Coastguard Worker       if (!android::base::ReadFully(params.fd, buffer, BLOCKSIZE)) {
1550*acea8879SAndroid Build Coastguard Worker         failure_type = errno == EIO ? kEioFailure : kFreadFailure;
1551*acea8879SAndroid Build Coastguard Worker         LOG(ERROR) << "Failed to read data in " << begin << ":" << end;
1552*acea8879SAndroid Build Coastguard Worker         return -1;
1553*acea8879SAndroid Build Coastguard Worker       }
1554*acea8879SAndroid Build Coastguard Worker 
1555*acea8879SAndroid Build Coastguard Worker       if (!builder.Update(reinterpret_cast<unsigned char*>(buffer), BLOCKSIZE)) {
1556*acea8879SAndroid Build Coastguard Worker         LOG(ERROR) << "Failed to update hash tree builder";
1557*acea8879SAndroid Build Coastguard Worker         return -1;
1558*acea8879SAndroid Build Coastguard Worker       }
1559*acea8879SAndroid Build Coastguard Worker     }
1560*acea8879SAndroid Build Coastguard Worker   }
1561*acea8879SAndroid Build Coastguard Worker 
1562*acea8879SAndroid Build Coastguard Worker   if (!builder.BuildHashTree()) {
1563*acea8879SAndroid Build Coastguard Worker     LOG(ERROR) << "Failed to build hash tree";
1564*acea8879SAndroid Build Coastguard Worker     return -1;
1565*acea8879SAndroid Build Coastguard Worker   }
1566*acea8879SAndroid Build Coastguard Worker 
1567*acea8879SAndroid Build Coastguard Worker   std::string root_hash_hex = HashTreeBuilder::BytesArrayToString(builder.root_hash());
1568*acea8879SAndroid Build Coastguard Worker   if (root_hash_hex != expected_root_hash) {
1569*acea8879SAndroid Build Coastguard Worker     LOG(ERROR) << "Root hash of the verity hash tree doesn't match the expected value. Expected: "
1570*acea8879SAndroid Build Coastguard Worker                << expected_root_hash << ", actual: " << root_hash_hex;
1571*acea8879SAndroid Build Coastguard Worker     return -1;
1572*acea8879SAndroid Build Coastguard Worker   }
1573*acea8879SAndroid Build Coastguard Worker 
1574*acea8879SAndroid Build Coastguard Worker   uint64_t write_offset = static_cast<uint64_t>(hash_tree_ranges.GetBlockNumber(0)) * BLOCKSIZE;
1575*acea8879SAndroid Build Coastguard Worker   if (params.canwrite && !builder.WriteHashTreeToFd(params.fd, write_offset)) {
1576*acea8879SAndroid Build Coastguard Worker     LOG(ERROR) << "Failed to write hash tree to output";
1577*acea8879SAndroid Build Coastguard Worker     return -1;
1578*acea8879SAndroid Build Coastguard Worker   }
1579*acea8879SAndroid Build Coastguard Worker 
1580*acea8879SAndroid Build Coastguard Worker   // TODO(xunchang) validates the written bytes
1581*acea8879SAndroid Build Coastguard Worker 
1582*acea8879SAndroid Build Coastguard Worker   return 0;
1583*acea8879SAndroid Build Coastguard Worker }
1584*acea8879SAndroid Build Coastguard Worker 
1585*acea8879SAndroid Build Coastguard Worker using CommandFunction = std::function<int(CommandParameters&)>;
1586*acea8879SAndroid Build Coastguard Worker 
1587*acea8879SAndroid Build Coastguard Worker using CommandMap = std::unordered_map<Command::Type, CommandFunction>;
1588*acea8879SAndroid Build Coastguard Worker 
Sha1DevicePath(const std::string & path,uint8_t digest[SHA_DIGEST_LENGTH])1589*acea8879SAndroid Build Coastguard Worker static bool Sha1DevicePath(const std::string& path, uint8_t digest[SHA_DIGEST_LENGTH]) {
1590*acea8879SAndroid Build Coastguard Worker   auto device_name = android::base::Basename(path);
1591*acea8879SAndroid Build Coastguard Worker   auto dm_target_name_path = "/sys/block/" + device_name + "/dm/name";
1592*acea8879SAndroid Build Coastguard Worker 
1593*acea8879SAndroid Build Coastguard Worker   struct stat sb;
1594*acea8879SAndroid Build Coastguard Worker   if (stat(dm_target_name_path.c_str(), &sb) == 0) {
1595*acea8879SAndroid Build Coastguard Worker     // This is a device mapper target. Use partition name as part of the hash instead. Do not
1596*acea8879SAndroid Build Coastguard Worker     // include extents as part of the hash, because the size of a partition may be shrunk after
1597*acea8879SAndroid Build Coastguard Worker     // the patches are applied.
1598*acea8879SAndroid Build Coastguard Worker     std::string dm_target_name;
1599*acea8879SAndroid Build Coastguard Worker     if (!android::base::ReadFileToString(dm_target_name_path, &dm_target_name)) {
1600*acea8879SAndroid Build Coastguard Worker       PLOG(ERROR) << "Cannot read " << dm_target_name_path;
1601*acea8879SAndroid Build Coastguard Worker       return false;
1602*acea8879SAndroid Build Coastguard Worker     }
1603*acea8879SAndroid Build Coastguard Worker     SHA1(reinterpret_cast<const uint8_t*>(dm_target_name.data()), dm_target_name.size(), digest);
1604*acea8879SAndroid Build Coastguard Worker     return true;
1605*acea8879SAndroid Build Coastguard Worker   }
1606*acea8879SAndroid Build Coastguard Worker 
1607*acea8879SAndroid Build Coastguard Worker   if (errno != ENOENT) {
1608*acea8879SAndroid Build Coastguard Worker     // This is a device mapper target, but its name cannot be retrieved.
1609*acea8879SAndroid Build Coastguard Worker     PLOG(ERROR) << "Cannot get dm target name for " << path;
1610*acea8879SAndroid Build Coastguard Worker     return false;
1611*acea8879SAndroid Build Coastguard Worker   }
1612*acea8879SAndroid Build Coastguard Worker 
1613*acea8879SAndroid Build Coastguard Worker   // This doesn't appear to be a device mapper target, but if its name starts with dm-, something
1614*acea8879SAndroid Build Coastguard Worker   // else might have gone wrong.
1615*acea8879SAndroid Build Coastguard Worker   if (android::base::StartsWith(device_name, "dm-")) {
1616*acea8879SAndroid Build Coastguard Worker     LOG(WARNING) << "Device " << path << " starts with dm- but is not mapped by device-mapper.";
1617*acea8879SAndroid Build Coastguard Worker   }
1618*acea8879SAndroid Build Coastguard Worker 
1619*acea8879SAndroid Build Coastguard Worker   // Stash directory should be different for each partition to avoid conflicts when updating
1620*acea8879SAndroid Build Coastguard Worker   // multiple partitions at the same time, so we use the hash of the block device name as the base
1621*acea8879SAndroid Build Coastguard Worker   // directory.
1622*acea8879SAndroid Build Coastguard Worker   SHA1(reinterpret_cast<const uint8_t*>(path.data()), path.size(), digest);
1623*acea8879SAndroid Build Coastguard Worker   return true;
1624*acea8879SAndroid Build Coastguard Worker }
1625*acea8879SAndroid Build Coastguard Worker 
PerformBlockImageUpdate(const char * name,State * state,const std::vector<std::unique_ptr<Expr>> & argv,const CommandMap & command_map,bool dryrun)1626*acea8879SAndroid Build Coastguard Worker static Value* PerformBlockImageUpdate(const char* name, State* state,
1627*acea8879SAndroid Build Coastguard Worker                                       const std::vector<std::unique_ptr<Expr>>& argv,
1628*acea8879SAndroid Build Coastguard Worker                                       const CommandMap& command_map, bool dryrun) {
1629*acea8879SAndroid Build Coastguard Worker   CommandParameters params{};
1630*acea8879SAndroid Build Coastguard Worker   stash_map.clear();
1631*acea8879SAndroid Build Coastguard Worker   params.canwrite = !dryrun;
1632*acea8879SAndroid Build Coastguard Worker 
1633*acea8879SAndroid Build Coastguard Worker   LOG(INFO) << "performing " << (dryrun ? "verification" : "update");
1634*acea8879SAndroid Build Coastguard Worker   if (state->is_retry) {
1635*acea8879SAndroid Build Coastguard Worker     is_retry = true;
1636*acea8879SAndroid Build Coastguard Worker     LOG(INFO) << "This update is a retry.";
1637*acea8879SAndroid Build Coastguard Worker   }
1638*acea8879SAndroid Build Coastguard Worker   if (argv.size() != 4) {
1639*acea8879SAndroid Build Coastguard Worker     ErrorAbort(state, kArgsParsingFailure, "block_image_update expects 4 arguments, got %zu",
1640*acea8879SAndroid Build Coastguard Worker                argv.size());
1641*acea8879SAndroid Build Coastguard Worker     return StringValue("");
1642*acea8879SAndroid Build Coastguard Worker   }
1643*acea8879SAndroid Build Coastguard Worker 
1644*acea8879SAndroid Build Coastguard Worker   std::vector<std::unique_ptr<Value>> args;
1645*acea8879SAndroid Build Coastguard Worker   if (!ReadValueArgs(state, argv, &args)) {
1646*acea8879SAndroid Build Coastguard Worker     return nullptr;
1647*acea8879SAndroid Build Coastguard Worker   }
1648*acea8879SAndroid Build Coastguard Worker 
1649*acea8879SAndroid Build Coastguard Worker   // args:
1650*acea8879SAndroid Build Coastguard Worker   //   - block device (or file) to modify in-place
1651*acea8879SAndroid Build Coastguard Worker   //   - transfer list (blob)
1652*acea8879SAndroid Build Coastguard Worker   //   - new data stream (filename within package.zip)
1653*acea8879SAndroid Build Coastguard Worker   //   - patch stream (filename within package.zip, must be uncompressed)
1654*acea8879SAndroid Build Coastguard Worker   const std::unique_ptr<Value>& blockdev_filename = args[0];
1655*acea8879SAndroid Build Coastguard Worker   const std::unique_ptr<Value>& transfer_list_value = args[1];
1656*acea8879SAndroid Build Coastguard Worker   const std::unique_ptr<Value>& new_data_fn = args[2];
1657*acea8879SAndroid Build Coastguard Worker   const std::unique_ptr<Value>& patch_data_fn = args[3];
1658*acea8879SAndroid Build Coastguard Worker 
1659*acea8879SAndroid Build Coastguard Worker   if (blockdev_filename->type != Value::Type::STRING) {
1660*acea8879SAndroid Build Coastguard Worker     ErrorAbort(state, kArgsParsingFailure, "blockdev_filename argument to %s must be string", name);
1661*acea8879SAndroid Build Coastguard Worker     return StringValue("");
1662*acea8879SAndroid Build Coastguard Worker   }
1663*acea8879SAndroid Build Coastguard Worker   if (transfer_list_value->type != Value::Type::BLOB) {
1664*acea8879SAndroid Build Coastguard Worker     ErrorAbort(state, kArgsParsingFailure, "transfer_list argument to %s must be blob", name);
1665*acea8879SAndroid Build Coastguard Worker     return StringValue("");
1666*acea8879SAndroid Build Coastguard Worker   }
1667*acea8879SAndroid Build Coastguard Worker   if (new_data_fn->type != Value::Type::STRING) {
1668*acea8879SAndroid Build Coastguard Worker     ErrorAbort(state, kArgsParsingFailure, "new_data_fn argument to %s must be string", name);
1669*acea8879SAndroid Build Coastguard Worker     return StringValue("");
1670*acea8879SAndroid Build Coastguard Worker   }
1671*acea8879SAndroid Build Coastguard Worker   if (patch_data_fn->type != Value::Type::STRING) {
1672*acea8879SAndroid Build Coastguard Worker     ErrorAbort(state, kArgsParsingFailure, "patch_data_fn argument to %s must be string", name);
1673*acea8879SAndroid Build Coastguard Worker     return StringValue("");
1674*acea8879SAndroid Build Coastguard Worker   }
1675*acea8879SAndroid Build Coastguard Worker 
1676*acea8879SAndroid Build Coastguard Worker   auto updater = state->updater;
1677*acea8879SAndroid Build Coastguard Worker   auto block_device_path = updater->FindBlockDeviceName(blockdev_filename->data);
1678*acea8879SAndroid Build Coastguard Worker   if (block_device_path.empty()) {
1679*acea8879SAndroid Build Coastguard Worker     LOG(ERROR) << "Block device path for " << blockdev_filename->data << " not found. " << name
1680*acea8879SAndroid Build Coastguard Worker                << " failed.";
1681*acea8879SAndroid Build Coastguard Worker     return StringValue("");
1682*acea8879SAndroid Build Coastguard Worker   }
1683*acea8879SAndroid Build Coastguard Worker 
1684*acea8879SAndroid Build Coastguard Worker   ZipArchiveHandle za = updater->GetPackageHandle();
1685*acea8879SAndroid Build Coastguard Worker   if (za == nullptr) {
1686*acea8879SAndroid Build Coastguard Worker     return StringValue("");
1687*acea8879SAndroid Build Coastguard Worker   }
1688*acea8879SAndroid Build Coastguard Worker 
1689*acea8879SAndroid Build Coastguard Worker   std::string_view path_data(patch_data_fn->data);
1690*acea8879SAndroid Build Coastguard Worker   ZipEntry64 patch_entry;
1691*acea8879SAndroid Build Coastguard Worker   if (FindEntry(za, path_data, &patch_entry) != 0) {
1692*acea8879SAndroid Build Coastguard Worker     LOG(ERROR) << name << "(): no file \"" << patch_data_fn->data << "\" in package";
1693*acea8879SAndroid Build Coastguard Worker     return StringValue("");
1694*acea8879SAndroid Build Coastguard Worker   }
1695*acea8879SAndroid Build Coastguard Worker   params.patch_start = updater->GetMappedPackageAddress() + patch_entry.offset;
1696*acea8879SAndroid Build Coastguard Worker 
1697*acea8879SAndroid Build Coastguard Worker   std::string_view new_data(new_data_fn->data);
1698*acea8879SAndroid Build Coastguard Worker   ZipEntry64 new_entry;
1699*acea8879SAndroid Build Coastguard Worker   if (FindEntry(za, new_data, &new_entry) != 0) {
1700*acea8879SAndroid Build Coastguard Worker     LOG(ERROR) << name << "(): no file \"" << new_data_fn->data << "\" in package";
1701*acea8879SAndroid Build Coastguard Worker     return StringValue("");
1702*acea8879SAndroid Build Coastguard Worker   }
1703*acea8879SAndroid Build Coastguard Worker 
1704*acea8879SAndroid Build Coastguard Worker   params.fd.reset(TEMP_FAILURE_RETRY(open(block_device_path.c_str(), O_RDWR)));
1705*acea8879SAndroid Build Coastguard Worker   if (params.fd == -1) {
1706*acea8879SAndroid Build Coastguard Worker     failure_type = errno == EIO ? kEioFailure : kFileOpenFailure;
1707*acea8879SAndroid Build Coastguard Worker     PLOG(ERROR) << "open \"" << block_device_path << "\" failed";
1708*acea8879SAndroid Build Coastguard Worker     return StringValue("");
1709*acea8879SAndroid Build Coastguard Worker   }
1710*acea8879SAndroid Build Coastguard Worker 
1711*acea8879SAndroid Build Coastguard Worker   uint8_t digest[SHA_DIGEST_LENGTH];
1712*acea8879SAndroid Build Coastguard Worker   if (!Sha1DevicePath(block_device_path, digest)) {
1713*acea8879SAndroid Build Coastguard Worker     return StringValue("");
1714*acea8879SAndroid Build Coastguard Worker   }
1715*acea8879SAndroid Build Coastguard Worker   params.stashbase = print_sha1(digest);
1716*acea8879SAndroid Build Coastguard Worker 
1717*acea8879SAndroid Build Coastguard Worker   // Possibly do return early on retry, by checking the marker. If the update on this partition has
1718*acea8879SAndroid Build Coastguard Worker   // been finished (but interrupted at a later point), there could be leftover on /cache that would
1719*acea8879SAndroid Build Coastguard Worker   // fail the no-op retry.
1720*acea8879SAndroid Build Coastguard Worker   std::string updated_marker = GetStashFileName(params.stashbase + ".UPDATED", "", "");
1721*acea8879SAndroid Build Coastguard Worker   if (is_retry) {
1722*acea8879SAndroid Build Coastguard Worker     struct stat sb;
1723*acea8879SAndroid Build Coastguard Worker     int result = stat(updated_marker.c_str(), &sb);
1724*acea8879SAndroid Build Coastguard Worker     if (result == 0) {
1725*acea8879SAndroid Build Coastguard Worker       LOG(INFO) << "Skipping already updated partition " << block_device_path << " based on marker";
1726*acea8879SAndroid Build Coastguard Worker       return StringValue("t");
1727*acea8879SAndroid Build Coastguard Worker     }
1728*acea8879SAndroid Build Coastguard Worker   } else {
1729*acea8879SAndroid Build Coastguard Worker     // Delete the obsolete marker if any.
1730*acea8879SAndroid Build Coastguard Worker     std::string err;
1731*acea8879SAndroid Build Coastguard Worker     if (!android::base::RemoveFileIfExists(updated_marker, &err)) {
1732*acea8879SAndroid Build Coastguard Worker       LOG(ERROR) << "Failed to remove partition updated marker " << updated_marker << ": " << err;
1733*acea8879SAndroid Build Coastguard Worker       return StringValue("");
1734*acea8879SAndroid Build Coastguard Worker     }
1735*acea8879SAndroid Build Coastguard Worker   }
1736*acea8879SAndroid Build Coastguard Worker 
1737*acea8879SAndroid Build Coastguard Worker   static constexpr size_t kTransferListHeaderLines = 4;
1738*acea8879SAndroid Build Coastguard Worker   std::vector<std::string> lines = android::base::Split(transfer_list_value->data, "\n");
1739*acea8879SAndroid Build Coastguard Worker   if (lines.size() < kTransferListHeaderLines) {
1740*acea8879SAndroid Build Coastguard Worker     ErrorAbort(state, kArgsParsingFailure, "too few lines in the transfer list [%zu]",
1741*acea8879SAndroid Build Coastguard Worker                lines.size());
1742*acea8879SAndroid Build Coastguard Worker     return StringValue("");
1743*acea8879SAndroid Build Coastguard Worker   }
1744*acea8879SAndroid Build Coastguard Worker 
1745*acea8879SAndroid Build Coastguard Worker   // First line in transfer list is the version number.
1746*acea8879SAndroid Build Coastguard Worker   if (!android::base::ParseInt(lines[0], &params.version, 3, 4)) {
1747*acea8879SAndroid Build Coastguard Worker     LOG(ERROR) << "unexpected transfer list version [" << lines[0] << "]";
1748*acea8879SAndroid Build Coastguard Worker     return StringValue("");
1749*acea8879SAndroid Build Coastguard Worker   }
1750*acea8879SAndroid Build Coastguard Worker 
1751*acea8879SAndroid Build Coastguard Worker   LOG(INFO) << "blockimg version is " << params.version;
1752*acea8879SAndroid Build Coastguard Worker 
1753*acea8879SAndroid Build Coastguard Worker   // Second line in transfer list is the total number of blocks we expect to write.
1754*acea8879SAndroid Build Coastguard Worker   size_t total_blocks;
1755*acea8879SAndroid Build Coastguard Worker   if (!android::base::ParseUint(lines[1], &total_blocks)) {
1756*acea8879SAndroid Build Coastguard Worker     ErrorAbort(state, kArgsParsingFailure, "unexpected block count [%s]", lines[1].c_str());
1757*acea8879SAndroid Build Coastguard Worker     return StringValue("");
1758*acea8879SAndroid Build Coastguard Worker   }
1759*acea8879SAndroid Build Coastguard Worker 
1760*acea8879SAndroid Build Coastguard Worker   if (total_blocks == 0) {
1761*acea8879SAndroid Build Coastguard Worker     return StringValue("t");
1762*acea8879SAndroid Build Coastguard Worker   }
1763*acea8879SAndroid Build Coastguard Worker 
1764*acea8879SAndroid Build Coastguard Worker   // Third line is how many stash entries are needed simultaneously.
1765*acea8879SAndroid Build Coastguard Worker   LOG(INFO) << "maximum stash entries " << lines[2];
1766*acea8879SAndroid Build Coastguard Worker 
1767*acea8879SAndroid Build Coastguard Worker   // Fourth line is the maximum number of blocks that will be stashed simultaneously
1768*acea8879SAndroid Build Coastguard Worker   size_t stash_max_blocks;
1769*acea8879SAndroid Build Coastguard Worker   if (!android::base::ParseUint(lines[3], &stash_max_blocks)) {
1770*acea8879SAndroid Build Coastguard Worker     ErrorAbort(state, kArgsParsingFailure, "unexpected maximum stash blocks [%s]",
1771*acea8879SAndroid Build Coastguard Worker                lines[3].c_str());
1772*acea8879SAndroid Build Coastguard Worker     return StringValue("");
1773*acea8879SAndroid Build Coastguard Worker   }
1774*acea8879SAndroid Build Coastguard Worker 
1775*acea8879SAndroid Build Coastguard Worker   int res = CreateStash(state, stash_max_blocks, params.stashbase);
1776*acea8879SAndroid Build Coastguard Worker   if (res == -1) {
1777*acea8879SAndroid Build Coastguard Worker     return StringValue("");
1778*acea8879SAndroid Build Coastguard Worker   }
1779*acea8879SAndroid Build Coastguard Worker   params.createdstash = res;
1780*acea8879SAndroid Build Coastguard Worker 
1781*acea8879SAndroid Build Coastguard Worker   // Set up the new data writer.
1782*acea8879SAndroid Build Coastguard Worker   if (params.canwrite) {
1783*acea8879SAndroid Build Coastguard Worker     params.nti.za = za;
1784*acea8879SAndroid Build Coastguard Worker     params.nti.entry = new_entry;
1785*acea8879SAndroid Build Coastguard Worker     params.nti.brotli_compressed = android::base::EndsWith(new_data_fn->data, ".br");
1786*acea8879SAndroid Build Coastguard Worker     if (params.nti.brotli_compressed) {
1787*acea8879SAndroid Build Coastguard Worker       // Initialize brotli decoder state.
1788*acea8879SAndroid Build Coastguard Worker       params.nti.brotli_decoder_state = BrotliDecoderCreateInstance(nullptr, nullptr, nullptr);
1789*acea8879SAndroid Build Coastguard Worker     }
1790*acea8879SAndroid Build Coastguard Worker     params.nti.receiver_available = true;
1791*acea8879SAndroid Build Coastguard Worker 
1792*acea8879SAndroid Build Coastguard Worker     pthread_mutex_init(&params.nti.mu, nullptr);
1793*acea8879SAndroid Build Coastguard Worker     pthread_cond_init(&params.nti.cv, nullptr);
1794*acea8879SAndroid Build Coastguard Worker     pthread_attr_t attr;
1795*acea8879SAndroid Build Coastguard Worker     pthread_attr_init(&attr);
1796*acea8879SAndroid Build Coastguard Worker     pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
1797*acea8879SAndroid Build Coastguard Worker 
1798*acea8879SAndroid Build Coastguard Worker     int error = pthread_create(&params.thread, &attr, unzip_new_data, &params.nti);
1799*acea8879SAndroid Build Coastguard Worker     if (error != 0) {
1800*acea8879SAndroid Build Coastguard Worker       LOG(ERROR) << "pthread_create failed: " << strerror(error);
1801*acea8879SAndroid Build Coastguard Worker       return StringValue("");
1802*acea8879SAndroid Build Coastguard Worker     }
1803*acea8879SAndroid Build Coastguard Worker   }
1804*acea8879SAndroid Build Coastguard Worker 
1805*acea8879SAndroid Build Coastguard Worker   // When performing an update, save the index and cmdline of the current command into the
1806*acea8879SAndroid Build Coastguard Worker   // last_command_file.
1807*acea8879SAndroid Build Coastguard Worker   // Upon resuming an update, read the saved index first; then
1808*acea8879SAndroid Build Coastguard Worker   //   1. In verification mode, check if the 'move' or 'diff' commands before the saved index has
1809*acea8879SAndroid Build Coastguard Worker   //      the expected target blocks already. If not, these commands cannot be skipped and we need
1810*acea8879SAndroid Build Coastguard Worker   //      to attempt to execute them again. Therefore, we will delete the last_command_file so that
1811*acea8879SAndroid Build Coastguard Worker   //      the update will resume from the start of the transfer list.
1812*acea8879SAndroid Build Coastguard Worker   //   2. In update mode, skip all commands before the saved index. Therefore, we can avoid deleting
1813*acea8879SAndroid Build Coastguard Worker   //      stashes with duplicate id unintentionally (b/69858743); and also speed up the update.
1814*acea8879SAndroid Build Coastguard Worker   // If an update succeeds or is unresumable, delete the last_command_file.
1815*acea8879SAndroid Build Coastguard Worker   bool skip_executed_command = true;
1816*acea8879SAndroid Build Coastguard Worker   size_t saved_last_command_index;
1817*acea8879SAndroid Build Coastguard Worker   if (!ParseLastCommandFile(&saved_last_command_index)) {
1818*acea8879SAndroid Build Coastguard Worker     DeleteLastCommandFile();
1819*acea8879SAndroid Build Coastguard Worker     // We failed to parse the last command. Disallow skipping executed commands.
1820*acea8879SAndroid Build Coastguard Worker     skip_executed_command = false;
1821*acea8879SAndroid Build Coastguard Worker   }
1822*acea8879SAndroid Build Coastguard Worker 
1823*acea8879SAndroid Build Coastguard Worker   int rc = -1;
1824*acea8879SAndroid Build Coastguard Worker 
1825*acea8879SAndroid Build Coastguard Worker   // Subsequent lines are all individual transfer commands
1826*acea8879SAndroid Build Coastguard Worker   for (size_t i = kTransferListHeaderLines; i < lines.size(); i++) {
1827*acea8879SAndroid Build Coastguard Worker     const std::string& line = lines[i];
1828*acea8879SAndroid Build Coastguard Worker     if (line.empty()) continue;
1829*acea8879SAndroid Build Coastguard Worker 
1830*acea8879SAndroid Build Coastguard Worker     size_t cmdindex = i - kTransferListHeaderLines;
1831*acea8879SAndroid Build Coastguard Worker     params.tokens = android::base::Split(line, " ");
1832*acea8879SAndroid Build Coastguard Worker     params.cpos = 0;
1833*acea8879SAndroid Build Coastguard Worker     params.cmdname = params.tokens[params.cpos++];
1834*acea8879SAndroid Build Coastguard Worker     params.cmdline = line;
1835*acea8879SAndroid Build Coastguard Worker     params.target_verified = false;
1836*acea8879SAndroid Build Coastguard Worker 
1837*acea8879SAndroid Build Coastguard Worker     Command::Type cmd_type = Command::ParseType(params.cmdname);
1838*acea8879SAndroid Build Coastguard Worker     if (cmd_type == Command::Type::LAST) {
1839*acea8879SAndroid Build Coastguard Worker       LOG(ERROR) << "unexpected command [" << params.cmdname << "]";
1840*acea8879SAndroid Build Coastguard Worker       goto pbiudone;
1841*acea8879SAndroid Build Coastguard Worker     }
1842*acea8879SAndroid Build Coastguard Worker 
1843*acea8879SAndroid Build Coastguard Worker     const CommandFunction& performer = command_map.at(cmd_type);
1844*acea8879SAndroid Build Coastguard Worker 
1845*acea8879SAndroid Build Coastguard Worker     // Skip the command if we explicitly set the corresponding function pointer to nullptr, e.g.
1846*acea8879SAndroid Build Coastguard Worker     // "erase" during block_image_verify.
1847*acea8879SAndroid Build Coastguard Worker     if (performer == nullptr) {
1848*acea8879SAndroid Build Coastguard Worker       LOG(DEBUG) << "skip executing command [" << line << "]";
1849*acea8879SAndroid Build Coastguard Worker       continue;
1850*acea8879SAndroid Build Coastguard Worker     }
1851*acea8879SAndroid Build Coastguard Worker 
1852*acea8879SAndroid Build Coastguard Worker     // Skip all commands before the saved last command index when resuming an update, except for
1853*acea8879SAndroid Build Coastguard Worker     // "new" command. Because new commands read in the data sequentially.
1854*acea8879SAndroid Build Coastguard Worker     if (params.canwrite && skip_executed_command && cmdindex <= saved_last_command_index &&
1855*acea8879SAndroid Build Coastguard Worker         cmd_type != Command::Type::NEW) {
1856*acea8879SAndroid Build Coastguard Worker       LOG(INFO) << "Skipping already executed command: " << cmdindex
1857*acea8879SAndroid Build Coastguard Worker                 << ", last executed command for previous update: " << saved_last_command_index;
1858*acea8879SAndroid Build Coastguard Worker       continue;
1859*acea8879SAndroid Build Coastguard Worker     }
1860*acea8879SAndroid Build Coastguard Worker 
1861*acea8879SAndroid Build Coastguard Worker     if (performer(params) == -1) {
1862*acea8879SAndroid Build Coastguard Worker       LOG(ERROR) << "failed to execute command [" << line << "]";
1863*acea8879SAndroid Build Coastguard Worker       if (cmd_type == Command::Type::COMPUTE_HASH_TREE && failure_type == kNoCause) {
1864*acea8879SAndroid Build Coastguard Worker         failure_type = kHashTreeComputationFailure;
1865*acea8879SAndroid Build Coastguard Worker       }
1866*acea8879SAndroid Build Coastguard Worker       goto pbiudone;
1867*acea8879SAndroid Build Coastguard Worker     }
1868*acea8879SAndroid Build Coastguard Worker 
1869*acea8879SAndroid Build Coastguard Worker     // In verify mode, check if the commands before the saved last_command_index have been executed
1870*acea8879SAndroid Build Coastguard Worker     // correctly. If some target blocks have unexpected contents, delete the last command file so
1871*acea8879SAndroid Build Coastguard Worker     // that we will resume the update from the first command in the transfer list.
1872*acea8879SAndroid Build Coastguard Worker     if (!params.canwrite && skip_executed_command && cmdindex <= saved_last_command_index) {
1873*acea8879SAndroid Build Coastguard Worker       // TODO(xunchang) check that the cmdline of the saved index is correct.
1874*acea8879SAndroid Build Coastguard Worker       if ((cmd_type == Command::Type::MOVE || cmd_type == Command::Type::BSDIFF ||
1875*acea8879SAndroid Build Coastguard Worker            cmd_type == Command::Type::IMGDIFF) &&
1876*acea8879SAndroid Build Coastguard Worker           !params.target_verified) {
1877*acea8879SAndroid Build Coastguard Worker         LOG(WARNING) << "Previously executed command " << saved_last_command_index << ": "
1878*acea8879SAndroid Build Coastguard Worker                      << params.cmdline << " doesn't produce expected target blocks.";
1879*acea8879SAndroid Build Coastguard Worker         skip_executed_command = false;
1880*acea8879SAndroid Build Coastguard Worker         DeleteLastCommandFile();
1881*acea8879SAndroid Build Coastguard Worker       }
1882*acea8879SAndroid Build Coastguard Worker     }
1883*acea8879SAndroid Build Coastguard Worker 
1884*acea8879SAndroid Build Coastguard Worker     if (params.canwrite) {
1885*acea8879SAndroid Build Coastguard Worker       if (fsync(params.fd) == -1) {
1886*acea8879SAndroid Build Coastguard Worker         failure_type = errno == EIO ? kEioFailure : kFsyncFailure;
1887*acea8879SAndroid Build Coastguard Worker         PLOG(ERROR) << "fsync failed";
1888*acea8879SAndroid Build Coastguard Worker         goto pbiudone;
1889*acea8879SAndroid Build Coastguard Worker       }
1890*acea8879SAndroid Build Coastguard Worker 
1891*acea8879SAndroid Build Coastguard Worker       if (!UpdateLastCommandIndex(cmdindex, params.cmdline)) {
1892*acea8879SAndroid Build Coastguard Worker         LOG(WARNING) << "Failed to update the last command file.";
1893*acea8879SAndroid Build Coastguard Worker       }
1894*acea8879SAndroid Build Coastguard Worker 
1895*acea8879SAndroid Build Coastguard Worker       updater->WriteToCommandPipe(
1896*acea8879SAndroid Build Coastguard Worker           android::base::StringPrintf("set_progress %.4f",
1897*acea8879SAndroid Build Coastguard Worker                                       static_cast<double>(params.written) / total_blocks),
1898*acea8879SAndroid Build Coastguard Worker           true);
1899*acea8879SAndroid Build Coastguard Worker     }
1900*acea8879SAndroid Build Coastguard Worker   }
1901*acea8879SAndroid Build Coastguard Worker 
1902*acea8879SAndroid Build Coastguard Worker   rc = 0;
1903*acea8879SAndroid Build Coastguard Worker 
1904*acea8879SAndroid Build Coastguard Worker pbiudone:
1905*acea8879SAndroid Build Coastguard Worker   if (params.canwrite) {
1906*acea8879SAndroid Build Coastguard Worker     pthread_mutex_lock(&params.nti.mu);
1907*acea8879SAndroid Build Coastguard Worker     if (params.nti.receiver_available) {
1908*acea8879SAndroid Build Coastguard Worker       LOG(WARNING) << "new data receiver is still available after executing all commands.";
1909*acea8879SAndroid Build Coastguard Worker     }
1910*acea8879SAndroid Build Coastguard Worker     params.nti.receiver_available = false;
1911*acea8879SAndroid Build Coastguard Worker     pthread_cond_broadcast(&params.nti.cv);
1912*acea8879SAndroid Build Coastguard Worker     pthread_mutex_unlock(&params.nti.mu);
1913*acea8879SAndroid Build Coastguard Worker     int ret = pthread_join(params.thread, nullptr);
1914*acea8879SAndroid Build Coastguard Worker     if (ret != 0) {
1915*acea8879SAndroid Build Coastguard Worker       LOG(WARNING) << "pthread join returned with " << strerror(ret);
1916*acea8879SAndroid Build Coastguard Worker     }
1917*acea8879SAndroid Build Coastguard Worker 
1918*acea8879SAndroid Build Coastguard Worker     if (rc == 0) {
1919*acea8879SAndroid Build Coastguard Worker       LOG(INFO) << "wrote " << params.written << " blocks; expected " << total_blocks;
1920*acea8879SAndroid Build Coastguard Worker       LOG(INFO) << "stashed " << params.stashed << " blocks";
1921*acea8879SAndroid Build Coastguard Worker       LOG(INFO) << "max alloc needed was " << params.buffer.size();
1922*acea8879SAndroid Build Coastguard Worker 
1923*acea8879SAndroid Build Coastguard Worker       const char* partition = strrchr(block_device_path.c_str(), '/');
1924*acea8879SAndroid Build Coastguard Worker       if (partition != nullptr && *(partition + 1) != 0) {
1925*acea8879SAndroid Build Coastguard Worker         updater->WriteToCommandPipe(
1926*acea8879SAndroid Build Coastguard Worker             android::base::StringPrintf("log bytes_written_%s: %" PRIu64, partition + 1,
1927*acea8879SAndroid Build Coastguard Worker                                         static_cast<uint64_t>(params.written) * BLOCKSIZE));
1928*acea8879SAndroid Build Coastguard Worker         updater->WriteToCommandPipe(
1929*acea8879SAndroid Build Coastguard Worker             android::base::StringPrintf("log bytes_stashed_%s: %" PRIu64, partition + 1,
1930*acea8879SAndroid Build Coastguard Worker                                         static_cast<uint64_t>(params.stashed) * BLOCKSIZE),
1931*acea8879SAndroid Build Coastguard Worker             true);
1932*acea8879SAndroid Build Coastguard Worker       }
1933*acea8879SAndroid Build Coastguard Worker       // Delete stash only after successfully completing the update, as it may contain blocks needed
1934*acea8879SAndroid Build Coastguard Worker       // to complete the update later.
1935*acea8879SAndroid Build Coastguard Worker       DeleteStash(params.stashbase);
1936*acea8879SAndroid Build Coastguard Worker       DeleteLastCommandFile();
1937*acea8879SAndroid Build Coastguard Worker 
1938*acea8879SAndroid Build Coastguard Worker       // Create a marker on /cache partition, which allows skipping the update on this partition on
1939*acea8879SAndroid Build Coastguard Worker       // retry. The marker will be removed once booting into normal boot, or before starting next
1940*acea8879SAndroid Build Coastguard Worker       // fresh install.
1941*acea8879SAndroid Build Coastguard Worker       if (!SetUpdatedMarker(updated_marker)) {
1942*acea8879SAndroid Build Coastguard Worker         LOG(WARNING) << "Failed to set updated marker; continuing";
1943*acea8879SAndroid Build Coastguard Worker       }
1944*acea8879SAndroid Build Coastguard Worker     }
1945*acea8879SAndroid Build Coastguard Worker 
1946*acea8879SAndroid Build Coastguard Worker     pthread_mutex_destroy(&params.nti.mu);
1947*acea8879SAndroid Build Coastguard Worker     pthread_cond_destroy(&params.nti.cv);
1948*acea8879SAndroid Build Coastguard Worker   } else if (rc == 0) {
1949*acea8879SAndroid Build Coastguard Worker     LOG(INFO) << "verified partition contents; update may be resumed";
1950*acea8879SAndroid Build Coastguard Worker   }
1951*acea8879SAndroid Build Coastguard Worker 
1952*acea8879SAndroid Build Coastguard Worker   if (fsync(params.fd) == -1) {
1953*acea8879SAndroid Build Coastguard Worker     failure_type = errno == EIO ? kEioFailure : kFsyncFailure;
1954*acea8879SAndroid Build Coastguard Worker     PLOG(ERROR) << "fsync failed";
1955*acea8879SAndroid Build Coastguard Worker   }
1956*acea8879SAndroid Build Coastguard Worker   // params.fd will be automatically closed because it's a unique_fd.
1957*acea8879SAndroid Build Coastguard Worker 
1958*acea8879SAndroid Build Coastguard Worker   if (params.nti.brotli_decoder_state != nullptr) {
1959*acea8879SAndroid Build Coastguard Worker     BrotliDecoderDestroyInstance(params.nti.brotli_decoder_state);
1960*acea8879SAndroid Build Coastguard Worker   }
1961*acea8879SAndroid Build Coastguard Worker 
1962*acea8879SAndroid Build Coastguard Worker   // Delete the last command file if the update cannot be resumed.
1963*acea8879SAndroid Build Coastguard Worker   if (params.isunresumable) {
1964*acea8879SAndroid Build Coastguard Worker     DeleteLastCommandFile();
1965*acea8879SAndroid Build Coastguard Worker   }
1966*acea8879SAndroid Build Coastguard Worker 
1967*acea8879SAndroid Build Coastguard Worker   // Only delete the stash if the update cannot be resumed, or it's a verification run and we
1968*acea8879SAndroid Build Coastguard Worker   // created the stash.
1969*acea8879SAndroid Build Coastguard Worker   if (params.isunresumable || (!params.canwrite && params.createdstash)) {
1970*acea8879SAndroid Build Coastguard Worker     DeleteStash(params.stashbase);
1971*acea8879SAndroid Build Coastguard Worker   }
1972*acea8879SAndroid Build Coastguard Worker 
1973*acea8879SAndroid Build Coastguard Worker   if (failure_type != kNoCause && state->cause_code == kNoCause) {
1974*acea8879SAndroid Build Coastguard Worker     state->cause_code = failure_type;
1975*acea8879SAndroid Build Coastguard Worker   }
1976*acea8879SAndroid Build Coastguard Worker 
1977*acea8879SAndroid Build Coastguard Worker   return StringValue(rc == 0 ? "t" : "");
1978*acea8879SAndroid Build Coastguard Worker }
1979*acea8879SAndroid Build Coastguard Worker 
1980*acea8879SAndroid Build Coastguard Worker /**
1981*acea8879SAndroid Build Coastguard Worker  * The transfer list is a text file containing commands to transfer data from one place to another
1982*acea8879SAndroid Build Coastguard Worker  * on the target partition. We parse it and execute the commands in order:
1983*acea8879SAndroid Build Coastguard Worker  *
1984*acea8879SAndroid Build Coastguard Worker  *    zero [rangeset]
1985*acea8879SAndroid Build Coastguard Worker  *      - Fill the indicated blocks with zeros.
1986*acea8879SAndroid Build Coastguard Worker  *
1987*acea8879SAndroid Build Coastguard Worker  *    new [rangeset]
1988*acea8879SAndroid Build Coastguard Worker  *      - Fill the blocks with data read from the new_data file.
1989*acea8879SAndroid Build Coastguard Worker  *
1990*acea8879SAndroid Build Coastguard Worker  *    erase [rangeset]
1991*acea8879SAndroid Build Coastguard Worker  *      - Mark the given blocks as empty.
1992*acea8879SAndroid Build Coastguard Worker  *
1993*acea8879SAndroid Build Coastguard Worker  *    move <...>
1994*acea8879SAndroid Build Coastguard Worker  *    bsdiff <patchstart> <patchlen> <...>
1995*acea8879SAndroid Build Coastguard Worker  *    imgdiff <patchstart> <patchlen> <...>
1996*acea8879SAndroid Build Coastguard Worker  *      - Read the source blocks, apply a patch (or not in the case of move), write result to target
1997*acea8879SAndroid Build Coastguard Worker  *      blocks.  bsdiff or imgdiff specifies the type of patch; move means no patch at all.
1998*acea8879SAndroid Build Coastguard Worker  *
1999*acea8879SAndroid Build Coastguard Worker  *        See the comments in LoadSrcTgtVersion3() for a description of the <...> format.
2000*acea8879SAndroid Build Coastguard Worker  *
2001*acea8879SAndroid Build Coastguard Worker  *    stash <stash_id> <src_range>
2002*acea8879SAndroid Build Coastguard Worker  *      - Load the given source range and stash the data in the given slot of the stash table.
2003*acea8879SAndroid Build Coastguard Worker  *
2004*acea8879SAndroid Build Coastguard Worker  *    free <stash_id>
2005*acea8879SAndroid Build Coastguard Worker  *      - Free the given stash data.
2006*acea8879SAndroid Build Coastguard Worker  *
2007*acea8879SAndroid Build Coastguard Worker  * The creator of the transfer list will guarantee that no block is read (ie, used as the source for
2008*acea8879SAndroid Build Coastguard Worker  * a patch or move) after it has been written.
2009*acea8879SAndroid Build Coastguard Worker  *
2010*acea8879SAndroid Build Coastguard Worker  * The creator will guarantee that a given stash is loaded (with a stash command) before it's used
2011*acea8879SAndroid Build Coastguard Worker  * in a move/bsdiff/imgdiff command.
2012*acea8879SAndroid Build Coastguard Worker  *
2013*acea8879SAndroid Build Coastguard Worker  * Within one command the source and target ranges may overlap so in general we need to read the
2014*acea8879SAndroid Build Coastguard Worker  * entire source into memory before writing anything to the target blocks.
2015*acea8879SAndroid Build Coastguard Worker  *
2016*acea8879SAndroid Build Coastguard Worker  * All the patch data is concatenated into one patch_data file in the update package. It must be
2017*acea8879SAndroid Build Coastguard Worker  * stored uncompressed because we memory-map it in directly from the archive. (Since patches are
2018*acea8879SAndroid Build Coastguard Worker  * already compressed, we lose very little by not compressing their concatenation.)
2019*acea8879SAndroid Build Coastguard Worker  *
2020*acea8879SAndroid Build Coastguard Worker  * Commands that read data from the partition (i.e. move/bsdiff/imgdiff/stash) have one or more
2021*acea8879SAndroid Build Coastguard Worker  * additional hashes before the range parameters, which are used to check if the command has already
2022*acea8879SAndroid Build Coastguard Worker  * been completed and verify the integrity of the source data.
2023*acea8879SAndroid Build Coastguard Worker  */
BlockImageVerifyFn(const char * name,State * state,const std::vector<std::unique_ptr<Expr>> & argv)2024*acea8879SAndroid Build Coastguard Worker Value* BlockImageVerifyFn(const char* name, State* state,
2025*acea8879SAndroid Build Coastguard Worker                           const std::vector<std::unique_ptr<Expr>>& argv) {
2026*acea8879SAndroid Build Coastguard Worker   // Commands which are not allowed are set to nullptr to skip them completely.
2027*acea8879SAndroid Build Coastguard Worker   const CommandMap command_map{
2028*acea8879SAndroid Build Coastguard Worker     // clang-format off
2029*acea8879SAndroid Build Coastguard Worker     { Command::Type::ABORT,             PerformCommandAbort },
2030*acea8879SAndroid Build Coastguard Worker     { Command::Type::BSDIFF,            PerformCommandDiff },
2031*acea8879SAndroid Build Coastguard Worker     { Command::Type::COMPUTE_HASH_TREE, nullptr },
2032*acea8879SAndroid Build Coastguard Worker     { Command::Type::ERASE,             nullptr },
2033*acea8879SAndroid Build Coastguard Worker     { Command::Type::FREE,              PerformCommandFree },
2034*acea8879SAndroid Build Coastguard Worker     { Command::Type::IMGDIFF,           PerformCommandDiff },
2035*acea8879SAndroid Build Coastguard Worker     { Command::Type::MOVE,              PerformCommandMove },
2036*acea8879SAndroid Build Coastguard Worker     { Command::Type::NEW,               nullptr },
2037*acea8879SAndroid Build Coastguard Worker     { Command::Type::STASH,             PerformCommandStash },
2038*acea8879SAndroid Build Coastguard Worker     { Command::Type::ZERO,              nullptr },
2039*acea8879SAndroid Build Coastguard Worker     // clang-format on
2040*acea8879SAndroid Build Coastguard Worker   };
2041*acea8879SAndroid Build Coastguard Worker   CHECK_EQ(static_cast<size_t>(Command::Type::LAST), command_map.size());
2042*acea8879SAndroid Build Coastguard Worker 
2043*acea8879SAndroid Build Coastguard Worker   // Perform a dry run without writing to test if an update can proceed.
2044*acea8879SAndroid Build Coastguard Worker   return PerformBlockImageUpdate(name, state, argv, command_map, true);
2045*acea8879SAndroid Build Coastguard Worker }
2046*acea8879SAndroid Build Coastguard Worker 
BlockImageUpdateFn(const char * name,State * state,const std::vector<std::unique_ptr<Expr>> & argv)2047*acea8879SAndroid Build Coastguard Worker Value* BlockImageUpdateFn(const char* name, State* state,
2048*acea8879SAndroid Build Coastguard Worker                           const std::vector<std::unique_ptr<Expr>>& argv) {
2049*acea8879SAndroid Build Coastguard Worker   const CommandMap command_map{
2050*acea8879SAndroid Build Coastguard Worker     // clang-format off
2051*acea8879SAndroid Build Coastguard Worker     { Command::Type::ABORT,             PerformCommandAbort },
2052*acea8879SAndroid Build Coastguard Worker     { Command::Type::BSDIFF,            PerformCommandDiff },
2053*acea8879SAndroid Build Coastguard Worker     { Command::Type::COMPUTE_HASH_TREE, PerformCommandComputeHashTree },
2054*acea8879SAndroid Build Coastguard Worker     { Command::Type::ERASE,             PerformCommandErase },
2055*acea8879SAndroid Build Coastguard Worker     { Command::Type::FREE,              PerformCommandFree },
2056*acea8879SAndroid Build Coastguard Worker     { Command::Type::IMGDIFF,           PerformCommandDiff },
2057*acea8879SAndroid Build Coastguard Worker     { Command::Type::MOVE,              PerformCommandMove },
2058*acea8879SAndroid Build Coastguard Worker     { Command::Type::NEW,               PerformCommandNew },
2059*acea8879SAndroid Build Coastguard Worker     { Command::Type::STASH,             PerformCommandStash },
2060*acea8879SAndroid Build Coastguard Worker     { Command::Type::ZERO,              PerformCommandZero },
2061*acea8879SAndroid Build Coastguard Worker     // clang-format on
2062*acea8879SAndroid Build Coastguard Worker   };
2063*acea8879SAndroid Build Coastguard Worker   CHECK_EQ(static_cast<size_t>(Command::Type::LAST), command_map.size());
2064*acea8879SAndroid Build Coastguard Worker 
2065*acea8879SAndroid Build Coastguard Worker   return PerformBlockImageUpdate(name, state, argv, command_map, false);
2066*acea8879SAndroid Build Coastguard Worker }
2067*acea8879SAndroid Build Coastguard Worker 
RangeSha1Fn(const char * name,State * state,const std::vector<std::unique_ptr<Expr>> & argv)2068*acea8879SAndroid Build Coastguard Worker Value* RangeSha1Fn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) {
2069*acea8879SAndroid Build Coastguard Worker   if (argv.size() != 2) {
2070*acea8879SAndroid Build Coastguard Worker     ErrorAbort(state, kArgsParsingFailure, "range_sha1 expects 2 arguments, got %zu", argv.size());
2071*acea8879SAndroid Build Coastguard Worker     return StringValue("");
2072*acea8879SAndroid Build Coastguard Worker   }
2073*acea8879SAndroid Build Coastguard Worker 
2074*acea8879SAndroid Build Coastguard Worker   std::vector<std::unique_ptr<Value>> args;
2075*acea8879SAndroid Build Coastguard Worker   if (!ReadValueArgs(state, argv, &args)) {
2076*acea8879SAndroid Build Coastguard Worker     return nullptr;
2077*acea8879SAndroid Build Coastguard Worker   }
2078*acea8879SAndroid Build Coastguard Worker 
2079*acea8879SAndroid Build Coastguard Worker   const std::unique_ptr<Value>& blockdev_filename = args[0];
2080*acea8879SAndroid Build Coastguard Worker   const std::unique_ptr<Value>& ranges = args[1];
2081*acea8879SAndroid Build Coastguard Worker 
2082*acea8879SAndroid Build Coastguard Worker   if (blockdev_filename->type != Value::Type::STRING) {
2083*acea8879SAndroid Build Coastguard Worker     ErrorAbort(state, kArgsParsingFailure, "blockdev_filename argument to %s must be string", name);
2084*acea8879SAndroid Build Coastguard Worker     return StringValue("");
2085*acea8879SAndroid Build Coastguard Worker   }
2086*acea8879SAndroid Build Coastguard Worker   if (ranges->type != Value::Type::STRING) {
2087*acea8879SAndroid Build Coastguard Worker     ErrorAbort(state, kArgsParsingFailure, "ranges argument to %s must be string", name);
2088*acea8879SAndroid Build Coastguard Worker     return StringValue("");
2089*acea8879SAndroid Build Coastguard Worker   }
2090*acea8879SAndroid Build Coastguard Worker 
2091*acea8879SAndroid Build Coastguard Worker   auto block_device_path = state->updater->FindBlockDeviceName(blockdev_filename->data);
2092*acea8879SAndroid Build Coastguard Worker   if (block_device_path.empty()) {
2093*acea8879SAndroid Build Coastguard Worker     LOG(ERROR) << "Block device path for " << blockdev_filename->data << " not found. " << name
2094*acea8879SAndroid Build Coastguard Worker                << " failed.";
2095*acea8879SAndroid Build Coastguard Worker     return StringValue("");
2096*acea8879SAndroid Build Coastguard Worker   }
2097*acea8879SAndroid Build Coastguard Worker 
2098*acea8879SAndroid Build Coastguard Worker   android::base::unique_fd fd(open(block_device_path.c_str(), O_RDWR));
2099*acea8879SAndroid Build Coastguard Worker   if (fd == -1) {
2100*acea8879SAndroid Build Coastguard Worker     CauseCode cause_code = errno == EIO ? kEioFailure : kFileOpenFailure;
2101*acea8879SAndroid Build Coastguard Worker     ErrorAbort(state, cause_code, "open \"%s\" failed: %s", block_device_path.c_str(),
2102*acea8879SAndroid Build Coastguard Worker                strerror(errno));
2103*acea8879SAndroid Build Coastguard Worker     return StringValue("");
2104*acea8879SAndroid Build Coastguard Worker   }
2105*acea8879SAndroid Build Coastguard Worker 
2106*acea8879SAndroid Build Coastguard Worker   RangeSet rs = RangeSet::Parse(ranges->data);
2107*acea8879SAndroid Build Coastguard Worker   CHECK(static_cast<bool>(rs));
2108*acea8879SAndroid Build Coastguard Worker 
2109*acea8879SAndroid Build Coastguard Worker   SHA_CTX ctx;
2110*acea8879SAndroid Build Coastguard Worker   SHA1_Init(&ctx);
2111*acea8879SAndroid Build Coastguard Worker 
2112*acea8879SAndroid Build Coastguard Worker   std::vector<uint8_t> buffer(BLOCKSIZE);
2113*acea8879SAndroid Build Coastguard Worker   for (const auto& [begin, end] : rs) {
2114*acea8879SAndroid Build Coastguard Worker     if (!check_lseek(fd, static_cast<off64_t>(begin) * BLOCKSIZE, SEEK_SET)) {
2115*acea8879SAndroid Build Coastguard Worker       ErrorAbort(state, kLseekFailure, "failed to seek %s: %s", block_device_path.c_str(),
2116*acea8879SAndroid Build Coastguard Worker                  strerror(errno));
2117*acea8879SAndroid Build Coastguard Worker       return StringValue("");
2118*acea8879SAndroid Build Coastguard Worker     }
2119*acea8879SAndroid Build Coastguard Worker 
2120*acea8879SAndroid Build Coastguard Worker     for (size_t j = begin; j < end; ++j) {
2121*acea8879SAndroid Build Coastguard Worker       if (!android::base::ReadFully(fd, buffer.data(), BLOCKSIZE)) {
2122*acea8879SAndroid Build Coastguard Worker         CauseCode cause_code = errno == EIO ? kEioFailure : kFreadFailure;
2123*acea8879SAndroid Build Coastguard Worker         ErrorAbort(state, cause_code, "failed to read %s: %s", block_device_path.c_str(),
2124*acea8879SAndroid Build Coastguard Worker                    strerror(errno));
2125*acea8879SAndroid Build Coastguard Worker         return StringValue("");
2126*acea8879SAndroid Build Coastguard Worker       }
2127*acea8879SAndroid Build Coastguard Worker 
2128*acea8879SAndroid Build Coastguard Worker       SHA1_Update(&ctx, buffer.data(), BLOCKSIZE);
2129*acea8879SAndroid Build Coastguard Worker     }
2130*acea8879SAndroid Build Coastguard Worker   }
2131*acea8879SAndroid Build Coastguard Worker   uint8_t digest[SHA_DIGEST_LENGTH];
2132*acea8879SAndroid Build Coastguard Worker   SHA1_Final(digest, &ctx);
2133*acea8879SAndroid Build Coastguard Worker 
2134*acea8879SAndroid Build Coastguard Worker   return StringValue(print_sha1(digest));
2135*acea8879SAndroid Build Coastguard Worker }
2136*acea8879SAndroid Build Coastguard Worker 
2137*acea8879SAndroid Build Coastguard Worker // This function checks if a device has been remounted R/W prior to an incremental
2138*acea8879SAndroid Build Coastguard Worker // OTA update. This is a common cause of update abortion. The function reads the
2139*acea8879SAndroid Build Coastguard Worker // 1st block of each partition and check for mounting time/count. It return string "t"
2140*acea8879SAndroid Build Coastguard Worker // if executes successfully and an empty string otherwise.
2141*acea8879SAndroid Build Coastguard Worker 
CheckFirstBlockFn(const char * name,State * state,const std::vector<std::unique_ptr<Expr>> & argv)2142*acea8879SAndroid Build Coastguard Worker Value* CheckFirstBlockFn(const char* name, State* state,
2143*acea8879SAndroid Build Coastguard Worker                          const std::vector<std::unique_ptr<Expr>>& argv) {
2144*acea8879SAndroid Build Coastguard Worker   if (argv.size() != 1) {
2145*acea8879SAndroid Build Coastguard Worker     ErrorAbort(state, kArgsParsingFailure, "check_first_block expects 1 argument, got %zu",
2146*acea8879SAndroid Build Coastguard Worker                argv.size());
2147*acea8879SAndroid Build Coastguard Worker     return StringValue("");
2148*acea8879SAndroid Build Coastguard Worker   }
2149*acea8879SAndroid Build Coastguard Worker 
2150*acea8879SAndroid Build Coastguard Worker   std::vector<std::unique_ptr<Value>> args;
2151*acea8879SAndroid Build Coastguard Worker   if (!ReadValueArgs(state, argv, &args)) {
2152*acea8879SAndroid Build Coastguard Worker     return nullptr;
2153*acea8879SAndroid Build Coastguard Worker   }
2154*acea8879SAndroid Build Coastguard Worker 
2155*acea8879SAndroid Build Coastguard Worker   const std::unique_ptr<Value>& arg_filename = args[0];
2156*acea8879SAndroid Build Coastguard Worker 
2157*acea8879SAndroid Build Coastguard Worker   if (arg_filename->type != Value::Type::STRING) {
2158*acea8879SAndroid Build Coastguard Worker     ErrorAbort(state, kArgsParsingFailure, "filename argument to %s must be string", name);
2159*acea8879SAndroid Build Coastguard Worker     return StringValue("");
2160*acea8879SAndroid Build Coastguard Worker   }
2161*acea8879SAndroid Build Coastguard Worker 
2162*acea8879SAndroid Build Coastguard Worker   auto block_device_path = state->updater->FindBlockDeviceName(arg_filename->data);
2163*acea8879SAndroid Build Coastguard Worker   if (block_device_path.empty()) {
2164*acea8879SAndroid Build Coastguard Worker     LOG(ERROR) << "Block device path for " << arg_filename->data << " not found. " << name
2165*acea8879SAndroid Build Coastguard Worker                << " failed.";
2166*acea8879SAndroid Build Coastguard Worker     return StringValue("");
2167*acea8879SAndroid Build Coastguard Worker   }
2168*acea8879SAndroid Build Coastguard Worker 
2169*acea8879SAndroid Build Coastguard Worker   android::base::unique_fd fd(open(block_device_path.c_str(), O_RDONLY));
2170*acea8879SAndroid Build Coastguard Worker   if (fd == -1) {
2171*acea8879SAndroid Build Coastguard Worker     CauseCode cause_code = errno == EIO ? kEioFailure : kFileOpenFailure;
2172*acea8879SAndroid Build Coastguard Worker     ErrorAbort(state, cause_code, "open \"%s\" failed: %s", block_device_path.c_str(),
2173*acea8879SAndroid Build Coastguard Worker                strerror(errno));
2174*acea8879SAndroid Build Coastguard Worker     return StringValue("");
2175*acea8879SAndroid Build Coastguard Worker   }
2176*acea8879SAndroid Build Coastguard Worker 
2177*acea8879SAndroid Build Coastguard Worker   RangeSet blk0(std::vector<Range>{ Range{ 0, 1 } });
2178*acea8879SAndroid Build Coastguard Worker   std::vector<uint8_t> block0_buffer(BLOCKSIZE);
2179*acea8879SAndroid Build Coastguard Worker 
2180*acea8879SAndroid Build Coastguard Worker   if (ReadBlocks(blk0, &block0_buffer, fd) == -1) {
2181*acea8879SAndroid Build Coastguard Worker     CauseCode cause_code = errno == EIO ? kEioFailure : kFreadFailure;
2182*acea8879SAndroid Build Coastguard Worker     ErrorAbort(state, cause_code, "failed to read %s: %s", block_device_path.c_str(),
2183*acea8879SAndroid Build Coastguard Worker                strerror(errno));
2184*acea8879SAndroid Build Coastguard Worker     return StringValue("");
2185*acea8879SAndroid Build Coastguard Worker   }
2186*acea8879SAndroid Build Coastguard Worker 
2187*acea8879SAndroid Build Coastguard Worker   // https://ext4.wiki.kernel.org/index.php/Ext4_Disk_Layout
2188*acea8879SAndroid Build Coastguard Worker   // Super block starts from block 0, offset 0x400
2189*acea8879SAndroid Build Coastguard Worker   //   0x2C: len32 Mount time
2190*acea8879SAndroid Build Coastguard Worker   //   0x30: len32 Write time
2191*acea8879SAndroid Build Coastguard Worker   //   0x34: len16 Number of mounts since the last fsck
2192*acea8879SAndroid Build Coastguard Worker   //   0x38: len16 Magic signature 0xEF53
2193*acea8879SAndroid Build Coastguard Worker 
2194*acea8879SAndroid Build Coastguard Worker   time_t mount_time = *reinterpret_cast<uint32_t*>(&block0_buffer[0x400 + 0x2C]);
2195*acea8879SAndroid Build Coastguard Worker   uint16_t mount_count = *reinterpret_cast<uint16_t*>(&block0_buffer[0x400 + 0x34]);
2196*acea8879SAndroid Build Coastguard Worker 
2197*acea8879SAndroid Build Coastguard Worker   if (mount_count > 0) {
2198*acea8879SAndroid Build Coastguard Worker     state->updater->UiPrint(
2199*acea8879SAndroid Build Coastguard Worker         android::base::StringPrintf("Device was remounted R/W %" PRIu16 " times", mount_count));
2200*acea8879SAndroid Build Coastguard Worker     state->updater->UiPrint(
2201*acea8879SAndroid Build Coastguard Worker         android::base::StringPrintf("Last remount happened on %s", ctime(&mount_time)));
2202*acea8879SAndroid Build Coastguard Worker   }
2203*acea8879SAndroid Build Coastguard Worker 
2204*acea8879SAndroid Build Coastguard Worker   return StringValue("t");
2205*acea8879SAndroid Build Coastguard Worker }
2206*acea8879SAndroid Build Coastguard Worker 
BlockImageRecoverFn(const char * name,State * state,const std::vector<std::unique_ptr<Expr>> & argv)2207*acea8879SAndroid Build Coastguard Worker Value* BlockImageRecoverFn(const char* name, State* state,
2208*acea8879SAndroid Build Coastguard Worker                            const std::vector<std::unique_ptr<Expr>>& argv) {
2209*acea8879SAndroid Build Coastguard Worker   if (argv.size() != 2) {
2210*acea8879SAndroid Build Coastguard Worker     ErrorAbort(state, kArgsParsingFailure, "block_image_recover expects 2 arguments, got %zu",
2211*acea8879SAndroid Build Coastguard Worker                argv.size());
2212*acea8879SAndroid Build Coastguard Worker     return StringValue("");
2213*acea8879SAndroid Build Coastguard Worker   }
2214*acea8879SAndroid Build Coastguard Worker 
2215*acea8879SAndroid Build Coastguard Worker   std::vector<std::unique_ptr<Value>> args;
2216*acea8879SAndroid Build Coastguard Worker   if (!ReadValueArgs(state, argv, &args)) {
2217*acea8879SAndroid Build Coastguard Worker     return nullptr;
2218*acea8879SAndroid Build Coastguard Worker   }
2219*acea8879SAndroid Build Coastguard Worker 
2220*acea8879SAndroid Build Coastguard Worker   const std::unique_ptr<Value>& filename = args[0];
2221*acea8879SAndroid Build Coastguard Worker   const std::unique_ptr<Value>& ranges = args[1];
2222*acea8879SAndroid Build Coastguard Worker 
2223*acea8879SAndroid Build Coastguard Worker   if (filename->type != Value::Type::STRING) {
2224*acea8879SAndroid Build Coastguard Worker     ErrorAbort(state, kArgsParsingFailure, "filename argument to %s must be string", name);
2225*acea8879SAndroid Build Coastguard Worker     return StringValue("");
2226*acea8879SAndroid Build Coastguard Worker   }
2227*acea8879SAndroid Build Coastguard Worker   if (ranges->type != Value::Type::STRING) {
2228*acea8879SAndroid Build Coastguard Worker     ErrorAbort(state, kArgsParsingFailure, "ranges argument to %s must be string", name);
2229*acea8879SAndroid Build Coastguard Worker     return StringValue("");
2230*acea8879SAndroid Build Coastguard Worker   }
2231*acea8879SAndroid Build Coastguard Worker   RangeSet rs = RangeSet::Parse(ranges->data);
2232*acea8879SAndroid Build Coastguard Worker   if (!rs) {
2233*acea8879SAndroid Build Coastguard Worker     ErrorAbort(state, kArgsParsingFailure, "failed to parse ranges: %s", ranges->data.c_str());
2234*acea8879SAndroid Build Coastguard Worker     return StringValue("");
2235*acea8879SAndroid Build Coastguard Worker   }
2236*acea8879SAndroid Build Coastguard Worker 
2237*acea8879SAndroid Build Coastguard Worker   auto block_device_path = state->updater->FindBlockDeviceName(filename->data);
2238*acea8879SAndroid Build Coastguard Worker   if (block_device_path.empty()) {
2239*acea8879SAndroid Build Coastguard Worker     LOG(ERROR) << "Block device path for " << filename->data << " not found. " << name
2240*acea8879SAndroid Build Coastguard Worker                << " failed.";
2241*acea8879SAndroid Build Coastguard Worker     return StringValue("");
2242*acea8879SAndroid Build Coastguard Worker   }
2243*acea8879SAndroid Build Coastguard Worker 
2244*acea8879SAndroid Build Coastguard Worker   // Output notice to log when recover is attempted
2245*acea8879SAndroid Build Coastguard Worker   LOG(INFO) << block_device_path << " image corrupted, attempting to recover...";
2246*acea8879SAndroid Build Coastguard Worker 
2247*acea8879SAndroid Build Coastguard Worker   // When opened with O_RDWR, libfec rewrites corrupted blocks when they are read
2248*acea8879SAndroid Build Coastguard Worker   fec::io fh(block_device_path, O_RDWR);
2249*acea8879SAndroid Build Coastguard Worker 
2250*acea8879SAndroid Build Coastguard Worker   if (!fh) {
2251*acea8879SAndroid Build Coastguard Worker     ErrorAbort(state, kLibfecFailure, "fec_open \"%s\" failed: %s", block_device_path.c_str(),
2252*acea8879SAndroid Build Coastguard Worker                strerror(errno));
2253*acea8879SAndroid Build Coastguard Worker     return StringValue("");
2254*acea8879SAndroid Build Coastguard Worker   }
2255*acea8879SAndroid Build Coastguard Worker 
2256*acea8879SAndroid Build Coastguard Worker   if (!fh.has_ecc() || !fh.has_verity()) {
2257*acea8879SAndroid Build Coastguard Worker     ErrorAbort(state, kLibfecFailure, "unable to use metadata to correct errors");
2258*acea8879SAndroid Build Coastguard Worker     return StringValue("");
2259*acea8879SAndroid Build Coastguard Worker   }
2260*acea8879SAndroid Build Coastguard Worker 
2261*acea8879SAndroid Build Coastguard Worker   fec_status status;
2262*acea8879SAndroid Build Coastguard Worker   if (!fh.get_status(status)) {
2263*acea8879SAndroid Build Coastguard Worker     ErrorAbort(state, kLibfecFailure, "failed to read FEC status");
2264*acea8879SAndroid Build Coastguard Worker     return StringValue("");
2265*acea8879SAndroid Build Coastguard Worker   }
2266*acea8879SAndroid Build Coastguard Worker 
2267*acea8879SAndroid Build Coastguard Worker   uint8_t buffer[BLOCKSIZE];
2268*acea8879SAndroid Build Coastguard Worker   for (const auto& [begin, end] : rs) {
2269*acea8879SAndroid Build Coastguard Worker     for (size_t j = begin; j < end; ++j) {
2270*acea8879SAndroid Build Coastguard Worker       // Stay within the data area, libfec validates and corrects metadata
2271*acea8879SAndroid Build Coastguard Worker       if (status.data_size <= static_cast<uint64_t>(j) * BLOCKSIZE) {
2272*acea8879SAndroid Build Coastguard Worker         continue;
2273*acea8879SAndroid Build Coastguard Worker       }
2274*acea8879SAndroid Build Coastguard Worker 
2275*acea8879SAndroid Build Coastguard Worker       if (fh.pread(buffer, BLOCKSIZE, static_cast<off64_t>(j) * BLOCKSIZE) != BLOCKSIZE) {
2276*acea8879SAndroid Build Coastguard Worker         ErrorAbort(state, kLibfecFailure, "failed to recover %s (block %zu): %s",
2277*acea8879SAndroid Build Coastguard Worker                    block_device_path.c_str(), j, strerror(errno));
2278*acea8879SAndroid Build Coastguard Worker         return StringValue("");
2279*acea8879SAndroid Build Coastguard Worker       }
2280*acea8879SAndroid Build Coastguard Worker 
2281*acea8879SAndroid Build Coastguard Worker       // If we want to be able to recover from a situation where rewriting a corrected
2282*acea8879SAndroid Build Coastguard Worker       // block doesn't guarantee the same data will be returned when re-read later, we
2283*acea8879SAndroid Build Coastguard Worker       // can save a copy of corrected blocks to /cache. Note:
2284*acea8879SAndroid Build Coastguard Worker       //
2285*acea8879SAndroid Build Coastguard Worker       //  1. Maximum space required from /cache is the same as the maximum number of
2286*acea8879SAndroid Build Coastguard Worker       //     corrupted blocks we can correct. For RS(255, 253) and a 2 GiB partition,
2287*acea8879SAndroid Build Coastguard Worker       //     this would be ~16 MiB, for example.
2288*acea8879SAndroid Build Coastguard Worker       //
2289*acea8879SAndroid Build Coastguard Worker       //  2. To find out if this block was corrupted, call fec_get_status after each
2290*acea8879SAndroid Build Coastguard Worker       //     read and check if the errors field value has increased.
2291*acea8879SAndroid Build Coastguard Worker     }
2292*acea8879SAndroid Build Coastguard Worker   }
2293*acea8879SAndroid Build Coastguard Worker   LOG(INFO) << "..." << block_device_path << " image recovered successfully.";
2294*acea8879SAndroid Build Coastguard Worker   return StringValue("t");
2295*acea8879SAndroid Build Coastguard Worker }
2296*acea8879SAndroid Build Coastguard Worker 
RegisterBlockImageFunctions()2297*acea8879SAndroid Build Coastguard Worker void RegisterBlockImageFunctions() {
2298*acea8879SAndroid Build Coastguard Worker   RegisterFunction("block_image_verify", BlockImageVerifyFn);
2299*acea8879SAndroid Build Coastguard Worker   RegisterFunction("block_image_update", BlockImageUpdateFn);
2300*acea8879SAndroid Build Coastguard Worker   RegisterFunction("block_image_recover", BlockImageRecoverFn);
2301*acea8879SAndroid Build Coastguard Worker   RegisterFunction("check_first_block", CheckFirstBlockFn);
2302*acea8879SAndroid Build Coastguard Worker   RegisterFunction("range_sha1", RangeSha1Fn);
2303*acea8879SAndroid Build Coastguard Worker }
2304