+
+/* Write @n bytes from @buf to the file descriptor @fd, retrying on internupt
+ * and on short writes.
+ *
+ * Returns short count and set errno on failure. */
+size_t
+full_write(int fd, const void *buf, size_t n)
+{
+ const void *p = buf;
+ ssize_t ret;
+ ssize_t total = 0;
+
+ while (total != n) {
+ ret = write(fd, p, n);
+ if (ret <= 0) {
+ if (errno == EINTR)
+ continue;
+ if (ret == 0)
+ errno = EIO;
+ break;
+ }
+ total += ret;
+ p += ret;
+ }
+ return total;
+}
+
+/* Read @n bytes from the file descriptor @fd to the buffer @buf, retrying on
+ * interrupt and on short reads.
+ *
+ * Returns short count and set errno on failure. */
+size_t
+full_read(int fd, void *buf, size_t n)
+{
+ size_t bytes_remaining = n;
+ while (bytes_remaining) {
+ ssize_t bytes_read = read(fd, buf, bytes_remaining);
+ if (bytes_read <= 0) {
+ if (errno == EINTR)
+ continue;
+ if (bytes_read == 0)
+ errno = EIO;
+ break;
+ }
+ bytes_remaining -= bytes_read;
+ buf += bytes_read;
+ }
+ return n - bytes_remaining;
+}
+
+/* Read @n bytes from the file descriptor @fd at the offset @offset to the
+ * buffer @buf, retrying on interrupt and on short reads.
+ *
+ * Returns short count and set errno on failure. */
+size_t
+full_pread(int fd, void *buf, size_t nbyte, off_t offset)
+{
+ size_t bytes_remaining = nbyte;
+ ssize_t bytes_read;
+
+ while (bytes_remaining) {
+ bytes_read = pread(fd, buf, bytes_remaining, offset);
+ if (bytes_read <= 0) {
+ if (errno == EINTR)
+ continue;
+ if (bytes_read == 0)
+ errno = EIO;
+ break;
+ }
+ bytes_remaining -= bytes_read;
+ buf += bytes_read;
+ offset += bytes_read;
+ }
+ return nbyte - bytes_remaining;
+}
+
+/* Like pwrite(), but keep trying until everything has been written or we know
+ * for sure that there was an error. */
+size_t
+full_pwrite(int fd, const void *buf, size_t count, off_t offset)
+{
+ ssize_t bytes_remaining = count;
+ ssize_t bytes_written;
+
+ while (bytes_remaining > 0) {
+ bytes_written = pwrite(fd, buf, bytes_remaining, offset);
+ if (bytes_written <= 0) {
+ if (errno == EINTR)
+ continue;
+ if (bytes_written == 0)
+ errno = EIO;
+ break;
+ }
+ bytes_remaining -= bytes_written;
+ buf += bytes_written;
+ offset += bytes_written;
+ }
+ return count - bytes_remaining;
+}
+
+
+off_t
+filedes_offset(filedes_t fd)
+{
+ return lseek(fd, 0, SEEK_CUR);
+}