diff options
Diffstat (limited to 'file_io/os2/readwrite.c')
-rw-r--r-- | file_io/os2/readwrite.c | 388 |
1 files changed, 388 insertions, 0 deletions
diff --git a/file_io/os2/readwrite.c b/file_io/os2/readwrite.c new file mode 100644 index 0000000..d00591d --- /dev/null +++ b/file_io/os2/readwrite.c @@ -0,0 +1,388 @@ +/* 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. + */ + +#define INCL_DOS +#define INCL_DOSERRORS + +#include "apr_arch_file_io.h" +#include "apr_file_io.h" +#include "apr_lib.h" +#include "apr_strings.h" + +#include <malloc.h> + +APR_DECLARE(apr_status_t) apr_file_read(apr_file_t *thefile, void *buf, apr_size_t *nbytes) +{ + ULONG rc = 0; + ULONG bytesread; + + if (!thefile->isopen) { + *nbytes = 0; + return APR_EBADF; + } + + if (thefile->buffered) { + char *pos = (char *)buf; + ULONG blocksize; + ULONG size = *nbytes; + + apr_thread_mutex_lock(thefile->mutex); + + if (thefile->direction == 1) { + int rv = apr_file_flush(thefile); + + if (rv != APR_SUCCESS) { + apr_thread_mutex_unlock(thefile->mutex); + return rv; + } + + thefile->bufpos = 0; + thefile->direction = 0; + thefile->dataRead = 0; + } + + while (rc == 0 && size > 0) { + if (thefile->bufpos >= thefile->dataRead) { + ULONG bytesread; + rc = DosRead(thefile->filedes, thefile->buffer, + thefile->bufsize, &bytesread); + + if (bytesread == 0) { + if (rc == 0) + thefile->eof_hit = TRUE; + 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 = rc == 0 ? pos - (char *)buf : 0; + apr_thread_mutex_unlock(thefile->mutex); + + if (*nbytes == 0 && rc == 0 && thefile->eof_hit) { + return APR_EOF; + } + + return APR_FROM_OS_ERROR(rc); + } else { + if (thefile->pipe) + DosResetEventSem(thefile->pipeSem, &rc); + + rc = DosRead(thefile->filedes, buf, *nbytes, &bytesread); + + if (rc == ERROR_NO_DATA && thefile->timeout != 0) { + int rcwait = DosWaitEventSem(thefile->pipeSem, thefile->timeout >= 0 ? thefile->timeout / 1000 : SEM_INDEFINITE_WAIT); + + if (rcwait == 0) { + rc = DosRead(thefile->filedes, buf, *nbytes, &bytesread); + } + else if (rcwait == ERROR_TIMEOUT) { + *nbytes = 0; + return APR_TIMEUP; + } + } + + if (rc) { + *nbytes = 0; + return APR_FROM_OS_ERROR(rc); + } + + *nbytes = bytesread; + + if (bytesread == 0) { + thefile->eof_hit = TRUE; + return APR_EOF; + } + + return APR_SUCCESS; + } +} + + + +APR_DECLARE(apr_status_t) apr_file_write(apr_file_t *thefile, const void *buf, apr_size_t *nbytes) +{ + ULONG rc = 0; + ULONG byteswritten; + + if (!thefile->isopen) { + *nbytes = 0; + return APR_EBADF; + } + + if (thefile->buffered) { + char *pos = (char *)buf; + int blocksize; + int size = *nbytes; + + apr_thread_mutex_lock(thefile->mutex); + + if ( thefile->direction == 0 ) { + /* Position file pointer for writing at the offset we are logically reading from */ + ULONG offset = thefile->filePtr - thefile->dataRead + thefile->bufpos; + if (offset != thefile->filePtr) + DosSetFilePtr(thefile->filedes, offset, FILE_BEGIN, &thefile->filePtr ); + thefile->bufpos = thefile->dataRead = 0; + thefile->direction = 1; + } + + while (rc == 0 && size > 0) { + if (thefile->bufpos == thefile->bufsize) /* write buffer is full */ + /* XXX bug; - rc is double-transformed os->apr below */ + rc = apr_file_flush(thefile); + + blocksize = size > thefile->bufsize - thefile->bufpos ? thefile->bufsize - thefile->bufpos : size; + memcpy(thefile->buffer + thefile->bufpos, pos, blocksize); + thefile->bufpos += blocksize; + pos += blocksize; + size -= blocksize; + } + + apr_thread_mutex_unlock(thefile->mutex); + return APR_FROM_OS_ERROR(rc); + } else { + if (thefile->flags & APR_FOPEN_APPEND) { + FILELOCK all = { 0, 0x7fffffff }; + ULONG newpos; + rc = DosSetFileLocks(thefile->filedes, NULL, &all, -1, 0); + + if (rc == 0) { + rc = DosSetFilePtr(thefile->filedes, 0, FILE_END, &newpos); + + if (rc == 0) { + rc = DosWrite(thefile->filedes, buf, *nbytes, &byteswritten); + } + + DosSetFileLocks(thefile->filedes, &all, NULL, -1, 0); + } + } else { + rc = DosWrite(thefile->filedes, buf, *nbytes, &byteswritten); + } + + if (rc) { + *nbytes = 0; + return APR_FROM_OS_ERROR(rc); + } + + *nbytes = byteswritten; + return APR_SUCCESS; + } +} + + + +#ifdef HAVE_WRITEV + +APR_DECLARE(apr_status_t) apr_file_writev(apr_file_t *thefile, const struct iovec *vec, apr_size_t nvec, apr_size_t *nbytes) +{ + int bytes; + + if (thefile->buffered) { + apr_status_t rv = apr_file_flush(thefile); + if (rv != APR_SUCCESS) { + return rv; + } + } + + if ((bytes = writev(thefile->filedes, vec, nvec)) < 0) { + *nbytes = 0; + return errno; + } + else { + *nbytes = bytes; + return APR_SUCCESS; + } +} +#endif + + + +APR_DECLARE(apr_status_t) apr_file_putc(char ch, apr_file_t *thefile) +{ + ULONG rc; + ULONG byteswritten; + + if (!thefile->isopen) { + return APR_EBADF; + } + + rc = DosWrite(thefile->filedes, &ch, 1, &byteswritten); + + if (rc) { + return APR_FROM_OS_ERROR(rc); + } + + return APR_SUCCESS; +} + + + +APR_DECLARE(apr_status_t) apr_file_ungetc(char ch, apr_file_t *thefile) +{ + apr_off_t offset = -1; + return apr_file_seek(thefile, APR_CUR, &offset); +} + + +APR_DECLARE(apr_status_t) apr_file_getc(char *ch, apr_file_t *thefile) +{ + ULONG rc; + apr_size_t bytesread; + + if (!thefile->isopen) { + return APR_EBADF; + } + + bytesread = 1; + rc = apr_file_read(thefile, ch, &bytesread); + + if (rc) { + return rc; + } + + if (bytesread == 0) { + thefile->eof_hit = TRUE; + return APR_EOF; + } + + return APR_SUCCESS; +} + + + +APR_DECLARE(apr_status_t) apr_file_puts(const char *str, apr_file_t *thefile) +{ + apr_size_t len; + + len = strlen(str); + return apr_file_write(thefile, str, &len); +} + + +APR_DECLARE(apr_status_t) apr_file_flush(apr_file_t *thefile) +{ + if (thefile->buffered) { + ULONG written = 0; + int rc = 0; + + if (thefile->direction == 1 && thefile->bufpos) { + rc = DosWrite(thefile->filedes, thefile->buffer, thefile->bufpos, &written); + thefile->filePtr += written; + + if (rc == 0) + thefile->bufpos = 0; + } + + return APR_FROM_OS_ERROR(rc); + } else { + /* There isn't anything to do if we aren't buffering the output + * so just return success. + */ + return APR_SUCCESS; + } +} + +APR_DECLARE(apr_status_t) apr_file_sync(apr_file_t *thefile) +{ + return APR_ENOTIMPL; +} + +APR_DECLARE(apr_status_t) apr_file_datasync(apr_file_t *thefile) +{ + return APR_ENOTIMPL; +} + +APR_DECLARE(apr_status_t) apr_file_gets(char *str, int len, apr_file_t *thefile) +{ + apr_size_t readlen; + apr_status_t rv = APR_SUCCESS; + int i; + + for (i = 0; i < len-1; i++) { + readlen = 1; + rv = apr_file_read(thefile, str+i, &readlen); + + if (rv != APR_SUCCESS) { + break; + } + + if (readlen != 1) { + rv = APR_EOF; + break; + } + + if (str[i] == '\n') { + i++; + break; + } + } + str[i] = 0; + if (i > 0) { + /* 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, ...) +{ + int 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; +} + + + +apr_status_t apr_file_check_read(apr_file_t *fd) +{ + int rc; + + if (!fd->pipe) + return APR_SUCCESS; /* Not a pipe, assume no waiting */ + + rc = DosWaitEventSem(fd->pipeSem, SEM_IMMEDIATE_RETURN); + + if (rc == ERROR_TIMEOUT) + return APR_TIMEUP; + + return APR_FROM_OS_ERROR(rc); +} |