lib: util: Add sys_pread_full().
authorJeremy Allison <jra@samba.org>
Thu, 7 May 2020 19:32:48 +0000 (12:32 -0700)
committerJeremy Allison <jra@samba.org>
Tue, 12 May 2020 19:53:43 +0000 (19:53 +0000)
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>
lib/util/sys_rw.c
lib/util/sys_rw.h

index 6fa7ca57365423aac7a752dae3994496b3d50ea5..bfeb2e6b4661177171e3fa5cdbcd046bf1e0ac7f 100644 (file)
@@ -143,6 +143,54 @@ ssize_t sys_pread(int fd, void *buf, size_t count, off_t off)
        return ret;
 }
 
+/*******************************************************************
+ 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
 ********************************************************************/
index 70864cb2b74a16466b7ec0d9c305a815596ee752..1e0dd3730a60d9d8ee84711942f776b20dcbca3c 100644 (file)
@@ -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