summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--otafault/Android.mk5
-rw-r--r--otafault/config.cpp36
-rw-r--r--recovery.cpp28
-rw-r--r--tools/ota/Android.mk33
-rw-r--r--tools/ota/add-property-tag.c141
-rw-r--r--tools/ota/check-lost+found.c145
-rw-r--r--tools/ota/convert-to-bmp.py79
-rw-r--r--updater/blockimg.cpp54
8 files changed, 74 insertions, 447 deletions
diff --git a/otafault/Android.mk b/otafault/Android.mk
index 52d706722..50e385efb 100644
--- a/otafault/Android.mk
+++ b/otafault/Android.mk
@@ -19,9 +19,10 @@ LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
otafault_static_libs := \
+ libbase \
libminzip \
- libselinux \
- libz
+ libz \
+ libselinux
LOCAL_SRC_FILES := config.cpp ota_io.cpp
LOCAL_MODULE := libotafault
diff --git a/otafault/config.cpp b/otafault/config.cpp
index c87f9a631..b4567392d 100644
--- a/otafault/config.cpp
+++ b/otafault/config.cpp
@@ -20,6 +20,8 @@
#include <stdio.h>
#include <unistd.h>
+#include <android-base/stringprintf.h>
+
#include "minzip/Zip.h"
#include "config.h"
#include "ota_io.h"
@@ -27,12 +29,10 @@
#define OTAIO_MAX_FNAME_SIZE 128
static ZipArchive* archive;
-static std::map<const char*, bool> should_inject_cache;
+static std::map<std::string, bool> should_inject_cache;
-static const char* get_type_path(const char* io_type) {
- char* path = (char*)calloc(strlen(io_type) + strlen(OTAIO_BASE_DIR) + 2, sizeof(char));
- sprintf(path, "%s/%s", OTAIO_BASE_DIR, io_type);
- return path;
+static std::string get_type_path(const char* io_type) {
+ return android::base::StringPrintf("%s/%s", OTAIO_BASE_DIR, io_type);
}
void ota_io_init(ZipArchive* za) {
@@ -41,13 +41,17 @@ void ota_io_init(ZipArchive* za) {
}
bool should_fault_inject(const char* io_type) {
- if (should_inject_cache.find(io_type) != should_inject_cache.end()) {
- return should_inject_cache[io_type];
+ // archive will be NULL if we used an entry point other
+ // than updater/updater.cpp:main
+ if (archive == NULL) {
+ return false;
+ }
+ const std::string type_path = get_type_path(io_type);
+ if (should_inject_cache.find(type_path) != should_inject_cache.end()) {
+ return should_inject_cache[type_path];
}
- const char* type_path = get_type_path(io_type);
- const ZipEntry* entry = mzFindZipEntry(archive, type_path);
+ const ZipEntry* entry = mzFindZipEntry(archive, type_path.c_str());
should_inject_cache[type_path] = entry != nullptr;
- free((void*)type_path);
return entry != NULL;
}
@@ -56,10 +60,10 @@ bool should_hit_cache() {
}
std::string fault_fname(const char* io_type) {
- const char* type_path = get_type_path(io_type);
- char* fname = (char*) calloc(OTAIO_MAX_FNAME_SIZE, sizeof(char));
- const ZipEntry* entry = mzFindZipEntry(archive, type_path);
- mzReadZipEntry(archive, entry, fname, OTAIO_MAX_FNAME_SIZE);
- free((void*)type_path);
- return std::string(fname);
+ std::string type_path = get_type_path(io_type);
+ std::string fname;
+ fname.resize(OTAIO_MAX_FNAME_SIZE);
+ const ZipEntry* entry = mzFindZipEntry(archive, type_path.c_str());
+ mzReadZipEntry(archive, entry, &fname[0], OTAIO_MAX_FNAME_SIZE);
+ return fname;
}
diff --git a/recovery.cpp b/recovery.cpp
index 6781fa4b4..4ee835c98 100644
--- a/recovery.cpp
+++ b/recovery.cpp
@@ -59,7 +59,6 @@
struct selabel_handle *sehandle;
static const struct option OPTIONS[] = {
- { "send_intent", required_argument, NULL, 'i' },
{ "update_package", required_argument, NULL, 'u' },
{ "retry_count", required_argument, NULL, 'n' },
{ "wipe_data", no_argument, NULL, 'w' },
@@ -77,7 +76,6 @@ static const struct option OPTIONS[] = {
static const char *CACHE_LOG_DIR = "/cache/recovery";
static const char *COMMAND_FILE = "/cache/recovery/command";
-static const char *INTENT_FILE = "/cache/recovery/intent";
static const char *LOG_FILE = "/cache/recovery/log";
static const char *LAST_INSTALL_FILE = "/cache/recovery/last_install";
static const char *LOCALE_FILE = "/cache/recovery/last_locale";
@@ -107,10 +105,8 @@ static bool has_cache = false;
* The recovery tool communicates with the main system through /cache files.
* /cache/recovery/command - INPUT - command line for tool, one arg per line
* /cache/recovery/log - OUTPUT - combined log file from recovery run(s)
- * /cache/recovery/intent - OUTPUT - intent that was passed in
*
* The arguments which may be supplied in the recovery.command file:
- * --send_intent=anystring - write the text out to recovery.intent
* --update_package=path - verify install an OTA package file
* --wipe_data - erase user data (and cache), then reboot
* --wipe_cache - wipe cache (but not user data), then reboot
@@ -467,22 +463,10 @@ static void copy_logs() {
}
// clear the recovery command and prepare to boot a (hopefully working) system,
-// copy our log file to cache as well (for the system to read), and
-// record any intent we were asked to communicate back to the system.
-// this function is idempotent: call it as many times as you like.
+// copy our log file to cache as well (for the system to read). This function is
+// idempotent: call it as many times as you like.
static void
-finish_recovery(const char *send_intent) {
- // By this point, we're ready to return to the main system...
- if (send_intent != NULL && has_cache) {
- FILE *fp = fopen_path(INTENT_FILE, "w");
- if (fp == NULL) {
- LOGE("Can't open %s\n", INTENT_FILE);
- } else {
- fputs(send_intent, fp);
- check_and_fclose(fp, INTENT_FILE);
- }
- }
-
+finish_recovery() {
// Save the locale to cache, so if recovery is next started up
// without a --locale argument (eg, directly from the bootloader)
// it will use the last-known locale.
@@ -947,7 +931,7 @@ static int apply_from_sdcard(Device* device, bool* wipe_cache) {
static Device::BuiltinAction
prompt_and_wait(Device* device, int status) {
for (;;) {
- finish_recovery(NULL);
+ finish_recovery();
switch (status) {
case INSTALL_SUCCESS:
case INSTALL_NONE:
@@ -1189,7 +1173,6 @@ int main(int argc, char **argv) {
get_args(&argc, &argv);
- const char *send_intent = NULL;
const char *update_package = NULL;
bool should_wipe_data = false;
bool should_wipe_cache = false;
@@ -1203,7 +1186,6 @@ int main(int argc, char **argv) {
int arg;
while ((arg = getopt_long(argc, argv, "", OPTIONS, NULL)) != -1) {
switch (arg) {
- case 'i': send_intent = optarg; break;
case 'n': android::base::ParseInt(optarg, &retry_count, 0); break;
case 'u': update_package = optarg; break;
case 'w': should_wipe_data = true; break;
@@ -1390,7 +1372,7 @@ int main(int argc, char **argv) {
}
// Save logs and clean up before rebooting or shutting down.
- finish_recovery(send_intent);
+ finish_recovery();
switch (after) {
case Device::SHUTDOWN:
diff --git a/tools/ota/Android.mk b/tools/ota/Android.mk
deleted file mode 100644
index 142c3b257..000000000
--- a/tools/ota/Android.mk
+++ /dev/null
@@ -1,33 +0,0 @@
-# Copyright (C) 2008 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-LOCAL_FORCE_STATIC_EXECUTABLE := true
-LOCAL_MODULE := add-property-tag
-LOCAL_MODULE_PATH := $(TARGET_OUT_OPTIONAL_EXECUTABLES)
-LOCAL_MODULE_TAGS := debug
-LOCAL_SRC_FILES := add-property-tag.c
-LOCAL_STATIC_LIBRARIES := libc
-include $(BUILD_EXECUTABLE)
-
-include $(CLEAR_VARS)
-LOCAL_FORCE_STATIC_EXECUTABLE := true
-LOCAL_MODULE := check-lost+found
-LOCAL_MODULE_PATH := $(TARGET_OUT_OPTIONAL_EXECUTABLES)
-LOCAL_MODULE_TAGS := debug
-LOCAL_SRC_FILES := check-lost+found.c
-LOCAL_STATIC_LIBRARIES := libcutils libc
-include $(BUILD_EXECUTABLE)
diff --git a/tools/ota/add-property-tag.c b/tools/ota/add-property-tag.c
deleted file mode 100644
index aab30b2d0..000000000
--- a/tools/ota/add-property-tag.c
+++ /dev/null
@@ -1,141 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <ctype.h>
-#include <errno.h>
-#include <getopt.h>
-#include <limits.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-/*
- * Append a tag to a property value in a .prop file if it isn't already there.
- * Normally used to modify build properties to record incremental updates.
- */
-
-// Return nonzero if the tag should be added to this line.
-int should_tag(const char *line, const char *propname) {
- const char *prop = strstr(line, propname);
- if (prop == NULL) return 0;
-
- // Make sure this is actually the property name (not an accidental hit)
- const char *ptr;
- for (ptr = line; ptr < prop && isspace(*ptr); ++ptr) ;
- if (ptr != prop) return 0; // Must be at the beginning of the line
-
- for (ptr += strlen(propname); *ptr != '\0' && isspace(*ptr); ++ptr) ;
- return (*ptr == '='); // Must be followed by a '='
-}
-
-// Remove existing tags from the line, return the following number (if any)
-int remove_tag(char *line, const char *tag) {
- char *pos = strstr(line, tag);
- if (pos == NULL) return 0;
-
- char *end;
- int num = strtoul(pos + strlen(tag), &end, 10);
- strcpy(pos, end);
- return num;
-}
-
-// Write line to output with the tag added, adding a number (if >0)
-void write_tagged(FILE *out, const char *line, const char *tag, int number) {
- const char *end = line + strlen(line);
- while (end > line && isspace(end[-1])) --end;
- if (number > 0) {
- fprintf(out, "%.*s%s%d%s", (int)(end - line), line, tag, number, end);
- } else {
- fprintf(out, "%.*s%s%s", (int)(end - line), line, tag, end);
- }
-}
-
-int main(int argc, char **argv) {
- const char *filename = "/system/build.prop";
- const char *propname = "ro.build.fingerprint";
- const char *tag = NULL;
- int do_remove = 0, do_number = 0;
-
- int opt;
- while ((opt = getopt(argc, argv, "f:p:rn")) != -1) {
- switch (opt) {
- case 'f': filename = optarg; break;
- case 'p': propname = optarg; break;
- case 'r': do_remove = 1; break;
- case 'n': do_number = 1; break;
- case '?': return 2;
- }
- }
-
- if (argc != optind + 1) {
- fprintf(stderr,
- "usage: add-property-tag [flags] tag-to-add\n"
- "flags: -f /dir/file.prop (default /system/build.prop)\n"
- " -p prop.name (default ro.build.fingerprint)\n"
- " -r (if set, remove the tag rather than adding it)\n"
- " -n (if set, add and increment a number after the tag)\n");
- return 2;
- }
-
- tag = argv[optind];
- FILE *input = fopen(filename, "r");
- if (input == NULL) {
- fprintf(stderr, "can't read %s: %s\n", filename, strerror(errno));
- return 1;
- }
-
- char tmpname[PATH_MAX];
- snprintf(tmpname, sizeof(tmpname), "%s.tmp", filename);
- FILE *output = fopen(tmpname, "w");
- if (output == NULL) {
- fprintf(stderr, "can't write %s: %s\n", tmpname, strerror(errno));
- return 1;
- }
-
- int found = 0;
- char line[4096];
- while (fgets(line, sizeof(line), input)) {
- if (!should_tag(line, propname)) {
- fputs(line, output); // Pass through unmodified
- } else {
- found = 1;
- int number = remove_tag(line, tag);
- if (do_remove) {
- fputs(line, output); // Remove the tag but don't re-add it
- } else {
- write_tagged(output, line, tag, number + do_number);
- }
- }
- }
-
- fclose(input);
- fclose(output);
-
- if (!found) {
- fprintf(stderr, "property %s not found in %s\n", propname, filename);
- remove(tmpname);
- return 1;
- }
-
- if (rename(tmpname, filename)) {
- fprintf(stderr, "can't rename %s to %s: %s\n",
- tmpname, filename, strerror(errno));
- remove(tmpname);
- return 1;
- }
-
- return 0;
-}
diff --git a/tools/ota/check-lost+found.c b/tools/ota/check-lost+found.c
deleted file mode 100644
index 8ce12d39f..000000000
--- a/tools/ota/check-lost+found.c
+++ /dev/null
@@ -1,145 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <dirent.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <limits.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/klog.h>
-#include <sys/reboot.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <time.h>
-#include <unistd.h>
-
-#include "private/android_filesystem_config.h"
-
-// Sentinel file used to track whether we've forced a reboot
-static const char *kMarkerFile = "/data/misc/check-lost+found-rebooted-2";
-
-// Output file in tombstones directory (first 8K will be uploaded)
-static const char *kOutputDir = "/data/tombstones";
-static const char *kOutputFile = "/data/tombstones/check-lost+found-log";
-
-// Partitions to check
-static const char *kPartitions[] = { "/system", "/data", "/cache", NULL };
-
-/*
- * 1. If /data/misc/forced-reboot is missing, touch it & force "unclean" boot.
- * 2. Write a log entry with the number of files in lost+found directories.
- */
-
-int main(int argc __attribute__((unused)), char **argv __attribute__((unused))) {
- mkdir(kOutputDir, 0755);
- chown(kOutputDir, AID_SYSTEM, AID_SYSTEM);
- FILE *out = fopen(kOutputFile, "a");
- if (out == NULL) {
- fprintf(stderr, "Can't write %s: %s\n", kOutputFile, strerror(errno));
- return 1;
- }
-
- // Note: only the first 8K of log will be uploaded, so be terse.
- time_t start = time(NULL);
- fprintf(out, "*** check-lost+found ***\nStarted: %s", ctime(&start));
-
- struct stat st;
- if (stat(kMarkerFile, &st)) {
- // No reboot marker -- need to force an unclean reboot.
- // But first, try to create the marker file. If that fails,
- // skip the reboot, so we don't get caught in an infinite loop.
-
- int fd = open(kMarkerFile, O_WRONLY|O_CREAT, 0444);
- if (fd >= 0 && close(fd) == 0) {
- fprintf(out, "Wrote %s, rebooting\n", kMarkerFile);
- fflush(out);
- sync(); // Make sure the marker file is committed to disk
-
- // If possible, dirty each of these partitions before rebooting,
- // to make sure the filesystem has to do a scan on mount.
- int i;
- for (i = 0; kPartitions[i] != NULL; ++i) {
- char fn[PATH_MAX];
- snprintf(fn, sizeof(fn), "%s/%s", kPartitions[i], "dirty");
- fd = open(fn, O_WRONLY|O_CREAT, 0444);
- if (fd >= 0) { // Don't sweat it if we can't write the file.
- TEMP_FAILURE_RETRY(write(fd, fn, sizeof(fn))); // write, you know, some data
- close(fd);
- unlink(fn);
- }
- }
-
- reboot(RB_AUTOBOOT); // reboot immediately, with dirty filesystems
- fprintf(out, "Reboot failed?!\n");
- exit(1);
- } else {
- fprintf(out, "Can't write %s: %s\n", kMarkerFile, strerror(errno));
- }
- } else {
- fprintf(out, "Found %s\n", kMarkerFile);
- }
-
- int i;
- for (i = 0; kPartitions[i] != NULL; ++i) {
- char fn[PATH_MAX];
- snprintf(fn, sizeof(fn), "%s/%s", kPartitions[i], "lost+found");
- DIR *dir = opendir(fn);
- if (dir == NULL) {
- fprintf(out, "Can't open %s: %s\n", fn, strerror(errno));
- } else {
- int count = 0;
- struct dirent *ent;
- while ((ent = readdir(dir))) {
- if (strcmp(ent->d_name, ".") && strcmp(ent->d_name, ".."))
- ++count;
- }
- closedir(dir);
- if (count > 0) {
- fprintf(out, "OMGZ FOUND %d FILES IN %s\n", count, fn);
- } else {
- fprintf(out, "%s is clean\n", fn);
- }
- }
- }
-
- char dmesg[131073];
- int len = klogctl(KLOG_READ_ALL, dmesg, sizeof(dmesg) - 1);
- if (len < 0) {
- fprintf(out, "Can't read kernel log: %s\n", strerror(errno));
- } else { // To conserve space, only write lines with certain keywords
- fprintf(out, "--- Kernel log ---\n");
- dmesg[len] = '\0';
- char *saveptr, *line;
- int in_yaffs = 0;
- for (line = strtok_r(dmesg, "\n", &saveptr); line != NULL;
- line = strtok_r(NULL, "\n", &saveptr)) {
- if (strstr(line, "yaffs: dev is")) in_yaffs = 1;
-
- if (in_yaffs ||
- strstr(line, "yaffs") ||
- strstr(line, "mtd") ||
- strstr(line, "msm_nand")) {
- fprintf(out, "%s\n", line);
- }
-
- if (strstr(line, "yaffs_read_super: isCheckpointed")) in_yaffs = 0;
- }
- }
-
- return 0;
-}
diff --git a/tools/ota/convert-to-bmp.py b/tools/ota/convert-to-bmp.py
deleted file mode 100644
index 446c09da8..000000000
--- a/tools/ota/convert-to-bmp.py
+++ /dev/null
@@ -1,79 +0,0 @@
-#!/usr/bin/python2.4
-
-"""A simple script to convert asset images to BMP files, that supports
-RGBA image."""
-
-import struct
-import Image
-import sys
-
-infile = sys.argv[1]
-outfile = sys.argv[2]
-
-if not outfile.endswith(".bmp"):
- print >> sys.stderr, "Warning: I'm expecting to write BMP files."
-
-im = Image.open(infile)
-if im.mode == 'RGB':
- im.save(outfile)
-elif im.mode == 'RGBA':
- # Python Imaging Library doesn't write RGBA BMP files, so we roll
- # our own.
-
- BMP_HEADER_FMT = ("<" # little-endian
- "H" # signature
- "L" # file size
- "HH" # reserved (set to 0)
- "L" # offset to start of bitmap data)
- )
-
- BITMAPINFO_HEADER_FMT= ("<" # little-endian
- "L" # size of this struct
- "L" # width
- "L" # height
- "H" # planes (set to 1)
- "H" # bit count
- "L" # compression (set to 0 for minui)
- "L" # size of image data (0 if uncompressed)
- "L" # x pixels per meter (1)
- "L" # y pixels per meter (1)
- "L" # colors used (0)
- "L" # important colors (0)
- )
-
- fileheadersize = struct.calcsize(BMP_HEADER_FMT)
- infoheadersize = struct.calcsize(BITMAPINFO_HEADER_FMT)
-
- header = struct.pack(BMP_HEADER_FMT,
- 0x4d42, # "BM" in little-endian
- (fileheadersize + infoheadersize +
- im.size[0] * im.size[1] * 4),
- 0, 0,
- fileheadersize + infoheadersize)
-
- info = struct.pack(BITMAPINFO_HEADER_FMT,
- infoheadersize,
- im.size[0],
- im.size[1],
- 1,
- 32,
- 0,
- 0,
- 1,
- 1,
- 0,
- 0)
-
- f = open(outfile, "wb")
- f.write(header)
- f.write(info)
- data = im.tostring()
- for j in range(im.size[1]-1, -1, -1): # rows bottom-to-top
- for i in range(j*im.size[0]*4, (j+1)*im.size[0]*4, 4):
- f.write(data[i+2]) # B
- f.write(data[i+1]) # G
- f.write(data[i+0]) # R
- f.write(data[i+3]) # A
- f.close()
-else:
- print >> sys.stderr, "Don't know how to handle image mode '%s'." % (im.mode,)
diff --git a/updater/blockimg.cpp b/updater/blockimg.cpp
index 56378d4f5..9d329cd24 100644
--- a/updater/blockimg.cpp
+++ b/updater/blockimg.cpp
@@ -33,6 +33,7 @@
#include <unistd.h>
#include <fec/io.h>
+#include <map>
#include <memory>
#include <string>
#include <vector>
@@ -67,6 +68,8 @@ struct RangeSet {
std::vector<size_t> pos; // Actual limit is INT_MAX.
};
+static std::map<std::string, RangeSet> stash_map;
+
static void parse_range(const std::string& range_text, RangeSet& rs) {
std::vector<std::string> pieces = android::base::Split(range_text, ",");
@@ -522,8 +525,28 @@ static void DeleteStash(const std::string& base) {
}
}
-static int LoadStash(const std::string& base, const std::string& id, bool verify, size_t* blocks,
- std::vector<uint8_t>& buffer, bool printnoent) {
+static int LoadStash(CommandParameters& params, const std::string& base, const std::string& id,
+ bool verify, size_t* blocks, std::vector<uint8_t>& buffer, bool printnoent) {
+ // In verify mode, if source range_set was saved for the given hash,
+ // check contents in the source blocks first. If the check fails,
+ // search for the stashed files on /cache as usual.
+ if (!params.canwrite) {
+ if (stash_map.find(id) != stash_map.end()) {
+ const RangeSet& src = stash_map[id];
+ allocate(src.size * BLOCKSIZE, buffer);
+
+ if (ReadBlocks(src, buffer, params.fd) == -1) {
+ fprintf(stderr, "failed to read source blocks in stash map.\n");
+ return -1;
+ }
+ if (VerifyBlocks(id, buffer, src.size, true) != 0) {
+ fprintf(stderr, "failed to verify loaded source blocks in stash map.\n");
+ return -1;
+ }
+ return 0;
+ }
+ }
+
if (base.empty()) {
return -1;
}
@@ -722,7 +745,7 @@ static int SaveStash(CommandParameters& params, const std::string& base,
const std::string& id = params.tokens[params.cpos++];
size_t blocks = 0;
- if (usehash && LoadStash(base, id, true, &blocks, buffer, false) == 0) {
+ if (usehash && LoadStash(params, base, id, true, &blocks, buffer, false) == 0) {
// Stash file already exists and has expected contents. Do not
// read from source again, as the source may have been already
// overwritten during a previous attempt.
@@ -747,6 +770,12 @@ static int SaveStash(CommandParameters& params, const std::string& base,
return 0;
}
+ // In verify mode, save source range_set instead of stashing blocks.
+ if (!params.canwrite && usehash) {
+ stash_map[id] = src;
+ return 0;
+ }
+
fprintf(stderr, "stashing %zu blocks to %s\n", blocks, id.c_str());
return WriteStash(base, id, blocks, buffer, false, nullptr);
}
@@ -857,7 +886,7 @@ static int LoadSrcTgtVersion2(CommandParameters& params, RangeSet& tgt, size_t&
}
std::vector<uint8_t> stash;
- int res = LoadStash(stashbase, tokens[0], false, nullptr, stash, true);
+ int res = LoadStash(params, stashbase, tokens[0], false, nullptr, stash, true);
if (res == -1) {
// These source blocks will fail verification if used later, but we
@@ -931,8 +960,9 @@ static int LoadSrcTgtVersion3(CommandParameters& params, RangeSet& tgt, size_t&
if (VerifyBlocks(srchash, params.buffer, src_blocks, true) == 0) {
// If source and target blocks overlap, stash the source blocks so we can
- // resume from possible write errors
- if (overlap) {
+ // resume from possible write errors. In verify mode, we can skip stashing
+ // because the source blocks won't be overwritten.
+ if (overlap && params.canwrite) {
fprintf(stderr, "stashing %zu overlapping blocks to %s\n", src_blocks,
srchash.c_str());
@@ -953,7 +983,8 @@ static int LoadSrcTgtVersion3(CommandParameters& params, RangeSet& tgt, size_t&
return 0;
}
- if (overlap && LoadStash(params.stashbase, srchash, true, nullptr, params.buffer, true) == 0) {
+ if (overlap && LoadStash(params, params.stashbase, srchash, true, nullptr, params.buffer,
+ true) == 0) {
// Overlapping source blocks were previously stashed, command can proceed.
// We are recovering from an interrupted command, so we don't know if the
// stash can safely be deleted after this command.
@@ -1028,8 +1059,15 @@ static int PerformCommandFree(CommandParameters& params) {
return -1;
}
+ const std::string& id = params.tokens[params.cpos++];
+
+ if (!params.canwrite && stash_map.find(id) != stash_map.end()) {
+ stash_map.erase(id);
+ return 0;
+ }
+
if (params.createdstash || params.canwrite) {
- return FreeStash(params.stashbase, params.tokens[params.cpos++]);
+ return FreeStash(params.stashbase, id);
}
return 0;