--- /dev/null
+#include "safeio.h"
+#include <sys/uio.h>
+
+const SafeIOError exception_SafeIOError;
+const SafeIOEOF exception_SafeIOEOF ;
+
+void read_safe(int fd,void *buf,size_t size) {
+ assert(size>0);
+ while (size>0) {
+ const ssize_t got(read(fd,buf,size));
+ assert(got>=-1);
+ if (got<=0) {
+ warning("read_safe: fd=%d size=%zu: %s",fd,size,(got==0?"EOF":strerror(errno)));
+ // Do not throw ?exc1:exc2 as it would get upcasted.
+ if (got==0||(got==-1&&errno==ECONNRESET))
+ throw exception_SafeIOEOF;
+ throw exception_SafeIOError;
+ }
+ assert(size_t(got)<=size);
+ buf=static_cast<uint8_t *>(buf)+got;
+ size-=got;
+ }
+}
+
+void read_safe(FILE *f,void *buf,size_t size) {
+ assert(size>0);
+ assert(!ferror(f));
+ assert(!feof(f));
+ const size_t got(fread(buf,1/*size*/,size/*nmemb*/,f));
+ if (ferror(f)||feof(f)) {
+ warning("read_safe: fd=%d size=%zu: %s",fileno(f),size,(ferror(f)?"error":"EOF"));
+ // Do not throw ?exc1:exc2 as it would get upcasted.
+ if (ferror(f))
+ throw exception_SafeIOError;
+ throw exception_SafeIOEOF;
+ }
+ // return [...] which is less than nitems only if a read error or end-of-file is encountered.
+ if (size_t(got)!=size) {
+ warning("read_safe: fd=%d size=%zu got=%zu",fileno(f),size,got);
+ throw exception_SafeIOError;
+ }
+}
+
+void write_safe(int fd,const void *buf,size_t size) {
+ assert(size>0);
+ const ssize_t got(write(fd,buf,size));
+ if (got==-1) {
+ warning("Error writing %zu to fd %d: %m",size,fd);
+ throw exception_SafeIOError;
+ }
+ assert(got>0);
+ if (size_t(got)!=size) {
+ warning("Wrote only %zd of %zu to fd %d",got,size,fd);
+ throw exception_SafeIOEOF;
+ }
+}
+
+void write_safe(FILE *f,const void *buf,size_t size) {
+ assert(size>0);
+ assert(!ferror(f));
+ const size_t got(fwrite(buf,1/*size*/,size/*nmemb*/,f));
+ if (ferror(f)) {
+ warning("Error writing %zu to FILE * of fd %d",size,fileno(f));
+ throw exception_SafeIOError;
+ }
+ if (got!=size) {
+ warning("Wrote only %zu of %zu to FILE * of fd %d",got,size,fileno(f));
+ throw exception_SafeIOEOF;
+ }
+}
+
+void writev_safe_(int fd,const struct iovec *iov, int iovcnt) {
+ size_t size=0;
+ for (int ix=0;ix<iovcnt;++ix)
+ size+=iov[ix].iov_len;
+ assert(size>0);
+ const ssize_t got(writev(fd,iov,iovcnt));
+ if (got==-1) {
+ warning("Error writing %zu iovec to fd %d: %m",size,fd);
+ throw exception_SafeIOError;
+ }
+ assert(got>0);
+ if (size_t(got)!=size) {
+ warning("Wrote only %zd of %zu iovec to fd %d",got,size,fd);
+ throw exception_SafeIOEOF;
+ }
+}