+.config/yt-dlp.conf
[nethome.git] / src / safeio.C
1 #include "safeio.h"
2 #include <sys/uio.h>
3
4 const SafeIOError exception_SafeIOError;
5 const SafeIOEOF   exception_SafeIOEOF  ;
6
7 void read_safe(int fd,void *buf,size_t size) {
8   assert(size>0);
9   while (size>0) {
10     const ssize_t got(read(fd,buf,size));
11     assert(got>=-1);
12     if (got<=0) {
13       warning("read_safe: fd=%d size=%zu: %s",fd,size,(got==0?"EOF":strerror(errno)));
14       // Do not throw ?exc1:exc2 as it would get upcasted.
15       if (got==0||(got==-1&&errno==ECONNRESET))
16         throw exception_SafeIOEOF;
17       throw exception_SafeIOError;
18     }
19     assert(size_t(got)<=size);
20     buf=static_cast<uint8_t *>(buf)+got;
21     size-=got;
22   }
23 }
24
25 void read_safe(FILE *f,void *buf,size_t size) {
26   assert(size>0);
27   assert(!ferror(f));
28   assert(!feof(f));
29   const size_t got(fread(buf,1/*size*/,size/*nmemb*/,f));
30   if (ferror(f)||feof(f)) {
31     warning("read_safe: fd=%d size=%zu: %s",fileno(f),size,(ferror(f)?"error":"EOF"));
32     // Do not throw ?exc1:exc2 as it would get upcasted.
33     if (ferror(f))
34       throw exception_SafeIOError;
35     throw exception_SafeIOEOF;
36   }
37   // return [...] which is less than nitems only if a read error or end-of-file is encountered.
38   if (size_t(got)!=size) {
39     warning("read_safe: fd=%d size=%zu got=%zu",fileno(f),size,got);
40     throw exception_SafeIOError;
41   }
42 }
43
44 void write_safe(int fd,const void *buf,size_t size) {
45   assert(size>0);
46   const ssize_t got(write(fd,buf,size));
47   if (got==-1) {
48     warning("Error writing %zu to fd %d: %m",size,fd);
49     throw exception_SafeIOError;
50   }
51   assert(got>0);
52   if (size_t(got)!=size) {
53     warning("Wrote only %zd of %zu to fd %d",got,size,fd);
54     throw exception_SafeIOEOF;
55   }
56 }
57
58 void write_safe(FILE *f,const void *buf,size_t size) {
59   assert(size>0);
60   assert(!ferror(f));
61   const size_t got(fwrite(buf,1/*size*/,size/*nmemb*/,f));
62   if (ferror(f)) {
63     warning("Error writing %zu to FILE * of fd %d",size,fileno(f));
64     throw exception_SafeIOError;
65   }
66   if (got!=size) {
67     warning("Wrote only %zu of %zu to FILE * of fd %d",got,size,fileno(f));
68     throw exception_SafeIOEOF;
69   }
70 }
71
72 void writev_safe_(int fd,const struct iovec *iov, int iovcnt) {
73   size_t size=0;
74   for (int ix=0;ix<iovcnt;++ix)
75     size+=iov[ix].iov_len;
76   assert(size>0);
77   const ssize_t got(writev(fd,iov,iovcnt));
78   if (got==-1) {
79     warning("Error writing %zu iovec to fd %d: %m",size,fd);
80     throw exception_SafeIOError;
81   }
82   assert(got>0);
83   if (size_t(got)!=size) {
84     warning("Wrote only %zd of %zu iovec to fd %d",got,size,fd);
85     throw exception_SafeIOEOF;
86   }
87 }