diff options
author | Jeremy Allison <jra@samba.org> | 2020-05-07 12:32:48 -0700 |
---|---|---|
committer | Jeremy Allison <jra@samba.org> | 2020-05-12 19:53:43 +0000 |
commit | 36af33bf9fcdf93fce5ef1520fcb7ddbb07b355e (patch) | |
tree | 3115539ad73627274c0aeca03b35644e97528fe0 /lib | |
parent | e02cbd5c3ea6903d2b7b43c3193b8662d029ecdd (diff) | |
download | samba-36af33bf9fcdf93fce5ef1520fcb7ddbb07b355e.tar.gz |
lib: util: Add sys_pread_full().
A pread wrapper that will deal with EINTR and never return a short
read unless pread returns zero meaning EOF.
Thread-safe so may be used as a replacement for pread
inside pread_do() thread functions.
BUG: https://bugzilla.samba.org/show_bug.cgi?id=14361
Pair-Programmed-With: Stefan Metzmacher <metze@samba.org>
Signed-off-by: Jeremy Allison <jra@samba.org>
Signed-off-by: Stefan Metzmacher <metze@samba.org>
Diffstat (limited to 'lib')
-rw-r--r-- | lib/util/sys_rw.c | 48 | ||||
-rw-r--r-- | lib/util/sys_rw.h | 1 |
2 files changed, 49 insertions, 0 deletions
diff --git a/lib/util/sys_rw.c b/lib/util/sys_rw.c index 6fa7ca57365..bfeb2e6b466 100644 --- a/lib/util/sys_rw.c +++ b/lib/util/sys_rw.c @@ -144,6 +144,54 @@ ssize_t sys_pread(int fd, void *buf, size_t count, off_t off) } /******************************************************************* + A pread wrapper that will deal with EINTR and never return a short + read unless pread returns zero meaning EOF. +********************************************************************/ + +ssize_t sys_pread_full(int fd, void *buf, size_t count, off_t off) +{ + ssize_t total_read = 0; + uint8_t *curr_buf = (uint8_t *)buf; + size_t curr_count = count; + off_t curr_off = off; + bool ok; + + ok = sys_valid_io_range(off, count); + if (!ok) { + errno = EINVAL; + return -1; + } + + while (curr_count != 0) { + ssize_t ret = sys_pread(fd, + curr_buf, + curr_count, + curr_off); + + if (ret == -1) { + return -1; + } + if (ret == 0) { + /* EOF */ + break; + } + + if (ret > curr_count) { + errno = EIO; + return -1; + } + + curr_buf += ret; + curr_count -= ret; + curr_off += ret; + + total_read += ret; + } + + return total_read; +} + +/******************************************************************* A write wrapper that will deal with EINTR ********************************************************************/ diff --git a/lib/util/sys_rw.h b/lib/util/sys_rw.h index 70864cb2b74..1e0dd3730a6 100644 --- a/lib/util/sys_rw.h +++ b/lib/util/sys_rw.h @@ -34,6 +34,7 @@ ssize_t sys_write(int fd, const void *buf, size_t count); void sys_write_v(int fd, const void *buf, size_t count); ssize_t sys_writev(int fd, const struct iovec *iov, int iovcnt); ssize_t sys_pread(int fd, void *buf, size_t count, off_t off); +ssize_t sys_pread_full(int fd, void *buf, size_t count, off_t off); ssize_t sys_pwrite(int fd, const void *buf, size_t count, off_t off); #endif |