Apache HTTPD
readwrite.c
Go to the documentation of this file.
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#include "apr_arch_file_io.h"
18#include "apr_strings.h"
19#include "apr_thread_mutex.h"
20#include "apr_support.h"
21
22/* The only case where we don't use wait_for_io_or_timeout is on
23 * pre-BONE BeOS, so this check should be sufficient and simpler */
24#if !defined(BEOS_R5)
25#define USE_WAIT_FOR_IO
26#endif
27
30{
31 apr_ssize_t rv;
32 char *pos = (char *)buf;
35
36 if (thefile->direction == 1) {
38 if (rv) {
39 return rv;
40 }
41 thefile->bufpos = 0;
42 thefile->direction = 0;
43 thefile->dataRead = 0;
44 }
45
46 rv = 0;
47 if (thefile->ungetchar != -1) {
48 *pos = (char)thefile->ungetchar;
49 ++pos;
50 --size;
51 thefile->ungetchar = -1;
52 }
53 while (rv == 0 && size > 0) {
54 if (thefile->bufpos >= thefile->dataRead) {
55 int bytesread = read(thefile->filedes, thefile->buffer,
57 if (bytesread == 0) {
59 rv = APR_EOF;
60 break;
61 }
62 else if (bytesread == -1) {
63 rv = errno;
64 break;
65 }
68 thefile->bufpos = 0;
69 }
70
74 pos += blocksize;
75 size -= blocksize;
76 }
77
78 *nbytes = pos - (char *)buf;
79 if (*nbytes) {
80 rv = 0;
81 }
82 return rv;
83}
84
86{
87 apr_ssize_t rv;
89
90 if (*nbytes <= 0) {
91 *nbytes = 0;
92 return APR_SUCCESS;
93 }
94
95 if (thefile->buffered) {
99 return rv;
100 }
101 else {
102 bytes_read = 0;
103 if (thefile->ungetchar != -1) {
104 bytes_read = 1;
105 *(char *)buf = (char)thefile->ungetchar;
106 buf = (char *)buf + 1;
107 (*nbytes)--;
108 thefile->ungetchar = -1;
109 if (*nbytes == 0) {
111 return APR_SUCCESS;
112 }
113 }
114
115 do {
116 rv = read(thefile->filedes, buf, *nbytes);
117 } while (rv == -1 && errno == EINTR);
118#ifdef USE_WAIT_FOR_IO
119 if (rv == -1 &&
120 (errno == EAGAIN || errno == EWOULDBLOCK) &&
121 thefile->timeout != 0) {
123 if (arv != APR_SUCCESS) {
125 return arv;
126 }
127 else {
128 do {
129 rv = read(thefile->filedes, buf, *nbytes);
130 } while (rv == -1 && errno == EINTR);
131 }
132 }
133#endif
135 if (rv == 0) {
137 return APR_EOF;
138 }
139 if (rv > 0) {
140 *nbytes += rv;
141 return APR_SUCCESS;
142 }
143 return errno;
144 }
145}
146
148{
150
151 if (thefile->buffered) {
152 char *pos = (char *)buf;
153 int blocksize;
154 int size = *nbytes;
155
157
158 if ( thefile->direction == 0 ) {
159 /* Position file pointer for writing at the offset we are
160 * logically reading from
161 */
163 if (offset != thefile->filePtr) {
165 if (thefile->filePtr == -1) rv = errno;
166 }
168 thefile->direction = 1;
169 }
170
171 while (rv == 0 && size > 0) {
172 if (thefile->bufpos == thefile->bufsize) /* write buffer is full*/
174
179 pos += blocksize;
180 size -= blocksize;
181 }
182
184
185 return rv;
186 }
187 else {
188 do {
189 rv = write(thefile->filedes, buf, *nbytes);
190 } while (rv == (apr_size_t)-1 && errno == EINTR);
191#ifdef USE_WAIT_FOR_IO
192 if (rv == (apr_size_t)-1 &&
193 (errno == EAGAIN || errno == EWOULDBLOCK) &&
194 thefile->timeout != 0) {
196 if (arv != APR_SUCCESS) {
197 *nbytes = 0;
198 return arv;
199 }
200 else {
201 do {
202 do {
203 rv = write(thefile->filedes, buf, *nbytes);
204 } while (rv == (apr_size_t)-1 && errno == EINTR);
205 if (rv == (apr_size_t)-1 &&
206 (errno == EAGAIN || errno == EWOULDBLOCK)) {
207 *nbytes /= 2; /* yes, we'll loop if kernel lied
208 * and we can't even write 1 byte
209 */
210 }
211 else {
212 break;
213 }
214 } while (1);
215 }
216 }
217#endif
218 if (rv == (apr_size_t)-1) {
219 (*nbytes) = 0;
220 return errno;
221 }
222 *nbytes = rv;
223 return APR_SUCCESS;
224 }
225}
226
227APR_DECLARE(apr_status_t) apr_file_writev(apr_file_t *thefile, const struct iovec *vec,
229{
230#ifdef HAVE_WRITEV
231 apr_status_t rv;
233
234 if (thefile->buffered) {
236
238 if (rv != APR_SUCCESS) {
240 return rv;
241 }
242 if (thefile->direction == 0) {
243 /* Position file pointer for writing at the offset we are
244 * logically reading from
245 */
248 if (offset != thefile->filePtr) {
250 if (thefile->filePtr == -1) rv = errno;
251 }
253 }
254
256 if (rv) return rv;
257 }
258
259 if ((bytes = writev(thefile->filedes, vec, nvec)) < 0) {
260 *nbytes = 0;
261 rv = errno;
262 }
263 else {
264 *nbytes = bytes;
265 rv = APR_SUCCESS;
266 }
267 return rv;
268#else
283 *nbytes = vec[0].iov_len;
285#endif
286}
287
289{
290 apr_size_t nbytes = 1;
291
292 return apr_file_write(thefile, &ch, &nbytes);
293}
294
296{
297 thefile->ungetchar = (unsigned char)ch;
298 return APR_SUCCESS;
299}
300
302{
303 apr_size_t nbytes = 1;
304
305 return apr_file_read(thefile, ch, &nbytes);
306}
307
309{
310 return apr_file_write_full(thefile, str, strlen(str), NULL);
311}
312
314{
316
317 if (thefile->direction == 1 && thefile->bufpos) {
318 apr_ssize_t written = 0, ret;
319
320 do {
321 ret = write(thefile->filedes, thefile->buffer + written,
322 thefile->bufpos - written);
323 if (ret > 0)
324 written += ret;
325 } while (written < thefile->bufpos &&
326 (ret > 0 || (ret == -1 && errno == EINTR)));
327 if (ret == -1) {
328 rv = errno;
329 } else {
330 thefile->filePtr += written;
331 thefile->bufpos = 0;
332 }
333 }
334
335 return rv;
336}
337
339{
341
342 if (thefile->buffered) {
346 }
347 /* There isn't anything to do if we aren't buffering the output
348 * so just return success.
349 */
350 return rv;
351}
352
354{
356
358
359 if (thefile->buffered) {
361
362 if (rv != APR_SUCCESS) {
364 return rv;
365 }
366 }
367
368 if (fsync(thefile->filedes)) {
369 rv = apr_get_os_error();
370 }
371
373
374 return rv;
375}
376
378{
380 int os_status = 0;
381
383
384 if (thefile->buffered) {
386
387 if (rv != APR_SUCCESS) {
389 return rv;
390 }
391 }
392
393#ifdef HAVE_FDATASYNC
395#elif defined(F_FULLFSYNC)
397 if (os_status) {
398 /* Fall back to fsync() if the device doesn't support F_FULLFSYNC. */
400 }
401#else
403#endif
404 if (os_status) {
405 rv = apr_get_os_error();
406 }
407
409
410 return rv;
411}
412
414{
415 apr_status_t rv = APR_SUCCESS; /* get rid of gcc warning */
417 const char *str_start = str;
418 char *final = str + len - 1;
419
420 if (len <= 1) {
421 /* sort of like fgets(), which returns NULL and stores no bytes
422 */
423 return APR_SUCCESS;
424 }
425
426 /* If we have an underlying buffer, we can be *much* more efficient
427 * and skip over the apr_file_read calls.
428 */
429 if (thefile->buffered) {
431
432 if (thefile->direction == 1) {
434 if (rv) {
436 return rv;
437 }
438
439 thefile->direction = 0;
440 thefile->bufpos = 0;
441 thefile->dataRead = 0;
442 }
443
444 while (str < final) { /* leave room for trailing '\0' */
445 /* Force ungetc leftover to call apr_file_read. */
446 if (thefile->bufpos < thefile->dataRead &&
447 thefile->ungetchar == -1) {
449 }
450 else {
451 nbytes = 1;
453 if (rv != APR_SUCCESS) {
454 break;
455 }
456 }
457 if (*str == '\n') {
458 ++str;
459 break;
460 }
461 ++str;
462 }
464 }
465 else {
466 while (str < final) { /* leave room for trailing '\0' */
467 nbytes = 1;
469 if (rv != APR_SUCCESS) {
470 break;
471 }
472 if (*str == '\n') {
473 ++str;
474 break;
475 }
476 ++str;
477 }
478 }
479
480 /* We must store a terminating '\0' if we've stored any chars. We can
481 * get away with storing it if we hit an error first.
482 */
483 *str = '\0';
484 if (str > str_start) {
485 /* we stored chars; don't report EOF or any other errors;
486 * the app will find out about that on the next call
487 */
488 return APR_SUCCESS;
489 }
490 return rv;
491}
492
498
500{
502
503 if (apr_file_write_full(data->fptr, data->buf,
504 data->vbuff.curpos - data->buf, NULL)) {
505 return -1;
506 }
507
508 data->vbuff.curpos = data->buf;
509 return 0;
510}
511
513 const char *format, ...)
514{
516 va_list ap;
517 int count;
518
519 /* don't really need a HUGE_STRING_LEN anymore */
521 if (data.buf == NULL) {
522 return -1;
523 }
524 data.vbuff.curpos = data.buf;
525 data.vbuff.endpos = data.buf + HUGE_STRING_LEN;
526 data.fptr = fptr;
530 /* apr_vformatter does not call flush for the last bits */
532
533 va_end(ap);
534
535 free(data.buf);
536
537 return count;
538}
const char * buff
Definition ap_regex.h:186
const char apr_size_t len
Definition ap_regex.h:187
#define TRUE
Definition abts.h:38
#define writev
APR Strings library.
APR Support functions.
APR Thread Mutex Routines.
#define HUGE_STRING_LEN
Definition httpd.h:303
const unsigned char * buf
Definition util_md5.h:50
#define APR_EOF
Definition apr_errno.h:461
unsigned int count
Definition apr_md5.h:152
const void apr_status_t(*) apr_status_t(* APR_DECLARE)(void) apr_pool_pre_cleanup_register(apr_pool_t *p
Definition apr_pools.h:646
apr_size_t size
#define APR_SUCCESS
Definition apr_errno.h:225
#define apr_get_os_error()
Definition apr_errno.h:1217
int apr_status_t
Definition apr_errno.h:44
apr_file_t * thefile
void apr_size_t * nbytes
const struct iovec * vec
apr_seek_where_t apr_off_t * offset
const char * format
void apr_size_t apr_size_t * bytes_read
void * data
const struct iovec apr_size_t nvec
apr_vformatter_buff_t const char va_list ap
Definition apr_lib.h:176
APR_DECLARE_NONSTD(void) apr_terminate(void)
Definition start.c:173
const void apr_size_t bytes
Definition apr_random.h:91
apr_status_t apr_wait_for_io_or_timeout(apr_file_t *f, apr_socket_t *s, int for_read)
return NULL
Definition mod_so.c:359
#define file_unlock(f)
#define file_lock(f)
apr_vformatter_buff_t vbuff
Definition readwrite.c:494
apr_file_t * fptr
Definition readwrite.c:495
apr_interval_time_t timeout
apr_size_t bufpos
apr_off_t filePtr
apr_off_t dataRead
apr_size_t bufsize
static int file_printf_flush(apr_vformatter_buff_t *buff)
Definition readwrite.c:499
static apr_status_t file_read_buffered(apr_file_t *thefile, void *buf, apr_size_t *nbytes)
Definition readwrite.c:28
apr_status_t apr_file_flush_locked(apr_file_t *thefile)
Definition readwrite.c:313
#define str