ViewVC Help
View File | Revision Log | Show Annotations | Download File | View Changeset | Root Listing
root/src/vendor/apache/apr/1.5.2/file_io/win32/open.c
Revision: 9274
Committed: Mon Feb 20 03:07:52 2017 UTC (7 years, 2 months ago) by laffer1
Content type: text/plain
File size: 23701 byte(s)
Log Message:
apr 1.5.2

File Contents

# Content
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_private.h"
18 #include "apr_arch_file_io.h"
19 #include "apr_file_io.h"
20 #include "apr_general.h"
21 #include "apr_strings.h"
22 #include "apr_portable.h"
23 #include "apr_thread_mutex.h"
24 #if APR_HAVE_ERRNO_H
25 #include <errno.h>
26 #endif
27 #include <winbase.h>
28 #include <string.h>
29 #ifdef HAVE_SYS_STAT_H
30 #include <sys/stat.h>
31 #endif
32 #include "apr_arch_misc.h"
33 #include "apr_arch_inherit.h"
34 #include <io.h>
35 #include <winioctl.h>
36
37 #if APR_HAS_UNICODE_FS
38 apr_status_t utf8_to_unicode_path(apr_wchar_t* retstr, apr_size_t retlen,
39 const char* srcstr)
40 {
41 /* TODO: The computations could preconvert the string to determine
42 * the true size of the retstr, but that's a memory over speed
43 * tradeoff that isn't appropriate this early in development.
44 *
45 * Allocate the maximum string length based on leading 4
46 * characters of \\?\ (allowing nearly unlimited path lengths)
47 * plus the trailing null, then transform /'s into \\'s since
48 * the \\?\ form doesn't allow '/' path seperators.
49 *
50 * Note that the \\?\ form only works for local drive paths, and
51 * \\?\UNC\ is needed UNC paths.
52 */
53 apr_size_t srcremains = strlen(srcstr) + 1;
54 apr_wchar_t *t = retstr;
55 apr_status_t rv;
56
57 /* This is correct, we don't twist the filename if it is will
58 * definitely be shorter than 248 characters. It merits some
59 * performance testing to see if this has any effect, but there
60 * seem to be applications that get confused by the resulting
61 * Unicode \\?\ style file names, especially if they use argv[0]
62 * or call the Win32 API functions such as GetModuleName, etc.
63 * Not every application is prepared to handle such names.
64 *
65 * Note also this is shorter than MAX_PATH, as directory paths
66 * are actually limited to 248 characters.
67 *
68 * Note that a utf-8 name can never result in more wide chars
69 * than the original number of utf-8 narrow chars.
70 */
71 if (srcremains > 248) {
72 if (srcstr[1] == ':' && (srcstr[2] == '/' || srcstr[2] == '\\')) {
73 wcscpy (retstr, L"\\\\?\\");
74 retlen -= 4;
75 t += 4;
76 }
77 else if ((srcstr[0] == '/' || srcstr[0] == '\\')
78 && (srcstr[1] == '/' || srcstr[1] == '\\')
79 && (srcstr[2] != '?')) {
80 /* Skip the slashes */
81 srcstr += 2;
82 srcremains -= 2;
83 wcscpy (retstr, L"\\\\?\\UNC\\");
84 retlen -= 8;
85 t += 8;
86 }
87 }
88
89 if ((rv = apr_conv_utf8_to_ucs2(srcstr, &srcremains, t, &retlen))) {
90 return (rv == APR_INCOMPLETE) ? APR_EINVAL : rv;
91 }
92 if (srcremains) {
93 return APR_ENAMETOOLONG;
94 }
95 for (; *t; ++t)
96 if (*t == L'/')
97 *t = L'\\';
98 return APR_SUCCESS;
99 }
100
101 apr_status_t unicode_to_utf8_path(char* retstr, apr_size_t retlen,
102 const apr_wchar_t* srcstr)
103 {
104 /* Skip the leading 4 characters if the path begins \\?\, or substitute
105 * // for the \\?\UNC\ path prefix, allocating the maximum string
106 * length based on the remaining string, plus the trailing null.
107 * then transform \\'s back into /'s since the \\?\ form never
108 * allows '/' path seperators, and APR always uses '/'s.
109 */
110 apr_size_t srcremains = wcslen(srcstr) + 1;
111 apr_status_t rv;
112 char *t = retstr;
113 if (srcstr[0] == L'\\' && srcstr[1] == L'\\' &&
114 srcstr[2] == L'?' && srcstr[3] == L'\\') {
115 if (srcstr[4] == L'U' && srcstr[5] == L'N' &&
116 srcstr[6] == L'C' && srcstr[7] == L'\\') {
117 srcremains -= 8;
118 srcstr += 8;
119 retstr[0] = '\\';
120 retstr[1] = '\\';
121 retlen -= 2;
122 t += 2;
123 }
124 else {
125 srcremains -= 4;
126 srcstr += 4;
127 }
128 }
129
130 if ((rv = apr_conv_ucs2_to_utf8(srcstr, &srcremains, t, &retlen))) {
131 return rv;
132 }
133 if (srcremains) {
134 return APR_ENAMETOOLONG;
135 }
136 return APR_SUCCESS;
137 }
138 #endif
139
140 void *res_name_from_filename(const char *file, int global, apr_pool_t *pool)
141 {
142 #if APR_HAS_UNICODE_FS
143 IF_WIN_OS_IS_UNICODE
144 {
145 apr_wchar_t *wpre, *wfile, *ch;
146 apr_size_t n = strlen(file) + 1;
147 apr_size_t r, d;
148
149 if (apr_os_level >= APR_WIN_2000) {
150 if (global)
151 wpre = L"Global\\";
152 else
153 wpre = L"Local\\";
154 }
155 else
156 wpre = L"";
157 r = wcslen(wpre);
158
159 if (n > 256 - r) {
160 file += n - 256 - r;
161 n = 256;
162 /* skip utf8 continuation bytes */
163 while ((*file & 0xC0) == 0x80) {
164 ++file;
165 --n;
166 }
167 }
168 wfile = apr_palloc(pool, (r + n) * sizeof(apr_wchar_t));
169 wcscpy(wfile, wpre);
170 d = n;
171 if (apr_conv_utf8_to_ucs2(file, &n, wfile + r, &d)) {
172 return NULL;
173 }
174 for (ch = wfile + r; *ch; ++ch) {
175 if (*ch == ':' || *ch == '/' || *ch == '\\')
176 *ch = '_';
177 }
178 return wfile;
179 }
180 #endif
181 #if APR_HAS_ANSI_FS
182 ELSE_WIN_OS_IS_ANSI
183 {
184 char *nfile, *ch;
185 apr_size_t n = strlen(file) + 1;
186
187 #if !APR_HAS_UNICODE_FS
188 apr_size_t r, d;
189 char *pre;
190
191 if (apr_os_level >= APR_WIN_2000) {
192 if (global)
193 pre = "Global\\";
194 else
195 pre = "Local\\";
196 }
197 else
198 pre = "";
199 r = strlen(pre);
200
201 if (n > 256 - r) {
202 file += n - 256 - r;
203 n = 256;
204 }
205 nfile = apr_palloc(pool, (r + n) * sizeof(apr_wchar_t));
206 memcpy(nfile, pre, r);
207 memcpy(nfile + r, file, n);
208 #else
209 const apr_size_t r = 0;
210 if (n > 256) {
211 file += n - 256;
212 n = 256;
213 }
214 nfile = apr_pmemdup(pool, file, n);
215 #endif
216 for (ch = nfile + r; *ch; ++ch) {
217 if (*ch == ':' || *ch == '/' || *ch == '\\')
218 *ch = '_';
219 }
220 return nfile;
221 }
222 #endif
223 }
224
225 #if APR_HAS_UNICODE_FS
226 static apr_status_t make_sparse_file(apr_file_t *file)
227 {
228 BY_HANDLE_FILE_INFORMATION info;
229 apr_status_t rv;
230 DWORD bytesread = 0;
231 DWORD res;
232
233 /* test */
234
235 if (GetFileInformationByHandle(file->filehand, &info)
236 && (info.dwFileAttributes & FILE_ATTRIBUTE_SPARSE_FILE))
237 return APR_SUCCESS;
238
239 if (file->pOverlapped) {
240 file->pOverlapped->Offset = 0;
241 file->pOverlapped->OffsetHigh = 0;
242 }
243
244 if (DeviceIoControl(file->filehand, FSCTL_SET_SPARSE, NULL, 0, NULL, 0,
245 &bytesread, file->pOverlapped)) {
246 rv = APR_SUCCESS;
247 }
248 else
249 {
250 rv = apr_get_os_error();
251
252 if (rv == APR_FROM_OS_ERROR(ERROR_IO_PENDING))
253 {
254 do {
255 res = WaitForSingleObject(file->pOverlapped->hEvent,
256 (file->timeout > 0)
257 ? (DWORD)(file->timeout/1000)
258 : ((file->timeout == -1)
259 ? INFINITE : 0));
260 } while (res == WAIT_ABANDONED);
261
262 if (res != WAIT_OBJECT_0) {
263 CancelIo(file->filehand);
264 }
265
266 if (GetOverlappedResult(file->filehand, file->pOverlapped,
267 &bytesread, TRUE))
268 rv = APR_SUCCESS;
269 else
270 rv = apr_get_os_error();
271 }
272 }
273 return rv;
274 }
275 #endif
276
277 apr_status_t file_cleanup(void *thefile)
278 {
279 apr_file_t *file = thefile;
280 apr_status_t flush_rv = APR_SUCCESS;
281
282 if (file->filehand != INVALID_HANDLE_VALUE) {
283
284 if (file->buffered) {
285 /* XXX: flush here is not mutex protected */
286 flush_rv = apr_file_flush((apr_file_t *)thefile);
287 }
288
289 /* In order to avoid later segfaults with handle 'reuse',
290 * we must protect against the case that a dup2'ed handle
291 * is being closed, and invalidate the corresponding StdHandle
292 * We also tell msvcrt when stdhandles are closed.
293 */
294 if (file->flags & APR_STD_FLAGS)
295 {
296 if ((file->flags & APR_STD_FLAGS) == APR_STDERR_FLAG) {
297 _close(2);
298 SetStdHandle(STD_ERROR_HANDLE, INVALID_HANDLE_VALUE);
299 }
300 else if ((file->flags & APR_STD_FLAGS) == APR_STDOUT_FLAG) {
301 _close(1);
302 SetStdHandle(STD_OUTPUT_HANDLE, INVALID_HANDLE_VALUE);
303 }
304 else if ((file->flags & APR_STD_FLAGS) == APR_STDIN_FLAG) {
305 _close(0);
306 SetStdHandle(STD_INPUT_HANDLE, INVALID_HANDLE_VALUE);
307 }
308 }
309 else
310 CloseHandle(file->filehand);
311
312 file->filehand = INVALID_HANDLE_VALUE;
313 }
314 if (file->pOverlapped && file->pOverlapped->hEvent) {
315 CloseHandle(file->pOverlapped->hEvent);
316 file->pOverlapped = NULL;
317 }
318 return flush_rv;
319 }
320
321 APR_DECLARE(apr_status_t) apr_file_open(apr_file_t **new, const char *fname,
322 apr_int32_t flag, apr_fileperms_t perm,
323 apr_pool_t *pool)
324 {
325 HANDLE handle = INVALID_HANDLE_VALUE;
326 DWORD oflags = 0;
327 DWORD createflags = 0;
328 DWORD attributes = 0;
329 DWORD sharemode = FILE_SHARE_READ | FILE_SHARE_WRITE;
330 apr_status_t rv;
331
332 if (flag & APR_FOPEN_NONBLOCK) {
333 return APR_ENOTIMPL;
334 }
335 if (flag & APR_FOPEN_READ) {
336 oflags |= GENERIC_READ;
337 }
338 if (flag & APR_FOPEN_WRITE) {
339 oflags |= GENERIC_WRITE;
340 }
341 if (flag & APR_WRITEATTRS) {
342 oflags |= FILE_WRITE_ATTRIBUTES;
343 }
344
345 if (apr_os_level >= APR_WIN_NT)
346 sharemode |= FILE_SHARE_DELETE;
347
348 if (flag & APR_FOPEN_CREATE) {
349 if (flag & APR_FOPEN_EXCL) {
350 /* only create new if file does not already exist */
351 createflags = CREATE_NEW;
352 } else if (flag & APR_FOPEN_TRUNCATE) {
353 /* truncate existing file or create new */
354 createflags = CREATE_ALWAYS;
355 } else {
356 /* open existing but create if necessary */
357 createflags = OPEN_ALWAYS;
358 }
359 } else if (flag & APR_FOPEN_TRUNCATE) {
360 /* only truncate if file already exists */
361 createflags = TRUNCATE_EXISTING;
362 } else {
363 /* only open if file already exists */
364 createflags = OPEN_EXISTING;
365 }
366
367 if ((flag & APR_FOPEN_EXCL) && !(flag & APR_FOPEN_CREATE)) {
368 return APR_EACCES;
369 }
370
371 if (flag & APR_FOPEN_DELONCLOSE) {
372 attributes |= FILE_FLAG_DELETE_ON_CLOSE;
373 }
374
375 if (flag & APR_OPENLINK) {
376 attributes |= FILE_FLAG_OPEN_REPARSE_POINT;
377 }
378
379 /* Without READ or WRITE, we fail unless apr called apr_file_open
380 * internally with the private APR_OPENINFO flag.
381 *
382 * With the APR_OPENINFO flag on NT, use the option flag
383 * FILE_FLAG_BACKUP_SEMANTICS to allow us to open directories.
384 * See the static resolve_ident() fn in file_io/win32/filestat.c
385 */
386 if (!(flag & (APR_FOPEN_READ | APR_FOPEN_WRITE))) {
387 if (flag & APR_OPENINFO) {
388 if (apr_os_level >= APR_WIN_NT) {
389 attributes |= FILE_FLAG_BACKUP_SEMANTICS;
390 }
391 }
392 else {
393 return APR_EACCES;
394 }
395 if (flag & APR_READCONTROL)
396 oflags |= READ_CONTROL;
397 }
398
399 if (flag & APR_FOPEN_XTHREAD) {
400 /* This win32 specific feature is required
401 * to allow multiple threads to work with the file.
402 */
403 attributes |= FILE_FLAG_OVERLAPPED;
404 }
405
406 #if APR_HAS_UNICODE_FS
407 IF_WIN_OS_IS_UNICODE
408 {
409 apr_wchar_t wfname[APR_PATH_MAX];
410
411 if (flag & APR_FOPEN_SENDFILE_ENABLED) {
412 /* This feature is required to enable sendfile operations
413 * against the file on Win32. Also implies APR_FOPEN_XTHREAD.
414 */
415 flag |= APR_FOPEN_XTHREAD;
416 attributes |= FILE_FLAG_SEQUENTIAL_SCAN | FILE_FLAG_OVERLAPPED;
417 }
418
419 if ((rv = utf8_to_unicode_path(wfname, sizeof(wfname)
420 / sizeof(apr_wchar_t), fname)))
421 return rv;
422 handle = CreateFileW(wfname, oflags, sharemode,
423 NULL, createflags, attributes, 0);
424 }
425 #endif
426 #if APR_HAS_ANSI_FS
427 ELSE_WIN_OS_IS_ANSI {
428 handle = CreateFileA(fname, oflags, sharemode,
429 NULL, createflags, attributes, 0);
430 /* This feature is not supported on this platform. */
431 flag &= ~APR_FOPEN_SENDFILE_ENABLED;
432 }
433 #endif
434 if (handle == INVALID_HANDLE_VALUE) {
435 return apr_get_os_error();
436 }
437
438 (*new) = (apr_file_t *)apr_pcalloc(pool, sizeof(apr_file_t));
439 (*new)->pool = pool;
440 (*new)->filehand = handle;
441 (*new)->fname = apr_pstrdup(pool, fname);
442 (*new)->flags = flag;
443 (*new)->timeout = -1;
444 (*new)->ungetchar = -1;
445
446 if (flag & APR_FOPEN_APPEND) {
447 (*new)->append = 1;
448 SetFilePointer((*new)->filehand, 0, NULL, FILE_END);
449 }
450 if (flag & APR_FOPEN_BUFFERED) {
451 (*new)->buffered = 1;
452 (*new)->buffer = apr_palloc(pool, APR_FILE_DEFAULT_BUFSIZE);
453 (*new)->bufsize = APR_FILE_DEFAULT_BUFSIZE;
454 }
455 /* Need the mutex to handled buffered and O_APPEND style file i/o */
456 if ((*new)->buffered || (*new)->append) {
457 rv = apr_thread_mutex_create(&(*new)->mutex,
458 APR_THREAD_MUTEX_DEFAULT, pool);
459 if (rv) {
460 if (file_cleanup(*new) == APR_SUCCESS) {
461 apr_pool_cleanup_kill(pool, *new, file_cleanup);
462 }
463 return rv;
464 }
465 }
466
467 #if APR_HAS_UNICODE_FS
468 if ((apr_os_level >= APR_WIN_2000) && ((*new)->flags & APR_FOPEN_SPARSE)) {
469 if ((rv = make_sparse_file(*new)) != APR_SUCCESS)
470 /* The great mystery; do we close the file and return an error?
471 * Do we add a new APR_INCOMPLETE style error saying opened, but
472 * NOTSPARSE? For now let's simply mark the file as not-sparse.
473 */
474 (*new)->flags &= ~APR_FOPEN_SPARSE;
475 }
476 else
477 #endif
478 /* This feature is not supported on this platform. */
479 (*new)->flags &= ~APR_FOPEN_SPARSE;
480
481 #if APR_FILES_AS_SOCKETS
482 /* Create a pollset with room for one descriptor. */
483 /* ### check return codes */
484 (void) apr_pollset_create(&(*new)->pollset, 1, pool, 0);
485 #endif
486 if (!(flag & APR_FOPEN_NOCLEANUP)) {
487 apr_pool_cleanup_register((*new)->pool, (void *)(*new), file_cleanup,
488 apr_pool_cleanup_null);
489 }
490 return APR_SUCCESS;
491 }
492
493 APR_DECLARE(apr_status_t) apr_file_close(apr_file_t *file)
494 {
495 apr_status_t stat;
496 if ((stat = file_cleanup(file)) == APR_SUCCESS) {
497 apr_pool_cleanup_kill(file->pool, file, file_cleanup);
498
499 if (file->mutex) {
500 apr_thread_mutex_destroy(file->mutex);
501 }
502
503 return APR_SUCCESS;
504 }
505 return stat;
506 }
507
508 APR_DECLARE(apr_status_t) apr_file_remove(const char *path, apr_pool_t *pool)
509 {
510 #if APR_HAS_UNICODE_FS
511 IF_WIN_OS_IS_UNICODE
512 {
513 apr_wchar_t wpath[APR_PATH_MAX];
514 apr_status_t rv;
515 if ((rv = utf8_to_unicode_path(wpath, sizeof(wpath)
516 / sizeof(apr_wchar_t), path))) {
517 return rv;
518 }
519 if (DeleteFileW(wpath))
520 return APR_SUCCESS;
521 }
522 #endif
523 #if APR_HAS_ANSI_FS
524 ELSE_WIN_OS_IS_ANSI
525 if (DeleteFile(path))
526 return APR_SUCCESS;
527 #endif
528 return apr_get_os_error();
529 }
530
531 APR_DECLARE(apr_status_t) apr_file_rename(const char *frompath,
532 const char *topath,
533 apr_pool_t *pool)
534 {
535 IF_WIN_OS_IS_UNICODE
536 {
537 #if APR_HAS_UNICODE_FS
538 apr_wchar_t wfrompath[APR_PATH_MAX], wtopath[APR_PATH_MAX];
539 apr_status_t rv;
540 if ((rv = utf8_to_unicode_path(wfrompath,
541 sizeof(wfrompath) / sizeof(apr_wchar_t),
542 frompath))) {
543 return rv;
544 }
545 if ((rv = utf8_to_unicode_path(wtopath,
546 sizeof(wtopath) / sizeof(apr_wchar_t),
547 topath))) {
548 return rv;
549 }
550 #ifndef _WIN32_WCE
551 if (MoveFileExW(wfrompath, wtopath, MOVEFILE_REPLACE_EXISTING |
552 MOVEFILE_COPY_ALLOWED))
553 #else
554 if (MoveFileW(wfrompath, wtopath))
555 #endif
556 return APR_SUCCESS;
557 #else
558 if (MoveFileEx(frompath, topath, MOVEFILE_REPLACE_EXISTING |
559 MOVEFILE_COPY_ALLOWED))
560 return APR_SUCCESS;
561 #endif
562 }
563 #if APR_HAS_ANSI_FS
564 ELSE_WIN_OS_IS_ANSI
565 {
566 /* Windows 95 and 98 do not support MoveFileEx, so we'll use
567 * the old MoveFile function. However, MoveFile requires that
568 * the new file not already exist...so we have to delete that
569 * file if it does. Perhaps we should back up the to-be-deleted
570 * file in case something happens?
571 */
572 HANDLE handle = INVALID_HANDLE_VALUE;
573
574 if ((handle = CreateFile(topath, GENERIC_WRITE, 0, 0,
575 OPEN_EXISTING, 0, 0 )) != INVALID_HANDLE_VALUE )
576 {
577 CloseHandle(handle);
578 if (!DeleteFile(topath))
579 return apr_get_os_error();
580 }
581 if (MoveFile(frompath, topath))
582 return APR_SUCCESS;
583 }
584 #endif
585 return apr_get_os_error();
586 }
587
588 APR_DECLARE(apr_status_t) apr_file_link(const char *from_path,
589 const char *to_path)
590 {
591 apr_status_t rv = APR_SUCCESS;
592
593 #if APR_HAS_UNICODE_FS
594 IF_WIN_OS_IS_UNICODE
595 {
596 apr_wchar_t wfrom_path[APR_PATH_MAX];
597 apr_wchar_t wto_path[APR_PATH_MAX];
598
599 if ((rv = utf8_to_unicode_path(wfrom_path,
600 sizeof(wfrom_path) / sizeof(apr_wchar_t),
601 from_path)))
602 return rv;
603 if ((rv = utf8_to_unicode_path(wto_path,
604 sizeof(wto_path) / sizeof(apr_wchar_t),
605 to_path)))
606 return rv;
607
608 if (!CreateHardLinkW(wto_path, wfrom_path, NULL))
609 return apr_get_os_error();
610 }
611 #endif
612 #if APR_HAS_ANSI_FS
613 ELSE_WIN_OS_IS_ANSI {
614 if (!CreateHardLinkA(to_path, from_path, NULL))
615 return apr_get_os_error();
616 }
617 #endif
618 return rv;
619 }
620
621 APR_DECLARE(apr_status_t) apr_os_file_get(apr_os_file_t *thefile,
622 apr_file_t *file)
623 {
624 *thefile = file->filehand;
625 return APR_SUCCESS;
626 }
627
628 APR_DECLARE(apr_status_t) apr_os_file_put(apr_file_t **file,
629 apr_os_file_t *thefile,
630 apr_int32_t flags,
631 apr_pool_t *pool)
632 {
633 (*file) = apr_pcalloc(pool, sizeof(apr_file_t));
634 (*file)->pool = pool;
635 (*file)->filehand = *thefile;
636 (*file)->ungetchar = -1; /* no char avail */
637 (*file)->timeout = -1;
638 (*file)->flags = flags;
639
640 if (flags & APR_FOPEN_APPEND) {
641 (*file)->append = 1;
642 }
643 if (flags & APR_FOPEN_BUFFERED) {
644 (*file)->buffered = 1;
645 (*file)->buffer = apr_palloc(pool, APR_FILE_DEFAULT_BUFSIZE);
646 (*file)->bufsize = APR_FILE_DEFAULT_BUFSIZE;
647 }
648
649 if ((*file)->append || (*file)->buffered) {
650 apr_status_t rv;
651 rv = apr_thread_mutex_create(&(*file)->mutex,
652 APR_THREAD_MUTEX_DEFAULT, pool);
653 if (rv) {
654 return rv;
655 }
656 }
657
658 #if APR_FILES_AS_SOCKETS
659 /* Create a pollset with room for one descriptor. */
660 /* ### check return codes */
661 (void) apr_pollset_create(&(*file)->pollset, 1, pool, 0);
662 #endif
663 /* Should we be testing if thefile is a handle to
664 * a PIPE and set up the mechanics appropriately?
665 *
666 * (*file)->pipe;
667 */
668 return APR_SUCCESS;
669 }
670
671 APR_DECLARE(apr_status_t) apr_file_eof(apr_file_t *fptr)
672 {
673 if (fptr->eof_hit == 1) {
674 return APR_EOF;
675 }
676 return APR_SUCCESS;
677 }
678
679 APR_DECLARE(apr_status_t) apr_file_open_flags_stderr(apr_file_t **thefile,
680 apr_int32_t flags,
681 apr_pool_t *pool)
682 {
683 #ifdef _WIN32_WCE
684 return APR_ENOTIMPL;
685 #else
686 apr_os_file_t file_handle;
687
688 apr_set_os_error(APR_SUCCESS);
689 file_handle = GetStdHandle(STD_ERROR_HANDLE);
690 if (!file_handle)
691 file_handle = INVALID_HANDLE_VALUE;
692
693 return apr_os_file_put(thefile, &file_handle,
694 flags | APR_FOPEN_WRITE | APR_STDERR_FLAG, pool);
695 #endif
696 }
697
698 APR_DECLARE(apr_status_t) apr_file_open_flags_stdout(apr_file_t **thefile,
699 apr_int32_t flags,
700 apr_pool_t *pool)
701 {
702 #ifdef _WIN32_WCE
703 return APR_ENOTIMPL;
704 #else
705 apr_os_file_t file_handle;
706
707 apr_set_os_error(APR_SUCCESS);
708 file_handle = GetStdHandle(STD_OUTPUT_HANDLE);
709 if (!file_handle)
710 file_handle = INVALID_HANDLE_VALUE;
711
712 return apr_os_file_put(thefile, &file_handle,
713 flags | APR_FOPEN_WRITE | APR_STDOUT_FLAG, pool);
714 #endif
715 }
716
717 APR_DECLARE(apr_status_t) apr_file_open_flags_stdin(apr_file_t **thefile,
718 apr_int32_t flags,
719 apr_pool_t *pool)
720 {
721 #ifdef _WIN32_WCE
722 return APR_ENOTIMPL;
723 #else
724 apr_os_file_t file_handle;
725
726 apr_set_os_error(APR_SUCCESS);
727 file_handle = GetStdHandle(STD_INPUT_HANDLE);
728 if (!file_handle)
729 file_handle = INVALID_HANDLE_VALUE;
730
731 return apr_os_file_put(thefile, &file_handle,
732 flags | APR_FOPEN_READ | APR_STDIN_FLAG, pool);
733 #endif
734 }
735
736 APR_DECLARE(apr_status_t) apr_file_open_stderr(apr_file_t **thefile, apr_pool_t *pool)
737 {
738 return apr_file_open_flags_stderr(thefile, 0, pool);
739 }
740
741 APR_DECLARE(apr_status_t) apr_file_open_stdout(apr_file_t **thefile, apr_pool_t *pool)
742 {
743 return apr_file_open_flags_stdout(thefile, 0, pool);
744 }
745
746 APR_DECLARE(apr_status_t) apr_file_open_stdin(apr_file_t **thefile, apr_pool_t *pool)
747 {
748 return apr_file_open_flags_stdin(thefile, 0, pool);
749 }
750
751 APR_POOL_IMPLEMENT_ACCESSOR(file);
752
753 APR_IMPLEMENT_INHERIT_SET(file, flags, pool, file_cleanup)
754
755 APR_IMPLEMENT_INHERIT_UNSET(file, flags, pool, file_cleanup)