summaryrefslogtreecommitdiffstats
path: root/updater/blockimg.c
diff options
context:
space:
mode:
Diffstat (limited to 'updater/blockimg.c')
-rw-r--r--updater/blockimg.c38
1 files changed, 28 insertions, 10 deletions
diff --git a/updater/blockimg.c b/updater/blockimg.c
index 90b55b2d2..d5344f991 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;
}