diff options
Diffstat (limited to 'c_src/filebuffer.c')
-rw-r--r-- | c_src/filebuffer.c | 36 |
1 files changed, 26 insertions, 10 deletions
diff --git a/c_src/filebuffer.c b/c_src/filebuffer.c index 1e4f89d..921ba37 100644 --- a/c_src/filebuffer.c +++ b/c_src/filebuffer.c @@ -15,6 +15,7 @@ #include <fcntl.h> #include <err.h> #include <sys/file.h> +#include <errno.h> #include <nettle/sha2.h> #include "permdb.h" @@ -140,8 +141,8 @@ unsigned char * bf_read(buffered_file *file, uint64_t offset, size_t length, char **error) { unsigned char *result = malloc(length); - dprintf(READ, (stderr, "reading data: offset %llu\n", - (unsigned long long) offset)); + dprintf(READ, (stderr, "reading data: offset %llu length %llu\n", + (unsigned long long) offset, (unsigned long long) length)); if (offset >= file->filesize) { uint64_t writebufferoffset = offset - file->filesize; @@ -164,14 +165,28 @@ bf_read(buffered_file *file, uint64_t offset, size_t length, char **error) return NULL; } - ssize_t ret = pread(file->fd, result, length, (off_t) offset); - if (ret != length) { - free(result); - set_error(error, - "short pread: %zd (wanted %zu) at offset %llu\n", - ret, length, (long long unsigned int) offset); - return NULL; - } + size_t bytes_read = 0; + while (length > 0) { + ssize_t ret = pread(file->fd, result + bytes_read, length, (off_t) offset + bytes_read); + dprintf(READ, (stderr, "pread: offset %llu length %llu ret %zu\n", + (unsigned long long) offset + bytes_read, (unsigned long long) length, ret)); + + if (ret == 0) { + free(result); + set_error(error, + "eof reading %zu bytes at offset %llu\n", + length, (long long unsigned int) offset); + return NULL; + } else if (ret < 0) { + free(result); + set_error(error, + "error %d reading %zu bytes at offset %llu\n", + errno, length, (long long unsigned int) offset); + return NULL; + } + bytes_read += ret; + length -= ret; + } } return result; @@ -219,6 +234,7 @@ void bf_close(buffered_file *file) { bf_flush(file); + flock(file->fd, LOCK_UN); close(file->fd); free(file->writebuffer); free(file); |