Return-Path: Delivered-To: apmail-commons-commits-archive@minotaur.apache.org Received: (qmail 48033 invoked from network); 8 Aug 2009 18:48:30 -0000 Received: from hermes.apache.org (HELO mail.apache.org) (140.211.11.3) by minotaur.apache.org with SMTP; 8 Aug 2009 18:48:30 -0000 Received: (qmail 89742 invoked by uid 500); 8 Aug 2009 18:48:37 -0000 Delivered-To: apmail-commons-commits-archive@commons.apache.org Received: (qmail 89668 invoked by uid 500); 8 Aug 2009 18:48:36 -0000 Mailing-List: contact commits-help@commons.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@commons.apache.org Delivered-To: mailing list commits@commons.apache.org Received: (qmail 89659 invoked by uid 99); 8 Aug 2009 18:48:34 -0000 Received: from athena.apache.org (HELO athena.apache.org) (140.211.11.136) by apache.org (qpsmtpd/0.29) with ESMTP; Sat, 08 Aug 2009 18:48:34 +0000 X-ASF-Spam-Status: No, hits=-2000.0 required=10.0 tests=ALL_TRUSTED X-Spam-Check-By: apache.org Received: from [140.211.11.4] (HELO eris.apache.org) (140.211.11.4) by apache.org (qpsmtpd/0.29) with ESMTP; Sat, 08 Aug 2009 18:48:25 +0000 Received: by eris.apache.org (Postfix, from userid 65534) id 8FE972388985; Sat, 8 Aug 2009 18:48:05 +0000 (UTC) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r802434 - in /commons/sandbox/runtime/trunk/src/main/native: Makefile.msc.in include/arch/windows/acr_arch.h os/win32/dirent.c os/win32/wutil.c Date: Sat, 08 Aug 2009 18:48:05 -0000 To: commits@commons.apache.org From: mturk@apache.org X-Mailer: svnmailer-1.0.8 Message-Id: <20090808184805.8FE972388985@eris.apache.org> X-Virus-Checked: Checked by ClamAV on apache.org Author: mturk Date: Sat Aug 8 18:48:04 2009 New Revision: 802434 URL: http://svn.apache.org/viewvc?rev=802434&view=rev Log: Add win32 posix dirent Added: commons/sandbox/runtime/trunk/src/main/native/os/win32/dirent.c (with props) Modified: commons/sandbox/runtime/trunk/src/main/native/Makefile.msc.in commons/sandbox/runtime/trunk/src/main/native/include/arch/windows/acr_arch.h commons/sandbox/runtime/trunk/src/main/native/os/win32/wutil.c Modified: commons/sandbox/runtime/trunk/src/main/native/Makefile.msc.in URL: http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/native/Makefile.msc.in?rev=802434&r1=802433&r2=802434&view=diff ============================================================================== --- commons/sandbox/runtime/trunk/src/main/native/Makefile.msc.in (original) +++ commons/sandbox/runtime/trunk/src/main/native/Makefile.msc.in Sat Aug 8 18:48:04 2009 @@ -92,6 +92,7 @@ $(SRCDIR)/modules/network/ssl/openssl.$(OBJ) WINDOWS_OBJS= \ + $(SRCDIR)/os/win32/dirent.$(OBJ) \ $(SRCDIR)/os/win32/execmem.$(OBJ) \ $(SRCDIR)/os/win32/file.$(OBJ) \ $(SRCDIR)/os/win32/main.$(OBJ) \ Modified: commons/sandbox/runtime/trunk/src/main/native/include/arch/windows/acr_arch.h URL: http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/native/include/arch/windows/acr_arch.h?rev=802434&r1=802433&r2=802434&view=diff ============================================================================== --- commons/sandbox/runtime/trunk/src/main/native/include/arch/windows/acr_arch.h (original) +++ commons/sandbox/runtime/trunk/src/main/native/include/arch/windows/acr_arch.h Sat Aug 8 18:48:04 2009 @@ -335,7 +335,35 @@ return; } +/** + * Utility functions + */ wchar_t *res_name_from_filenamew(int, wchar_t *, const wchar_t *); +int utf8_to_unicode_path(wchar_t *, size_t, const char *, size_t); +int unicode_to_utf8_path(char *, size_t, const wchar_t *); + + +struct dirent { + ino_t d_ino; /* inode number */ + off_t d_off; /* offset to the next dirent */ + unsigned short d_reclen; /* length of this record (name) */ + unsigned char d_type; /* unused */ + char d_name[1024]; /* extended from MAX_PATH + * file name is UTF-8 encoded + */ +}; + +typedef struct DIR { + HANDLE d_find; /* Handle to FindFirstFile */ + off_t d_stat; /* Status of search + * 0 -> Not started yet + * -1 -> EOF + * >0 -> o based index of next entry. + */ + + struct dirent d_dir; + wchar_t d_name[8192]; +} DIR; /* * --------------------------------------------------------------------- Added: commons/sandbox/runtime/trunk/src/main/native/os/win32/dirent.c URL: http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/native/os/win32/dirent.c?rev=802434&view=auto ============================================================================== --- commons/sandbox/runtime/trunk/src/main/native/os/win32/dirent.c (added) +++ commons/sandbox/runtime/trunk/src/main/native/os/win32/dirent.c Sat Aug 8 18:48:04 2009 @@ -0,0 +1,236 @@ +/* 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. + */ + +/* + * dirent.c + * + * Derived from DIRLIB.C by Matt J. Weinstein + * This note appears in the DIRLIB.H + * DIRLIB.H by M. J. Weinstein Released to public domain 1-Jan-89 + * + */ + +#include "acr.h" +#include "acr_private.h" +#include "acr_arch.h" +#include "acr_memory.h" +#include "acr_error.h" + +DIR *opendir(const char *path) +{ + DIR *dir; + DWORD rc; + size_t len; + wchar_t wpath[ACR_HBUFF_SIZ]; /* Limited to 8K paths */ + + if (!path) { + /* Not a directory */ + ACR_SET_OS_ERROR(ACR_EFAULT); + return NULL; + } + if (!*path) { + /* Not a directory */ + ACR_SET_OS_ERROR(ACR_ENOTDIR); + return NULL; + } + if (utf8_to_unicode_path(wpath, ACR_HBUFF_LEN - 3, path, ACR_HBUFF_LEN - 3)) + return NULL; + + if ((rc = GetFileAttributesW(wpath)) == INVALID_FILE_ATTRIBUTES) + return NULL; + if (!(rc & FILE_ATTRIBUTE_DIRECTORY)) { + /* Not a directory */ + ACR_SET_OS_ERROR(ACR_ENOTDIR); + return NULL; + } + if (!(dir = malloc(sizeof(dir)))) + return NULL; + + + rc = GetFullPathNameW(wpath, ACR_HBUFF_LEN - 3, dir->d_name, NULL); + if (rc == 0 || rc > ACR_HBUFF_LEN - 3) { + free(dir); + /* Invalid file name */ + ACR_SET_OS_ERROR(ACR_EBADF); + return NULL; + } + len = wcslen(dir->d_name); + if (dir->d_name[len-1] != L'\\') + dir->d_name[len++] = L'\\'; + dir->d_name[len++] = L'*'; + dir->d_name[len++] = 0; + + dir->d_find = INVALID_HANDLE_VALUE; + dir->d_stat = 0; + + return dir; +} + +int closedir(DIR *dir) +{ + int rc = 0; + if (!dir) { + ACR_SET_OS_ERROR(ACR_EFAULT); + return -1; + } + + if (dir->d_find != INVALID_HANDLE_VALUE) { + if (!FindClose(dir->d_find)) + rc = GetLastError(); + } + free(dir); + if (rc) { + SetLastError(rc); + return -1; + } + else + return 0; +} + +void rewinddir(DIR *dir) +{ + if (!dir) { + ACR_SET_OS_ERROR(ACR_EFAULT); + return; + } + + if (dir->d_find != INVALID_HANDLE_VALUE) + FindClose(dir->d_find); + + dir->d_find = INVALID_HANDLE_VALUE; + dir->d_stat = 0; +} + +off_t telldir(DIR *dir) +{ + if (!dir) { + ACR_SET_OS_ERROR(ACR_EFAULT); + return -1; + } + + return dir->d_stat; +} + +int readdir_r(DIR *dir, struct dirent *entry, struct dirent **result) +{ + DWORD rc = 0; + WIN32_FIND_DATAW wfind; + + if (!dir) { + return ACR_EFAULT; + } + if (dir->d_stat < 0) { + /* Already at the end + */ + *result = NULL; + return 0; + } + else if (dir->d_stat == 0) { + /* Start the search + */ + dir->d_find = FindFirstFileW(dir->d_name, &wfind); + if (dir->d_find == INVALID_HANDLE_VALUE) { + /* No files in the dir? + */ + dir->d_stat = -1; + } + else + dir->d_stat = 1; + } + else { + /* Find the next entry + */ + if (FindNextFileW(dir->d_find, &wfind)) { + /* Increment position counter + */ + dir->d_stat++; + } + else { + rc = GetLastError(); + if (rc == ERROR_NO_MORE_FILES) + rc = 0; + /* EOF or error + * Close the search handle + */ + FindClose(dir->d_find); + dir->d_find = INVALID_HANDLE_VALUE; + dir->d_stat = -1; + } + } + if (dir->d_stat > 0) { + int mblen; + /* Fill in the dirent structure + */ + mblen = WideCharToMultiByte(CP_UTF8, 0, wfind.cFileName, -1, + entry->d_name, 1023, NULL, 0); + if (!mblen) + return GetLastError(); + entry->d_ino = 0; + entry->d_type = 0; + entry->d_off = dir->d_stat; + entry->d_reclen = (unsigned short)(mblen - 1); + *result = entry; + } + else + *result = NULL; + return rc; +} + +struct dirent *readdir(DIR *dir) +{ + int rc; + struct dirent *entry = NULL; + + if (!dir) { + ACR_SET_OS_ERROR(ACR_EFAULT); + return NULL; + } + + rc = readdir_r(dir, &dir->d_dir, &entry); + if (rc) + SetLastError(rc); + + return entry; +} + +void seekdir(DIR *dir, off_t pos) +{ + if (!dir) { + ACR_SET_OS_ERROR(ACR_EFAULT); + return; + } + if (pos < -1) { + ACR_SET_OS_ERROR(ACR_EINVAL); + return; + } + else if (pos == -1) { + /* Seek past end */ + if (dir->d_find != INVALID_HANDLE_VALUE) + FindClose(dir->d_find); + + dir->d_find = INVALID_HANDLE_VALUE; + dir->d_stat = -1; + } + else { + rewinddir(dir); + + while (dir->d_stat < pos) { + if (readdir(dir) == NULL) + break; + } + } + +} Propchange: commons/sandbox/runtime/trunk/src/main/native/os/win32/dirent.c ------------------------------------------------------------------------------ svn:eol-style = native Modified: commons/sandbox/runtime/trunk/src/main/native/os/win32/wutil.c URL: http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/native/os/win32/wutil.c?rev=802434&r1=802433&r2=802434&view=diff ============================================================================== --- commons/sandbox/runtime/trunk/src/main/native/os/win32/wutil.c (original) +++ commons/sandbox/runtime/trunk/src/main/native/os/win32/wutil.c Sat Aug 8 18:48:04 2009 @@ -58,3 +58,94 @@ return rname; } +int utf8_to_unicode_path(wchar_t* retstr, size_t retlen, + const char* srcstr, size_t unc) +{ + /* 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. + */ + size_t srcremains = strlen(srcstr) + 1; + wchar_t *t = retstr; + + /* leave an extra space for double zero */ + t[--retlen] = L'\0'; + /* This is correct, we don't twist the filename if it is will + * definately be shorter than MAX_PATH. 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 that a utf-8 name can never result in more wide chars + * than the original number of utf-8 narrow chars. + */ + if (srcremains > unc) { + 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 (!MultiByteToWideChar(CP_UTF8, 0, srcstr, -1, t, retlen)) + return ACR_GET_OS_ERROR(); + for (; *t; t++) { + if (*t == L'/') + *t = L'\\'; + } + *t = L'\0'; + return 0; +} + +int unicode_to_utf8_path(char* retstr, size_t retlen, + const 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. + */ + 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'\\') { + srcstr += 8; + retstr[0] = '\\'; + retstr[1] = '\\'; + retlen -= 2; + retstr += 2; + } + else { + srcstr += 4; + } + } + + if (!WideCharToMultiByte(CP_UTF8, 0, srcstr, -1, + retstr, retlen, NULL, 0)) + return ACR_GET_OS_ERROR(); + for (; *retstr; retstr++) { + if (*retstr == '/') + *retstr = '\\'; + } + return 0; +}