diff --git a/lib/internal.h b/lib/internal.h index 78816c0b..e60af497 100644 --- a/lib/internal.h +++ b/lib/internal.h @@ -106,6 +106,7 @@ ssize_t read_buffer(int fd, void *buf, size_t count); ssize_t write_blockwise(int fd, int bsize, void *buf, size_t count); ssize_t read_blockwise(int fd, int bsize, void *_buf, size_t count); ssize_t write_lseek_blockwise(int fd, int bsize, char *buf, size_t count, off_t offset); +ssize_t read_lseek_blockwise(int fd, int bsize, char *buf, size_t count, off_t offset); unsigned crypt_getpagesize(void); int init_crypto(struct crypt_device *ctx); diff --git a/lib/utils.c b/lib/utils.c index b5a21ef9..9b825573 100644 --- a/lib/utils.c +++ b/lib/utils.c @@ -273,6 +273,52 @@ out: return ret; } +ssize_t read_lseek_blockwise(int fd, int bsize, char *buf, size_t count, off_t offset) +{ + char *frontPadBuf; + void *frontPadBuf_base = NULL; + int r, frontHang; + size_t innerCount = 0; + ssize_t ret = -1; + + if (fd == -1 || !buf || bsize <= 0) + return -1; + + frontHang = offset % bsize; + + if (lseek(fd, offset - frontHang, SEEK_SET) < 0) + return ret; + + if (frontHang) { + frontPadBuf = aligned_malloc(&frontPadBuf_base, + bsize, get_alignment(fd)); + + if (!frontPadBuf) + return ret; + + r = read_buffer(fd, frontPadBuf, bsize); + if (r < 0 || r != bsize) + goto out; + + innerCount = bsize - frontHang; + if (innerCount > count) + innerCount = count; + + memcpy(buf, frontPadBuf + frontHang, innerCount); + + buf += innerCount; + count -= innerCount; + } + + ret = read_blockwise(fd, bsize, buf, count); + if (ret >= 0) + ret += innerCount; +out: + free(frontPadBuf_base); + + return ret; +} + /* MEMLOCK */ #define DEFAULT_PROCESS_PRIORITY -18