upload http
[bottlenecks.git] / rubbos / app / httpd-2.0.64 / srclib / apr / file_io / os2 / readwrite.c
1 /* Licensed to the Apache Software Foundation (ASF) under one or more
2  * contributor license agreements.  See the NOTICE file distributed with
3  * this work for additional information regarding copyright ownership.
4  * The ASF licenses this file to You under the Apache License, Version 2.0
5  * (the "License"); you may not use this file except in compliance with
6  * the License.  You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #define INCL_DOS
18 #define INCL_DOSERRORS
19
20 #include "apr_arch_file_io.h"
21 #include "apr_file_io.h"
22 #include "apr_lib.h"
23 #include "apr_strings.h"
24
25 #include <malloc.h>
26
27 APR_DECLARE(apr_status_t) apr_file_read(apr_file_t *thefile, void *buf, apr_size_t *nbytes)
28 {
29     ULONG rc = 0;
30     ULONG bytesread;
31
32     if (!thefile->isopen) {
33         *nbytes = 0;
34         return APR_EBADF;
35     }
36
37     if (thefile->buffered) {
38         char *pos = (char *)buf;
39         ULONG blocksize;
40         ULONG size = *nbytes;
41
42         apr_thread_mutex_lock(thefile->mutex);
43
44         if (thefile->direction == 1) {
45             int rv = apr_file_flush(thefile);
46
47             if (rv != APR_SUCCESS) {
48                 apr_thread_mutex_unlock(thefile->mutex);
49                 return rv;
50             }
51
52             thefile->bufpos = 0;
53             thefile->direction = 0;
54             thefile->dataRead = 0;
55         }
56
57         while (rc == 0 && size > 0) {
58             if (thefile->bufpos >= thefile->dataRead) {
59                 ULONG bytesread;
60                 rc = DosRead(thefile->filedes, thefile->buffer,
61                              APR_FILE_BUFSIZE, &bytesread);
62
63                 if (bytesread == 0) {
64                     if (rc == 0)
65                         thefile->eof_hit = TRUE;
66                     break;
67                 }
68
69                 thefile->dataRead = bytesread;
70                 thefile->filePtr += thefile->dataRead;
71                 thefile->bufpos = 0;
72             }
73
74             blocksize = size > thefile->dataRead - thefile->bufpos ? thefile->dataRead - thefile->bufpos : size;
75             memcpy(pos, thefile->buffer + thefile->bufpos, blocksize);
76             thefile->bufpos += blocksize;
77             pos += blocksize;
78             size -= blocksize;
79         }
80
81         *nbytes = rc == 0 ? pos - (char *)buf : 0;
82         apr_thread_mutex_unlock(thefile->mutex);
83
84         if (*nbytes == 0 && rc == 0 && thefile->eof_hit) {
85             return APR_EOF;
86         }
87
88         return APR_FROM_OS_ERROR(rc);
89     } else {
90         if (thefile->pipe)
91             DosResetEventSem(thefile->pipeSem, &rc);
92
93         rc = DosRead(thefile->filedes, buf, *nbytes, &bytesread);
94
95         if (rc == ERROR_NO_DATA && thefile->timeout != 0) {
96             int rcwait = DosWaitEventSem(thefile->pipeSem, thefile->timeout >= 0 ? thefile->timeout / 1000 : SEM_INDEFINITE_WAIT);
97
98             if (rcwait == 0) {
99                 rc = DosRead(thefile->filedes, buf, *nbytes, &bytesread);
100             }
101             else if (rcwait == ERROR_TIMEOUT) {
102                 *nbytes = 0;
103                 return APR_TIMEUP;
104             }
105         }
106
107         if (rc) {
108             *nbytes = 0;
109             return APR_FROM_OS_ERROR(rc);
110         }
111
112         *nbytes = bytesread;
113         
114         if (bytesread == 0) {
115             thefile->eof_hit = TRUE;
116             return APR_EOF;
117         }
118
119         return APR_SUCCESS;
120     }
121 }
122
123
124
125 APR_DECLARE(apr_status_t) apr_file_write(apr_file_t *thefile, const void *buf, apr_size_t *nbytes)
126 {
127     ULONG rc = 0;
128     ULONG byteswritten;
129
130     if (!thefile->isopen) {
131         *nbytes = 0;
132         return APR_EBADF;
133     }
134
135     if (thefile->buffered) {
136         char *pos = (char *)buf;
137         int blocksize;
138         int size = *nbytes;
139
140         apr_thread_mutex_lock(thefile->mutex);
141
142         if ( thefile->direction == 0 ) {
143             // Position file pointer for writing at the offset we are logically reading from
144             ULONG offset = thefile->filePtr - thefile->dataRead + thefile->bufpos;
145             if (offset != thefile->filePtr)
146                 DosSetFilePtr(thefile->filedes, offset, FILE_BEGIN, &thefile->filePtr );
147             thefile->bufpos = thefile->dataRead = 0;
148             thefile->direction = 1;
149         }
150
151         while (rc == 0 && size > 0) {
152             if (thefile->bufpos == APR_FILE_BUFSIZE)   // write buffer is full
153                 rc = apr_file_flush(thefile);
154
155             blocksize = size > APR_FILE_BUFSIZE - thefile->bufpos ? APR_FILE_BUFSIZE - thefile->bufpos : size;
156             memcpy(thefile->buffer + thefile->bufpos, pos, blocksize);
157             thefile->bufpos += blocksize;
158             pos += blocksize;
159             size -= blocksize;
160         }
161
162         apr_thread_mutex_unlock(thefile->mutex);
163         return APR_FROM_OS_ERROR(rc);
164     } else {
165         if (thefile->flags & APR_APPEND) {
166             FILELOCK all = { 0, 0x7fffffff };
167             ULONG newpos;
168             rc = DosSetFileLocks(thefile->filedes, NULL, &all, -1, 0);
169
170             if (rc == 0) {
171                 rc = DosSetFilePtr(thefile->filedes, 0, FILE_END, &newpos);
172
173                 if (rc == 0) {
174                     rc = DosWrite(thefile->filedes, buf, *nbytes, &byteswritten);
175                 }
176
177                 DosSetFileLocks(thefile->filedes, &all, NULL, -1, 0);
178             }
179         } else {
180             rc = DosWrite(thefile->filedes, buf, *nbytes, &byteswritten);
181         }
182
183         if (rc) {
184             *nbytes = 0;
185             return APR_FROM_OS_ERROR(rc);
186         }
187
188         *nbytes = byteswritten;
189         return APR_SUCCESS;
190     }
191 }
192
193
194
195 #ifdef HAVE_WRITEV
196
197 APR_DECLARE(apr_status_t) apr_file_writev(apr_file_t *thefile, const struct iovec *vec, apr_size_t nvec, apr_size_t *nbytes)
198 {
199     int bytes;
200     if ((bytes = writev(thefile->filedes, vec, nvec)) < 0) {
201         *nbytes = 0;
202         return errno;
203     }
204     else {
205         *nbytes = bytes;
206         return APR_SUCCESS;
207     }
208 }
209 #endif
210
211
212
213 APR_DECLARE(apr_status_t) apr_file_putc(char ch, apr_file_t *thefile)
214 {
215     ULONG rc;
216     ULONG byteswritten;
217
218     if (!thefile->isopen) {
219         return APR_EBADF;
220     }
221
222     rc = DosWrite(thefile->filedes, &ch, 1, &byteswritten);
223
224     if (rc) {
225         return APR_FROM_OS_ERROR(rc);
226     }
227     
228     return APR_SUCCESS;
229 }
230
231
232
233 APR_DECLARE(apr_status_t) apr_file_ungetc(char ch, apr_file_t *thefile)
234 {
235     apr_off_t offset = -1;
236     return apr_file_seek(thefile, APR_CUR, &offset);
237 }
238
239
240 APR_DECLARE(apr_status_t) apr_file_getc(char *ch, apr_file_t *thefile)
241 {
242     ULONG rc;
243     apr_size_t bytesread;
244
245     if (!thefile->isopen) {
246         return APR_EBADF;
247     }
248
249     bytesread = 1;
250     rc = apr_file_read(thefile, ch, &bytesread);
251
252     if (rc) {
253         return rc;
254     }
255     
256     if (bytesread == 0) {
257         thefile->eof_hit = TRUE;
258         return APR_EOF;
259     }
260     
261     return APR_SUCCESS;
262 }
263
264
265
266 APR_DECLARE(apr_status_t) apr_file_puts(const char *str, apr_file_t *thefile)
267 {
268     apr_size_t len;
269
270     len = strlen(str);
271     return apr_file_write(thefile, str, &len); 
272 }
273
274
275 APR_DECLARE(apr_status_t) apr_file_flush(apr_file_t *thefile)
276 {
277     if (thefile->buffered) {
278         ULONG written = 0;
279         int rc = 0;
280
281         if (thefile->direction == 1 && thefile->bufpos) {
282             rc = DosWrite(thefile->filedes, thefile->buffer, thefile->bufpos, &written);
283             thefile->filePtr += written;
284
285             if (rc == 0)
286                 thefile->bufpos = 0;
287         }
288
289         return APR_FROM_OS_ERROR(rc);
290     } else {
291         /* There isn't anything to do if we aren't buffering the output
292          * so just return success.
293          */
294         return APR_SUCCESS;
295     }
296 }
297
298
299 APR_DECLARE(apr_status_t) apr_file_gets(char *str, int len, apr_file_t *thefile)
300 {
301     apr_size_t readlen;
302     apr_status_t rv = APR_SUCCESS;
303     int i;    
304
305     for (i = 0; i < len-1; i++) {
306         readlen = 1;
307         rv = apr_file_read(thefile, str+i, &readlen);
308
309         if (rv != APR_SUCCESS) {
310             break;
311         }
312
313         if (readlen != 1) {
314             rv = APR_EOF;
315             break;
316         }
317         
318         if (str[i] == '\n') {
319             i++;
320             break;
321         }
322     }
323     str[i] = 0;
324     if (i > 0) {
325         /* we stored chars; don't report EOF or any other errors;
326          * the app will find out about that on the next call
327          */
328         return APR_SUCCESS;
329     }
330     return rv;
331 }
332
333
334
335 APR_DECLARE_NONSTD(int) apr_file_printf(apr_file_t *fptr, 
336                                         const char *format, ...)
337 {
338     int cc;
339     va_list ap;
340     char *buf;
341     int len;
342
343     buf = malloc(HUGE_STRING_LEN);
344     if (buf == NULL) {
345         return 0;
346     }
347     va_start(ap, format);
348     len = apr_vsnprintf(buf, HUGE_STRING_LEN, format, ap);
349     cc = apr_file_puts(buf, fptr);
350     va_end(ap);
351     free(buf);
352     return (cc == APR_SUCCESS) ? len : -1;
353 }
354
355
356
357 apr_status_t apr_file_check_read(apr_file_t *fd)
358 {
359     int rc;
360
361     if (!fd->pipe)
362         return APR_SUCCESS; /* Not a pipe, assume no waiting */
363
364     rc = DosWaitEventSem(fd->pipeSem, SEM_IMMEDIATE_RETURN);
365
366     if (rc == ERROR_TIMEOUT)
367         return APR_TIMEUP;
368
369     return APR_FROM_OS_ERROR(rc);
370 }