~ubuntu-branches/ubuntu/feisty/apache2/feisty

« back to all changes in this revision

Viewing changes to srclib/apr/file_io/win32/open.c

  • Committer: Bazaar Package Importer
  • Author(s): Andreas Barth
  • Date: 2006-12-09 21:05:45 UTC
  • mfrom: (0.6.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20061209210545-h70s0xaqc2v8vqr2
Tags: 2.2.3-3.2
* Non-maintainer upload.
* 043_ajp_connection_reuse: Patch from upstream Bugzilla, fixing a critical
  issue with regard to connection reuse in mod_proxy_ajp.
  Closes: #396265

Show diffs side-by-side

added added

removed removed

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