aboutsummaryrefslogtreecommitdiffstats
path: root/updater/blockimg.c
diff options
context:
space:
mode:
Diffstat (limited to 'updater/blockimg.c')
-rw-r--r--updater/blockimg.c101
1 files changed, 84 insertions, 17 deletions
diff --git a/updater/blockimg.c b/updater/blockimg.c
index b006d10..be56fbd 100644
--- a/updater/blockimg.c
+++ b/updater/blockimg.c
@@ -61,30 +61,91 @@ typedef struct {
int pos[0];
} RangeSet;
+#define RANGESET_MAX_POINTS \
+ ((int)((INT_MAX / sizeof(int)) - sizeof(RangeSet)))
+
static RangeSet* parse_range(char* text) {
char* save;
- int num;
- num = strtol(strtok_r(text, ",", &save), NULL, 0);
+ char* token;
+ int i, num;
+ long int val;
+ RangeSet* out = NULL;
+ size_t bufsize;
- RangeSet* out = malloc(sizeof(RangeSet) + num * sizeof(int));
- if (out == NULL) {
- fprintf(stderr, "failed to allocate range of %zu bytes\n",
- sizeof(RangeSet) + num * sizeof(int));
- exit(1);
+ if (!text) {
+ goto err;
+ }
+
+ token = strtok_r(text, ",", &save);
+
+ if (!token) {
+ goto err;
}
+
+ val = strtol(token, NULL, 0);
+
+ if (val < 2 || val > RANGESET_MAX_POINTS) {
+ goto err;
+ } else if (val % 2) {
+ goto err; // must be even
+ }
+
+ num = (int) val;
+ bufsize = sizeof(RangeSet) + num * sizeof(int);
+
+ out = malloc(bufsize);
+
+ if (!out) {
+ fprintf(stderr, "failed to allocate range of %zu bytes\n", bufsize);
+ goto err;
+ }
+
out->count = num / 2;
out->size = 0;
- int i;
+
for (i = 0; i < num; ++i) {
- out->pos[i] = strtol(strtok_r(NULL, ",", &save), NULL, 0);
- if (i%2) {
+ token = strtok_r(NULL, ",", &save);
+
+ if (!token) {
+ goto err;
+ }
+
+ val = strtol(token, NULL, 0);
+
+ if (val < 0 || val > INT_MAX) {
+ goto err;
+ }
+
+ out->pos[i] = (int) val;
+
+ if (i % 2) {
+ if (out->pos[i - 1] >= out->pos[i]) {
+ goto err; // empty or negative range
+ }
+
+ if (out->size > INT_MAX - out->pos[i]) {
+ goto err; // overflow
+ }
+
out->size += out->pos[i];
} else {
+ if (out->size < 0) {
+ goto err;
+ }
+
out->size -= out->pos[i];
}
}
+ if (out->size <= 0) {
+ goto err;
+ }
+
return out;
+
+err:
+ fprintf(stderr, "failed to parse range '%s'\n", text ? text : "NULL");
+ exit(1);
}
static int range_overlaps(RangeSet* r1, RangeSet* r2) {
@@ -135,11 +196,6 @@ static int write_all(int fd, const uint8_t* data, size_t size) {
written += w;
}
- if (fsync(fd) == -1) {
- fprintf(stderr, "fsync failed: %s\n", strerror(errno));
- return -1;
- }
-
return 0;
}
@@ -285,7 +341,12 @@ static bool receive_new_data(const unsigned char* data, int size, void* cookie)
static void* unzip_new_data(void* cookie) {
NewThreadInfo* nti = (NewThreadInfo*) cookie;
- mzProcessZipEntryContents(nti->za, nti->entry, receive_new_data, nti);
+ if (strncmp(".xz", nti->entry->fileName + (nti->entry->fileNameLen - 3), 3) == 0) {
+ mzProcessZipEntryContentsXZ(nti->za, nti->entry, receive_new_data, nti);
+ } else {
+ mzProcessZipEntryContents(nti->za, nti->entry, receive_new_data, nti);
+ }
+
return NULL;
}
@@ -671,7 +732,7 @@ static int WriteStash(const char* base, const char* id, int blocks, uint8_t* buf
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));
+ fd = TEMP_FAILURE_RETRY(open(fn, O_WRONLY | O_CREAT | O_TRUNC, STASH_FILE_MODE));
if (fd == -1) {
fprintf(stderr, "failed to create \"%s\": %s\n", fn, strerror(errno));
@@ -1465,10 +1526,12 @@ static int PerformCommandErase(CommandParameters* params) {
// length in bytes
blocks[1] = (tgt->pos[i * 2 + 1] - tgt->pos[i * 2]) * (uint64_t) BLOCKSIZE;
+#ifndef SUPPRESS_EMMC_WIPE
if (ioctl(params->fd, BLKDISCARD, &blocks) == -1) {
fprintf(stderr, "BLKDISCARD ioctl failed: %s\n", strerror(errno));
goto pceout;
}
+#endif
}
}
@@ -1726,6 +1789,10 @@ static Value* PerformBlockImageUpdate(const char* name, State* state, int argc,
}
if (params.canwrite) {
+ if (fsync(params.fd) == -1) {
+ fprintf(stderr, "fsync failed: %s\n", strerror(errno));
+ goto pbiudone;
+ }
fprintf(cmd_pipe, "set_progress %.4f\n", (double) params.written / total_blocks);
fflush(cmd_pipe);
}