Check all lseek calls succeed.

Also add missing TEMP_FAILURE_RETRYs on read, write, and lseek.

Bug: http://b/20625546
Change-Id: I03b198e11c1921b35518ee2dd005a7cfcf4fd94b
This commit is contained in:
Elliott Hughes 2015-04-28 17:24:24 -07:00
parent 8c389e9c76
commit 7bad7c4646
14 changed files with 112 additions and 128 deletions

View file

@ -42,7 +42,7 @@ set_usb_driver(bool enabled) {
ui->Print("failed to open driver control: %s\n", strerror(errno));
return;
}
if (write(fd, enabled ? "1" : "0", 1) < 0) {
if (TEMP_FAILURE_RETRY(write(fd, enabled ? "1" : "0", 1)) == -1) {
ui->Print("failed to set driver control: %s\n", strerror(errno));
}
if (close(fd) < 0) {

View file

@ -422,21 +422,20 @@ int WriteToPartition(unsigned char* data, size_t len,
int attempt;
for (attempt = 0; attempt < 2; ++attempt) {
lseek(fd, start, SEEK_SET);
if (TEMP_FAILURE_RETRY(lseek(fd, start, SEEK_SET)) == -1) {
printf("failed seek on %s: %s\n",
partition, strerror(errno));
return -1;
}
while (start < len) {
size_t to_write = len - start;
if (to_write > 1<<20) to_write = 1<<20;
ssize_t written = write(fd, data+start, to_write);
if (written < 0) {
if (errno == EINTR) {
written = 0;
} else {
printf("failed write writing to %s (%s)\n",
partition, strerror(errno));
ssize_t written = TEMP_FAILURE_RETRY(write(fd, data+start, to_write));
if (written == -1) {
printf("failed write writing to %s: %s\n", partition, strerror(errno));
return -1;
}
}
start += written;
}
if (fsync(fd) != 0) {
@ -460,13 +459,20 @@ int WriteToPartition(unsigned char* data, size_t len,
// won't just be reading the cache.
sync();
int dc = open("/proc/sys/vm/drop_caches", O_WRONLY);
write(dc, "3\n", 2);
if (TEMP_FAILURE_RETRY(write(dc, "3\n", 2)) == -1) {
printf("write to /proc/sys/vm/drop_caches failed: %s\n", strerror(errno));
} else {
printf(" caches dropped\n");
}
close(dc);
sleep(1);
printf(" caches dropped\n");
// verify
lseek(fd, 0, SEEK_SET);
if (TEMP_FAILURE_RETRY(lseek(fd, 0, SEEK_SET)) == -1) {
printf("failed to seek back to beginning of %s: %s\n",
partition, strerror(errno));
return -1;
}
unsigned char buffer[4096];
start = len;
size_t p;
@ -476,16 +482,13 @@ int WriteToPartition(unsigned char* data, size_t len,
size_t so_far = 0;
while (so_far < to_read) {
ssize_t read_count = read(fd, buffer+so_far, to_read-so_far);
if (read_count < 0) {
if (errno == EINTR) {
read_count = 0;
} else {
ssize_t read_count =
TEMP_FAILURE_RETRY(read(fd, buffer+so_far, to_read-so_far));
if (read_count == -1) {
printf("verify read error %s at %zu: %s\n",
partition, p, strerror(errno));
return -1;
}
}
if ((size_t)read_count < to_read) {
printf("short verify read %s at %zu: %zd %zu %s\n",
partition, p, read_count, to_read, strerror(errno));
@ -625,8 +628,8 @@ ssize_t FileSink(const unsigned char* data, ssize_t len, void* token) {
ssize_t done = 0;
ssize_t wrote;
while (done < (ssize_t) len) {
wrote = write(fd, data+done, len-done);
if (wrote <= 0) {
wrote = TEMP_FAILURE_RETRY(write(fd, data+done, len-done));
if (wrote == -1) {
printf("error writing %d bytes: %s\n", (int)(len-done), strerror(errno));
return done;
}

View file

@ -36,20 +36,18 @@ struct file_data {
static int read_block_file(void* cookie, uint32_t block, uint8_t* buffer, uint32_t fetch_size) {
struct file_data* fd = (struct file_data*)cookie;
if (lseek(fd->fd, block * fd->block_size, SEEK_SET) < 0) {
printf("seek on sdcard failed: %s\n", strerror(errno));
off64_t offset = ((off64_t) block) * fd->block_size;
if (TEMP_FAILURE_RETRY(lseek64(fd->fd, offset, SEEK_SET)) == -1) {
fprintf(stderr, "seek on sdcard failed: %s\n", strerror(errno));
return -EIO;
}
while (fetch_size > 0) {
ssize_t r = read(fd->fd, buffer, fetch_size);
if (r < 0) {
if (r != -EINTR) {
printf("read on sdcard failed: %s\n", strerror(errno));
ssize_t r = TEMP_FAILURE_RETRY(read(fd->fd, buffer, fetch_size));
if (r == -1) {
fprintf(stderr, "read on sdcard failed: %s\n", strerror(errno));
return -EIO;
}
r = 0;
}
fetch_size -= r;
buffer += r;
}

View file

@ -442,15 +442,13 @@ int run_fuse_sideload(struct provider_vtab* vtab, void* cookie,
}
uint8_t request_buffer[sizeof(struct fuse_in_header) + PATH_MAX*8];
for (;;) {
ssize_t len = read(fd.ffd, request_buffer, sizeof(request_buffer));
if (len < 0) {
if (errno != EINTR) {
ssize_t len = TEMP_FAILURE_RETRY(read(fd.ffd, request_buffer, sizeof(request_buffer)));
if (len == -1) {
perror("read request");
if (errno == ENODEV) {
result = -1;
break;
}
}
continue;
}
@ -508,7 +506,7 @@ int run_fuse_sideload(struct provider_vtab* vtab, void* cookie,
outhdr.len = sizeof(outhdr);
outhdr.error = result;
outhdr.unique = hdr->unique;
write(fd.ffd, &outhdr, sizeof(outhdr));
TEMP_FAILURE_RETRY(write(fd.ffd, &outhdr, sizeof(outhdr)));
}
}

View file

@ -15,6 +15,7 @@
*/
#include <dirent.h>
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
@ -165,7 +166,7 @@ void ev_dispatch(void) {
int ev_get_input(int fd, uint32_t epevents, input_event* ev) {
if (epevents & EPOLLIN) {
ssize_t r = read(fd, ev, sizeof(*ev));
ssize_t r = TEMP_FAILURE_RETRY(read(fd, ev, sizeof(*ev)));
if (r == sizeof(*ev)) {
return 0;
}

View file

@ -27,11 +27,13 @@ static int getFileStartAndLength(int fd, off_t *start_, size_t *length_)
assert(start_ != NULL);
assert(length_ != NULL);
start = lseek(fd, 0L, SEEK_CUR);
end = lseek(fd, 0L, SEEK_END);
(void) lseek(fd, start, SEEK_SET);
// TODO: isn't start always 0 for the single call site? just use fstat instead?
if (start == (off_t) -1 || end == (off_t) -1) {
start = TEMP_FAILURE_RETRY(lseek(fd, 0L, SEEK_CUR));
end = TEMP_FAILURE_RETRY(lseek(fd, 0L, SEEK_END));
if (TEMP_FAILURE_RETRY(lseek(fd, start, SEEK_SET)) == -1 ||
start == (off_t) -1 || end == (off_t) -1) {
LOGE("could not determine length of file\n");
return -1;
}

View file

@ -675,13 +675,11 @@ static bool writeProcessFunction(const unsigned char *data, int dataLen,
}
ssize_t soFar = 0;
while (true) {
ssize_t n = write(fd, data+soFar, dataLen-soFar);
ssize_t n = TEMP_FAILURE_RETRY(write(fd, data+soFar, dataLen-soFar));
if (n <= 0) {
LOGE("Error writing %zd bytes from zip file from %p: %s\n",
dataLen-soFar, data+soFar, strerror(errno));
if (errno != EINTR) {
return false;
}
} else if (n > 0) {
soFar += n;
if (soFar == dataLen) return true;

View file

@ -72,7 +72,7 @@ int main(int argc, char **argv) {
if (fd < 0) die("error opening %s", argv[2]);
char header[HEADER_SIZE];
int headerlen = read(fd, header, sizeof(header));
int headerlen = TEMP_FAILURE_RETRY(read(fd, header, sizeof(header)));
if (headerlen <= 0) die("error reading %s header", argv[2]);
MtdReadContext *in = mtd_read_partition(partition);
@ -104,7 +104,7 @@ int main(int argc, char **argv) {
if (wrote != headerlen) die("error writing %s", argv[1]);
int len;
while ((len = read(fd, buf, sizeof(buf))) > 0) {
while ((len = TEMP_FAILURE_RETRY(read(fd, buf, sizeof(buf)))) > 0) {
wrote = mtd_write_data(out, buf, len);
if (wrote != len) die("error writing %s", argv[1]);
}
@ -125,13 +125,13 @@ int main(int argc, char **argv) {
if (mtd_partition_info(partition, NULL, &block_size, NULL))
die("error getting %s block size", argv[1]);
if (lseek(fd, headerlen, SEEK_SET) != headerlen)
if (TEMP_FAILURE_RETRY(lseek(fd, headerlen, SEEK_SET)) != headerlen)
die("error rewinding %s", argv[2]);
int left = block_size - headerlen;
while (left < 0) left += block_size;
while (left > 0) {
len = read(fd, buf, left > (int)sizeof(buf) ? (int)sizeof(buf) : left);
len = TEMP_FAILURE_RETRY(read(fd, buf, left > (int)sizeof(buf) ? (int)sizeof(buf) : left));
if (len <= 0) die("error reading %s", argv[2]);
if (mtd_write_data(out, buf, len) != len)
die("error writing %s", argv[1]);

View file

@ -108,7 +108,7 @@ mtd_scan_partitions()
if (fd < 0) {
goto bail;
}
nbytes = read(fd, buf, sizeof(buf) - 1);
nbytes = TEMP_FAILURE_RETRY(read(fd, buf, sizeof(buf) - 1));
close(fd);
if (nbytes < 0) {
goto bail;
@ -279,12 +279,6 @@ MtdReadContext *mtd_read_partition(const MtdPartition *partition)
return ctx;
}
// Seeks to a location in the partition. Don't mix with reads of
// anything other than whole blocks; unpredictable things will result.
void mtd_read_skip_to(const MtdReadContext* ctx, size_t offset) {
lseek64(ctx->fd, offset, SEEK_SET);
}
static int read_block(const MtdPartition *partition, int fd, char *data)
{
struct mtd_ecc_stats before, after;
@ -293,13 +287,18 @@ static int read_block(const MtdPartition *partition, int fd, char *data)
return -1;
}
loff_t pos = lseek64(fd, 0, SEEK_CUR);
loff_t pos = TEMP_FAILURE_RETRY(lseek64(fd, 0, SEEK_CUR));
if (pos == -1) {
printf("mtd: read_block: couldn't SEEK_CUR: %s\n", strerror(errno));
return -1;
}
ssize_t size = partition->erase_size;
int mgbb;
while (pos + size <= (int) partition->size) {
if (lseek64(fd, pos, SEEK_SET) != pos || read(fd, data, size) != size) {
if (TEMP_FAILURE_RETRY(lseek64(fd, pos, SEEK_SET)) != pos ||
TEMP_FAILURE_RETRY(read(fd, data, size)) != size) {
printf("mtd: read error at 0x%08llx (%s)\n",
pos, strerror(errno));
} else if (ioctl(fd, ECCGETSTATS, &after)) {
@ -409,8 +408,11 @@ static int write_block(MtdWriteContext *ctx, const char *data)
const MtdPartition *partition = ctx->partition;
int fd = ctx->fd;
off_t pos = lseek(fd, 0, SEEK_CUR);
if (pos == (off_t) -1) return 1;
off_t pos = TEMP_FAILURE_RETRY(lseek(fd, 0, SEEK_CUR));
if (pos == (off_t) -1) {
printf("mtd: write_block: couldn't SEEK_CUR: %s\n", strerror(errno));
return -1;
}
ssize_t size = partition->erase_size;
while (pos + size <= (int) partition->size) {
@ -435,15 +437,15 @@ static int write_block(MtdWriteContext *ctx, const char *data)
pos, strerror(errno));
continue;
}
if (lseek(fd, pos, SEEK_SET) != pos ||
write(fd, data, size) != size) {
if (TEMP_FAILURE_RETRY(lseek(fd, pos, SEEK_SET)) != pos ||
TEMP_FAILURE_RETRY(write(fd, data, size)) != size) {
printf("mtd: write error at 0x%08lx (%s)\n",
pos, strerror(errno));
}
char verify[size];
if (lseek(fd, pos, SEEK_SET) != pos ||
read(fd, verify, size) != size) {
if (TEMP_FAILURE_RETRY(lseek(fd, pos, SEEK_SET)) != pos ||
TEMP_FAILURE_RETRY(read(fd, verify, size)) != size) {
printf("mtd: re-read error at 0x%08lx (%s)\n",
pos, strerror(errno));
continue;
@ -512,8 +514,11 @@ off_t mtd_erase_blocks(MtdWriteContext *ctx, int blocks)
ctx->stored = 0;
}
off_t pos = lseek(ctx->fd, 0, SEEK_CUR);
if ((off_t) pos == (off_t) -1) return pos;
off_t pos = TEMP_FAILURE_RETRY(lseek(ctx->fd, 0, SEEK_CUR));
if ((off_t) pos == (off_t) -1) {
printf("mtd_erase_blocks: couldn't SEEK_CUR: %s\n", strerror(errno));
return -1;
}
const int total = (ctx->partition->size - pos) / ctx->partition->erase_size;
if (blocks < 0) blocks = total;
@ -554,18 +559,3 @@ int mtd_write_close(MtdWriteContext *ctx)
free(ctx);
return r;
}
/* Return the offset of the first good block at or after pos (which
* might be pos itself).
*/
off_t mtd_find_write_start(MtdWriteContext *ctx, off_t pos) {
int i;
for (i = 0; i < ctx->bad_block_count; ++i) {
if (ctx->bad_block_offsets[i] == pos) {
pos += ctx->partition->erase_size;
} else if (ctx->bad_block_offsets[i] > pos) {
return pos;
}
}
return pos;
}

View file

@ -49,12 +49,10 @@ typedef struct MtdWriteContext MtdWriteContext;
MtdReadContext *mtd_read_partition(const MtdPartition *);
ssize_t mtd_read_data(MtdReadContext *, char *data, size_t data_len);
void mtd_read_close(MtdReadContext *);
void mtd_read_skip_to(const MtdReadContext *, size_t offset);
MtdWriteContext *mtd_write_partition(const MtdPartition *);
ssize_t mtd_write_data(MtdWriteContext *, const char *data, size_t data_len);
off_t mtd_erase_blocks(MtdWriteContext *, int blocks); /* 0 ok, -1 for all */
off_t mtd_find_write_start(MtdWriteContext *ctx, off_t pos);
int mtd_write_close(MtdWriteContext *);
#ifdef __cplusplus

View file

@ -78,7 +78,7 @@ int main(int argc __attribute__((unused)), char **argv __attribute__((unused)))
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.
write(fd, fn, sizeof(fn)); // write, you know, some data
TEMP_FAILURE_RETRY(write(fd, fn, sizeof(fn))); // write, you know, some data
close(fd);
unlink(fn);
}

2
ui.cpp
View file

@ -251,7 +251,7 @@ bool RecoveryUI::IsUsbConnected() {
char buf;
// USB is connected if android_usb state is CONNECTED or CONFIGURED.
int connected = (read(fd, &buf, 1) == 1) && (buf == 'C');
int connected = (TEMP_FAILURE_RETRY(read(fd, &buf, 1)) == 1) && (buf == 'C');
if (close(fd) < 0) {
printf("failed to close /sys/class/android_usb/android0/state: %s\n",
strerror(errno));

View file

@ -65,12 +65,15 @@ static struct fstab* fstab = NULL;
static int write_at_offset(unsigned char* buffer, size_t size,
int wfd, off64_t offset)
{
lseek64(wfd, offset, SEEK_SET);
if (TEMP_FAILURE_RETRY(lseek64(wfd, offset, SEEK_SET)) == -1) {
ALOGE("error seeking to offset %lld: %s\n", offset, strerror(errno));
return -1;
}
size_t written = 0;
while (written < size) {
ssize_t wrote = write(wfd, buffer + written, size - written);
if (wrote < 0) {
ALOGE("error writing offset %lld: %s\n", offset, strerror(errno));
ssize_t wrote = TEMP_FAILURE_RETRY(write(wfd, buffer + written, size - written));
if (wrote == -1) {
ALOGE("error writing offset %lld: %s\n", (offset + written), strerror(errno));
return -1;
}
written += wrote;
@ -275,8 +278,9 @@ int produce_block_map(const char* path, const char* map_file, const char* blk_de
if (encrypted) {
size_t so_far = 0;
while (so_far < sb.st_blksize && pos < sb.st_size) {
ssize_t this_read = read(fd, buffers[tail] + so_far, sb.st_blksize - so_far);
if (this_read < 0) {
ssize_t this_read =
TEMP_FAILURE_RETRY(read(fd, buffers[tail] + so_far, sb.st_blksize - so_far));
if (this_read == -1) {
ALOGE("failed to read: %s\n", strerror(errno));
return -1;
}
@ -340,8 +344,8 @@ void wipe_misc() {
size_t written = 0;
size_t size = sizeof(zeroes);
while (written < size) {
ssize_t w = write(fd, zeroes, size-written);
if (w < 0 && errno != EINTR) {
ssize_t w = TEMP_FAILURE_RETRY(write(fd, zeroes, size-written));
if (w == -1) {
ALOGE("zero write failed: %s\n", strerror(errno));
return;
} else {

View file

@ -113,13 +113,12 @@ static int range_overlaps(RangeSet* r1, RangeSet* r2) {
static int read_all(int fd, uint8_t* data, size_t size) {
size_t so_far = 0;
while (so_far < size) {
ssize_t r = read(fd, data+so_far, size-so_far);
if (r < 0 && errno != EINTR) {
ssize_t r = TEMP_FAILURE_RETRY(read(fd, data+so_far, size-so_far));
if (r == -1) {
fprintf(stderr, "read failed: %s\n", strerror(errno));
return -1;
} else {
so_far += r;
}
so_far += r;
}
return 0;
}
@ -127,13 +126,12 @@ static int read_all(int fd, uint8_t* data, size_t size) {
static int write_all(int fd, const uint8_t* data, size_t size) {
size_t written = 0;
while (written < size) {
ssize_t w = write(fd, data+written, size-written);
if (w < 0 && errno != EINTR) {
ssize_t w = TEMP_FAILURE_RETRY(write(fd, data+written, size-written));
if (w == -1) {
fprintf(stderr, "write failed: %s\n", strerror(errno));
return -1;
} else {
written += w;
}
written += w;
}
if (fsync(fd) == -1) {
@ -144,19 +142,13 @@ static int write_all(int fd, const uint8_t* data, size_t size) {
return 0;
}
static int check_lseek(int fd, off64_t offset, int whence) {
while (true) {
off64_t ret = lseek64(fd, offset, whence);
if (ret < 0) {
if (errno != EINTR) {
static bool check_lseek(int fd, off64_t offset, int whence) {
off64_t rc = TEMP_FAILURE_RETRY(lseek64(fd, offset, whence));
if (rc == -1) {
fprintf(stderr, "lseek64 failed: %s\n", strerror(errno));
return -1;
return false;
}
} else {
break;
}
}
return 0;
return true;
}
static void allocate(size_t size, uint8_t** buffer, size_t* buffer_alloc) {
@ -213,8 +205,8 @@ static ssize_t RangeSinkWrite(const uint8_t* data, ssize_t size, void* token) {
rss->p_remain = (rss->tgt->pos[rss->p_block * 2 + 1] -
rss->tgt->pos[rss->p_block * 2]) * BLOCKSIZE;
if (check_lseek(rss->fd, (off64_t)rss->tgt->pos[rss->p_block*2] * BLOCKSIZE,
SEEK_SET) == -1) {
if (!check_lseek(rss->fd, (off64_t)rss->tgt->pos[rss->p_block*2] * BLOCKSIZE,
SEEK_SET)) {
break;
}
} else {
@ -306,7 +298,7 @@ static int ReadBlocks(RangeSet* src, uint8_t* buffer, int fd) {
}
for (i = 0; i < src->count; ++i) {
if (check_lseek(fd, (off64_t) src->pos[i * 2] * BLOCKSIZE, SEEK_SET) == -1) {
if (!check_lseek(fd, (off64_t) src->pos[i * 2] * BLOCKSIZE, SEEK_SET)) {
return -1;
}
@ -332,7 +324,7 @@ static int WriteBlocks(RangeSet* tgt, uint8_t* buffer, int fd) {
}
for (i = 0; i < tgt->count; ++i) {
if (check_lseek(fd, (off64_t) tgt->pos[i * 2] * BLOCKSIZE, SEEK_SET) == -1) {
if (!check_lseek(fd, (off64_t) tgt->pos[i * 2] * BLOCKSIZE, SEEK_SET)) {
return -1;
}
@ -1217,7 +1209,7 @@ static int PerformCommandZero(CommandParameters* params) {
if (params->canwrite) {
for (i = 0; i < tgt->count; ++i) {
if (check_lseek(params->fd, (off64_t) tgt->pos[i * 2] * BLOCKSIZE, SEEK_SET) == -1) {
if (!check_lseek(params->fd, (off64_t) tgt->pos[i * 2] * BLOCKSIZE, SEEK_SET)) {
goto pczout;
}
@ -1271,7 +1263,7 @@ static int PerformCommandNew(CommandParameters* params) {
rss.p_block = 0;
rss.p_remain = (tgt->pos[1] - tgt->pos[0]) * BLOCKSIZE;
if (check_lseek(params->fd, (off64_t) tgt->pos[0] * BLOCKSIZE, SEEK_SET) == -1) {
if (!check_lseek(params->fd, (off64_t) tgt->pos[0] * BLOCKSIZE, SEEK_SET)) {
goto pcnout;
}
@ -1367,7 +1359,7 @@ static int PerformCommandDiff(CommandParameters* params) {
rss.p_block = 0;
rss.p_remain = (tgt->pos[1] - tgt->pos[0]) * BLOCKSIZE;
if (check_lseek(params->fd, (off64_t) tgt->pos[0] * BLOCKSIZE, SEEK_SET) == -1) {
if (!check_lseek(params->fd, (off64_t) tgt->pos[0] * BLOCKSIZE, SEEK_SET)) {
goto pcdout;
}
@ -1906,7 +1898,7 @@ Value* RangeSha1Fn(const char* name, State* state, int argc, Expr* argv[]) {
int i, j;
for (i = 0; i < rs->count; ++i) {
if (check_lseek(fd, (off64_t)rs->pos[i*2] * BLOCKSIZE, SEEK_SET) == -1) {
if (!check_lseek(fd, (off64_t)rs->pos[i*2] * BLOCKSIZE, SEEK_SET)) {
ErrorAbort(state, "failed to seek %s: %s", blockdev_filename->data,
strerror(errno));
goto done;