This is the mail archive of the elfutils-devel@sourceware.org mailing list for the elfutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] Handle partial read or write.


Ran into a situation where pread was returning less data than requested for
remote files on a networked filesystem. This patch modifies the IO wrappers
to request the remaining data as long as no real errors occured.

Signed-off-by: Adam Markey <adam@etinternational.com>
---
 lib/ChangeLog |    5 +++++
 lib/system.h  |   42 ++++++++++++++++++++++++++++++++++++------
 2 files changed, 41 insertions(+), 6 deletions(-)

diff --git a/lib/ChangeLog b/lib/ChangeLog
index 47e831e..ac0ffd8 100644
--- a/lib/ChangeLog
+++ b/lib/ChangeLog
@@ -1,3 +1,8 @@
+2012-10-5  Adam Markey  <adam@etinternational.com>
+
+	* system.h: Changed pwrite_retry, write_retry, and pread_retry to 
+	handle case where not all data was read/written.
+
 2012-01-21  Ulrich Drepper  <drepper@gmail.com>
 
 	* Makefile.am (libeu_a_SOURCES): Add color.c.
diff --git a/lib/system.h b/lib/system.h
index 9ac01f8..7315a3e 100644
--- a/lib/system.h
+++ b/lib/system.h
@@ -34,6 +34,7 @@
 #include <stdint.h>
 #include <endian.h>
 #include <byteswap.h>
+#include <unistd.h>
 
 #if __BYTE_ORDER == __LITTLE_ENDIAN
 # define LE32(n)	(n)
@@ -64,12 +65,41 @@ extern int crc32_file (int fd, uint32_t *resp);
 #define gettext_noop(Str) Str
 
 
-#define pwrite_retry(fd, buf,  len, off) \
-  TEMP_FAILURE_RETRY (pwrite (fd, buf, len, off))
-#define write_retry(fd, buf, n) \
-     TEMP_FAILURE_RETRY (write (fd, buf, n))
-#define pread_retry(fd, buf,  len, off) \
-  TEMP_FAILURE_RETRY (pread (fd, buf, len, off))
+static inline ssize_t pwrite_retry(int fd, const void *buf, size_t len, off_t off) {
+    ssize_t ret;
+    ssize_t recvd = 0;
+
+    do {
+        ret = TEMP_FAILURE_RETRY (pwrite (fd, buf + recvd, len - recvd, off + recvd));
+        if (ret > 0) recvd += ret;
+    } while (ret > 0 && (size_t)recvd < len);
+
+    return ret < 0 ? ret : recvd;
+}
+
+static inline ssize_t write_retry(int fd, const void *buf, size_t len) {
+    ssize_t ret;
+    ssize_t recvd = 0;
+
+    do {
+        ret = TEMP_FAILURE_RETRY (write (fd, buf + recvd, len - recvd));
+        if (ret > 0) recvd += ret;
+    } while (ret > 0 && (size_t)recvd < len);
+
+    return ret < 0 ? ret : recvd;
+}
+
+static inline ssize_t pread_retry(int fd, void *buf, size_t len, off_t off) {
+    ssize_t ret;
+    ssize_t recvd = 0;
+
+    do {
+        ret = TEMP_FAILURE_RETRY (pread (fd, buf + recvd, len - recvd, off + recvd));
+        if (ret > 0) recvd += ret;
+    } while (ret > 0 && (size_t)recvd < len);
+
+    return ret < 0 ? ret : recvd;
+}
 
 
 /* We need define two variables, argp_program_version_hook and
-- 
1.7.0.4



Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]