diff options
author | 2015-11-30 01:45:08 -0500 | |
---|---|---|
committer | 2015-11-30 01:45:08 -0500 | |
commit | e8ec7aa8e38a93f5b034ac74cebce5de23710317 (patch) | |
tree | aa031937bf856c1f8d6ad7877b8d2cb0224da5ef /rubbos/app/httpd-2.0.64/srclib/apr/file_io/unix/readwrite.c | |
parent | cc40af334e619bb549038238507407866f774f8f (diff) |
upload http
JIRA: BOTTLENECK-10
Change-Id: I7598427ff904df438ce77c2819ee48ac75ffa8da
Signed-off-by: hongbotian <hongbo.tianhongbo@huawei.com>
Diffstat (limited to 'rubbos/app/httpd-2.0.64/srclib/apr/file_io/unix/readwrite.c')
-rw-r--r-- | rubbos/app/httpd-2.0.64/srclib/apr/file_io/unix/readwrite.c | 387 |
1 files changed, 387 insertions, 0 deletions
diff --git a/rubbos/app/httpd-2.0.64/srclib/apr/file_io/unix/readwrite.c b/rubbos/app/httpd-2.0.64/srclib/apr/file_io/unix/readwrite.c new file mode 100644 index 00000000..541ab587 --- /dev/null +++ b/rubbos/app/httpd-2.0.64/srclib/apr/file_io/unix/readwrite.c @@ -0,0 +1,387 @@ +/* Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "apr_arch_file_io.h" +#include "apr_strings.h" +#include "apr_thread_mutex.h" +#include "apr_support.h" + +/* The only case where we don't use wait_for_io_or_timeout is on + * pre-BONE BeOS, so this check should be sufficient and simpler */ +#if !BEOS_R5 +#define USE_WAIT_FOR_IO +#endif + +/* problems: + * 1) ungetchar not used for buffered files + */ +APR_DECLARE(apr_status_t) apr_file_read(apr_file_t *thefile, void *buf, apr_size_t *nbytes) +{ + apr_ssize_t rv; + apr_size_t bytes_read; + + if (*nbytes <= 0) { + *nbytes = 0; + return APR_SUCCESS; + } + + if (thefile->buffered) { + char *pos = (char *)buf; + apr_uint64_t blocksize; + apr_uint64_t size = *nbytes; + + file_lock(thefile); + + if (thefile->direction == 1) { + rv = apr_file_flush_locked(thefile); + if (rv) { + file_unlock(thefile); + return rv; + } + thefile->bufpos = 0; + thefile->direction = 0; + thefile->dataRead = 0; + } + + rv = 0; + if (thefile->ungetchar != -1) { + *pos = (char)thefile->ungetchar; + ++pos; + --size; + thefile->ungetchar = -1; + } + while (rv == 0 && size > 0) { + if (thefile->bufpos >= thefile->dataRead) { + int bytesread = read(thefile->filedes, thefile->buffer, APR_FILE_BUFSIZE); + if (bytesread == 0) { + thefile->eof_hit = TRUE; + rv = APR_EOF; + break; + } + else if (bytesread == -1) { + rv = errno; + break; + } + thefile->dataRead = bytesread; + thefile->filePtr += thefile->dataRead; + thefile->bufpos = 0; + } + + blocksize = size > thefile->dataRead - thefile->bufpos ? thefile->dataRead - thefile->bufpos : size; + memcpy(pos, thefile->buffer + thefile->bufpos, blocksize); + thefile->bufpos += blocksize; + pos += blocksize; + size -= blocksize; + } + + *nbytes = pos - (char *)buf; + if (*nbytes) { + rv = 0; + } + + file_unlock(thefile); + + return rv; + } + else { + bytes_read = 0; + if (thefile->ungetchar != -1) { + bytes_read = 1; + *(char *)buf = (char)thefile->ungetchar; + buf = (char *)buf + 1; + (*nbytes)--; + thefile->ungetchar = -1; + if (*nbytes == 0) { + *nbytes = bytes_read; + return APR_SUCCESS; + } + } + + do { + rv = read(thefile->filedes, buf, *nbytes); + } while (rv == -1 && errno == EINTR); +#ifdef USE_WAIT_FOR_IO + if (rv == -1 && + (errno == EAGAIN || errno == EWOULDBLOCK) && + thefile->timeout != 0) { + apr_status_t arv = apr_wait_for_io_or_timeout(thefile, NULL, 1); + if (arv != APR_SUCCESS) { + *nbytes = bytes_read; + return arv; + } + else { + do { + rv = read(thefile->filedes, buf, *nbytes); + } while (rv == -1 && errno == EINTR); + } + } +#endif + *nbytes = bytes_read; + if (rv == 0) { + thefile->eof_hit = TRUE; + return APR_EOF; + } + if (rv > 0) { + *nbytes += rv; + return APR_SUCCESS; + } + return errno; + } +} + +APR_DECLARE(apr_status_t) apr_file_write(apr_file_t *thefile, const void *buf, apr_size_t *nbytes) +{ + apr_size_t rv; + + if (thefile->buffered) { + char *pos = (char *)buf; + int blocksize; + int size = *nbytes; + + file_lock(thefile); + + if ( thefile->direction == 0 ) { + /* Position file pointer for writing at the offset we are + * logically reading from + */ + apr_int64_t offset = thefile->filePtr - thefile->dataRead + thefile->bufpos; + if (offset != thefile->filePtr) + lseek(thefile->filedes, offset, SEEK_SET); + thefile->bufpos = thefile->dataRead = 0; + thefile->direction = 1; + } + + rv = 0; + while (rv == 0 && size > 0) { + if (thefile->bufpos == APR_FILE_BUFSIZE) /* write buffer is full*/ + rv = apr_file_flush_locked(thefile); + + blocksize = size > APR_FILE_BUFSIZE - thefile->bufpos ? + APR_FILE_BUFSIZE - thefile->bufpos : size; + memcpy(thefile->buffer + thefile->bufpos, pos, blocksize); + thefile->bufpos += blocksize; + pos += blocksize; + size -= blocksize; + } + + file_unlock(thefile); + + return rv; + } + else { + do { + rv = write(thefile->filedes, buf, *nbytes); + } while (rv == (apr_size_t)-1 && errno == EINTR); +#ifdef USE_WAIT_FOR_IO + if (rv == (apr_size_t)-1 && + (errno == EAGAIN || errno == EWOULDBLOCK) && + thefile->timeout != 0) { + apr_status_t arv = apr_wait_for_io_or_timeout(thefile, NULL, 0); + if (arv != APR_SUCCESS) { + *nbytes = 0; + return arv; + } + else { + do { + do { + rv = write(thefile->filedes, buf, *nbytes); + } while (rv == (apr_size_t)-1 && errno == EINTR); + if (rv == (apr_size_t)-1 && + (errno == EAGAIN || errno == EWOULDBLOCK)) { + *nbytes /= 2; /* yes, we'll loop if kernel lied + * and we can't even write 1 byte + */ + } + else { + break; + } + } while (1); + } + } +#endif + if (rv == (apr_size_t)-1) { + (*nbytes) = 0; + return errno; + } + *nbytes = rv; + return APR_SUCCESS; + } +} + +APR_DECLARE(apr_status_t) apr_file_writev(apr_file_t *thefile, const struct iovec *vec, + apr_size_t nvec, apr_size_t *nbytes) +{ +#ifdef HAVE_WRITEV + apr_status_t rv; + int bytes; + + if (thefile->buffered) { + file_lock(thefile); + + rv = apr_file_flush_locked(thefile); + if (rv != APR_SUCCESS) { + file_unlock(thefile); + return rv; + } + if (thefile->direction == 0) { + /* Position file pointer for writing at the offset we are + * logically reading from + */ + apr_int64_t offset = thefile->filePtr - thefile->dataRead + + thefile->bufpos; + if (offset != thefile->filePtr) + lseek(thefile->filedes, offset, SEEK_SET); + thefile->bufpos = thefile->dataRead = 0; + } + + file_unlock(thefile); + } + + if ((bytes = writev(thefile->filedes, vec, nvec)) < 0) { + *nbytes = 0; + rv = errno; + } + else { + *nbytes = bytes; + rv = APR_SUCCESS; + } + return rv; +#else + *nbytes = vec[0].iov_len; + return apr_file_write(thefile, vec[0].iov_base, nbytes); +#endif +} + +APR_DECLARE(apr_status_t) apr_file_putc(char ch, apr_file_t *thefile) +{ + apr_size_t nbytes = 1; + + return apr_file_write(thefile, &ch, &nbytes); +} + +APR_DECLARE(apr_status_t) apr_file_ungetc(char ch, apr_file_t *thefile) +{ + thefile->ungetchar = (unsigned char)ch; + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_file_getc(char *ch, apr_file_t *thefile) +{ + apr_size_t nbytes = 1; + + return apr_file_read(thefile, ch, &nbytes); +} + +APR_DECLARE(apr_status_t) apr_file_puts(const char *str, apr_file_t *thefile) +{ + apr_size_t nbytes = strlen(str); + + return apr_file_write(thefile, str, &nbytes); +} + +apr_status_t apr_file_flush_locked(apr_file_t *thefile) +{ + apr_status_t rv = APR_SUCCESS; + + if (thefile->direction == 1 && thefile->bufpos) { + apr_ssize_t written; + + do { + written = write(thefile->filedes, thefile->buffer, thefile->bufpos); + } while (written == -1 && errno == EINTR); + if (written == -1) { + rv = errno; + } else { + thefile->filePtr += written; + thefile->bufpos = 0; + } + } + + return rv; +} + +APR_DECLARE(apr_status_t) apr_file_flush(apr_file_t *thefile) +{ + apr_status_t rv = APR_SUCCESS; + + if (thefile->buffered) { + file_lock(thefile); + rv = apr_file_flush_locked(thefile); + file_unlock(thefile); + } + /* There isn't anything to do if we aren't buffering the output + * so just return success. + */ + return rv; +} + +APR_DECLARE(apr_status_t) apr_file_gets(char *str, int len, apr_file_t *thefile) +{ + apr_status_t rv = APR_SUCCESS; /* get rid of gcc warning */ + apr_size_t nbytes; + const char *str_start = str; + char *final = str + len - 1; + + if (len <= 1) { + /* sort of like fgets(), which returns NULL and stores no bytes + */ + return APR_SUCCESS; + } + + while (str < final) { /* leave room for trailing '\0' */ + nbytes = 1; + rv = apr_file_read(thefile, str, &nbytes); + if (rv != APR_SUCCESS) { + break; + } + if (*str == '\n') { + ++str; + break; + } + ++str; + } + /* We must store a terminating '\0' if we've stored any chars. We can + * get away with storing it if we hit an error first. + */ + *str = '\0'; + if (str > str_start) { + /* we stored chars; don't report EOF or any other errors; + * the app will find out about that on the next call + */ + return APR_SUCCESS; + } + return rv; +} + +APR_DECLARE_NONSTD(int) apr_file_printf(apr_file_t *fptr, + const char *format, ...) +{ + apr_status_t cc; + va_list ap; + char *buf; + int len; + + buf = malloc(HUGE_STRING_LEN); + if (buf == NULL) { + return 0; + } + va_start(ap, format); + len = apr_vsnprintf(buf, HUGE_STRING_LEN, format, ap); + cc = apr_file_puts(buf, fptr); + va_end(ap); + free(buf); + return (cc == APR_SUCCESS) ? len : -1; +} |