1 #include <sys/types.h>
2 #include "config.h"
3 #if HAVE_SYS_STAT_H
4 #include <sys/stat.h>
5 #endif
6 #include <errno.h>
7
8 #include "mio.h"
9 #include "funcs.h"
10 #include "buffer.h"
11
12 static const char rcsid[]="$Id: mio.C,v 1.5 2003/09/29 03:52:05 mrsam Exp $";
13
mopen(const char * fname,int flags,mode_t mode)14 int mopen(const char *fname, int flags, mode_t mode)
15 {
16 int rc;
17
18 while ((rc=open(fname, flags, mode)) < 0 && errno == EINTR)
19 ;
20 return (rc);
21 }
22
mread(int fd,void * buf,size_t count)23 int mread(int fd, void *buf, size_t count)
24 {
25 int n;
26
27 while ((n=read(fd, buf, count)) < 0 && errno == EINTR)
28 ;
29 return (n);
30 }
31
mwrite(int fd,const void * buf,size_t count)32 int mwrite(int fd, const void *buf, size_t count)
33 {
34 int n;
35
36 while ((n=write(fd, buf, count)) < 0 && errno == EINTR)
37 ;
38 return (n);
39 }
40
mseek(int fd,off_t off,int whence)41 off_t mseek(int fd, off_t off, int whence)
42 {
43 off_t n;
44
45 while ((n=lseek(fd, off, whence)) < 0 && errno == EINTR)
46 ;
47 return (n);
48 }
49
mclose(int fd)50 int mclose(int fd)
51 {
52 int n;
53
54 while ((n=close(fd)) < 0 && errno == EINTR)
55 ;
56 return (n);
57 }
58
59 //-------------------------------------------------------------------------
60
Mio()61 Mio::Mio() : fd_(-1), readcnt(0), writecnt(0), err(0)
62 {
63 }
64
~Mio()65 Mio::~Mio() { Close(); }
66
Close()67 void Mio::Close()
68 {
69 if (fd_ < 0) return;
70 if (writeptr > buf) flush(-1);
71 mclose(fd_);
72 fd_= -1;
73 }
74
Open(const char * filename,int flags,mode_t m)75 int Mio::Open(const char *filename, int flags, mode_t m)
76 {
77 fd(mopen(filename, flags, m));
78 return (fd_);
79 }
80
fill()81 int Mio::fill()
82 {
83 readcnt=0;
84 if (fd_ < 0 || err) return (-1);
85 if (writeptr > buf && flush(-1) < 0) return (-1);
86
87 readstartpos=tell();
88 readcnt=mread(fd_, buf, sizeof(buf));
89 readsize=readcnt;
90
91 if (readcnt <= 0)
92 {
93 readcnt=0;
94 readsize=0;
95 err= -1;
96 return (-1);
97 }
98 --readcnt;
99 return (*(readptr=buf)++);
100 }
101
flush(int c)102 int Mio::flush(int c)
103 {
104 if (fd_ < 0 || err) return (-1);
105 if (readcnt && mseek(fd_, -readcnt, SEEK_CUR) < 0) return (-1);
106 readcnt=0;
107 readptr=buf;
108
109 while (writeptr > buf)
110 {
111 int n;
112
113 if ((n=mwrite(fd_, buf, writeptr-buf)) <= 0)
114 {
115 err= -1;
116 return (-1);
117 }
118 memorycopy(buf, buf+n, writeptr-buf-n);
119 writeptr -= n;
120 }
121
122 writecnt=sizeof(buf);
123 if (c >= 0)
124 {
125 --writecnt;
126 *writeptr++ = c;
127 }
128 return (0);
129 }
130
Rewind()131 int Mio::Rewind()
132 {
133 readstartpos= -1;
134 return ( seek (0L, SEEK_SET) );
135 }
136
seek(off_t off,int whence)137 int Mio::seek(off_t off, int whence)
138 {
139 if (fd_ < 0) return (-1);
140 if (writeptr > buf && flush(-1) < 0) return (-1);
141 if (whence == SEEK_CUR && err == 0) off -= readcnt;
142
143 // Optimize - seek can be satisfied within the read buffer.
144
145 if (whence == SEEK_SET && readstartpos != -1 &&
146 off >= readstartpos && off <= readstartpos + readsize)
147 {
148 readptr = buf + (off - readstartpos);
149 readcnt = readsize - (off - readstartpos);
150 return (0);
151 }
152
153 if (mseek(fd_, off, whence) < 0)
154 {
155 err= -1;
156 return (-1);
157 }
158 err=0;
159 readcnt=0;
160 readptr=buf;
161 return (0);
162 }
163
write(const void * p,int cnt)164 int Mio::write(const void *p, int cnt)
165 {
166 const unsigned char *cp=(const unsigned char *)p;
167 int done=0;
168
169 if (fd_ < 0 || err) return (-1);
170
171 while (cnt)
172 {
173 int l;
174
175 if (writecnt == 0 && flush() < 0)
176 {
177 if (done == 0) done= -1;
178 break;
179 }
180
181 if (writeptr > buf || cnt <= writecnt)
182 {
183 l=writecnt;
184
185 if (l > cnt) l=cnt;
186 memcpy(writeptr, cp, l);
187 writecnt -= l;
188 writeptr += l;
189 }
190 else
191 {
192 l=mwrite(fd_, cp, cnt);
193 if (l <= 0)
194 {
195 if (done == 0) done= -1;
196 break;
197 }
198 }
199
200 cp += l;
201 done += l;
202 cnt -= l;
203 }
204 return (done);
205 }
206
tell()207 off_t Mio::tell()
208 {
209 if (fd_ < 0) return (0);
210
211 off_t p=mseek(fd_, 0L, SEEK_CUR);
212
213 if (p == -1) return (-1);
214 return (p + (writeptr - buf) - readcnt);
215 }
216
217 Mio &Mio::operator<<(const class Buffer &b)
218 {
219 write( (const char *)b, b.Length() );
220 return (*this);
221 }
222
223 MioStdio mout(1), merr(2);
224
MioStdio(int f)225 MioStdio::MioStdio(int f)
226 {
227 fd(f);
228 }
229
~MioStdio()230 MioStdio::~MioStdio()
231 {
232 fd(-1);
233 }
234
write(const void * p,int cnt)235 int MioStdio::write(const void *p, int cnt)
236 {
237 int n;
238
239 n=Mio::write(p, cnt);
240 if (n > 0) Mio::flush();
241 return (n);
242 }
243
244 extern MioStdio mout, merr;
245