Updates for move of net apps to rosapps
[reactos.git] / reactos / apps / utils / net / ncftp / sio / SWrite.c
1 #include "syshdrs.h"
2
3 #ifndef NO_SIGNALS
4 extern volatile Sjmp_buf gNetTimeoutJmp;
5 extern volatile Sjmp_buf gPipeJmp;
6 #endif
7
8 #ifndef NO_SIGNALS
9
10 int
11 SWrite(int sfd, const char *const buf0, size_t size, int tlen, int swopts)
12 {
13 volatile int nleft;
14 const char *volatile buf = buf0;
15 int nwrote, tleft;
16 vsio_sigproc_t sigalrm, sigpipe;
17 time_t done, now;
18
19 if (SSetjmp(gNetTimeoutJmp) != 0) {
20 alarm(0);
21 (void) SSignal(SIGALRM, (sio_sigproc_t) sigalrm);
22 (void) SSignal(SIGPIPE, (sio_sigproc_t) sigpipe);
23 nwrote = size - nleft;
24 if (nwrote > 0)
25 return (nwrote);
26 errno = ETIMEDOUT;
27 return (kTimeoutErr);
28 }
29
30 if (SSetjmp(gPipeJmp) != 0) {
31 alarm(0);
32 (void) SSignal(SIGALRM, (sio_sigproc_t) sigalrm);
33 (void) SSignal(SIGPIPE, (sio_sigproc_t) sigpipe);
34 nwrote = size - nleft;
35 if (nwrote > 0)
36 return (nwrote);
37 errno = EPIPE;
38 return (kBrokenPipeErr);
39 }
40
41 sigalrm = (vsio_sigproc_t) SSignal(SIGALRM, SIOHandler);
42 sigpipe = (vsio_sigproc_t) SSignal(SIGPIPE, SIOHandler);
43
44 nleft = (int) size;
45 time(&now);
46 done = now + tlen;
47 forever {
48 tleft = (int) (done - now);
49 if (tleft < 1) {
50 nwrote = size - nleft;
51 if (nwrote == 0) {
52 nwrote = kTimeoutErr;
53 errno = ETIMEDOUT;
54 }
55 goto done;
56 }
57 (void) alarm((unsigned int) tleft);
58 nwrote = write(sfd, buf, nleft);
59 (void) alarm(0);
60 if (nwrote < 0) {
61 if (errno != EINTR) {
62 nwrote = size - nleft;
63 if (nwrote == 0)
64 nwrote = -1;
65 goto done;
66 } else {
67 errno = 0;
68 nwrote = 0;
69 /* Try again. */
70 }
71 }
72 nleft -= nwrote;
73 if (nleft <= 0)
74 break;
75 buf += nwrote;
76 time(&now);
77 }
78 nwrote = size - nleft;
79
80 done:
81 (void) SSignal(SIGALRM, (sio_sigproc_t) sigalrm);
82 (void) SSignal(SIGPIPE, (sio_sigproc_t) sigpipe);
83
84 return (nwrote);
85 } /* SWrite */
86
87 #else
88
89 int
90 SWrite(int sfd, const char *const buf0, size_t size, int tlen, int swopts)
91 {
92 int nleft;
93 const char *buf = buf0;
94 int nwrote, tleft;
95 time_t done, now;
96 fd_set ss;
97 struct timeval tv;
98 int result, firstWrite;
99
100 nleft = (int) size;
101 time(&now);
102 done = now + tlen;
103 firstWrite = 1;
104
105 forever {
106 tleft = (int) (done - now);
107 if (tleft < 1) {
108 nwrote = size - nleft;
109 if (nwrote == 0) {
110 nwrote = kTimeoutErr;
111 errno = ETIMEDOUT;
112 SETWSATIMEOUTERR
113 }
114 goto done;
115 }
116
117
118 /* Unfortunately this doesn't help when the
119 * send buffer fills during the time we're
120 * writing to it, so you could still be
121 * blocked after breaking this loop and starting
122 * the write.
123 */
124 if (!firstWrite || ((swopts & kNoFirstSelect) == 0)) {
125 forever {
126 errno = 0;
127 FD_ZERO(&ss);
128 FD_SET(sfd, &ss);
129 tv.tv_sec = tlen;
130 tv.tv_usec = 0;
131 result = select(sfd + 1, NULL, SELECT_TYPE_ARG234 &ss, NULL, SELECT_TYPE_ARG5 &tv);
132 if (result == 1) {
133 /* ready */
134 break;
135 } else if (result == 0) {
136 /* timeout */
137 nwrote = size - nleft;
138 if (nwrote > 0)
139 return (nwrote);
140 errno = ETIMEDOUT;
141 SETWSATIMEOUTERR
142 return (kTimeoutErr);
143 } else if (errno != EINTR) {
144 return (-1);
145 }
146 }
147 firstWrite = 0;
148 }
149
150 #if defined(WIN32) || defined(_WINDOWS)
151 nwrote = send(sfd, buf, size, 0);
152 #else
153 nwrote = write(sfd, buf, size);
154 #endif
155
156 if (nwrote < 0) {
157 if (errno != EINTR) {
158 nwrote = size - nleft;
159 if (nwrote == 0)
160 nwrote = -1;
161 goto done;
162 } else {
163 errno = 0;
164 nwrote = 0;
165 /* Try again. */
166 }
167 }
168 nleft -= nwrote;
169 if (nleft <= 0)
170 break;
171 buf += nwrote;
172 time(&now);
173 }
174 nwrote = size - nleft;
175
176 done:
177 return (nwrote);
178 } /* SWrite */
179
180 #endif