xref: /aosp_15_r20/external/cronet/third_party/apache-portable-runtime/src/file_io/os2/readwrite.c (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
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 #define INCL_DOS
18 #define INCL_DOSERRORS
19 
20 #include "apr_arch_file_io.h"
21 #include "apr_file_io.h"
22 #include "apr_lib.h"
23 #include "apr_strings.h"
24 
25 #include <malloc.h>
26 
apr_file_read(apr_file_t * thefile,void * buf,apr_size_t * nbytes)27 APR_DECLARE(apr_status_t) apr_file_read(apr_file_t *thefile, void *buf, apr_size_t *nbytes)
28 {
29     ULONG rc = 0;
30     ULONG bytesread;
31 
32     if (!thefile->isopen) {
33         *nbytes = 0;
34         return APR_EBADF;
35     }
36 
37     if (thefile->buffered) {
38         char *pos = (char *)buf;
39         ULONG blocksize;
40         ULONG size = *nbytes;
41 
42         apr_thread_mutex_lock(thefile->mutex);
43 
44         if (thefile->direction == 1) {
45             int rv = apr_file_flush(thefile);
46 
47             if (rv != APR_SUCCESS) {
48                 apr_thread_mutex_unlock(thefile->mutex);
49                 return rv;
50             }
51 
52             thefile->bufpos = 0;
53             thefile->direction = 0;
54             thefile->dataRead = 0;
55         }
56 
57         while (rc == 0 && size > 0) {
58             if (thefile->bufpos >= thefile->dataRead) {
59                 ULONG bytesread;
60                 rc = DosRead(thefile->filedes, thefile->buffer,
61                              thefile->bufsize, &bytesread);
62 
63                 if (bytesread == 0) {
64                     if (rc == 0)
65                         thefile->eof_hit = TRUE;
66                     break;
67                 }
68 
69                 thefile->dataRead = bytesread;
70                 thefile->filePtr += thefile->dataRead;
71                 thefile->bufpos = 0;
72             }
73 
74             blocksize = size > thefile->dataRead - thefile->bufpos ? thefile->dataRead - thefile->bufpos : size;
75             memcpy(pos, thefile->buffer + thefile->bufpos, blocksize);
76             thefile->bufpos += blocksize;
77             pos += blocksize;
78             size -= blocksize;
79         }
80 
81         *nbytes = rc == 0 ? pos - (char *)buf : 0;
82         apr_thread_mutex_unlock(thefile->mutex);
83 
84         if (*nbytes == 0 && rc == 0 && thefile->eof_hit) {
85             return APR_EOF;
86         }
87 
88         return APR_FROM_OS_ERROR(rc);
89     } else {
90         if (thefile->pipe)
91             DosResetEventSem(thefile->pipeSem, &rc);
92 
93         rc = DosRead(thefile->filedes, buf, *nbytes, &bytesread);
94 
95         if (rc == ERROR_NO_DATA && thefile->timeout != 0) {
96             int rcwait = DosWaitEventSem(thefile->pipeSem, thefile->timeout >= 0 ? thefile->timeout / 1000 : SEM_INDEFINITE_WAIT);
97 
98             if (rcwait == 0) {
99                 rc = DosRead(thefile->filedes, buf, *nbytes, &bytesread);
100             }
101             else if (rcwait == ERROR_TIMEOUT) {
102                 *nbytes = 0;
103                 return APR_TIMEUP;
104             }
105         }
106 
107         if (rc) {
108             *nbytes = 0;
109             return APR_FROM_OS_ERROR(rc);
110         }
111 
112         *nbytes = bytesread;
113 
114         if (bytesread == 0) {
115             thefile->eof_hit = TRUE;
116             return APR_EOF;
117         }
118 
119         return APR_SUCCESS;
120     }
121 }
122 
123 
124 
apr_file_write(apr_file_t * thefile,const void * buf,apr_size_t * nbytes)125 APR_DECLARE(apr_status_t) apr_file_write(apr_file_t *thefile, const void *buf, apr_size_t *nbytes)
126 {
127     ULONG rc = 0;
128     ULONG byteswritten;
129 
130     if (!thefile->isopen) {
131         *nbytes = 0;
132         return APR_EBADF;
133     }
134 
135     if (thefile->buffered) {
136         char *pos = (char *)buf;
137         int blocksize;
138         int size = *nbytes;
139 
140         apr_thread_mutex_lock(thefile->mutex);
141 
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;
149         }
150 
151         while (rc == 0 && size > 0) {
152             if (thefile->bufpos == thefile->bufsize) /* write buffer is full */
153                 /* XXX bug; - rc is double-transformed os->apr below */
154                 rc = apr_file_flush(thefile);
155 
156             blocksize = size > thefile->bufsize - thefile->bufpos ? thefile->bufsize - thefile->bufpos : size;
157             memcpy(thefile->buffer + thefile->bufpos, pos, blocksize);
158             thefile->bufpos += blocksize;
159             pos += blocksize;
160             size -= blocksize;
161         }
162 
163         apr_thread_mutex_unlock(thefile->mutex);
164         return APR_FROM_OS_ERROR(rc);
165     } else {
166         if (thefile->flags & APR_FOPEN_APPEND) {
167             FILELOCK all = { 0, 0x7fffffff };
168             ULONG newpos;
169             rc = DosSetFileLocks(thefile->filedes, NULL, &all, -1, 0);
170 
171             if (rc == 0) {
172                 rc = DosSetFilePtr(thefile->filedes, 0, FILE_END, &newpos);
173 
174                 if (rc == 0) {
175                     rc = DosWrite(thefile->filedes, buf, *nbytes, &byteswritten);
176                 }
177 
178                 DosSetFileLocks(thefile->filedes, &all, NULL, -1, 0);
179             }
180         } else {
181             rc = DosWrite(thefile->filedes, buf, *nbytes, &byteswritten);
182         }
183 
184         if (rc) {
185             *nbytes = 0;
186             return APR_FROM_OS_ERROR(rc);
187         }
188 
189         *nbytes = byteswritten;
190         return APR_SUCCESS;
191     }
192 }
193 
194 
195 
196 #ifdef HAVE_WRITEV
197 
apr_file_writev(apr_file_t * thefile,const struct iovec * vec,apr_size_t nvec,apr_size_t * nbytes)198 APR_DECLARE(apr_status_t) apr_file_writev(apr_file_t *thefile, const struct iovec *vec, apr_size_t nvec, apr_size_t *nbytes)
199 {
200     int bytes;
201 
202     if (thefile->buffered) {
203         apr_status_t rv = apr_file_flush(thefile);
204         if (rv != APR_SUCCESS) {
205             return rv;
206         }
207     }
208 
209     if ((bytes = writev(thefile->filedes, vec, nvec)) < 0) {
210         *nbytes = 0;
211         return errno;
212     }
213     else {
214         *nbytes = bytes;
215         return APR_SUCCESS;
216     }
217 }
218 #endif
219 
220 
221 
apr_file_putc(char ch,apr_file_t * thefile)222 APR_DECLARE(apr_status_t) apr_file_putc(char ch, apr_file_t *thefile)
223 {
224     ULONG rc;
225     ULONG byteswritten;
226 
227     if (!thefile->isopen) {
228         return APR_EBADF;
229     }
230 
231     rc = DosWrite(thefile->filedes, &ch, 1, &byteswritten);
232 
233     if (rc) {
234         return APR_FROM_OS_ERROR(rc);
235     }
236 
237     return APR_SUCCESS;
238 }
239 
240 
241 
apr_file_ungetc(char ch,apr_file_t * thefile)242 APR_DECLARE(apr_status_t) apr_file_ungetc(char ch, apr_file_t *thefile)
243 {
244     apr_off_t offset = -1;
245     return apr_file_seek(thefile, APR_CUR, &offset);
246 }
247 
248 
apr_file_getc(char * ch,apr_file_t * thefile)249 APR_DECLARE(apr_status_t) apr_file_getc(char *ch, apr_file_t *thefile)
250 {
251     ULONG rc;
252     apr_size_t bytesread;
253 
254     if (!thefile->isopen) {
255         return APR_EBADF;
256     }
257 
258     bytesread = 1;
259     rc = apr_file_read(thefile, ch, &bytesread);
260 
261     if (rc) {
262         return rc;
263     }
264 
265     if (bytesread == 0) {
266         thefile->eof_hit = TRUE;
267         return APR_EOF;
268     }
269 
270     return APR_SUCCESS;
271 }
272 
273 
274 
apr_file_puts(const char * str,apr_file_t * thefile)275 APR_DECLARE(apr_status_t) apr_file_puts(const char *str, apr_file_t *thefile)
276 {
277     apr_size_t len;
278 
279     len = strlen(str);
280     return apr_file_write(thefile, str, &len);
281 }
282 
283 
apr_file_flush(apr_file_t * thefile)284 APR_DECLARE(apr_status_t) apr_file_flush(apr_file_t *thefile)
285 {
286     if (thefile->buffered) {
287         ULONG written = 0;
288         int rc = 0;
289 
290         if (thefile->direction == 1 && thefile->bufpos) {
291             rc = DosWrite(thefile->filedes, thefile->buffer, thefile->bufpos, &written);
292             thefile->filePtr += written;
293 
294             if (rc == 0)
295                 thefile->bufpos = 0;
296         }
297 
298         return APR_FROM_OS_ERROR(rc);
299     } else {
300         /* There isn't anything to do if we aren't buffering the output
301          * so just return success.
302          */
303         return APR_SUCCESS;
304     }
305 }
306 
apr_file_sync(apr_file_t * thefile)307 APR_DECLARE(apr_status_t) apr_file_sync(apr_file_t *thefile)
308 {
309     return APR_ENOTIMPL;
310 }
311 
apr_file_datasync(apr_file_t * thefile)312 APR_DECLARE(apr_status_t) apr_file_datasync(apr_file_t *thefile)
313 {
314     return APR_ENOTIMPL;
315 }
316 
apr_file_gets(char * str,int len,apr_file_t * thefile)317 APR_DECLARE(apr_status_t) apr_file_gets(char *str, int len, apr_file_t *thefile)
318 {
319     apr_size_t readlen;
320     apr_status_t rv = APR_SUCCESS;
321     int i;
322 
323     for (i = 0; i < len-1; i++) {
324         readlen = 1;
325         rv = apr_file_read(thefile, str+i, &readlen);
326 
327         if (rv != APR_SUCCESS) {
328             break;
329         }
330 
331         if (readlen != 1) {
332             rv = APR_EOF;
333             break;
334         }
335 
336         if (str[i] == '\n') {
337             i++;
338             break;
339         }
340     }
341     str[i] = 0;
342     if (i > 0) {
343         /* we stored chars; don't report EOF or any other errors;
344          * the app will find out about that on the next call
345          */
346         return APR_SUCCESS;
347     }
348     return rv;
349 }
350 
351 
352 
apr_file_printf(apr_file_t * fptr,const char * format,...)353 APR_DECLARE_NONSTD(int) apr_file_printf(apr_file_t *fptr,
354                                         const char *format, ...)
355 {
356     int cc;
357     va_list ap;
358     char *buf;
359     int len;
360 
361     buf = malloc(HUGE_STRING_LEN);
362     if (buf == NULL) {
363         return 0;
364     }
365     va_start(ap, format);
366     len = apr_vsnprintf(buf, HUGE_STRING_LEN, format, ap);
367     cc = apr_file_puts(buf, fptr);
368     va_end(ap);
369     free(buf);
370     return (cc == APR_SUCCESS) ? len : -1;
371 }
372 
373 
374 
apr_file_check_read(apr_file_t * fd)375 apr_status_t apr_file_check_read(apr_file_t *fd)
376 {
377     int rc;
378 
379     if (!fd->pipe)
380         return APR_SUCCESS; /* Not a pipe, assume no waiting */
381 
382     rc = DosWaitEventSem(fd->pipeSem, SEM_IMMEDIATE_RETURN);
383 
384     if (rc == ERROR_TIMEOUT)
385         return APR_TIMEUP;
386 
387     return APR_FROM_OS_ERROR(rc);
388 }
389