Commit 0d28d64b authored by mevenson@1c010e3e-69d0-11dd-93a8-456734b0d56f's avatar mevenson@1c010e3e-69d0-11dd-93a8-456734b0d56f
Browse files

Fix Uniform Naming Convention (aka "UNC" or "network") paths under Windows.

DIRECTORY now works again on UNC paths.

UNC paths may be either specified with either back slash (#\\) or
forward slash (#\/) doubled as the first character in a Pathname
namestring.

The patterns in

        //<server>/<share>/[directories-and-files]

are parsed as

    <server> is stored as HOST.

    <share> is stored as DEVICE.

    [directories-and-files] gets parsed as per the normal rules under
    Windows.

Mixing namestrings with both backslash and slash characters can lead
to unpredictable results.  It is recommended not to use backslash
characters in namestrings if it can be avoided.  The pathname printed
representation is always normalized to using forward slash delimiters.
parent 7b83d272
...@@ -242,28 +242,34 @@ public class Pathname extends LispObject { ...@@ -242,28 +242,34 @@ public class Pathname extends LispObject {
return; return;
} }
if (Utilities.isPlatformWindows) { if (Utilities.isPlatformWindows) {
if (s.startsWith("\\\\")) { // XXX What if string starts with '//'? if (s.startsWith("\\\\") || s.startsWith("//")) {
//UNC path support // UNC path support
// match \\<server>\<share>\[directories-and-files] int shareIndex;
int dirIndex;
int shareIndex = s.indexOf('\\', 2); // match \\<server>\<share>\[directories-and-files]
int dirIndex = s.indexOf('\\', shareIndex + 1); if (s.startsWith("\\\\")) {
shareIndex = s.indexOf('\\', 2);
if (shareIndex == -1 || dirIndex == -1) { dirIndex = s.indexOf('\\', shareIndex + 1);
error(new LispError("Unsupported UNC path format: \"" + s + '"')); // match //<server>/<share>/[directories-and-files]
} } else {
shareIndex = s.indexOf('/', 2);
dirIndex = s.indexOf('/', shareIndex + 1);
}
if (shareIndex == -1 || dirIndex == -1) {
error(new LispError("Unsupported UNC path format: \"" + s + '"'));
}
host = new SimpleString(s.substring(2, shareIndex)); host = new SimpleString(s.substring(2, shareIndex));
device = new SimpleString(s.substring(shareIndex + 1, dirIndex)); device = new SimpleString(s.substring(shareIndex + 1, dirIndex));
Pathname p = new Pathname(s.substring(dirIndex)); Pathname p = new Pathname(s.substring(dirIndex));
directory = p.directory; directory = p.directory;
name = p.name; name = p.name;
type = p.type; type = p.type;
version = p.version; version = p.version;
invalidateNamestring(); invalidateNamestring();
return; return;
} }
} }
// A JAR file // A JAR file
...@@ -381,10 +387,10 @@ public class Pathname extends LispObject { ...@@ -381,10 +387,10 @@ public class Pathname extends LispObject {
String uriPath = uri.getPath(); String uriPath = uri.getPath();
if (null == uriPath) { if (null == uriPath) {
// Under Windows, deal with pathnames containing // Under Windows, deal with pathnames containing
// devices expressed as "file:z:/foo/path" // devices expressed as "file:z:/foo/path"
uriPath = uri.getSchemeSpecificPart(); uriPath = uri.getSchemeSpecificPart();
if (uriPath == null || uriPath.equals("")) { if (uriPath == null || uriPath.equals("")) {
error(new LispError("The URI has no path: " + uri)); error(new LispError("The URI has no path: " + uri));
} }
} }
...@@ -651,8 +657,8 @@ public class Pathname extends LispObject { ...@@ -651,8 +657,8 @@ public class Pathname extends LispObject {
sb.append(host.getStringValue()); sb.append(host.getStringValue());
sb.append(':'); sb.append(':');
} else { } else {
// UNC paths now use unprintable representation // A UNC path
return null; sb.append("//").append(host.getStringValue()).append("/");
} }
} }
boolean uriEncoded = false; boolean uriEncoded = false;
...@@ -663,20 +669,20 @@ public class Pathname extends LispObject { ...@@ -663,20 +669,20 @@ public class Pathname extends LispObject {
StringBuilder prefix = new StringBuilder(); StringBuilder prefix = new StringBuilder();
for (int i = 0; i < jars.length; i++) { for (int i = 0; i < jars.length; i++) {
prefix.append("jar:"); prefix.append("jar:");
LispObject component = jars[i]; LispObject component = jars[i];
if (!(component instanceof Pathname)) { if (!(component instanceof Pathname)) {
return null; // If DEVICE is a CONS, it should only contain Pathname return null; // If DEVICE is a CONS, it should only contain Pathname
} }
if (! ((Pathname)component).isURL() && i == 0) { if (! ((Pathname)component).isURL() && i == 0) {
sb.append("file:"); sb.append("file:");
uriEncoded = true; uriEncoded = true;
} }
Pathname jar = (Pathname) component; Pathname jar = (Pathname) component;
String encodedNamestring; String encodedNamestring;
if (uriEncoded) { if (uriEncoded) {
encodedNamestring = uriEncode(jar.getNamestring()); encodedNamestring = uriEncode(jar.getNamestring());
} else { } else {
encodedNamestring = jar.getNamestring(); encodedNamestring = jar.getNamestring();
} }
sb.append(encodedNamestring); sb.append(encodedNamestring);
sb.append("!/"); sb.append("!/");
...@@ -685,8 +691,8 @@ public class Pathname extends LispObject { ...@@ -685,8 +691,8 @@ public class Pathname extends LispObject {
} else if (device instanceof AbstractString) { } else if (device instanceof AbstractString) {
sb.append(device.getStringValue()); sb.append(device.getStringValue());
if (this instanceof LogicalPathname if (this instanceof LogicalPathname
|| host == NIL) { || host == NIL) {
sb.append(':'); // non-UNC paths sb.append(':'); // non-UNC paths
} }
} else { } else {
Debug.assertTrue(false); Debug.assertTrue(false);
......
...@@ -121,9 +121,15 @@ error to its caller." ...@@ -121,9 +121,15 @@ error to its caller."
(let ((namestring (directory-namestring pathname))) (let ((namestring (directory-namestring pathname)))
(when (and namestring (> (length namestring) 0)) (when (and namestring (> (length namestring) 0))
(when (featurep :windows) (when (featurep :windows)
(let ((device (pathname-device pathname))) (let ((host (pathname-host pathname))
(when device (device (pathname-device pathname)))
(setq namestring (concatenate 'string device ":" namestring))))) (cond
((and host device)
(setq namestring
(concatenate 'string "//" host "/" device namestring)))
(device
(setq namestring
(concatenate 'string device ":" namestring))))))
(let ((entries (list-directories-with-wildcards (let ((entries (list-directories-with-wildcards
namestring nil resolve-symlinks)) namestring nil resolve-symlinks))
(matching-entries ())) (matching-entries ()))
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment