Merge branch 'maint-1.8.5' into maint
[gitweb.git] / wrapper.c
index 9a6aaafaf35bbd6d2a7a97589edfd9b0b12102c7..bc1bfb86003cb4133cc4ce3ce6423ce780ed7c84 100644 (file)
--- a/wrapper.c
+++ b/wrapper.c
@@ -133,7 +133,7 @@ void *xcalloc(size_t nmemb, size_t size)
 /*
  * Limit size of IO chunks, because huge chunks only cause pain.  OS X
  * 64-bit is buggy, returning EINVAL if len >= INT_MAX; and even in
- * the absense of bugs, large chunks can result in bad latencies when
+ * the absence of bugs, large chunks can result in bad latencies when
  * you decide to kill the process.
  */
 #define MAX_IO_SIZE (8*1024*1024)
@@ -174,6 +174,24 @@ ssize_t xwrite(int fd, const void *buf, size_t len)
        }
 }
 
+/*
+ * xpread() is the same as pread(), but it automatically restarts pread()
+ * operations with a recoverable error (EAGAIN and EINTR). xpread() DOES
+ * NOT GUARANTEE that "len" bytes is read even if the data is available.
+ */
+ssize_t xpread(int fd, void *buf, size_t len, off_t offset)
+{
+       ssize_t nr;
+       if (len > MAX_IO_SIZE)
+               len = MAX_IO_SIZE;
+       while (1) {
+               nr = pread(fd, buf, len, offset);
+               if ((nr < 0) && (errno == EAGAIN || errno == EINTR))
+                       continue;
+               return nr;
+       }
+}
+
 ssize_t read_in_full(int fd, void *buf, size_t count)
 {
        char *p = buf;
@@ -214,6 +232,26 @@ ssize_t write_in_full(int fd, const void *buf, size_t count)
        return total;
 }
 
+ssize_t pread_in_full(int fd, void *buf, size_t count, off_t offset)
+{
+       char *p = buf;
+       ssize_t total = 0;
+
+       while (count > 0) {
+               ssize_t loaded = xpread(fd, p, count, offset);
+               if (loaded < 0)
+                       return -1;
+               if (loaded == 0)
+                       return total;
+               count -= loaded;
+               p += loaded;
+               total += loaded;
+               offset += loaded;
+       }
+
+       return total;
+}
+
 int xdup(int fd)
 {
        int ret = dup(fd);