aboutsummaryrefslogtreecommitdiffstats
path: root/updater
diff options
context:
space:
mode:
authorSami Tolvanen <samitolvanen@google.com>2015-04-17 12:50:31 +0100
committerSami Tolvanen <samitolvanen@google.com>2015-04-17 13:07:08 +0100
commit43b748f2541ea77b2aa7b2f7eb4e0e8387beecca (patch)
treebd2094bf767a24c8795b5ec20d29c59aa7125f8d /updater
parent4381767aa6410902e07376f62f66bbef83ebf2c4 (diff)
downloadbootable_recovery-43b748f2541ea77b2aa7b2f7eb4e0e8387beecca.zip
bootable_recovery-43b748f2541ea77b2aa7b2f7eb4e0e8387beecca.tar.gz
bootable_recovery-43b748f2541ea77b2aa7b2f7eb4e0e8387beecca.tar.bz2
Don't remove existing explicitly stashed blocks
When automatically stashing overlapping blocks, should the stash file already exist due to an explicit stash command, it's not safe to remove the stash file after the command has completed. Note that it is safe to assume that the stash file will remain in place during the execution of the next command, so we don't have take other measures to preserve overlapping blocks. The stash file itself will be removed by a free command when it's no longer needed. Bug: 20297065 Change-Id: I8ff1a798b94086adff183c5aac03260eb947ae2c
Diffstat (limited to 'updater')
-rw-r--r--updater/blockimg.c38
1 files changed, 28 insertions, 10 deletions
diff --git a/updater/blockimg.c b/updater/blockimg.c
index 90b55b2..d5344f9 100644
--- a/updater/blockimg.c
+++ b/updater/blockimg.c
@@ -635,12 +635,13 @@ lsout:
}
static int WriteStash(const char* base, const char* id, int blocks, uint8_t* buffer,
- int checkspace) {
+ int checkspace, int *exists) {
char *fn = NULL;
char *cn = NULL;
int fd = -1;
int rc = -1;
int res;
+ struct stat st;
if (base == NULL || buffer == NULL) {
goto wsout;
@@ -658,6 +659,22 @@ static int WriteStash(const char* base, const char* id, int blocks, uint8_t* buf
goto wsout;
}
+ if (exists) {
+ res = stat(cn, &st);
+
+ if (res == 0) {
+ // The file already exists and since the name is the hash of the contents,
+ // it's safe to assume the contents are identical (accidental hash collisions
+ // are unlikely)
+ fprintf(stderr, " skipping %d existing blocks in %s\n", blocks, cn);
+ *exists = 1;
+ rc = 0;
+ goto wsout;
+ }
+
+ *exists = 0;
+ }
+
fprintf(stderr, " writing %d blocks to %s\n", blocks, cn);
fd = TEMP_FAILURE_RETRY(open(fn, O_WRONLY | O_CREAT | O_TRUNC | O_SYNC, STASH_FILE_MODE));
@@ -821,7 +838,7 @@ static int SaveStash(const char* base, char** wordsave, uint8_t** buffer, size_t
}
fprintf(stderr, "stashing %d blocks to %s\n", blocks, id);
- return WriteStash(base, id, blocks, *buffer, 0);
+ return WriteStash(base, id, blocks, *buffer, 0, NULL);
}
static int FreeStash(const char* base, const char* id) {
@@ -997,6 +1014,7 @@ static int LoadSrcTgtVersion3(CommandParameters* params, RangeSet** tgt, int* sr
int onehash, int* overlap) {
char* srchash = NULL;
char* tgthash = NULL;
+ int stash_exists = 0;
int overlap_blocks = 0;
int rc = -1;
uint8_t* tgtbuffer = NULL;
@@ -1052,13 +1070,16 @@ static int LoadSrcTgtVersion3(CommandParameters* params, RangeSet** tgt, int* sr
fprintf(stderr, "stashing %d overlapping blocks to %s\n", *src_blocks,
srchash);
- if (WriteStash(params->stashbase, srchash, *src_blocks, params->buffer, 1) != 0) {
+ if (WriteStash(params->stashbase, srchash, *src_blocks, params->buffer, 1,
+ &stash_exists) != 0) {
fprintf(stderr, "failed to stash overlapping source blocks\n");
goto v3out;
}
// Can be deleted when the write has completed
- params->freestash = srchash;
+ if (!stash_exists) {
+ params->freestash = srchash;
+ }
}
// Source blocks have expected content, command can proceed
@@ -1068,12 +1089,9 @@ static int LoadSrcTgtVersion3(CommandParameters* params, RangeSet** tgt, int* sr
if (*overlap && LoadStash(params->stashbase, srchash, 1, NULL, &params->buffer,
&params->bufsize, 1) == 0) {
- // Overlapping source blocks were previously stashed, command can proceed
- if (params->canwrite) {
- // We didn't create the stash, so delete after write only if we will
- // actually perform the write
- params->freestash = srchash;
- }
+ // 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.
rc = 0;
goto v3out;
}