|
|
7cdc99 |
From a117f431179a2747f2b1d5293f43d9e198f1bac9 Mon Sep 17 00:00:00 2001
|
|
|
7cdc99 |
From: Ondrej Kozina <okozina@redhat.com>
|
|
|
7cdc99 |
Date: Mon, 30 Nov 2015 16:44:15 +0100
|
|
|
7cdc99 |
Subject: [PATCH] Fix access to unaligned hidden TrueCrypt header.
|
|
|
7cdc99 |
|
|
|
7cdc99 |
backport all changes needed to fix unaligned access
|
|
|
7cdc99 |
to hidden TrueCrypt hedaer.
|
|
|
7cdc99 |
---
|
|
|
7cdc99 |
lib/internal.h | 7 ++-
|
|
|
7cdc99 |
lib/luks1/keymanage.c | 6 +-
|
|
|
7cdc99 |
lib/tcrypt/tcrypt.c | 24 ++++----
|
|
|
7cdc99 |
lib/utils.c | 155 +++++++++++++++++++++++++++++++++++++++++++-------
|
|
|
7cdc99 |
4 files changed, 152 insertions(+), 40 deletions(-)
|
|
|
7cdc99 |
|
|
|
7cdc99 |
diff --git a/lib/internal.h b/lib/internal.h
|
|
|
7cdc99 |
index 382a600..f1525f2 100644
|
|
|
7cdc99 |
--- a/lib/internal.h
|
|
|
7cdc99 |
+++ b/lib/internal.h
|
|
|
7cdc99 |
@@ -101,9 +101,12 @@ char *crypt_get_partition_device(const char *dev_path, uint64_t offset, uint64_t
|
|
|
7cdc99 |
char *crypt_get_base_device(const char *dev_path);
|
|
|
7cdc99 |
uint64_t crypt_dev_partition_offset(const char *dev_path);
|
|
|
7cdc99 |
|
|
|
7cdc99 |
+ssize_t write_buffer(int fd, const void *buf, size_t count);
|
|
|
7cdc99 |
+ssize_t read_buffer(int fd, void *buf, size_t count);
|
|
|
7cdc99 |
ssize_t write_blockwise(int fd, int bsize, void *buf, size_t count);
|
|
|
7cdc99 |
-ssize_t read_blockwise(int fd, int bsize, void *_buf, size_t count);
|
|
|
7cdc99 |
-ssize_t write_lseek_blockwise(int fd, int bsize, char *buf, size_t count, off_t offset);
|
|
|
7cdc99 |
+ssize_t read_blockwise(int fd, int bsize, void *buf, size_t count);
|
|
|
7cdc99 |
+ssize_t write_lseek_blockwise(int fd, int bsize, void *buf, size_t count, off_t offset);
|
|
|
7cdc99 |
+ssize_t read_lseek_blockwise(int fd, int bsize, void *buf, size_t count, off_t offset);
|
|
|
7cdc99 |
|
|
|
7cdc99 |
unsigned crypt_getpagesize(void);
|
|
|
7cdc99 |
int init_crypto(struct crypt_device *ctx);
|
|
|
7cdc99 |
diff --git a/lib/luks1/keymanage.c b/lib/luks1/keymanage.c
|
|
|
7cdc99 |
index 23e3fe2..b193ee9 100644
|
|
|
7cdc99 |
--- a/lib/luks1/keymanage.c
|
|
|
7cdc99 |
+++ b/lib/luks1/keymanage.c
|
|
|
7cdc99 |
@@ -201,7 +201,7 @@ int LUKS_hdr_backup(const char *backup_file, struct crypt_device *ctx)
|
|
|
7cdc99 |
r = -EINVAL;
|
|
|
7cdc99 |
goto out;
|
|
|
7cdc99 |
}
|
|
|
7cdc99 |
- if (write(devfd, buffer, buffer_size) < buffer_size) {
|
|
|
7cdc99 |
+ if (write_buffer(devfd, buffer, buffer_size) < buffer_size) {
|
|
|
7cdc99 |
log_err(ctx, _("Cannot write header backup file %s.\n"), backup_file);
|
|
|
7cdc99 |
r = -EIO;
|
|
|
7cdc99 |
goto out;
|
|
|
7cdc99 |
@@ -253,7 +253,7 @@ int LUKS_hdr_restore(
|
|
|
7cdc99 |
goto out;
|
|
|
7cdc99 |
}
|
|
|
7cdc99 |
|
|
|
7cdc99 |
- if (read(devfd, buffer, buffer_size) < buffer_size) {
|
|
|
7cdc99 |
+ if (read_buffer(devfd, buffer, buffer_size) < buffer_size) {
|
|
|
7cdc99 |
log_err(ctx, _("Cannot read header backup file %s.\n"), backup_file);
|
|
|
7cdc99 |
r = -EIO;
|
|
|
7cdc99 |
goto out;
|
|
|
7cdc99 |
@@ -498,7 +498,7 @@ int LUKS_read_phdr_backup(const char *backup_file,
|
|
|
7cdc99 |
return -ENOENT;
|
|
|
7cdc99 |
}
|
|
|
7cdc99 |
|
|
|
7cdc99 |
- if (read(devfd, hdr, hdr_size) < hdr_size)
|
|
|
7cdc99 |
+ if (read_buffer(devfd, hdr, hdr_size) < hdr_size)
|
|
|
7cdc99 |
r = -EIO;
|
|
|
7cdc99 |
else {
|
|
|
7cdc99 |
LUKS_fix_header_compatible(hdr);
|
|
|
7cdc99 |
diff --git a/lib/tcrypt/tcrypt.c b/lib/tcrypt/tcrypt.c
|
|
|
7cdc99 |
index 45154ed..9ff7157 100644
|
|
|
7cdc99 |
--- a/lib/tcrypt/tcrypt.c
|
|
|
7cdc99 |
+++ b/lib/tcrypt/tcrypt.c
|
|
|
7cdc99 |
@@ -469,8 +469,7 @@ static int TCRYPT_pool_keyfile(struct crypt_device *cd,
|
|
|
7cdc99 |
return -EIO;
|
|
|
7cdc99 |
}
|
|
|
7cdc99 |
|
|
|
7cdc99 |
- /* FIXME: add while */
|
|
|
7cdc99 |
- data_size = read(fd, data, TCRYPT_KEYFILE_LEN);
|
|
|
7cdc99 |
+ data_size = read_buffer(fd, data, TCRYPT_KEYFILE_LEN);
|
|
|
7cdc99 |
close(fd);
|
|
|
7cdc99 |
if (data_size < 0) {
|
|
|
7cdc99 |
log_err(cd, _("Error reading keyfile %s.\n"), keyfile);
|
|
|
7cdc99 |
@@ -628,27 +627,26 @@ int TCRYPT_read_phdr(struct crypt_device *cd,
|
|
|
7cdc99 |
|
|
|
7cdc99 |
r = -EIO;
|
|
|
7cdc99 |
if (params->flags & CRYPT_TCRYPT_SYSTEM_HEADER) {
|
|
|
7cdc99 |
- if (lseek(devfd, TCRYPT_HDR_SYSTEM_OFFSET, SEEK_SET) >= 0 &&
|
|
|
7cdc99 |
- read_blockwise(devfd, bs, hdr, hdr_size) == hdr_size) {
|
|
|
7cdc99 |
+ if (read_lseek_blockwise(devfd, bs, hdr, hdr_size,
|
|
|
7cdc99 |
+ TCRYPT_HDR_SYSTEM_OFFSET) == hdr_size) {
|
|
|
7cdc99 |
r = TCRYPT_init_hdr(cd, hdr, params);
|
|
|
7cdc99 |
}
|
|
|
7cdc99 |
} else if (params->flags & CRYPT_TCRYPT_HIDDEN_HEADER) {
|
|
|
7cdc99 |
if (params->flags & CRYPT_TCRYPT_BACKUP_HEADER) {
|
|
|
7cdc99 |
- if (lseek(devfd, TCRYPT_HDR_HIDDEN_OFFSET_BCK, SEEK_END) >= 0 &&
|
|
|
7cdc99 |
- read_blockwise(devfd, bs, hdr, hdr_size) == hdr_size)
|
|
|
7cdc99 |
+ if (read_lseek_blockwise(devfd, bs, hdr, hdr_size,
|
|
|
7cdc99 |
+ TCRYPT_HDR_HIDDEN_OFFSET_BCK) == hdr_size)
|
|
|
7cdc99 |
r = TCRYPT_init_hdr(cd, hdr, params);
|
|
|
7cdc99 |
} else {
|
|
|
7cdc99 |
- if (lseek(devfd, TCRYPT_HDR_HIDDEN_OFFSET, SEEK_SET) >= 0 &&
|
|
|
7cdc99 |
- read_blockwise(devfd, bs, hdr, hdr_size) == hdr_size)
|
|
|
7cdc99 |
+ if (read_lseek_blockwise(devfd, bs, hdr, hdr_size,
|
|
|
7cdc99 |
+ TCRYPT_HDR_HIDDEN_OFFSET) == hdr_size)
|
|
|
7cdc99 |
r = TCRYPT_init_hdr(cd, hdr, params);
|
|
|
7cdc99 |
- if (r &&
|
|
|
7cdc99 |
- lseek(devfd, TCRYPT_HDR_HIDDEN_OFFSET_OLD, SEEK_END) >= 0 &&
|
|
|
7cdc99 |
- read_blockwise(devfd, bs, hdr, hdr_size) == hdr_size)
|
|
|
7cdc99 |
+ if (r && read_lseek_blockwise(devfd, bs, hdr, hdr_size,
|
|
|
7cdc99 |
+ TCRYPT_HDR_HIDDEN_OFFSET_OLD) == hdr_size)
|
|
|
7cdc99 |
r = TCRYPT_init_hdr(cd, hdr, params);
|
|
|
7cdc99 |
}
|
|
|
7cdc99 |
} else if (params->flags & CRYPT_TCRYPT_BACKUP_HEADER) {
|
|
|
7cdc99 |
- if (lseek(devfd, TCRYPT_HDR_OFFSET_BCK, SEEK_END) >= 0 &&
|
|
|
7cdc99 |
- read_blockwise(devfd, bs, hdr, hdr_size) == hdr_size)
|
|
|
7cdc99 |
+ if (read_lseek_blockwise(devfd, bs, hdr, hdr_size,
|
|
|
7cdc99 |
+ TCRYPT_HDR_OFFSET_BCK) == hdr_size)
|
|
|
7cdc99 |
r = TCRYPT_init_hdr(cd, hdr, params);
|
|
|
7cdc99 |
} else if (read_blockwise(devfd, bs, hdr, hdr_size) == hdr_size)
|
|
|
7cdc99 |
r = TCRYPT_init_hdr(cd, hdr, params);
|
|
|
7cdc99 |
diff --git a/lib/utils.c b/lib/utils.c
|
|
|
7cdc99 |
index 2dcf753..802ba55 100644
|
|
|
7cdc99 |
--- a/lib/utils.c
|
|
|
7cdc99 |
+++ b/lib/utils.c
|
|
|
7cdc99 |
@@ -56,22 +56,70 @@ static void *aligned_malloc(void **base, int size, int alignment)
|
|
|
7cdc99 |
/* Credits go to Michal's padlock patches for this alignment code */
|
|
|
7cdc99 |
char *ptr;
|
|
|
7cdc99 |
|
|
|
7cdc99 |
- ptr = malloc(size + alignment);
|
|
|
7cdc99 |
- if(ptr == NULL) return NULL;
|
|
|
7cdc99 |
+ ptr = malloc(size + alignment);
|
|
|
7cdc99 |
+ if (!ptr)
|
|
|
7cdc99 |
+ return NULL;
|
|
|
7cdc99 |
|
|
|
7cdc99 |
*base = ptr;
|
|
|
7cdc99 |
- if(alignment > 1 && ((long)ptr & (alignment - 1))) {
|
|
|
7cdc99 |
+ if (alignment > 1 && ((long)ptr & (alignment - 1)))
|
|
|
7cdc99 |
ptr += alignment - ((long)(ptr) & (alignment - 1));
|
|
|
7cdc99 |
- }
|
|
|
7cdc99 |
+
|
|
|
7cdc99 |
return ptr;
|
|
|
7cdc99 |
#endif
|
|
|
7cdc99 |
}
|
|
|
7cdc99 |
|
|
|
7cdc99 |
+ssize_t read_buffer(int fd, void *buf, size_t count)
|
|
|
7cdc99 |
+{
|
|
|
7cdc99 |
+ size_t read_size = 0;
|
|
|
7cdc99 |
+ ssize_t r;
|
|
|
7cdc99 |
+
|
|
|
7cdc99 |
+ if (fd < 0 || !buf)
|
|
|
7cdc99 |
+ return -EINVAL;
|
|
|
7cdc99 |
+
|
|
|
7cdc99 |
+ do {
|
|
|
7cdc99 |
+ r = read(fd, buf, count - read_size);
|
|
|
7cdc99 |
+ if (r == -1 && errno != EINTR)
|
|
|
7cdc99 |
+ return r;
|
|
|
7cdc99 |
+ if (r == 0)
|
|
|
7cdc99 |
+ return (ssize_t)read_size;
|
|
|
7cdc99 |
+ if (r > 0) {
|
|
|
7cdc99 |
+ read_size += (size_t)r;
|
|
|
7cdc99 |
+ buf = (uint8_t*)buf + r;
|
|
|
7cdc99 |
+ }
|
|
|
7cdc99 |
+ } while (read_size != count);
|
|
|
7cdc99 |
+
|
|
|
7cdc99 |
+ return (ssize_t)count;
|
|
|
7cdc99 |
+}
|
|
|
7cdc99 |
+
|
|
|
7cdc99 |
+ssize_t write_buffer(int fd, const void *buf, size_t count)
|
|
|
7cdc99 |
+{
|
|
|
7cdc99 |
+ size_t write_size = 0;
|
|
|
7cdc99 |
+ ssize_t w;
|
|
|
7cdc99 |
+
|
|
|
7cdc99 |
+ if (fd < 0 || !buf || !count)
|
|
|
7cdc99 |
+ return -EINVAL;
|
|
|
7cdc99 |
+
|
|
|
7cdc99 |
+ do {
|
|
|
7cdc99 |
+ w = write(fd, buf, count - write_size);
|
|
|
7cdc99 |
+ if (w < 0 && errno != EINTR)
|
|
|
7cdc99 |
+ return w;
|
|
|
7cdc99 |
+ if (w == 0)
|
|
|
7cdc99 |
+ return (ssize_t)write_size;
|
|
|
7cdc99 |
+ if (w > 0) {
|
|
|
7cdc99 |
+ write_size += (size_t) w;
|
|
|
7cdc99 |
+ buf = (const uint8_t*)buf + w;
|
|
|
7cdc99 |
+ }
|
|
|
7cdc99 |
+ } while (write_size != count);
|
|
|
7cdc99 |
+
|
|
|
7cdc99 |
+ return (ssize_t)write_size;
|
|
|
7cdc99 |
+}
|
|
|
7cdc99 |
+
|
|
|
7cdc99 |
ssize_t write_blockwise(int fd, int bsize, void *orig_buf, size_t count)
|
|
|
7cdc99 |
{
|
|
|
7cdc99 |
void *hangover_buf, *hangover_buf_base = NULL;
|
|
|
7cdc99 |
void *buf, *buf_base = NULL;
|
|
|
7cdc99 |
- int r, hangover, solid, alignment;
|
|
|
7cdc99 |
+ int r, alignment;
|
|
|
7cdc99 |
+ size_t hangover, solid;
|
|
|
7cdc99 |
ssize_t ret = -1;
|
|
|
7cdc99 |
|
|
|
7cdc99 |
if (fd == -1 || !orig_buf || bsize <= 0)
|
|
|
7cdc99 |
@@ -89,17 +137,19 @@ ssize_t write_blockwise(int fd, int bsize, void *orig_buf, size_t count)
|
|
|
7cdc99 |
} else
|
|
|
7cdc99 |
buf = orig_buf;
|
|
|
7cdc99 |
|
|
|
7cdc99 |
- r = write(fd, buf, solid);
|
|
|
7cdc99 |
- if (r < 0 || r != solid)
|
|
|
7cdc99 |
- goto out;
|
|
|
7cdc99 |
+ if (solid) {
|
|
|
7cdc99 |
+ r = write_buffer(fd, buf, solid);
|
|
|
7cdc99 |
+ if (r < 0 || r != (ssize_t)solid)
|
|
|
7cdc99 |
+ goto out;
|
|
|
7cdc99 |
+ }
|
|
|
7cdc99 |
|
|
|
7cdc99 |
if (hangover) {
|
|
|
7cdc99 |
hangover_buf = aligned_malloc(&hangover_buf_base, bsize, alignment);
|
|
|
7cdc99 |
if (!hangover_buf)
|
|
|
7cdc99 |
goto out;
|
|
|
7cdc99 |
|
|
|
7cdc99 |
- r = read(fd, hangover_buf, bsize);
|
|
|
7cdc99 |
- if (r < 0 || r < hangover)
|
|
|
7cdc99 |
+ r = read_buffer(fd, hangover_buf, bsize);
|
|
|
7cdc99 |
+ if (r < 0 || r < (ssize_t)hangover)
|
|
|
7cdc99 |
goto out;
|
|
|
7cdc99 |
|
|
|
7cdc99 |
if (r < bsize)
|
|
|
7cdc99 |
@@ -110,8 +160,8 @@ ssize_t write_blockwise(int fd, int bsize, void *orig_buf, size_t count)
|
|
|
7cdc99 |
|
|
|
7cdc99 |
memcpy(hangover_buf, (char*)buf + solid, hangover);
|
|
|
7cdc99 |
|
|
|
7cdc99 |
- r = write(fd, hangover_buf, bsize);
|
|
|
7cdc99 |
- if (r < 0 || r < hangover)
|
|
|
7cdc99 |
+ r = write_buffer(fd, hangover_buf, bsize);
|
|
|
7cdc99 |
+ if (r < 0 || r < (ssize_t)hangover)
|
|
|
7cdc99 |
goto out;
|
|
|
7cdc99 |
}
|
|
|
7cdc99 |
ret = count;
|
|
|
7cdc99 |
@@ -122,10 +172,12 @@ out:
|
|
|
7cdc99 |
return ret;
|
|
|
7cdc99 |
}
|
|
|
7cdc99 |
|
|
|
7cdc99 |
-ssize_t read_blockwise(int fd, int bsize, void *orig_buf, size_t count) {
|
|
|
7cdc99 |
+ssize_t read_blockwise(int fd, int bsize, void *orig_buf, size_t count)
|
|
|
7cdc99 |
+{
|
|
|
7cdc99 |
void *hangover_buf, *hangover_buf_base = NULL;
|
|
|
7cdc99 |
void *buf, *buf_base = NULL;
|
|
|
7cdc99 |
- int r, hangover, solid, alignment;
|
|
|
7cdc99 |
+ int r, alignment;
|
|
|
7cdc99 |
+ size_t hangover, solid;
|
|
|
7cdc99 |
ssize_t ret = -1;
|
|
|
7cdc99 |
|
|
|
7cdc99 |
if (fd == -1 || !orig_buf || bsize <= 0)
|
|
|
7cdc99 |
@@ -142,16 +194,16 @@ ssize_t read_blockwise(int fd, int bsize, void *orig_buf, size_t count) {
|
|
|
7cdc99 |
} else
|
|
|
7cdc99 |
buf = orig_buf;
|
|
|
7cdc99 |
|
|
|
7cdc99 |
- r = read(fd, buf, solid);
|
|
|
7cdc99 |
- if(r < 0 || r != solid)
|
|
|
7cdc99 |
+ r = read_buffer(fd, buf, solid);
|
|
|
7cdc99 |
+ if (r < 0 || r != (ssize_t)solid)
|
|
|
7cdc99 |
goto out;
|
|
|
7cdc99 |
|
|
|
7cdc99 |
if (hangover) {
|
|
|
7cdc99 |
hangover_buf = aligned_malloc(&hangover_buf_base, bsize, alignment);
|
|
|
7cdc99 |
if (!hangover_buf)
|
|
|
7cdc99 |
goto out;
|
|
|
7cdc99 |
- r = read(fd, hangover_buf, bsize);
|
|
|
7cdc99 |
- if (r < 0 || r < hangover)
|
|
|
7cdc99 |
+ r = read_buffer(fd, hangover_buf, bsize);
|
|
|
7cdc99 |
+ if (r < 0 || r < (ssize_t)hangover)
|
|
|
7cdc99 |
goto out;
|
|
|
7cdc99 |
|
|
|
7cdc99 |
memcpy((char *)buf + solid, hangover_buf, hangover);
|
|
|
7cdc99 |
@@ -172,7 +224,8 @@ out:
|
|
|
7cdc99 |
* is implicitly included in the read/write offset, which can not be set to non-aligned
|
|
|
7cdc99 |
* boundaries. Hence, we combine llseek with write.
|
|
|
7cdc99 |
*/
|
|
|
7cdc99 |
-ssize_t write_lseek_blockwise(int fd, int bsize, char *buf, size_t count, off_t offset) {
|
|
|
7cdc99 |
+ssize_t write_lseek_blockwise(int fd, int bsize, void *buf, size_t count, off_t offset)
|
|
|
7cdc99 |
+{
|
|
|
7cdc99 |
char *frontPadBuf;
|
|
|
7cdc99 |
void *frontPadBuf_base = NULL;
|
|
|
7cdc99 |
int r, frontHang;
|
|
|
7cdc99 |
@@ -182,6 +235,12 @@ ssize_t write_lseek_blockwise(int fd, int bsize, char *buf, size_t count, off_t
|
|
|
7cdc99 |
if (fd == -1 || !buf || bsize <= 0)
|
|
|
7cdc99 |
return -1;
|
|
|
7cdc99 |
|
|
|
7cdc99 |
+ if (offset < 0)
|
|
|
7cdc99 |
+ offset = lseek(fd, offset, SEEK_END);
|
|
|
7cdc99 |
+
|
|
|
7cdc99 |
+ if (offset < 0)
|
|
|
7cdc99 |
+ return -1;
|
|
|
7cdc99 |
+
|
|
|
7cdc99 |
frontHang = offset % bsize;
|
|
|
7cdc99 |
|
|
|
7cdc99 |
if (lseek(fd, offset - frontHang, SEEK_SET) < 0)
|
|
|
7cdc99 |
@@ -193,7 +252,7 @@ ssize_t write_lseek_blockwise(int fd, int bsize, char *buf, size_t count, off_t
|
|
|
7cdc99 |
if (!frontPadBuf)
|
|
|
7cdc99 |
goto out;
|
|
|
7cdc99 |
|
|
|
7cdc99 |
- r = read(fd, frontPadBuf, bsize);
|
|
|
7cdc99 |
+ r = read_buffer(fd, frontPadBuf, bsize);
|
|
|
7cdc99 |
if (r < 0 || r != bsize)
|
|
|
7cdc99 |
goto out;
|
|
|
7cdc99 |
|
|
|
7cdc99 |
@@ -206,11 +265,11 @@ ssize_t write_lseek_blockwise(int fd, int bsize, char *buf, size_t count, off_t
|
|
|
7cdc99 |
if (lseek(fd, offset - frontHang, SEEK_SET) < 0)
|
|
|
7cdc99 |
goto out;
|
|
|
7cdc99 |
|
|
|
7cdc99 |
- r = write(fd, frontPadBuf, bsize);
|
|
|
7cdc99 |
+ r = write_buffer(fd, frontPadBuf, bsize);
|
|
|
7cdc99 |
if (r < 0 || r != bsize)
|
|
|
7cdc99 |
goto out;
|
|
|
7cdc99 |
|
|
|
7cdc99 |
- buf += innerCount;
|
|
|
7cdc99 |
+ buf = (char*)buf + innerCount;
|
|
|
7cdc99 |
count -= innerCount;
|
|
|
7cdc99 |
}
|
|
|
7cdc99 |
|
|
|
7cdc99 |
@@ -223,6 +282,58 @@ out:
|
|
|
7cdc99 |
return ret;
|
|
|
7cdc99 |
}
|
|
|
7cdc99 |
|
|
|
7cdc99 |
+ssize_t read_lseek_blockwise(int fd, int bsize, void *buf, size_t count, off_t offset)
|
|
|
7cdc99 |
+{
|
|
|
7cdc99 |
+ char *frontPadBuf;
|
|
|
7cdc99 |
+ void *frontPadBuf_base = NULL;
|
|
|
7cdc99 |
+ int r, frontHang;
|
|
|
7cdc99 |
+ size_t innerCount = 0;
|
|
|
7cdc99 |
+ ssize_t ret = -1;
|
|
|
7cdc99 |
+
|
|
|
7cdc99 |
+ if (fd == -1 || !buf || bsize <= 0)
|
|
|
7cdc99 |
+ return -1;
|
|
|
7cdc99 |
+
|
|
|
7cdc99 |
+ if (offset < 0)
|
|
|
7cdc99 |
+ offset = lseek(fd, offset, SEEK_END);
|
|
|
7cdc99 |
+
|
|
|
7cdc99 |
+ if (offset < 0)
|
|
|
7cdc99 |
+ return -1;
|
|
|
7cdc99 |
+
|
|
|
7cdc99 |
+ frontHang = offset % bsize;
|
|
|
7cdc99 |
+
|
|
|
7cdc99 |
+ if (lseek(fd, offset - frontHang, SEEK_SET) < 0)
|
|
|
7cdc99 |
+ return ret;
|
|
|
7cdc99 |
+
|
|
|
7cdc99 |
+ if (frontHang) {
|
|
|
7cdc99 |
+ frontPadBuf = aligned_malloc(&frontPadBuf_base,
|
|
|
7cdc99 |
+ bsize, get_alignment(fd));
|
|
|
7cdc99 |
+
|
|
|
7cdc99 |
+ if (!frontPadBuf)
|
|
|
7cdc99 |
+ return ret;
|
|
|
7cdc99 |
+
|
|
|
7cdc99 |
+ r = read_buffer(fd, frontPadBuf, bsize);
|
|
|
7cdc99 |
+ if (r < 0 || r != bsize)
|
|
|
7cdc99 |
+ goto out;
|
|
|
7cdc99 |
+
|
|
|
7cdc99 |
+ innerCount = bsize - frontHang;
|
|
|
7cdc99 |
+ if (innerCount > count)
|
|
|
7cdc99 |
+ innerCount = count;
|
|
|
7cdc99 |
+
|
|
|
7cdc99 |
+ memcpy(buf, frontPadBuf + frontHang, innerCount);
|
|
|
7cdc99 |
+
|
|
|
7cdc99 |
+ buf = (char*)buf + innerCount;
|
|
|
7cdc99 |
+ count -= innerCount;
|
|
|
7cdc99 |
+ }
|
|
|
7cdc99 |
+
|
|
|
7cdc99 |
+ ret = read_blockwise(fd, bsize, buf, count);
|
|
|
7cdc99 |
+ if (ret >= 0)
|
|
|
7cdc99 |
+ ret += innerCount;
|
|
|
7cdc99 |
+out:
|
|
|
7cdc99 |
+ free(frontPadBuf_base);
|
|
|
7cdc99 |
+
|
|
|
7cdc99 |
+ return ret;
|
|
|
7cdc99 |
+}
|
|
|
7cdc99 |
+
|
|
|
7cdc99 |
/* MEMLOCK */
|
|
|
7cdc99 |
#define DEFAULT_PROCESS_PRIORITY -18
|
|
|
7cdc99 |
|
|
|
7cdc99 |
--
|
|
|
7cdc99 |
2.7.4
|
|
|
7cdc99 |
|