summaryrefslogtreecommitdiff
path: root/c_src/filebuffer.c
diff options
context:
space:
mode:
Diffstat (limited to 'c_src/filebuffer.c')
-rw-r--r--c_src/filebuffer.c36
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);