#include "safeio.h" #include 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(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;ix0); 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; } }