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