- Rearrange reactos.dff according to rosapps rearrange.
[reactos.git] / rosapps / applications / net / ncftp / sio / SRead.c
1 #include "syshdrs.h"
2
3 static char UNUSED(gSioVersion[]) = "@(#) sio 6.0.3 ** Copyright 1992-2001 Mike Gleason. All rights reserved.";
4
5 #ifdef NO_SIGNALS
6 static char UNUSED(gNoSignalsMarker[]) = "@(#) sio - NO_SIGNALS";
7 #else
8 extern volatile Sjmp_buf gNetTimeoutJmp;
9 extern volatile Sjmp_buf gPipeJmp;
10 #endif
11
12 /* Read up to "size" bytes on sfd before "tlen" seconds.
13 *
14 * If "retry" is on, after a successful read of less than "size"
15 * bytes, it will attempt to read more, upto "size."
16 *
17 * If the timer elapses and one or more bytes were read, it returns
18 * that number, otherwise a timeout error is returned.
19 *
20 * Although "retry" would seem to indicate you may want to always
21 * read "size" bytes or else it is an error, even with that on you
22 * may get back a value < size. Set "retry" to 0 when you want to
23 * return as soon as there is a chunk of data whose size is <= "size".
24 */
25
26 #ifndef NO_SIGNALS
27
28 int
29 SRead(int sfd, char *const buf0, size_t size, int tlen, int retry)
30 {
31 int nread;
32 volatile int nleft;
33 char *volatile buf = buf0;
34 int tleft;
35 vsio_sigproc_t sigalrm, sigpipe;
36 time_t done, now;
37
38 if (SSetjmp(gNetTimeoutJmp) != 0) {
39 alarm(0);
40 (void) SSignal(SIGALRM, (sio_sigproc_t) sigalrm);
41 (void) SSignal(SIGPIPE, (sio_sigproc_t) sigpipe);
42 nread = size - nleft;
43 if ((nread > 0) && ((retry & (kFullBufferRequired|kFullBufferRequiredExceptLast)) == 0))
44 return (nread);
45 errno = ETIMEDOUT;
46 return (kTimeoutErr);
47 }
48
49 if (SSetjmp(gPipeJmp) != 0) {
50 alarm(0);
51 (void) SSignal(SIGALRM, (sio_sigproc_t) sigalrm);
52 (void) SSignal(SIGPIPE, (sio_sigproc_t) sigpipe);
53 nread = size - nleft;
54 if ((nread > 0) && ((retry & (kFullBufferRequired|kFullBufferRequiredExceptLast)) == 0))
55 return (nread);
56 errno = EPIPE;
57 return (kBrokenPipeErr);
58 }
59
60 sigalrm = (vsio_sigproc_t) SSignal(SIGALRM, SIOHandler);
61 sigpipe = (vsio_sigproc_t) SSignal(SIGPIPE, SIOHandler);
62 errno = 0;
63
64 nleft = (int) size;
65 time(&now);
66 done = now + tlen;
67 forever {
68 tleft = (int) (done - now);
69 if (tleft < 1) {
70 nread = size - nleft;
71 if ((nread == 0) || ((retry & (kFullBufferRequired)) != 0)) {
72 nread = kTimeoutErr;
73 errno = ETIMEDOUT;
74 }
75 goto done;
76 }
77 (void) alarm((unsigned int) tleft);
78 nread = read(sfd, (char *) buf, nleft);
79 (void) alarm(0);
80 if (nread <= 0) {
81 if (nread == 0) {
82 /* EOF */
83 if (retry == ((retry & (kFullBufferRequiredExceptLast)) != 0))
84 nread = size - nleft;
85 goto done;
86 } else if (errno != EINTR) {
87 nread = size - nleft;
88 if (nread == 0)
89 nread = -1;
90 goto done;
91 } else {
92 errno = 0;
93 nread = 0;
94 /* Try again. */
95
96 /* Ignore this line... */
97 LIBSIO_USE_VAR(gSioVersion);
98 }
99 }
100 nleft -= nread;
101 if ((nleft <= 0) || (((retry & (kFullBufferRequired|kFullBufferRequiredExceptLast)) == 0) && (nleft != (int) size)))
102 break;
103 buf += nread;
104 time(&now);
105 }
106 nread = size - nleft;
107
108 done:
109 (void) SSignal(SIGALRM, (sio_sigproc_t) sigalrm);
110 (void) SSignal(SIGPIPE, (sio_sigproc_t) sigpipe);
111
112 return (nread);
113 } /* SRead */
114
115 #else
116
117 int
118 SRead(int sfd, char *const buf0, size_t size, int tlen, int retry)
119 {
120 int nread;
121 volatile int nleft;
122 char *buf = buf0;
123 int tleft;
124 time_t done, now;
125 fd_set ss;
126 struct timeval tv;
127 int result, firstRead;
128
129 errno = 0;
130
131 nleft = (int) size;
132 time(&now);
133 done = now + tlen;
134 firstRead = 1;
135
136 forever {
137 tleft = (int) (done - now);
138 if (tleft < 1) {
139 nread = size - nleft;
140 if ((nread == 0) || ((retry & (kFullBufferRequired|kFullBufferRequiredExceptLast)) != 0)) {
141 nread = kTimeoutErr;
142 errno = ETIMEDOUT;
143 SETWSATIMEOUTERR
144 }
145 goto done;
146 }
147
148 if (!firstRead || ((retry & kNoFirstSelect) == 0)) {
149 forever {
150 errno = 0;
151 FD_ZERO(&ss);
152 FD_SET(sfd, &ss);
153 tv.tv_sec = tlen;
154 tv.tv_usec = 0;
155 result = select(sfd + 1, SELECT_TYPE_ARG234 &ss, NULL, NULL, SELECT_TYPE_ARG5 &tv);
156 if (result == 1) {
157 /* ready */
158 break;
159 } else if (result == 0) {
160 /* timeout */
161 nread = size - nleft;
162 if ((nread > 0) && ((retry & (kFullBufferRequired|kFullBufferRequiredExceptLast)) == 0))
163 return (nread);
164 errno = ETIMEDOUT;
165 SETWSATIMEOUTERR
166 return (kTimeoutErr);
167 } else if (errno != EINTR) {
168 return (-1);
169 }
170 }
171 firstRead = 0;
172 }
173
174 #if defined(WIN32) || defined(_WINDOWS)
175 nread = recv(sfd, (char *) buf, nleft, 0);
176 #else
177 nread = read(sfd, (char *) buf, nleft);
178 #endif
179
180 if (nread <= 0) {
181 if (nread == 0) {
182 /* EOF */
183 if (retry == ((retry & (kFullBufferRequiredExceptLast)) != 0))
184 nread = size - nleft;
185 goto done;
186 } else if (errno != EINTR) {
187 nread = size - nleft;
188 if (nread == 0)
189 nread = -1;
190 goto done;
191 } else {
192 errno = 0;
193 nread = 0;
194 /* Try again. */
195
196 /* Ignore these two lines */
197 LIBSIO_USE_VAR(gSioVersion);
198 LIBSIO_USE_VAR(gNoSignalsMarker);
199 }
200 }
201 nleft -= nread;
202 if ((nleft <= 0) || (((retry & (kFullBufferRequired|kFullBufferRequiredExceptLast)) == 0) && (nleft != (int) size)))
203 break;
204 buf += nread;
205 time(&now);
206 }
207 nread = size - nleft;
208
209 done:
210 return (nread);
211 } /* SRead */
212
213 #endif