Author: mturk Date: Wed Oct 21 13:05:01 2009 New Revision: 828002 URL: http://svn.apache.org/viewvc?rev=828002&view=rev Log: Add Path class support and our path format (same as for APR)
Added: commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/io/Path.java (with props) commons/sandbox/runtime/trunk/src/main/native/os/unix/path.c (with props) commons/sandbox/runtime/trunk/src/main/native/os/win32/path.c (with props) Modified: commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/io/Directory.java commons/sandbox/runtime/trunk/src/main/native/Makefile.in commons/sandbox/runtime/trunk/src/main/native/Makefile.msc.in commons/sandbox/runtime/trunk/src/main/native/include/acr_private.h commons/sandbox/runtime/trunk/src/main/native/os/unix/dir.c commons/sandbox/runtime/trunk/src/main/native/os/unix/uutils.c commons/sandbox/runtime/trunk/src/test/org/apache/commons/runtime/TestFile.java Modified: commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/io/Directory.java URL: http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/io/Directory.java?rev=828002&r1=828001&r2=828002&view=diff ============================================================================== --- commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/io/Directory.java (original) +++ commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/io/Directory.java Wed Oct 21 13:05:01 2009 @@ -58,10 +58,10 @@ /** * Open a {...@code Directory} for reading. */ - public Directory(File path) + public Directory(Path path) throws FileNotFoundException, IOException, SecurityException { - this.path = path.getPath(); + this.path = path.toString(); dd = open0(this.path); } @@ -115,12 +115,12 @@ private static native int mkdir0(String path, int perms); private static native int mkdir1(String path, int perms); - public static boolean create(File path, EnumSet<FileProtection> prot) + public static boolean create(Path path, EnumSet<FileProtection> prot) throws FileNotFoundException, IOException, SecurityException { int rc; - rc = mkdir0(path.getPath(), FileProtection.bitmapOf(prot)); + rc = mkdir0(path.toString(), FileProtection.bitmapOf(prot)); if (rc == 0) return true; if (Status.STATUS_IS_EEXIST(rc)) @@ -138,13 +138,13 @@ throw new IOException(Status.describe(rc)); } - public static boolean createRecursive(File path, + public static boolean createRecursive(Path path, EnumSet<FileProtection> prot) throws IOException, SecurityException { int rc; - rc = mkdir1(path.getPath(), FileProtection.bitmapOf(prot)); + rc = mkdir1(path.toString(), FileProtection.bitmapOf(prot)); if (rc == 0) return true; if (Status.STATUS_IS_EEXIST(rc)) @@ -173,10 +173,10 @@ * @throws SecurityException if Write access to the directory specified * by {...@code path} is denied. */ - public static File createTemp(File path, String prefix) + public static File createTemp(Path path, String prefix) throws IOException, SecurityException { - String tmp = tmpdir0(path.getPath(), prefix); + String tmp = tmpdir0(path.toString(), prefix); return new File(tmp, FileType.DIR); } @@ -198,7 +198,7 @@ return new File(tmp, FileType.DIR); } - private static File tmpDir; + private static Path tmpDir; private static native String tmpdir1(String paths); /** * Get system temporary directory path. @@ -210,16 +210,42 @@ * @throws SecurityException if Write access to directories listed inside * {...@code searchPath} is denied. */ - public synchronized static File getTemp(String searchPath) + public synchronized static Path getTempPath(String searchPath) throws SecurityException { String dir = tmpdir1(searchPath); if (dir == null) throw new SecurityException(); - tmpDir = new File(dir, FileType.DIR); + tmpDir = new Path(dir); return tmpDir; } + public static native String cur0() + throws IOException; + public static Path getCurrentPath() + throws IOException + { + return new Path(cur0()); + } + + public static native int cwd0(String path) + throws IOException; + public static void setCurrentPath(Path path) + throws IOException + { + int rc = cwd0(path.toString()); + if (rc != 0) { + throw new IOException(Status.describe(rc)); + } + } + public static void setCurrentPath(String path) + throws IOException + { + int rc = cwd0(path); + if (rc != 0) { + throw new IOException(Status.describe(rc)); + } + } } Added: 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=828002&view=auto ============================================================================== --- commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/io/Path.java (added) +++ commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/io/Path.java Wed Oct 21 13:05:01 2009 @@ -0,0 +1,259 @@ +/* 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. + */ + +package org.apache.commons.runtime.io; + +import java.io.IOException; +import java.net.URI; +import org.apache.commons.runtime.Os; +import org.apache.commons.runtime.OsType; +import org.apache.commons.runtime.util.StringManager; + +/** + * An abstract representation of file and directory pathnames. The path + * is not required to exit. + * <p> + * All paths are in posix form with (@code /} character as path separator. + * </p> + * <p> + * Windows accepts several odd forms of a {...@code 'root'} path. + * Under Unicode calls {...@code (ApiFunctionW)} the {...@code //?/C:/foo} or + * {...@code //?/UNC/mach/share/foo} forms are accepted. + * Ansi and Unicode functions both accept the {...@code //./C:/foo} + * form under WinNT/2K. Since these forms are handled in the utf-8 to + * unicode translation phase, we don't want the user confused by them, so + * we will accept them but always return the canonical + * {...@code C:/} or {...@code //mach/share/}. One distinction for path is + * NT pipe naming that starts with {...@code //./pipe/}. + * </p> + */ +public final class Path implements Comparable<Path> +{ + + /** + * Native {...@code Path} separator character. + */ + public static final char SEPARATOR; + /** + * Native {...@code Path} components separator character. + */ + public static final char DELIMITER; + /** + * Maximum length of {...@code Path} supported by platform. + */ + public static final int MAX; + /** + * {...@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]; + init0(ia); + SEPARATOR = (char)ia[0]; + DELIMITER = (char)ia[1]; + MAX = ia[2]; + CASE_SENSITIVE = ia[3] == 1; + } + + private static native String normal0(String path) + throws IOException; + /** + * Remove all embedded {...@code .} and {...@code ..} + * characters from the {...@code path}. + */ + private static String normal(final String path) + throws IllegalArgumentException + { + try { + return normal0(path); + } catch (IOException ex) { + throw new IllegalArgumentException(ex.getMessage()); + } + } + private static native String merge0(String root, String path) + throws IOException; + private static native String merge1(String root, String path) + throws IOException; + /** + * Merge two paths. + */ + private static String merge(final String root, final String path, + boolean allowAboveRoot) + throws IllegalArgumentException + { + try { + if (allowAboveRoot) + return merge0(root, path); + else + return merge1(root, path); + } catch (IOException ex) { + throw new IllegalArgumentException(ex.getMessage()); + } + } + + /** + * Normalized Path + */ + private String path; + + private Path() + throws NullPointerException, IOException + { + } + /** + * Creates a new {...@code Path} instance from a {...@code parent} pathname + * string and a {...@code child} pathname string. + * <p> + * If {...@code parent} is {...@code null} then the new {...@code Path} instance + * is created as if by invoking the single-argument {...@code Path} + * constructor on the given {...@code child} pathname string. + * </p> + * <p> + * Otherwise the {...@code parent} pathname string is taken to denote a + * directory, and the {...@code child} pathname string is taken to denote + * either a directory or a file. If the {...@code child} pathname string is + * absolute then it is converted into a relative pathname in a + * system-dependent way. If {...@code parent} is the empty string then the + * new {...@code Path} instance is created by converting child into an + * abstract pathname and resolving the result against a system-dependent + * default directory. Otherwise each pathname string is converted into an + * abstract pathname and the child abstract pathname is resolved + * against the parent. + * + * @param parent The parent pathname string. + * @param child The child pathname string. + * @throws NullPointerException If the {...@code child} is {...@code null}. + */ + public Path(String parent, String child) + throws NullPointerException, IllegalArgumentException + { + if (parent == null || child == null) + throw new NullPointerException(); + path = merge(parent, child, true); + } + + /** + * Creates a new {...@code Path} instance from a {...@code parent} abstract + * pathname and a {...@code child} pathname string. + * <p> + * If {...@code parent} is {...@code null} then the new {...@code Path} instance is + * created as if by invoking the single-argument {...@code Path} constructor + * on the given {...@code child} pathname string. + * </p> + * <p> + * Otherwise the {...@code parent} abstract pathname is taken to denote a + * directory, and the {...@code child} pathname string is taken to denote + * either a directory or a file. If the {...@code child} pathname string is + * absolute then it is converted into a relative pathname in a + * system-dependent way. If {...@code parent} is the empty abstract pathname + * then the new {...@code Path} instance is created by converting {...@code child} + * into an abstract pathname and resolving the result against a + * system-dependent default directory. Otherwise each pathname string + * is converted into an abstract pathname and the child abstract pathname + * is resolved against the parent. + * + * @param parent The parent abstract pathname. + * @param child The child pathname string. + * @throws NullPointerException If the {...@code child} is {...@code null}. + */ + public Path(Path parent, String child) + throws NullPointerException, IllegalArgumentException + { + if (parent == null || child == null) + throw new NullPointerException(); + path = merge(parent.path, child, false); + } + + /** + * Create new {...@code Path} instance by converting the given pathname + * into an abstract pathname. If the given string is the empty path, + * then the result is empty pathname. + * + * @param pathname A pathname string. + * @throws NullPointerException If the {...@code path} is {...@code null}. + * @throws IllegalArgumentException If the {...@code path} is invalid. + */ + public Path(String path) + throws NullPointerException, IllegalArgumentException + + { + if (path == null) + throw new NullPointerException(); + this.path = normal(path); + } + + public static native int compare0(String path, String other); + public int compareTo(Path other) + { + if (other == null) + return 1; + else + return compare0(path, other.path); + } + + public static native String native0(String path) + throws Exception; + /** + * Get this abstract pathname platform native string. + * <p> + * Returned pathname is platform dependant. + * </p> + */ + public String getPath() + { + try { + return native0(path); + } catch (Exception ex) { + return path; + } + } + + /** + * Get this abstract pathname string. + * <p> + * Returned pathname is always in normalized form with all embedded + * backpaths removed and resolved. + * </p> + */ + @Override + public String toString() + { + return path; + } + + private static native String canon0(String path) + throws Exception; + /** + * Returns canonical pathname of this abstract pathname. + * <p> + * </p> + * + * @return The canonical pathname string denoting the same file or + * directory as this abstract pathname. + */ + public static String getCanonical(String path) + throws IOException + { + try { + return canon0(path); + } catch (Exception ex) { + throw new IOException(ex.getMessage()); + } + } + +} Propchange: commons/sandbox/runtime/trunk/src/main/java/org/apache/commons/runtime/io/Path.java ------------------------------------------------------------------------------ svn:eol-style = native Modified: commons/sandbox/runtime/trunk/src/main/native/Makefile.in URL: http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/native/Makefile.in?rev=828002&r1=828001&r2=828002&view=diff ============================================================================== --- commons/sandbox/runtime/trunk/src/main/native/Makefile.in (original) +++ commons/sandbox/runtime/trunk/src/main/native/Makefile.in Wed Oct 21 13:05:01 2009 @@ -131,6 +131,7 @@ $(SRCDIR)/os/unix/memalign.$(OBJ) \ $(SRCDIR)/os/unix/mmap.$(OBJ) \ $(SRCDIR)/os/unix/mutex.$(OBJ) \ + $(SRCDIR)/os/unix/path.$(OBJ) \ $(SRCDIR)/os/unix/pipe.$(OBJ) \ $(SRCDIR)/os/unix/proc.$(OBJ) \ $(SRCDIR)/os/unix/secmem.$(OBJ) \ @@ -169,6 +170,7 @@ $(SRCDIR)/os/unix/memalign.$(OBJ) \ $(SRCDIR)/os/unix/mmap.$(OBJ) \ $(SRCDIR)/os/unix/mutex.$(OBJ) \ + $(SRCDIR)/os/unix/path.$(OBJ) \ $(SRCDIR)/os/unix/pipe.$(OBJ) \ $(SRCDIR)/os/unix/proc.$(OBJ) \ $(SRCDIR)/os/unix/secmem.$(OBJ) \ @@ -203,6 +205,7 @@ $(SRCDIR)/os/unix/user.$(OBJ) \ $(SRCDIR)/os/unix/memalign.$(OBJ) \ $(SRCDIR)/os/unix/mmap.$(OBJ) \ + $(SRCDIR)/os/unix/path.$(OBJ) \ $(SRCDIR)/os/unix/pipe.$(OBJ) \ $(SRCDIR)/os/unix/proc.$(OBJ) \ $(SRCDIR)/os/unix/secmem.$(OBJ) \ @@ -240,6 +243,7 @@ $(SRCDIR)/os/unix/memalign.$(OBJ) \ $(SRCDIR)/os/unix/mmap.$(OBJ) \ $(SRCDIR)/os/unix/mutex.$(OBJ) \ + $(SRCDIR)/os/unix/path.$(OBJ) \ $(SRCDIR)/os/unix/pipe.$(OBJ) \ $(SRCDIR)/os/unix/proc.$(OBJ) \ $(SRCDIR)/os/unix/secmem.$(OBJ) \ 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=828002&r1=828001&r2=828002&view=diff ============================================================================== --- commons/sandbox/runtime/trunk/src/main/native/Makefile.msc.in (original) +++ commons/sandbox/runtime/trunk/src/main/native/Makefile.msc.in Wed Oct 21 13:05:01 2009 @@ -127,6 +127,7 @@ $(SRCDIR)/os/win32/module.$(OBJ) \ $(SRCDIR)/os/win32/mutex.$(OBJ) \ $(SRCDIR)/os/win32/ntpipe.$(OBJ) \ + $(SRCDIR)/os/win32/path.$(OBJ) \ $(SRCDIR)/os/win32/pipe.$(OBJ) \ $(SRCDIR)/os/win32/posix.$(OBJ) \ $(SRCDIR)/os/win32/registry.$(OBJ) \ Modified: commons/sandbox/runtime/trunk/src/main/native/include/acr_private.h URL: http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/native/include/acr_private.h?rev=828002&r1=828001&r2=828002&view=diff ============================================================================== --- commons/sandbox/runtime/trunk/src/main/native/include/acr_private.h (original) +++ commons/sandbox/runtime/trunk/src/main/native/include/acr_private.h Wed Oct 21 13:05:01 2009 @@ -118,6 +118,18 @@ (*_E)->ReleaseByteArrayElements(_E, V, (jbyte *)_c##V, JNI_ABORT); \ } } else ACR_ThrowException(_E, THROW_FMARK, ACR_EX_ENULL, 0) +#define WITH_WPATH(V) \ + if ((V)) { \ + wchar_t _b##V[ACR_MBUFF_SIZ]; \ + wchar_t *_w##V = ACR_GetJavaNativePathW(_E, (V), _b##V); \ + if (!_w##V) goto _cw##V; + +#define WITH_ZWPATH(V) \ + if (_E) { \ + wchar_t _b##V[ACR_MBUFF_SIZ]; \ + wchar_t *_w##V = ACR_GetJavaNativePathW(_E, (V), _b##V); \ + if (!_w##V && (V)) goto _cw##V; + #define WITH_WSTR(V) \ if ((V)) { \ wchar_t _b##V[ACR_MBUFF_SIZ]; \ Modified: commons/sandbox/runtime/trunk/src/main/native/os/unix/dir.c URL: http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/native/os/unix/dir.c?rev=828002&r1=828001&r2=828002&view=diff ============================================================================== --- commons/sandbox/runtime/trunk/src/main/native/os/unix/dir.c (original) +++ commons/sandbox/runtime/trunk/src/main/native/os/unix/dir.c Wed Oct 21 13:05:01 2009 @@ -277,3 +277,33 @@ else return NULL; } + +ACR_IO_EXPORT_DECLARE(jstring, Directory, getcwd0)(ACR_JNISTDARGS) +{ + size_t l; + char path[PATH_MAX]; + + UNREFERENCED_O; + if (!getcwd(path, sizeof(path))) { + ACR_THROW_IO_ERRNO(); + } + l = strlen(path); + if (l > 1 && path[l - 1] == '/') + path[l - 1] = '\0'; + return ACR_NewJavaStringA(_E, path); +} + +ACR_IO_EXPORT_DECLARE(jint, Directory, chdir0)(ACR_JNISTDARGS, jstring path) +{ + int rv = ACR_EINVAL; + + UNREFERENCED_O; + WITH_ZCSTR(path) { + if (chdir(J2S(path))) + rv = ACR_GET_OS_ERROR(); + else + rv = 0; + } END_WITH_CSTR(path); + + return rv; +} Added: 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=828002&view=auto ============================================================================== --- commons/sandbox/runtime/trunk/src/main/native/os/unix/path.c (added) +++ commons/sandbox/runtime/trunk/src/main/native/os/unix/path.c Wed Oct 21 13:05:01 2009 @@ -0,0 +1,302 @@ +/* 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 "acr.h" +#include "acr_private.h" +#include "acr_arch.h" +#include "acr_port.h" +#include "acr_error.h" +#include "acr_string.h" +#include "acr_descriptor.h" +#include "acr_file.h" +#include "acr_port.h" + +/** + * Posix file path functions + * + */ +#define UCPATH_MAX (PATH_MAX * 2) +#define IS_PATH_SEP(C) ((C) == '/' || (C) == '\0') + +static char *_rel_path(char *pcopy, size_t size, const char *path) +{ + char *cp; + int ch = '/'; + size_t l; + + strlcpy(pcopy, path, size); + l = strlen(pcopy); + if (l > 1 && pcopy[l - 1] == '/') + pcopy[l - 1] = '\0'; + + path = cp = pcopy; + while (*path) { + if (IS_PATH_SEP(ch) && *path == '.') { + size_t nd = 0; + while (path[nd] == '.') + 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 = '\0'; + /* Duplicate the final path + */ + return pcopy; + +} + +static char *_abs_path(char *pcopy, size_t size, const char *path) +{ + + char *cp; + int ch = '/'; + size_t l; + if (*path == '/' && !strstr(path, "./")) { + /* Already an absolute path + */ + strlcpy(pcopy, path, size); + return pcopy; + } + if (!IS_PATH_SEP(*path)) { + if (!getcwd(pcopy, PATH_MAX)) { + return NULL; + } + strlcat(pcopy, "/", size); + strlcat(pcopy, path, size); + } + else + strlcpy(pcopy, path, size); + l = strlen(pcopy); + if (l > 1 && pcopy[l - 1] == '/') + pcopy[l - 1] = '\0'; + + path = cp = pcopy; + while (*path) { + if (IS_PATH_SEP(ch) && *path == '.') { + size_t nd = 0; + while (path[nd] == '.') + 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 = '\0'; + /* Duplicate the final path + */ + return pcopy; +} + +/* Calculate the absolute path by merging the current + * working directory in case of relative paths. + * Function doesn't resolve symbolic links. + */ +char *acr_GetAbsolutePath(JNIEnv *_E, const char *path) +{ + char pcopy[UCPATH_MAX]; + char *cp; + + cp = _abs_path(pcopy, UCPATH_MAX, path); + if (!cp) { + ACR_THROW_IO_ERRNO(); + return NULL; + } + else { + /* Duplicate the final path + */ + return ACR_StrdupA(_E, THROW_FMARK, cp); + } +} + +ACR_IO_EXPORT_DECLARE(void, Path, init0)(ACR_JNISTDARGS, + jintArray p) +{ + jint ia[4]; + + UNREFERENCED_O; + + ia[0] = '/'; + ia[1] = ':'; + ia[2] = PATH_MAX - 1; + ia[3] = 1; + (*_E)->SetIntArrayRegion(_E, p, 0, 4, &ia[0]); +} + +ACR_IO_EXPORT_DECLARE(jstring, Path, canon0)(ACR_JNISTDARGS, jstring path) +{ + int rc = 0; + jstring rv = NULL; + + UNREFERENCED_O; + WITH_CSTR(path) { + char pcopy[UCPATH_MAX]; + char *abs; + if ((abs = _abs_path(pcopy, UCPATH_MAX, J2S(path)))) + rv = ACR_NewJavaStringA(_E, abs); + else + rc = ACR_GET_OS_ERROR(); + } END_WITH_CSTR(path); + + ACR_THROW_IO_IF_ERR(rc); + return rv; +} + +ACR_IO_EXPORT_DECLARE(jstring, Path, merge0)(ACR_JNISTDARGS, + jstring root, + jstring path) +{ + int rc = 0; + jstring rv = NULL; + + UNREFERENCED_O; + WITH_CSTR(root) { + WITH_CSTR(path) { + char pcopy[UCPATH_MAX]; + char merge[UCPATH_MAX]; + char *abs; + strlcpy(merge, J2S(root), UCPATH_MAX); + strlcat(merge, "/", UCPATH_MAX); + strlcpy(merge, J2S(path), UCPATH_MAX); + if ((abs = _abs_path(pcopy, UCPATH_MAX, merge))) + rv = ACR_NewJavaStringA(_E, abs); + else + rc = ACR_GET_OS_ERROR(); + } END_WITH_CSTR(path); + } END_WITH_CSTR(root); + + ACR_THROW_IO_IF_ERR(rc); + return rv; +} + +ACR_IO_EXPORT_DECLARE(jstring, Path, merge1)(ACR_JNISTDARGS, + jstring root, + jstring path) +{ + int rc = 0; + jstring rv = NULL; + + UNREFERENCED_O; + WITH_CSTR(root) { + WITH_CSTR(path) { + char pcopy[UCPATH_MAX]; + char merge[UCPATH_MAX]; + char *abs; + /* Normalize path */ + if ((abs = _abs_path(pcopy, UCPATH_MAX, J2S(path)))) { + /* Prepend root */ + strlcpy(merge, J2S(root), UCPATH_MAX); + strlcat(merge, "/", UCPATH_MAX); + strlcat(merge, abs, UCPATH_MAX); + rv = ACR_NewJavaStringA(_E, merge); + } + else + rc = ACR_GET_OS_ERROR(); + } END_WITH_CSTR(path); + } END_WITH_CSTR(root); + + ACR_THROW_IO_IF_ERR(rc); + return rv; +} + +ACR_IO_EXPORT_DECLARE(jstring, Path, normal0)(ACR_JNISTDARGS, jstring path) +{ + int rc = 0; + jstring rv = NULL; + + UNREFERENCED_O; + WITH_CSTR(path) { + char pcopy[UCPATH_MAX]; + char *rel; + if ((rel = _rel_path(pcopy, UCPATH_MAX, J2S(path)))) + rv = ACR_NewJavaStringA(_E, rel); + else + rc = ACR_GET_OS_ERROR(); + } END_WITH_CSTR(path); + + ACR_THROW_IO_IF_ERR(rc); + return rv; +} + +ACR_IO_EXPORT_DECLARE(jstring, Path, native0)(ACR_JNISTDARGS, jstring path) +{ + /* On unix the Path is native path + */ + return path; +} + +ACR_IO_EXPORT_DECLARE(jint, Path, compare0)(ACR_JNISTDARGS, + jstring path, + jstring other) +{ + int rc = 1; + + UNREFERENCED_O; + WITH_CSTR(path) { + WITH_CSTR(other) { + rc = strcmp(J2S(path), J2S(other)); + } END_WITH_CSTR(other); + } END_WITH_CSTR(path); + + return rc; +} Propchange: commons/sandbox/runtime/trunk/src/main/native/os/unix/path.c ------------------------------------------------------------------------------ svn:eol-style = native Modified: commons/sandbox/runtime/trunk/src/main/native/os/unix/uutils.c URL: http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/native/os/unix/uutils.c?rev=828002&r1=828001&r2=828002&view=diff ============================================================================== --- commons/sandbox/runtime/trunk/src/main/native/os/unix/uutils.c (original) +++ commons/sandbox/runtime/trunk/src/main/native/os/unix/uutils.c Wed Oct 21 13:05:01 2009 @@ -206,70 +206,3 @@ arr[i] = NULL; return arr; } - -#define IS_PATH_SEP(C) ((C) == '/' || (C) == '\0') -/* Calculate the absolute path by merging the current - * working directory in case of relative paths. - * Function doesn't resolve symbolic links. - */ -char *acr_GetAbsolutePath(JNIEnv *_E, const char *path) -{ - char pcopy[PATH_MAX * 2]; - char *cp; - int ch = '/'; - - if (*path == '/' && !strstr(path, "./")) { - /* Already an absolute path - */ - return ACR_StrdupA(_E, THROW_FMARK, path); - } - if (!IS_PATH_SEP(*path)) { - if (!getcwd(pcopy, PATH_MAX)) { - ACR_THROW_IO_ERRNO(); - return NULL; - } - strlcat(pcopy, "/", PATH_MAX * 2); - strlcat(pcopy, path, PATH_MAX * 2); - } - else - strlcpy(pcopy, path, PATH_MAX * 2); - - path = cp = pcopy; - while (*path) { - if (IS_PATH_SEP(ch) && *path == '.') { - size_t nd = 0; - while (path[nd] == '.') - nd++; - if (nd > 2) { - ACR_THROW_IO_IF_ERR(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 = '\0'; - /* Duplicate the final path - */ - return ACR_StrdupA(_E, THROW_FMARK, pcopy); -} Added: 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=828002&view=auto ============================================================================== --- commons/sandbox/runtime/trunk/src/main/native/os/win32/path.c (added) +++ commons/sandbox/runtime/trunk/src/main/native/os/win32/path.c Wed Oct 21 13:05:01 2009 @@ -0,0 +1,204 @@ +/* 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 "acr.h" +#include "acr_private.h" +#define ACR_WANT_LATE_DLL +#include "acr_arch.h" +#include "acr_error.h" +#include "acr_memory.h" +#include "acr_port.h" +#include "acr_string.h" +#include "acr_descriptor.h" +#include "acr_file.h" + +/** + * Win32 file path functions + * + */ + +#define NON_UNC_PATH_LENGTH 248 +/* + * 1. Remove \\?\ prefix + * 2. Replace UNC\ with \\ + */ +static __inline wchar_t *NO2UNC(wchar_t *fname) +{ + if (wcsncmp(fname, L"\\\\?\\", 4) == 0) { + fname += 4; + if (wcsncmp(fname, L"UNC\\", 4) == 0) { + fname += 2; + *fname = L'\\'; + } + else if (wcsncmp(fname, L"UN\\\\", 4) == 0) { + /* Already modified in-place. + */ + fname += 2; + } + } + return fname; +} + +static __inline void FS2BS(wchar_t *path) +{ + while (*path) { + if (*path == L'/') + *path = L'\\'; + path++; + } +} + +ACR_DECLARE(wchar_t *) ACR_GetJavaNativePathW(JNIEnv *_E, jstring str, wchar_t *b) +{ + size_t srclen; + size_t retlen; + const jchar *sr; + wchar_t *rv = NULL; + wchar_t *retstr; + wchar_t *srcstr; + + if (!str) { + return NULL; + } + if ((*_E)->EnsureLocalCapacity(_E, 2) < 0) { + /* JNI out of memory error */ + return NULL; + } + retlen = srclen = (size_t)(*_E)->GetStringLength(_E, str); + if (b && srclen < (ACR_MBUFF_LEN - 8)) + rv = b; + else { + rv = ACR_MALLOC(wchar_t, srclen + 9); + if (!rv) { + /* Exception has already neen throw from ACR_Malloc + */ + return NULL; + } + } + srcstr = sr = (*_E)->GetStringCritical(_E, str, NULL); + if (!srcstr) { + if (rv != b) + x_free(rv); + return NULL; + } + else { + retstr = rv; + if (srclen > NON_UNC_PATH_LENGTH) { + if (srcstr[1] == L':' && (srcstr[2] == L'/' || srcstr[2] == L'\\')) { + wcscpy(retstr, L"\\\\?\\"); + retstr += 4; + retlen += 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"\\\\.\\"); + retstr += 4; + srcstr += 4; + srclen -= 4; + } + else { + /* Skip the slashes and ? */ + srcstr += 2; + srclen -= 2; + wcscpy (retstr, L"\\\\?\\UNC\\"); + retlen += 8; + retstr += 8; + } + } + else if (srcstr[0] == '/' || srcstr[0] == '\\') { + 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; + retstr += 6; + } + } + + memcpy(retstr, srcstr, srclen * sizeof(wchar_t)); + } + rv[retlen] = L'\0'; + FS2BS(retstr); + (*_E)->ReleaseStringCritical(_E, str, sr); + return rv; +} + +ACR_DECLARE(jstring) ACR_NewJavaNativePathW(JNIEnv *_E, const wchar_t *s) +{ + jstring r = NULL; + if (s) { + wchar_t *retstr; + wchar_t *srcstr; + wchar_t buff[ACR_MBUFF_SIZ]; + size_t retlen = wcslen(s); + + if (l > ACR_MBUFF_LEN) { + srcstr = ACR_StrdupW(_E, THROW_FMARK, s); + if (!srcstr) + return NULL; + else { + wcscpy(buff, s); + srcstr = buff; + } + retstr = 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'\\') { + retstr[0] = '\\'; + retstr[1] = '\\'; + retstr += 2; + retlen -= 6; + } + else { + retstr += 4; + retlen -= 4; + } + } + /* Translate all back to forward slashes. + * On Win32 for utf8 paths we always use the forwrd slashes. + * They are converted to backward on translatio from utf8 + */ + for (; *retstr; retstr++) { + if (*retstr == '\\') + *retstr = '/'; + } + r = (*_E)->NewString(_E, (const jchar *)s, (jsize)retlen); + } + return r; +} Propchange: commons/sandbox/runtime/trunk/src/main/native/os/win32/path.c ------------------------------------------------------------------------------ svn:eol-style = native Modified: commons/sandbox/runtime/trunk/src/test/org/apache/commons/runtime/TestFile.java URL: http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/test/org/apache/commons/runtime/TestFile.java?rev=828002&r1=828001&r2=828002&view=diff ============================================================================== --- commons/sandbox/runtime/trunk/src/test/org/apache/commons/runtime/TestFile.java (original) +++ commons/sandbox/runtime/trunk/src/test/org/apache/commons/runtime/TestFile.java Wed Oct 21 13:05:01 2009 @@ -202,7 +202,7 @@ User u = User.getEffective(); - f.setFileOwner(u); + f.setOwner(u); f.delete(); } @@ -213,7 +213,7 @@ f.createNewFile(); Group g = Group.getEffective(); - f.setFileOwner(g); + f.setOwner(g); f.delete(); } @@ -327,5 +327,25 @@ f2.delete(); } + public void testPath() + throws Exception + { + String [] paths = { + "/", + "\\\\", + "foo/", + "/foo/", + "/foo/bar", + "c:/foo/../../bar", + "foo/../bar", + "foo/../../../bar", + "/foo/../bar", + "/foo/../../../bar" + }; + for (int i = 0; i < paths.length; i++) { + Path p = new Path(paths[i]); + System.out.println("Path (" + paths[i] + ") is : " + p.getPath()); + } + } }