X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ian/git?a=blobdiff_plain;f=lib%2Fxwrite.c;fp=lib%2Fxwrite.c;h=0000000000000000000000000000000000000000;hb=b7a32e2d73e3ab1add8208d3e157f7269a31ef4d;hp=67c3d97de8d05a1f233afaf6bb7b7a28132182dd;hpb=ac902a8299ff4469b356836f431ead31c3377377;p=innduct.git diff --git a/lib/xwrite.c b/lib/xwrite.c deleted file mode 100644 index 67c3d97..0000000 --- a/lib/xwrite.c +++ /dev/null @@ -1,177 +0,0 @@ -/* $Id: xwrite.c 5771 2002-09-17 17:00:05Z alexk $ -** -** write and writev replacements to handle partial writes. -** -** Usage: -** -** ssize_t xwrite(int fildes, const void *buf, size_t nbyte); -** ssize_t xpwrite(int fildes, const void *buf, size_t nbyte, -** off_t offset); -** ssize_t xwritev(int fildes, const struct iovec *iov, int iovcnt); -** -** xwrite, xpwrite, and xwritev behave exactly like their C library -** counterparts except that, if write or writev succeeds but returns a number -** of bytes written less than the total bytes, the write is repeated picking -** up where it left off until the full amount of the data is written. The -** write is also repeated if it failed with EINTR. The write will be aborted -** after 10 successive writes with no forward progress. -** -** Both functions return the number of bytes written on success or -1 on an -** error, and will leave errno set to whatever the underlying system call -** set it to. Note that it is possible for a write to fail after some data -** was written, on the subsequent additional write; in that case, these -** functions will return -1 and the number of bytes actually written will -** be lost. -*/ - -#include "config.h" -#include "clibrary.h" -#include -#include - -#include "libinn.h" - -/* If we're running the test suite, call testing versions of the write - functions. #undef pwrite first because large file support may define a - macro pwrite (pointing to pwrite64) on some platforms (e.g. Solaris). */ -#if TESTING -# undef pwrite -# define pwrite fake_pwrite -# define write fake_write -# define writev fake_writev -ssize_t fake_pwrite(int, const void *, size_t, off_t); -ssize_t fake_write(int, const void *, size_t); -ssize_t fake_writev(int, const struct iovec *, int); -#endif - -ssize_t -xwrite(int fd, const void *buffer, size_t size) -{ - size_t total; - ssize_t status; - int count = 0; - - if (size == 0) - return 0; - - /* Abort the write if we try ten times with no forward progress. */ - for (total = 0; total < size; total += status) { - if (++count > 10) - break; - status = write(fd, (const char *) buffer + total, size - total); - if (status > 0) - count = 0; - if (status < 0) { - if (errno != EINTR) - break; - status = 0; - } - } - return (total < size) ? -1 : (ssize_t) total; -} - -ssize_t -xpwrite(int fd, const void *buffer, size_t size, off_t offset) -{ - size_t total; - ssize_t status; - int count = 0; - - if (size == 0) - return 0; - - /* Abort the write if we try ten times with no forward progress. */ - for (total = 0; total < size; total += status) { - if (++count > 10) - break; - status = pwrite(fd, (const char *) buffer + total, size - total, - offset + total); - if (status > 0) - count = 0; - if (status < 0) { - if (errno != EINTR) - break; - status = 0; - } - } - return (total < size) ? -1 : (ssize_t) total; -} - -ssize_t -xwritev(int fd, const struct iovec iov[], int iovcnt) -{ - ssize_t total, status = 0; - size_t left, offset; - int iovleft, i, count; - struct iovec *tmpiov; - - if (iovcnt == 0) - return 0; - - /* Get a count of the total number of bytes in the iov array. */ - for (total = 0, i = 0; i < iovcnt; i++) - total += iov[i].iov_len; - - if (total == 0) - return 0; - - /* First, try just writing it all out. Most of the time this will - succeed and save us lots of work. Abort the write if we try ten times - with no forward progress. */ - count = 0; - do { - if (++count > 10) - break; - status = writev(fd, iov, iovcnt); - if (status > 0) - count = 0; - } while (status < 0 && errno == EINTR); - if (status < 0) - return -1; - if (status == total) - return total; - - /* If we fell through to here, the first write partially succeeded. - Figure out how far through the iov array we got, and then duplicate - the rest of it so that we can modify it to reflect how much we manage - to write on successive tries. */ - offset = status; - left = total - offset; - for (i = 0; offset >= (size_t) iov[i].iov_len; i++) - offset -= iov[i].iov_len; - iovleft = iovcnt - i; - tmpiov = xmalloc(iovleft * sizeof(struct iovec)); - memcpy(tmpiov, iov + i, iovleft * sizeof(struct iovec)); - - /* status now contains the offset into the first iovec struct in tmpiov. - Go into the write loop, trying to write out everything remaining at - each point. At the top of the loop, status will contain a count of - bytes written out at the beginning of the set of iovec structs. */ - i = 0; - do { - if (++count > 10) - break; - - /* Skip any leading data that has been written out. */ - for (; offset >= (size_t) tmpiov[i].iov_len && iovleft > 0; i++) { - offset -= tmpiov[i].iov_len; - iovleft--; - } - tmpiov[i].iov_base = (char *) tmpiov[i].iov_base + offset; - tmpiov[i].iov_len -= offset; - - /* Write out what's left and return success if it's all written. */ - status = writev(fd, tmpiov + i, iovleft); - if (status <= 0) - offset = 0; - else { - offset = status; - left -= offset; - count = 0; - } - } while (left > 0 && (status >= 0 || errno == EINTR)); - - /* We're either done or got an error; if we're done, left is now 0. */ - free(tmpiov); - return (left == 0) ? total : -1; -}