apr  1.7.0
About: APR (Apache Portable Runtime) project offers software libraries that provide a predictable and consistent interface to underlying platform-specific implementations (APR core library).
  Fossies Dox: apr-1.7.0.tar.bz2  ("inofficial" and yet experimental doxygen-generated source code documentation)  

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 
29  apr_size_t *nbytes)
30 {
31  apr_ssize_t rv;
32  char *pos = (char *)buf;
33  apr_uint64_t blocksize;
34  apr_uint64_t size = *nbytes;
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,
56  thefile->bufsize);
57  if (bytesread == 0) {
58  thefile->eof_hit = TRUE;
59  rv = APR_EOF;
60  break;
61  }
62  else if (bytesread == -1) {
63  rv = errno;
64  break;
65  }
66  thefile->dataRead = bytesread;
68  thefile->bufpos = 0;
69  }
70 
72  memcpy(pos, thefile->buffer + thefile->bufpos, blocksize);
73  thefile->bufpos += blocksize;
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 
85 APR_DECLARE(apr_status_t) apr_file_read(apr_file_t *thefile, void *buf, apr_size_t *nbytes)
86 {
87  apr_ssize_t rv;
88  apr_size_t bytes_read;
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) {
110  *nbytes = bytes_read;
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) {
124  *nbytes = bytes_read;
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
134  *nbytes = bytes_read;
135  if (rv == 0) {
136  thefile->eof_hit = TRUE;
137  return APR_EOF;
138  }
139  if (rv > 0) {
140  *nbytes += rv;
141  return APR_SUCCESS;
142  }
143  return errno;
144  }
145 }
146 
147 APR_DECLARE(apr_status_t) apr_file_write(apr_file_t *thefile, const void *buf, apr_size_t *nbytes)
148 {
149  apr_size_t rv;
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  */
162  apr_int64_t offset = thefile->filePtr - thefile->dataRead + thefile->bufpos;
163  if (offset != thefile->filePtr)
164  lseek(thefile->filedes, offset, SEEK_SET);
165  thefile->bufpos = thefile->dataRead = 0;
166  thefile->direction = 1;
167  }
168 
169  rv = 0;
170  while (rv == 0 && size > 0) {
171  if (thefile->bufpos == thefile->bufsize) /* write buffer is full*/
173 
174  blocksize = size > thefile->bufsize - thefile->bufpos ?
176  memcpy(thefile->buffer + thefile->bufpos, pos, blocksize);
177  thefile->bufpos += blocksize;
178  pos += blocksize;
179  size -= blocksize;
180  }
181 
183 
184  return rv;
185  }
186  else {
187  do {
188  rv = write(thefile->filedes, buf, *nbytes);
189  } while (rv == (apr_size_t)-1 && errno == EINTR);
190 #ifdef USE_WAIT_FOR_IO
191  if (rv == (apr_size_t)-1 &&
192  (errno == EAGAIN || errno == EWOULDBLOCK) &&
193  thefile->timeout != 0) {
195  if (arv != APR_SUCCESS) {
196  *nbytes = 0;
197  return arv;
198  }
199  else {
200  do {
201  do {
202  rv = write(thefile->filedes, buf, *nbytes);
203  } while (rv == (apr_size_t)-1 && errno == EINTR);
204  if (rv == (apr_size_t)-1 &&
205  (errno == EAGAIN || errno == EWOULDBLOCK)) {
206  *nbytes /= 2; /* yes, we'll loop if kernel lied
207  * and we can't even write 1 byte
208  */
209  }
210  else {
211  break;
212  }
213  } while (1);
214  }
215  }
216 #endif
217  if (rv == (apr_size_t)-1) {
218  (*nbytes) = 0;
219  return errno;
220  }
221  *nbytes = rv;
222  return APR_SUCCESS;
223  }
224 }
225 
226 APR_DECLARE(apr_status_t) apr_file_writev(apr_file_t *thefile, const struct iovec *vec,
227  apr_size_t nvec, apr_size_t *nbytes)
228 {
229 #ifdef HAVE_WRITEV
230  apr_status_t rv;
231  apr_ssize_t bytes;
232 
233  if (thefile->buffered) {
235 
237  if (rv != APR_SUCCESS) {
239  return rv;
240  }
241  if (thefile->direction == 0) {
242  /* Position file pointer for writing at the offset we are
243  * logically reading from
244  */
245  apr_int64_t offset = thefile->filePtr - thefile->dataRead +
246  thefile->bufpos;
247  if (offset != thefile->filePtr)
248  lseek(thefile->filedes, offset, SEEK_SET);
249  thefile->bufpos = thefile->dataRead = 0;
250  }
251 
253  }
254 
255  if ((bytes = writev(thefile->filedes, vec, nvec)) < 0) {
256  *nbytes = 0;
257  rv = errno;
258  }
259  else {
260  *nbytes = bytes;
261  rv = APR_SUCCESS;
262  }
263  return rv;
264 #else
265 
279  *nbytes = vec[0].iov_len;
280  return apr_file_write(thefile, vec[0].iov_base, nbytes);
281 #endif
282 }
283 
284 APR_DECLARE(apr_status_t) apr_file_putc(char ch, apr_file_t *thefile)
285 {
286  apr_size_t nbytes = 1;
287 
288  return apr_file_write(thefile, &ch, &nbytes);
289 }
290 
291 APR_DECLARE(apr_status_t) apr_file_ungetc(char ch, apr_file_t *thefile)
292 {
293  thefile->ungetchar = (unsigned char)ch;
294  return APR_SUCCESS;
295 }
296 
297 APR_DECLARE(apr_status_t) apr_file_getc(char *ch, apr_file_t *thefile)
298 {
299  apr_size_t nbytes = 1;
300 
301  return apr_file_read(thefile, ch, &nbytes);
302 }
303 
304 APR_DECLARE(apr_status_t) apr_file_puts(const char *str, apr_file_t *thefile)
305 {
306  return apr_file_write_full(thefile, str, strlen(str), NULL);
307 }
308 
310 {
312 
313  if (thefile->direction == 1 && thefile->bufpos) {
314  apr_ssize_t written = 0, ret;
315 
316  do {
317  ret = write(thefile->filedes, thefile->buffer + written,
318  thefile->bufpos - written);
319  if (ret > 0)
320  written += ret;
321  } while (written < thefile->bufpos &&
322  (ret > 0 || (ret == -1 && errno == EINTR)));
323  if (ret == -1) {
324  rv = errno;
325  } else {
326  thefile->filePtr += written;
327  thefile->bufpos = 0;
328  }
329  }
330 
331  return rv;
332 }
333 
334 APR_DECLARE(apr_status_t) apr_file_flush(apr_file_t *thefile)
335 {
337 
338  if (thefile->buffered) {
342  }
343  /* There isn't anything to do if we aren't buffering the output
344  * so just return success.
345  */
346  return rv;
347 }
348 
350 {
352 
354 
355  if (thefile->buffered) {
357 
358  if (rv != APR_SUCCESS) {
360  return rv;
361  }
362  }
363 
364  if (fsync(thefile->filedes)) {
365  rv = apr_get_os_error();
366  }
367 
369 
370  return rv;
371 }
372 
373 APR_DECLARE(apr_status_t) apr_file_datasync(apr_file_t *thefile)
374 {
376 
378 
379  if (thefile->buffered) {
381 
382  if (rv != APR_SUCCESS) {
384  return rv;
385  }
386  }
387 
388 #ifdef HAVE_FDATASYNC
389  if (fdatasync(thefile->filedes)) {
390 #elif defined(F_FULLFSYNC)
391  if (fcntl(thefile->filedes, F_FULLFSYNC)) {
392 #else
393  if (fsync(thefile->filedes)) {
394 #endif
395  rv = apr_get_os_error();
396  }
397 
399 
400  return rv;
401 }
402 
403 APR_DECLARE(apr_status_t) apr_file_gets(char *str, int len, apr_file_t *thefile)
404 {
405  apr_status_t rv = APR_SUCCESS; /* get rid of gcc warning */
406  apr_size_t nbytes;
407  const char *str_start = str;
408  char *final = str + len - 1;
409 
410  if (len <= 1) {
411  /* sort of like fgets(), which returns NULL and stores no bytes
412  */
413  return APR_SUCCESS;
414  }
415 
416  /* If we have an underlying buffer, we can be *much* more efficient
417  * and skip over the apr_file_read calls.
418  */
419  if (thefile->buffered) {
421 
422  if (thefile->direction == 1) {
424  if (rv) {
426  return rv;
427  }
428 
429  thefile->direction = 0;
430  thefile->bufpos = 0;
431  thefile->dataRead = 0;
432  }
433 
434  while (str < final) { /* leave room for trailing '\0' */
435  /* Force ungetc leftover to call apr_file_read. */
436  if (thefile->bufpos < thefile->dataRead &&
437  thefile->ungetchar == -1) {
438  *str = thefile->buffer[thefile->bufpos++];
439  }
440  else {
441  nbytes = 1;
443  if (rv != APR_SUCCESS) {
444  break;
445  }
446  }
447  if (*str == '\n') {
448  ++str;
449  break;
450  }
451  ++str;
452  }
454  }
455  else {
456  while (str < final) { /* leave room for trailing '\0' */
457  nbytes = 1;
458  rv = apr_file_read(thefile, str, &nbytes);
459  if (rv != APR_SUCCESS) {
460  break;
461  }
462  if (*str == '\n') {
463  ++str;
464  break;
465  }
466  ++str;
467  }
468  }
469 
470  /* We must store a terminating '\0' if we've stored any chars. We can
471  * get away with storing it if we hit an error first.
472  */
473  *str = '\0';
474  if (str > str_start) {
475  /* we stored chars; don't report EOF or any other errors;
476  * the app will find out about that on the next call
477  */
478  return APR_SUCCESS;
479  }
480  return rv;
481 }
482 
486  char *buf;
487 };
488 
490 {
491  struct apr_file_printf_data *data = (struct apr_file_printf_data *)buff;
492 
493  if (apr_file_write_full(data->fptr, data->buf,
494  data->vbuff.curpos - data->buf, NULL)) {
495  return -1;
496  }
497 
498  data->vbuff.curpos = data->buf;
499  return 0;
500 }
501 
502 APR_DECLARE_NONSTD(int) apr_file_printf(apr_file_t *fptr,
503  const char *format, ...)
504 {
505  struct apr_file_printf_data data;
506  va_list ap;
507  int count;
508 
509  /* don't really need a HUGE_STRING_LEN anymore */
510  data.buf = malloc(HUGE_STRING_LEN);
511  if (data.buf == NULL) {
512  return -1;
513  }
514  data.vbuff.curpos = data.buf;
515  data.vbuff.endpos = data.buf + HUGE_STRING_LEN;
516  data.fptr = fptr;
517  va_start(ap, format);
518  count = apr_vformatter(file_printf_flush,
520  /* apr_vformatter does not call flush for the last bits */
521  if (count >= 0) file_printf_flush((apr_vformatter_buff_t *)&data);
522 
523  va_end(ap);
524 
525  free(data.buf);
526 
527  return count;
528 }
apr_file_flush_locked
apr_status_t apr_file_flush_locked(apr_file_t *thefile)
Definition: readwrite.c:309
apr_file_t::buffer
char * buffer
Definition: apr_arch_file_io.h:113
data
void * data
Definition: apr_file_io.h:861
apr_file_t::bufpos
apr_size_t bufpos
Definition: apr_arch_file_io.h:114
str
char ** str
Definition: apr_cstr.h:125
apr_file_t::eof_hit
int eof_hit
Definition: apr_arch_file_io.h:102
apr_support.h
APR Support functions.
apr_strings.h
APR Strings library.
apr_file_printf_data::buf
char * buf
Definition: readwrite.c:486
nvec
const struct iovec apr_size_t nvec
Definition: apr_file_io.h:519
apr_file_t::buffered
int buffered
Definition: apr_arch_file_io.h:105
file_unlock
#define file_unlock(f)
Definition: apr_arch_file_io.h:87
file_read_buffered
static apr_status_t file_read_buffered(apr_file_t *thefile, void *buf, apr_size_t *nbytes)
Definition: readwrite.c:28
offset
apr_seek_where_t apr_off_t * offset
Definition: apr_file_io.h:717
APR_DECLARE
APR_DECLARE(apr_status_t)
Definition: readwrite.c:27
apr_vformatter_buff_t
Definition: apr_lib.h:64
ap
apr_vformatter_buff_t const char va_list ap
Definition: apr_lib.h:175
thefile
apr_file_t * thefile
Definition: apr_file_io.h:594
len
const char apr_ssize_t int apr_size_t * len
Definition: apr_encode.h:162
apr_file_t::bufsize
apr_size_t bufsize
Definition: apr_arch_file_io.h:115
format
const char * format
Definition: apr_file_io.h:873
apr_file_t::dataRead
apr_off_t dataRead
Definition: apr_arch_file_io.h:116
buf
char * buf
Definition: apr_errno.h:52
size
apr_size_t size
Definition: apr_allocator.h:115
vec
const struct iovec * vec
Definition: apr_file_io.h:519
apr_file_printf_data::vbuff
apr_vformatter_buff_t vbuff
Definition: readwrite.c:484
TRUE
#define TRUE
Definition: apr_snprintf.c:53
apr_get_os_error
#define apr_get_os_error()
Definition: apr_errno.h:1217
apr_file_t
Definition: apr_arch_file_io.h:97
bytes
const void apr_size_t bytes
Definition: apr_random.h:90
APR_DECLARE_NONSTD
APR_DECLARE_NONSTD(int)
Definition: readwrite.c:353
apr_status_t
int apr_status_t
Definition: apr_errno.h:44
bytes_read
void apr_size_t apr_size_t * bytes_read
Definition: apr_file_io.h:542
APR_SUCCESS
#define APR_SUCCESS
Definition: apr_errno.h:225
nbytes
void apr_size_t * nbytes
Definition: apr_file_io.h:482
apr_file_t::timeout
apr_interval_time_t timeout
Definition: apr_arch_file_io.h:104
HUGE_STRING_LEN
#define HUGE_STRING_LEN
Definition: apr_lib.h:52
apr_file_t::filedes
int filedes
Definition: apr_arch_file_io.h:99
apr_file_t::direction
int direction
Definition: apr_arch_file_io.h:117
file_lock
#define file_lock(f)
Definition: apr_arch_file_io.h:86
apr_file_t::ungetchar
int ungetchar
Definition: apr_arch_file_io.h:107
apr_file_printf_data::fptr
apr_file_t * fptr
Definition: readwrite.c:485
apr_file_printf_data
Definition: readwrite.c:483
apr_wait_for_io_or_timeout
apr_status_t apr_wait_for_io_or_timeout(apr_file_t *f, apr_socket_t *s, int for_read)
writev
#define writev
Definition: apr_arch_os2calls.h:57
file_printf_flush
static int file_printf_flush(apr_vformatter_buff_t *buff)
Definition: readwrite.c:489
apr_file_t::filePtr
apr_off_t filePtr
Definition: apr_arch_file_io.h:118
APR_EOF
#define APR_EOF
Definition: apr_errno.h:461
apr_thread_mutex.h
APR Thread Mutex Routines.