From e8ec7aa8e38a93f5b034ac74cebce5de23710317 Mon Sep 17 00:00:00 2001 From: hongbotian Date: Mon, 30 Nov 2015 01:45:08 -0500 Subject: upload http JIRA: BOTTLENECK-10 Change-Id: I7598427ff904df438ce77c2819ee48ac75ffa8da Signed-off-by: hongbotian --- .../httpd-2.0.64/srclib/apr/file_io/win32/open.c | 628 +++++++++++++++++++++ 1 file changed, 628 insertions(+) create mode 100644 rubbos/app/httpd-2.0.64/srclib/apr/file_io/win32/open.c (limited to 'rubbos/app/httpd-2.0.64/srclib/apr/file_io/win32/open.c') diff --git a/rubbos/app/httpd-2.0.64/srclib/apr/file_io/win32/open.c b/rubbos/app/httpd-2.0.64/srclib/apr/file_io/win32/open.c new file mode 100644 index 00000000..a60fba26 --- /dev/null +++ b/rubbos/app/httpd-2.0.64/srclib/apr/file_io/win32/open.c @@ -0,0 +1,628 @@ +/* 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. + */ + +#include "apr_private.h" +#include "apr_arch_file_io.h" +#include "apr_file_io.h" +#include "apr_general.h" +#include "apr_strings.h" +#include "apr_portable.h" +#include "apr_thread_mutex.h" +#if APR_HAVE_ERRNO_H +#include +#endif +#include +#include +#if APR_HAVE_SYS_STAT_H +#include +#endif +#include "apr_arch_misc.h" +#include "apr_arch_inherit.h" +#include + +#if APR_HAS_UNICODE_FS +apr_status_t utf8_to_unicode_path(apr_wchar_t* retstr, apr_size_t retlen, + const char* srcstr) +{ + /* TODO: The computations could preconvert the string to determine + * the true size of the retstr, but that's a memory over speed + * tradeoff that isn't appropriate this early in development. + * + * Allocate the maximum string length based on leading 4 + * characters of \\?\ (allowing nearly unlimited path lengths) + * plus the trailing null, then transform /'s into \\'s since + * the \\?\ form doesn't allow '/' path seperators. + * + * Note that the \\?\ form only works for local drive paths, and + * \\?\UNC\ is needed UNC paths. + */ + int srcremains = strlen(srcstr) + 1; + apr_wchar_t *t = retstr; + apr_status_t rv; + + /* This is correct, we don't twist the filename if it is will + * definately be shorter than 248 characters. It merits some + * performance testing to see if this has any effect, but there + * seem to be applications that get confused by the resulting + * Unicode \\?\ style file names, especially if they use argv[0] + * or call the Win32 API functions such as GetModuleName, etc. + * Not every application is prepared to handle such names. + * + * Note also this is shorter than MAX_PATH, as directory paths + * are actually limited to 248 characters. + * + * Note that a utf-8 name can never result in more wide chars + * than the original number of utf-8 narrow chars. + */ + if (srcremains > 248) { + if (srcstr[1] == ':' && (srcstr[2] == '/' || srcstr[2] == '\\')) { + wcscpy (retstr, L"\\\\?\\"); + retlen -= 4; + t += 4; + } + else if ((srcstr[0] == '/' || srcstr[0] == '\\') + && (srcstr[1] == '/' || srcstr[1] == '\\') + && (srcstr[2] != '?')) { + /* Skip the slashes */ + srcstr += 2; + srcremains -= 2; + wcscpy (retstr, L"\\\\?\\UNC\\"); + retlen -= 8; + t += 8; + } + } + + if (rv = apr_conv_utf8_to_ucs2(srcstr, &srcremains, t, &retlen)) { + return (rv == APR_INCOMPLETE) ? APR_EINVAL : rv; + } + if (srcremains) { + return APR_ENAMETOOLONG; + } + for (; *t; ++t) + if (*t == L'/') + *t = L'\\'; + return APR_SUCCESS; +} + +apr_status_t unicode_to_utf8_path(char* retstr, apr_size_t retlen, + const apr_wchar_t* srcstr) +{ + /* Skip the leading 4 characters if the path begins \\?\, or substitute + * // for the \\?\UNC\ path prefix, allocating the maximum string + * length based on the remaining string, plus the trailing null. + * then transform \\'s back into /'s since the \\?\ form never + * allows '/' path seperators, and APR always uses '/'s. + */ + int srcremains = wcslen(srcstr) + 1; + apr_status_t rv; + char *t = retstr; + if (srcstr[0] == L'\\' && srcstr[1] == L'\\' && + srcstr[2] == L'?' && srcstr[3] == L'\\') { + if (srcstr[4] == L'U' && srcstr[5] == L'N' && + srcstr[6] == L'C' && srcstr[7] == L'\\') { + srcremains -= 8; + srcstr += 8; + retstr[0] = '\\'; + retstr[1] = '\\'; + retlen -= 2; + t += 2; + } + else { + srcremains -= 4; + srcstr += 4; + } + } + + if (rv = apr_conv_ucs2_to_utf8(srcstr, &srcremains, t, &retlen)) { + return rv; + } + if (srcremains) { + return APR_ENAMETOOLONG; + } + return APR_SUCCESS; +} +#endif + +void *res_name_from_filename(const char *file, int global, apr_pool_t *pool) +{ +#if APR_HAS_UNICODE_FS + IF_WIN_OS_IS_UNICODE + { + apr_wchar_t *wpre, *wfile, *ch; + apr_size_t n = strlen(file) + 1; + apr_size_t r, d; + apr_status_t rv; + + if (apr_os_level >= APR_WIN_2000) { + if (global) + wpre = L"Global\\"; + else + wpre = L"Local\\"; + } + else + wpre = L""; + r = wcslen(wpre); + + if (n > 256 - r) { + file += n - 256 - r; + n = 256; + /* skip utf8 continuation bytes */ + while ((*file & 0xC0) == 0x80) { + ++file; + --n; + } + } + wfile = apr_palloc(pool, (r + n) * sizeof(apr_wchar_t)); + wcscpy(wfile, wpre); + d = n; + if (rv = apr_conv_utf8_to_ucs2(file, &n, wfile + r, &d)) { + return NULL; + } + for (ch = wfile + r; *ch; ++ch) { + if (*ch == ':' || *ch == '/' || *ch == '\\') + *ch = '_'; + } + return wfile; + } +#endif +#if APR_HAS_ANSI_FS + ELSE_WIN_OS_IS_ANSI + { + char *nfile, *ch; + apr_size_t n = strlen(file) + 1; + +#if !APR_HAS_UNICODE_FS + apr_status_t rv; + apr_size_t r, d; + char *pre; + + if (apr_os_level >= APR_WIN_2000) { + if (global) + pre = "Global\\"; + else + pre = "Local\\"; + } + else + pre = ""; + r = strlen(pre); + + if (n > 256 - r) { + file += n - 256 - r; + n = 256; + } + nfile = apr_palloc(pool, (r + n) * sizeof(apr_wchar_t)); + memcpy(nfile, pre, r); + memcpy(nfile + r, file, n); +#else + const apr_size_t r = 0; + if (n > 256) { + file += n - 256; + n = 256; + } + nfile = apr_pmemdup(pool, file, n); +#endif + for (ch = nfile + r; *ch; ++ch) { + if (*ch == ':' || *ch == '/' || *ch == '\\') + *ch = '_'; + } + return nfile; + } +#endif +} + + +apr_status_t file_cleanup(void *thefile) +{ + apr_file_t *file = thefile; + apr_status_t flush_rv = APR_SUCCESS; + + if (file->filehand != INVALID_HANDLE_VALUE) { + + if (file->buffered) { + /* XXX: flush here is not mutex protected */ + flush_rv = apr_file_flush((apr_file_t *)thefile); + } + + /* In order to avoid later segfaults with handle 'reuse', + * we must protect against the case that a dup2'ed handle + * is being closed, and invalidate the corresponding StdHandle + * We also tell msvcrt when stdhandles are closed. + */ + if (file->flags & APR_STD_FLAGS) + { + if ((file->flags & APR_STD_FLAGS) == APR_STDERR_FLAG) { + _close(2); + SetStdHandle(STD_ERROR_HANDLE, INVALID_HANDLE_VALUE); + } + else if ((file->flags & APR_STD_FLAGS) == APR_STDOUT_FLAG) { + _close(1); + SetStdHandle(STD_OUTPUT_HANDLE, INVALID_HANDLE_VALUE); + } + else if ((file->flags & APR_STD_FLAGS) == APR_STDIN_FLAG) { + _close(0); + SetStdHandle(STD_INPUT_HANDLE, INVALID_HANDLE_VALUE); + } + } + else + CloseHandle(file->filehand); + + file->filehand = INVALID_HANDLE_VALUE; + } + if (file->pOverlapped && file->pOverlapped->hEvent) { + CloseHandle(file->pOverlapped->hEvent); + file->pOverlapped = NULL; + } + return flush_rv; +} + +APR_DECLARE(apr_status_t) apr_file_open(apr_file_t **new, const char *fname, + apr_int32_t flag, apr_fileperms_t perm, + apr_pool_t *pool) +{ + HANDLE handle = INVALID_HANDLE_VALUE; + DWORD oflags = 0; + DWORD createflags = 0; + DWORD attributes = 0; + DWORD sharemode = FILE_SHARE_READ | FILE_SHARE_WRITE; + apr_status_t rv; + + if (flag & APR_READ) { + oflags |= GENERIC_READ; + } + if (flag & APR_WRITE) { + oflags |= GENERIC_WRITE; + } + if (flag & APR_WRITEATTRS) { + oflags |= FILE_WRITE_ATTRIBUTES; + } + + if (apr_os_level >= APR_WIN_NT) + sharemode |= FILE_SHARE_DELETE; + + if (flag & APR_CREATE) { + if (flag & APR_EXCL) { + /* only create new if file does not already exist */ + createflags = CREATE_NEW; + } else if (flag & APR_TRUNCATE) { + /* truncate existing file or create new */ + createflags = CREATE_ALWAYS; + } else { + /* open existing but create if necessary */ + createflags = OPEN_ALWAYS; + } + } else if (flag & APR_TRUNCATE) { + /* only truncate if file already exists */ + createflags = TRUNCATE_EXISTING; + } else { + /* only open if file already exists */ + createflags = OPEN_EXISTING; + } + + if ((flag & APR_EXCL) && !(flag & APR_CREATE)) { + return APR_EACCES; + } + + if (flag & APR_DELONCLOSE) { + attributes |= FILE_FLAG_DELETE_ON_CLOSE; + } + + if (flag & APR_OPENLINK) { + attributes |= FILE_FLAG_OPEN_REPARSE_POINT; + } + + /* Without READ or WRITE, we fail unless apr called apr_file_open + * internally with the private APR_OPENINFO flag. + * + * With the APR_OPENINFO flag on NT, use the option flag + * FILE_FLAG_BACKUP_SEMANTICS to allow us to open directories. + * See the static resolve_ident() fn in file_io/win32/filestat.c + */ + if (!(flag & (APR_READ | APR_WRITE))) { + if (flag & APR_OPENINFO) { + if (apr_os_level >= APR_WIN_NT) { + attributes |= FILE_FLAG_BACKUP_SEMANTICS; + } + } + else { + return APR_EACCES; + } + if (flag & APR_READCONTROL) + oflags |= READ_CONTROL; + } + + if (flag & APR_XTHREAD) { + /* This win32 specific feature is required + * to allow multiple threads to work with the file. + */ + attributes |= FILE_FLAG_OVERLAPPED; + } + +#if APR_HAS_UNICODE_FS + IF_WIN_OS_IS_UNICODE + { + apr_wchar_t wfname[APR_PATH_MAX]; + + if (flag & APR_SENDFILE_ENABLED) { + /* This feature is required to enable sendfile operations + * against the file on Win32. Also implies APR_XTHREAD. + */ + flag |= APR_XTHREAD; + attributes |= FILE_FLAG_SEQUENTIAL_SCAN | FILE_FLAG_OVERLAPPED; + } + + if (rv = utf8_to_unicode_path(wfname, sizeof(wfname) + / sizeof(apr_wchar_t), fname)) + return rv; + handle = CreateFileW(wfname, oflags, sharemode, + NULL, createflags, attributes, 0); + } +#endif +#if APR_HAS_ANSI_FS + ELSE_WIN_OS_IS_ANSI { + handle = CreateFileA(fname, oflags, sharemode, + NULL, createflags, attributes, 0); + if (flag & APR_SENDFILE_ENABLED) { + /* This feature is not supported on this platform. + */ + flag &= ~APR_SENDFILE_ENABLED; + } + + } +#endif + if (handle == INVALID_HANDLE_VALUE) { + return apr_get_os_error(); + } + + (*new) = (apr_file_t *)apr_pcalloc(pool, sizeof(apr_file_t)); + (*new)->pool = pool; + (*new)->filehand = handle; + (*new)->fname = apr_pstrdup(pool, fname); + (*new)->flags = flag; + (*new)->timeout = -1; + (*new)->ungetchar = -1; + + if (flag & APR_APPEND) { + (*new)->append = 1; + SetFilePointer((*new)->filehand, 0, NULL, FILE_END); + } + if (flag & APR_BUFFERED) { + (*new)->buffered = 1; + (*new)->buffer = apr_palloc(pool, APR_FILE_BUFSIZE); + } + /* Need the mutex to handled buffered and O_APPEND style file i/o */ + if ((*new)->buffered || (*new)->append) { + rv = apr_thread_mutex_create(&(*new)->mutex, + APR_THREAD_MUTEX_DEFAULT, pool); + if (rv) { + if (file_cleanup(*new) == APR_SUCCESS) { + apr_pool_cleanup_kill(pool, *new, file_cleanup); + } + return rv; + } + } + + if (!(flag & APR_FILE_NOCLEANUP)) { + apr_pool_cleanup_register((*new)->pool, (void *)(*new), file_cleanup, + apr_pool_cleanup_null); + } + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_file_close(apr_file_t *file) +{ + apr_status_t stat; + if ((stat = file_cleanup(file)) == APR_SUCCESS) { + apr_pool_cleanup_kill(file->pool, file, file_cleanup); + + if (file->mutex) { + apr_thread_mutex_destroy(file->mutex); + } + + return APR_SUCCESS; + } + return stat; +} + +APR_DECLARE(apr_status_t) apr_file_remove(const char *path, apr_pool_t *pool) +{ +#if APR_HAS_UNICODE_FS + IF_WIN_OS_IS_UNICODE + { + apr_wchar_t wpath[APR_PATH_MAX]; + apr_status_t rv; + if (rv = utf8_to_unicode_path(wpath, sizeof(wpath) + / sizeof(apr_wchar_t), path)) { + return rv; + } + if (DeleteFileW(wpath)) + return APR_SUCCESS; + } +#endif +#if APR_HAS_ANSI_FS + ELSE_WIN_OS_IS_ANSI + if (DeleteFile(path)) + return APR_SUCCESS; +#endif + return apr_get_os_error(); +} + +APR_DECLARE(apr_status_t) apr_file_rename(const char *frompath, + const char *topath, + apr_pool_t *pool) +{ + IF_WIN_OS_IS_UNICODE + { +#if APR_HAS_UNICODE_FS + apr_wchar_t wfrompath[APR_PATH_MAX], wtopath[APR_PATH_MAX]; + apr_status_t rv; + if (rv = utf8_to_unicode_path(wfrompath, sizeof(wfrompath) + / sizeof(apr_wchar_t), frompath)) { + return rv; + } + if (rv = utf8_to_unicode_path(wtopath, sizeof(wtopath) + / sizeof(apr_wchar_t), topath)) { + return rv; + } +#ifndef _WIN32_WCE + if (MoveFileExW(wfrompath, wtopath, MOVEFILE_REPLACE_EXISTING | + MOVEFILE_COPY_ALLOWED)) +#else + if (MoveFileW(wfrompath, wtopath)) +#endif + return APR_SUCCESS; +#else + if (MoveFileEx(frompath, topath, MOVEFILE_REPLACE_EXISTING | + MOVEFILE_COPY_ALLOWED)) + return APR_SUCCESS; +#endif + } +#if APR_HAS_ANSI_FS + ELSE_WIN_OS_IS_ANSI + { + /* Windows 95 and 98 do not support MoveFileEx, so we'll use + * the old MoveFile function. However, MoveFile requires that + * the new file not already exist...so we have to delete that + * file if it does. Perhaps we should back up the to-be-deleted + * file in case something happens? + */ + HANDLE handle = INVALID_HANDLE_VALUE; + + if ((handle = CreateFile(topath, GENERIC_WRITE, 0, 0, + OPEN_EXISTING, 0, 0 )) != INVALID_HANDLE_VALUE ) + { + CloseHandle(handle); + if (!DeleteFile(topath)) + return apr_get_os_error(); + } + if (MoveFile(frompath, topath)) + return APR_SUCCESS; + } +#endif + return apr_get_os_error(); +} + +APR_DECLARE(apr_status_t) apr_os_file_get(apr_os_file_t *thefile, + apr_file_t *file) +{ + *thefile = file->filehand; + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_os_file_put(apr_file_t **file, + apr_os_file_t *thefile, + apr_int32_t flags, + apr_pool_t *pool) +{ + (*file) = apr_pcalloc(pool, sizeof(apr_file_t)); + (*file)->pool = pool; + (*file)->filehand = *thefile; + (*file)->ungetchar = -1; /* no char avail */ + (*file)->timeout = -1; + (*file)->flags = flags; + + if (flags & APR_APPEND) { + (*file)->append = 1; + } + if (flags & APR_BUFFERED) { + (*file)->buffered = 1; + (*file)->buffer = apr_palloc(pool, APR_FILE_BUFSIZE); + } + + if ((*file)->append || (*file)->buffered) { + apr_status_t rv; + rv = apr_thread_mutex_create(&(*file)->mutex, + APR_THREAD_MUTEX_DEFAULT, pool); + if (rv) { + if (file_cleanup(*file) == APR_SUCCESS) { + apr_pool_cleanup_kill(pool, *file, file_cleanup); + } + return rv; + } + } + + /* XXX... we pcalloc above so all others are zeroed. + * Should we be testing if thefile is a handle to + * a PIPE and set up the mechanics appropriately? + * + * (*file)->pipe; + */ + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_file_eof(apr_file_t *fptr) +{ + if (fptr->eof_hit == 1) { + return APR_EOF; + } + return APR_SUCCESS; +} + +APR_DECLARE(apr_status_t) apr_file_open_stderr(apr_file_t **thefile, apr_pool_t *pool) +{ +#ifdef _WIN32_WCE + return APR_ENOTIMPL; +#else + apr_os_file_t file_handle; + + apr_set_os_error(APR_SUCCESS); + file_handle = GetStdHandle(STD_ERROR_HANDLE); + if (!file_handle) + file_handle = INVALID_HANDLE_VALUE; + + return apr_os_file_put(thefile, &file_handle, + APR_WRITE | APR_STDERR_FLAG, pool); +#endif +} + +APR_DECLARE(apr_status_t) apr_file_open_stdout(apr_file_t **thefile, apr_pool_t *pool) +{ +#ifdef _WIN32_WCE + return APR_ENOTIMPL; +#else + apr_os_file_t file_handle; + + apr_set_os_error(APR_SUCCESS); + file_handle = GetStdHandle(STD_OUTPUT_HANDLE); + if (!file_handle) + file_handle = INVALID_HANDLE_VALUE; + + return apr_os_file_put(thefile, &file_handle, + APR_WRITE | APR_STDOUT_FLAG, pool); +#endif +} + +APR_DECLARE(apr_status_t) apr_file_open_stdin(apr_file_t **thefile, apr_pool_t *pool) +{ +#ifdef _WIN32_WCE + return APR_ENOTIMPL; +#else + apr_os_file_t file_handle; + + apr_set_os_error(APR_SUCCESS); + file_handle = GetStdHandle(STD_INPUT_HANDLE); + if (!file_handle) + file_handle = INVALID_HANDLE_VALUE; + + return apr_os_file_put(thefile, &file_handle, + APR_READ | APR_STDIN_FLAG, pool); +#endif +} + +APR_POOL_IMPLEMENT_ACCESSOR(file); + +APR_IMPLEMENT_INHERIT_SET(file, flags, pool, file_cleanup) + +APR_IMPLEMENT_INHERIT_UNSET(file, flags, pool, file_cleanup) -- cgit 1.2.3-korg