You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by mt...@apache.org on 2009/10/21 17:26:56 UTC

svn commit: r828045 - in /commons/sandbox/runtime/trunk/src/main: java/org/apache/commons/runtime/io/Path.java native/os/unix/path.c native/os/win32/path.c native/os/win32/wutil.c

Author: mturk
Date: Wed Oct 21 15:26:55 2009
New Revision: 828045

URL: http://svn.apache.org/viewvc?rev=828045&view=rev
Log:
Implement firts part of windows Path methods

Modified:
    commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/io/Path.java
    commons/sandbox/runtime/trunk/src/main/native/os/unix/path.c
    commons/sandbox/runtime/trunk/src/main/native/os/win32/path.c
    commons/sandbox/runtime/trunk/src/main/native/os/win32/wutil.c

Modified: commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/io/Path.java
URL: http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/io/Path.java?rev=828045&r1=828044&r2=828045&view=diff
==============================================================================
--- commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/io/Path.java (original)
+++ commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/io/Path.java Wed Oct 21 15:26:55 2009
@@ -56,18 +56,23 @@
      */
     public static final int     MAX;
     /**
+     * Maximum length of individual {@code Path} part.
+     */
+    public static final int     PART_SIZE;
+    /**
      * {@code true} if file system is case sensitive.
      */
     public static final boolean CASE_SENSITIVE;
 
     private static native void init0(int [] p);
     static {
-        int [] ia = new int[4];
+        int [] ia = new int[8];
         init0(ia);
         SEPARATOR      = (char)ia[0];
         DELIMITER      = (char)ia[1];
         MAX            = ia[2];
-        CASE_SENSITIVE = ia[3] == 1;
+        PART_SIZE      = ia[3];
+        CASE_SENSITIVE = ia[4] == 0;
     }
 
     private static native String normal0(String path)

Modified: commons/sandbox/runtime/trunk/src/main/native/os/unix/path.c
URL: http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/native/os/unix/path.c?rev=828045&r1=828044&r2=828045&view=diff
==============================================================================
--- commons/sandbox/runtime/trunk/src/main/native/os/unix/path.c (original)
+++ commons/sandbox/runtime/trunk/src/main/native/os/unix/path.c Wed Oct 21 15:26:55 2009
@@ -172,15 +172,16 @@
 ACR_IO_EXPORT_DECLARE(void, Path, init0)(ACR_JNISTDARGS,
                                          jintArray p)
 {
-    jint ia[4];
+    jint ia[8];
 
     UNREFERENCED_O;
 
     ia[0] = '/';
     ia[1] = ':';
     ia[2] = PATH_MAX - 1;
-    ia[3] = 1;
-    (*_E)->SetIntArrayRegion(_E, p, 0, 4, &ia[0]);
+    ia[3] = PATH_MAX - 2;
+    ia[4] = 1;
+    (*_E)->SetIntArrayRegion(_E, p, 0, 8, &ia[0]);
 }
 
 ACR_IO_EXPORT_DECLARE(jstring, Path, canon0)(ACR_JNISTDARGS, jstring path)

Modified: commons/sandbox/runtime/trunk/src/main/native/os/win32/path.c
URL: http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/native/os/win32/path.c?rev=828045&r1=828044&r2=828045&view=diff
==============================================================================
--- commons/sandbox/runtime/trunk/src/main/native/os/win32/path.c (original)
+++ commons/sandbox/runtime/trunk/src/main/native/os/win32/path.c Wed Oct 21 15:26:55 2009
@@ -38,13 +38,17 @@
  */
 static __inline wchar_t *NO2UNC(wchar_t *fname)
 {
-    if (wcsncmp(fname, L"\\\\?\\", 4) == 0) {
+    if (fname[0] == L'/' && fname[1] == L'/' &&
+        fname[2] == L'?' && fname[2] == L'/') {
         fname += 4;
-        if (wcsncmp(fname, L"UNC\\", 4) == 0) {
+        if (fname[0] == L'U' && fname[1] == L'N' &&
+            fname[2] == L'C' && fname[3] == L'/') {
             fname += 2;
             *fname = L'\\';
         }
-        else if (wcsncmp(fname, L"UN\\\\", 4) == 0) {
+        else if (fname[0] == L'U' && fname[1] == L'N' &&
+            fname[2] == L'/' && fname[3] == L'/') {
+            fname += 2;
             /* Already modified in-place.
              */
             fname += 2;
@@ -62,6 +66,99 @@
     }
 }
 
+static __inline void BS2FS(wchar_t *path)
+{
+    while (*path) {
+        if (*path == L'\\')
+            *path = L'/';
+        path++;
+    }
+}
+
+#define UCPATH_MAX     8192
+#define IS_PATH_SEP(C) ((C) == L'/' || (C) == L'\0')
+
+static wchar_t *_rel_path(wchar_t *pcopy, size_t size, const wchar_t *path)
+{
+    wchar_t *cp;
+    wchar_t *rv;
+    int      ch = '/';
+    size_t   l;
+
+    wcslcpy(pcopy, path, size);
+    /* Convert everything to back slashes
+     */
+    BS2FS(pcopy);
+    /* Remove \\?\ and replace \\?\UNC\ with \\
+     */
+    pcopy = NO2UNC(pcopy);
+    l = wcslen(pcopy);
+    if (l > 1 && pcopy[l - 1] == L'/')
+        pcopy[l - 1] = L'\0';
+
+    rv = pcopy;
+    if (((pcopy[0] >= L'A' && pcopy[0] <= 'Z')  ||
+         (pcopy[0] >= L'a' && pcopy[0] <= 'z')) && pcopy[1] == L':') {
+        /* Never go above C: */
+        pcopy += 2;
+    }
+    else if (pcopy[0] == L'/' && pcopy[1] == '/') {
+        /* Never go above //share/
+         */
+        if (pcopy[2] == L'.' && pcopy[3] == L'/') {
+            /* This is //./pipe/ */
+            return pcopy;
+        }
+        cp = wcschr(pcopy + 2, '/');
+        if (cp)
+            pcopy = cp;
+        else {
+            /* We only have //share
+             */
+            return pcopy;
+        }
+    }
+    path = cp = pcopy;
+    while (*path) {
+        if (IS_PATH_SEP(ch) && *path == L'.') {
+            size_t nd = 0;
+            while (path[nd] == L'.')
+                nd++;
+            if (nd > 2) {
+                errno = ACR_EINVAL;
+                return NULL;
+            }
+            if (IS_PATH_SEP(path[nd])) {
+                path += nd;
+                if (*path)
+                    path++;
+                while (nd > 1) {
+                    if (cp > pcopy + 1) {
+                        cp--;
+                        while (cp > pcopy) {
+                            if (IS_PATH_SEP(*(cp - 1)))
+                                break;
+                            cp--;
+                        }
+                    }
+                    else
+                        break;
+                    nd--;
+                }
+            }
+            else
+                ch = *cp++ = *path++;
+        }
+        else
+            ch = *cp++ = *path++;
+    }
+    *cp = L'\0';
+    /* Duplicate the final path
+     */
+    return rv;
+
+}
+
 wchar_t * acr_GetJavaNativePathW(JNIEnv *_E, jstring str, wchar_t *b)
 {
     size_t srclen;
@@ -204,3 +301,66 @@
     }
     return r;
 }
+
+
+ACR_IO_EXPORT_DECLARE(void, Path, init0)(ACR_JNISTDARGS,
+                                         jintArray p)
+{
+    jint ia[8];
+
+    UNREFERENCED_O;
+
+    ia[0] = '\\';
+    ia[1] = ';';
+    ia[2] = UCPATH_MAX; /* Use our path limit */
+    ia[3] = NON_UNC_PATH_LENGTH;
+    ia[4] = 1;
+    (*_E)->SetIntArrayRegion(_E, p, 0, 8, &ia[0]);
+}
+
+ACR_IO_EXPORT_DECLARE(jstring, Path, normal0)(ACR_JNISTDARGS, jstring path)
+{
+    int rc = 0;
+    jstring rv = NULL;
+
+    UNREFERENCED_O;
+    WITH_WSTR(path) {
+        wchar_t  pcopy[UCPATH_MAX];
+        wchar_t *rel;
+        if ((rel = _rel_path(pcopy, UCPATH_MAX, J2W(path))))
+            rv = ACR_NewJavaStringW(_E, rel);
+        else
+            rc = ACR_GET_OS_ERROR();
+    } END_WITH_WSTR(path);
+
+    ACR_THROW_IO_IF_ERR(rc);
+    return rv;
+}
+
+ACR_IO_EXPORT_DECLARE(jstring, Path, native0)(ACR_JNISTDARGS, jstring path)
+{
+    jstring  rv = NULL;
+
+    WITH_WPATH(path) {
+        rv = ACR_NewJavaStringW(_E, J2W(path));
+    } END_WITH_WPATH(path);
+    return rv;
+}
+
+ACR_IO_EXPORT_DECLARE(jint, Path, compare0)(ACR_JNISTDARGS,
+                                            jstring path,
+                                            jstring other)
+{
+    int rc = 1;
+
+    UNREFERENCED_O;
+    WITH_WSTR(path) {
+    WITH_WSTR(other) {
+        /* Presume case insensitive file system
+         */
+        rc = _wcsicmp(J2W(path), J2W(other));
+    } END_WITH_WSTR(other);
+    } END_WITH_WSTR(path);
+
+    return rc;
+}

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=828045&r1=828044&r2=828045&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 Wed Oct 21 15:26:55 2009
@@ -220,6 +220,96 @@
     return 0;
 }
 
+static int acr_to_unicode_path(wchar_t* retstr, size_t retlen,
+                               const wchar_t* 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.
+     */
+    size_t srclen = wcslen(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 (srclen > NON_UNC_PATH_LENGTH) {
+        if (srcstr[1] == L':' && (srcstr[2] == L'/' || srcstr[2] == L'\\')) {
+            wcscpy (retstr, L"\\\\?\\");
+            retlen -= 4;
+            t += 4;
+        }
+        else if ((srcstr[0] == L'/' || srcstr[0] == L'\\')
+              && (srcstr[1] == L'/' || srcstr[1] == L'\\')
+              && (srcstr[2] != L'?')) {
+            if (srcstr[2] == L'.' && (srcstr[3] == L'/' || srcstr[3] == L'\\')) {
+                /* We have \\.\ sequence that can apear only
+                 * if we have something like \\.\pipe\
+                 */
+                wcscpy (retstr, L"\\\\.\\");
+                srcstr += 4;
+                retlen -= 4;
+                t += 4;
+            }
+            else {
+                /* Skip the slashes and ? */
+                srcstr += 2;
+                srclen -= 2;
+                wcscpy (retstr, L"\\\\?\\UNC\\");
+                retlen -= 8;
+                t += 8;
+            }
+        }
+        else if (srcstr[0] == L'/' || srcstr[0] == L'\\') {
+            int cd;
+            /* Addition to APR. Allow \FilePath
+             * and construct \\?\CurrenttDrive:\FilePath
+             * We use _getdrive CRT function
+             */
+            wcscpy (retstr, L"\\\\?\\");
+            if ((cd = _getdrive()))
+                retstr[4] = L'A' + cd - 1;
+            else {
+                /* C:\ should always be there
+                 * If not later open will fail anyhow
+                 */
+                retstr[4] = L'C';
+            }
+            retstr[5] = L':';
+            retlen -= 6;
+            t += 6;
+        }
+    }
+    if (srclen > retlen)
+        return ACR_EOVERFLOW;
+    memcpy(t, srcstr, srclen * sizeof(wchar_t));
+    t[srclen] = L'\0';
+    for (; *t; t++) {
+        if (*t == L'/')
+            *t = L'\\';
+    }
+    return 0;
+}
+
+
 wchar_t *x_wcsdup_utf8_path(const char *str)
 {
     int      rc;