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;
+}