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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
18 #define INCL_DOSERRORS
20 #include "apr_arch_file_io.h"
21 #include "apr_file_io.h"
23 #include "apr_strings.h"
27 APR_DECLARE(apr_status_t) apr_file_read(apr_file_t *thefile, void *buf, apr_size_t *nbytes)
32 if (!thefile->isopen) {
37 if (thefile->buffered) {
38 char *pos = (char *)buf;
42 apr_thread_mutex_lock(thefile->mutex);
44 if (thefile->direction == 1) {
45 int rv = apr_file_flush(thefile);
47 if (rv != APR_SUCCESS) {
48 apr_thread_mutex_unlock(thefile->mutex);
53 thefile->direction = 0;
54 thefile->dataRead = 0;
57 while (rc == 0 && size > 0) {
58 if (thefile->bufpos >= thefile->dataRead) {
60 rc = DosRead(thefile->filedes, thefile->buffer,
61 APR_FILE_BUFSIZE, &bytesread);
65 thefile->eof_hit = TRUE;
69 thefile->dataRead = bytesread;
70 thefile->filePtr += thefile->dataRead;
74 blocksize = size > thefile->dataRead - thefile->bufpos ? thefile->dataRead - thefile->bufpos : size;
75 memcpy(pos, thefile->buffer + thefile->bufpos, blocksize);
76 thefile->bufpos += blocksize;
81 *nbytes = rc == 0 ? pos - (char *)buf : 0;
82 apr_thread_mutex_unlock(thefile->mutex);
84 if (*nbytes == 0 && rc == 0 && thefile->eof_hit) {
88 return APR_FROM_OS_ERROR(rc);
91 DosResetEventSem(thefile->pipeSem, &rc);
93 rc = DosRead(thefile->filedes, buf, *nbytes, &bytesread);
95 if (rc == ERROR_NO_DATA && thefile->timeout != 0) {
96 int rcwait = DosWaitEventSem(thefile->pipeSem, thefile->timeout >= 0 ? thefile->timeout / 1000 : SEM_INDEFINITE_WAIT);
99 rc = DosRead(thefile->filedes, buf, *nbytes, &bytesread);
101 else if (rcwait == ERROR_TIMEOUT) {
109 return APR_FROM_OS_ERROR(rc);
114 if (bytesread == 0) {
115 thefile->eof_hit = TRUE;
125 APR_DECLARE(apr_status_t) apr_file_write(apr_file_t *thefile, const void *buf, apr_size_t *nbytes)
130 if (!thefile->isopen) {
135 if (thefile->buffered) {
136 char *pos = (char *)buf;
140 apr_thread_mutex_lock(thefile->mutex);
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;
151 while (rc == 0 && size > 0) {
152 if (thefile->bufpos == APR_FILE_BUFSIZE) // write buffer is full
153 rc = apr_file_flush(thefile);
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;
162 apr_thread_mutex_unlock(thefile->mutex);
163 return APR_FROM_OS_ERROR(rc);
165 if (thefile->flags & APR_APPEND) {
166 FILELOCK all = { 0, 0x7fffffff };
168 rc = DosSetFileLocks(thefile->filedes, NULL, &all, -1, 0);
171 rc = DosSetFilePtr(thefile->filedes, 0, FILE_END, &newpos);
174 rc = DosWrite(thefile->filedes, buf, *nbytes, &byteswritten);
177 DosSetFileLocks(thefile->filedes, &all, NULL, -1, 0);
180 rc = DosWrite(thefile->filedes, buf, *nbytes, &byteswritten);
185 return APR_FROM_OS_ERROR(rc);
188 *nbytes = byteswritten;
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)
200 if ((bytes = writev(thefile->filedes, vec, nvec)) < 0) {
213 APR_DECLARE(apr_status_t) apr_file_putc(char ch, apr_file_t *thefile)
218 if (!thefile->isopen) {
222 rc = DosWrite(thefile->filedes, &ch, 1, &byteswritten);
225 return APR_FROM_OS_ERROR(rc);
233 APR_DECLARE(apr_status_t) apr_file_ungetc(char ch, apr_file_t *thefile)
235 apr_off_t offset = -1;
236 return apr_file_seek(thefile, APR_CUR, &offset);
240 APR_DECLARE(apr_status_t) apr_file_getc(char *ch, apr_file_t *thefile)
243 apr_size_t bytesread;
245 if (!thefile->isopen) {
250 rc = apr_file_read(thefile, ch, &bytesread);
256 if (bytesread == 0) {
257 thefile->eof_hit = TRUE;
266 APR_DECLARE(apr_status_t) apr_file_puts(const char *str, apr_file_t *thefile)
271 return apr_file_write(thefile, str, &len);
275 APR_DECLARE(apr_status_t) apr_file_flush(apr_file_t *thefile)
277 if (thefile->buffered) {
281 if (thefile->direction == 1 && thefile->bufpos) {
282 rc = DosWrite(thefile->filedes, thefile->buffer, thefile->bufpos, &written);
283 thefile->filePtr += written;
289 return APR_FROM_OS_ERROR(rc);
291 /* There isn't anything to do if we aren't buffering the output
292 * so just return success.
299 APR_DECLARE(apr_status_t) apr_file_gets(char *str, int len, apr_file_t *thefile)
302 apr_status_t rv = APR_SUCCESS;
305 for (i = 0; i < len-1; i++) {
307 rv = apr_file_read(thefile, str+i, &readlen);
309 if (rv != APR_SUCCESS) {
318 if (str[i] == '\n') {
325 /* we stored chars; don't report EOF or any other errors;
326 * the app will find out about that on the next call
335 APR_DECLARE_NONSTD(int) apr_file_printf(apr_file_t *fptr,
336 const char *format, ...)
343 buf = malloc(HUGE_STRING_LEN);
347 va_start(ap, format);
348 len = apr_vsnprintf(buf, HUGE_STRING_LEN, format, ap);
349 cc = apr_file_puts(buf, fptr);
352 return (cc == APR_SUCCESS) ? len : -1;
357 apr_status_t apr_file_check_read(apr_file_t *fd)
362 return APR_SUCCESS; /* Not a pipe, assume no waiting */
364 rc = DosWaitEventSem(fd->pipeSem, SEM_IMMEDIATE_RETURN);
366 if (rc == ERROR_TIMEOUT)
369 return APR_FROM_OS_ERROR(rc);