Mercurial > hg > release > icedtea6-1.9
changeset 1366:9923df826001
Ensure NIO2 is in sync with the latest build drop, b98.
2009-02-05 Andrew John Hughes <ahughes@redhat.com>
Ensure the NIO2 code is in sync with the latest
build drop, b98.
* overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/attribute/NamedAttributeView.java,
* overlays/nio2/openjdk/jdk/src/share/classes/sun/nio/fs/AbstractNamedAttributeView.java,
* overlays/nio2/openjdk/jdk/src/share/classes/sun/nio/fs/Cancellable.java,
* overlays/nio2/openjdk/jdk/src/windows/classes/sun/nio/fs/WindowsAclFileAttributeView.java,
* overlays/nio2/openjdk/jdk/src/windows/classes/sun/nio/fs/WindowsChannelFactory.java,
* overlays/nio2/openjdk/jdk/src/windows/classes/sun/nio/fs/WindowsDirectoryStream.java,
* overlays/nio2/openjdk/jdk/src/windows/classes/sun/nio/fs/WindowsFileAttributeViews.java,
* overlays/nio2/openjdk/jdk/src/windows/classes/sun/nio/fs/WindowsFileCopy.java,
* overlays/nio2/openjdk/jdk/src/windows/classes/sun/nio/fs/WindowsFileStore.java,
* overlays/nio2/openjdk/jdk/src/windows/classes/sun/nio/fs/WindowsFileSystemProvider.java,
* overlays/nio2/openjdk/jdk/src/windows/classes/sun/nio/fs/WindowsLinkSupport.java,
* overlays/nio2/openjdk/jdk/src/windows/classes/sun/nio/fs/WindowsNamedAttributeView.java,
* overlays/nio2/openjdk/jdk/src/windows/classes/sun/nio/fs/WindowsPath.java,
* overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/Path/InterruptCopy.java,
* overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/attribute/NamedAttributeView/Basic.java,
line wrap: on
line diff
--- a/ChangeLog Wed Feb 04 12:48:30 2009 +0000 +++ b/ChangeLog Thu Feb 05 19:03:06 2009 +0000 @@ -1,3 +1,23 @@ +2009-02-05 Andrew John Hughes <ahughes@redhat.com> + + Ensure the NIO2 code is in sync with the latest + build drop, b98. + * overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/attribute/NamedAttributeView.java, + * overlays/nio2/openjdk/jdk/src/share/classes/sun/nio/fs/AbstractNamedAttributeView.java, + * overlays/nio2/openjdk/jdk/src/share/classes/sun/nio/fs/Cancellable.java, + * overlays/nio2/openjdk/jdk/src/windows/classes/sun/nio/fs/WindowsAclFileAttributeView.java, + * overlays/nio2/openjdk/jdk/src/windows/classes/sun/nio/fs/WindowsChannelFactory.java, + * overlays/nio2/openjdk/jdk/src/windows/classes/sun/nio/fs/WindowsDirectoryStream.java, + * overlays/nio2/openjdk/jdk/src/windows/classes/sun/nio/fs/WindowsFileAttributeViews.java, + * overlays/nio2/openjdk/jdk/src/windows/classes/sun/nio/fs/WindowsFileCopy.java, + * overlays/nio2/openjdk/jdk/src/windows/classes/sun/nio/fs/WindowsFileStore.java, + * overlays/nio2/openjdk/jdk/src/windows/classes/sun/nio/fs/WindowsFileSystemProvider.java, + * overlays/nio2/openjdk/jdk/src/windows/classes/sun/nio/fs/WindowsLinkSupport.java, + * overlays/nio2/openjdk/jdk/src/windows/classes/sun/nio/fs/WindowsNamedAttributeView.java, + * overlays/nio2/openjdk/jdk/src/windows/classes/sun/nio/fs/WindowsPath.java, + * overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/Path/InterruptCopy.java, + * overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/attribute/NamedAttributeView/Basic.java, + 2009-02-04 Andrew John Hughes <ahughes@redhat.com> * acinclude.m4:
--- a/overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/attribute/NamedAttributeView.java Wed Feb 04 12:48:30 2009 +0000 +++ b/overlays/nio2/openjdk/jdk/src/share/classes/org/classpath/icedtea/java/nio/file/attribute/NamedAttributeView.java Thu Feb 05 19:03:06 2009 +0000 @@ -48,9 +48,6 @@ * intended for use where the size of an attribute value is larger than {@link * Integer#MAX_VALUE}. * - * <p> {@note There has been feedback that the read/write methods should use byte - * arrays instead of ByteBuffers.} - * * <p> Named attributes may be used in some implementations to store security * related attributes so consequently, in the case of the default provider at * least, all methods that access named attributes require the @@ -64,13 +61,10 @@ * <p> Where dynamic access to file attributes is required, the {@link * #getAttribute getAttribute} or {@link #readAttributes(String,String[]) * readAttributes(String,String[])} methods may be used to read the attribute - * value as if by invoking the {@link #read read} method. Upon return, the - * buffer's {@link ByteBuffer#position position} is the index of the first - * byte of the attribute value, and its {@link ByteBuffer#limit limit} is - * the index of the first byte that should not be read. The {@link + * value. The attribute value is returned as a byte array (byte[]). The {@link * #setAttribute setAttribute} method may be used to write the value of a - * user-defined/named attribute from a buffer as if by invoking the {@link - * #write write} method. + * user-defined/named attribute from a buffer (as if by invoking the {@link + * #write write} method), or byte array (byte[]). * * @since 1.7 */
--- a/overlays/nio2/openjdk/jdk/src/share/classes/sun/nio/fs/AbstractNamedAttributeView.java Wed Feb 04 12:48:30 2009 +0000 +++ b/overlays/nio2/openjdk/jdk/src/share/classes/sun/nio/fs/AbstractNamedAttributeView.java Thu Feb 05 19:03:06 2009 +0000 @@ -62,18 +62,31 @@ public final Object getAttribute(String attribute) throws IOException { - int size = size(attribute); - ByteBuffer buf = ByteBuffer.allocate(size); - read(attribute, buf); - buf.flip(); - return buf; + int size; + try { + size = size(attribute); + } catch (IOException e) { + // not found or some other I/O error + if (list().contains(attribute)) + throw e; + return null; + } + byte[] buf = new byte[size]; + int n = read(attribute, ByteBuffer.wrap(buf)); + return (n == size) ? buf : Arrays.copyOf(buf, n); } public final void setAttribute(String attribute, Object value) throws IOException { - write(attribute, (ByteBuffer)value); + ByteBuffer bb; + if (value instanceof byte[]) { + bb = ByteBuffer.wrap((byte[])value); + } else { + bb = (ByteBuffer)value; + } + write(attribute, bb); } @@ -88,29 +101,23 @@ readAll = true; } else { names.add(first); - for (String name: rest) { - if (name.equals("*")) { - readAll = true; - break; - } + } + for (String name: rest) { + if (name.equals("*")) { + readAll = true; + } else { names.add(name); } } - if (readAll) { - names.clear(); - for (String name: list()) { - names.add(name); - } - } + if (readAll) + names = list(); - // allocate buffer for each value and return as map - Map<String,ByteBuffer> result = new HashMap<String,ByteBuffer>(); + // read each value and return in map + Map<String,Object> result = new HashMap<String,Object>(); for (String name: names) { - int size = size(name); - ByteBuffer buf = ByteBuffer.allocate(size); - read(name, buf); - result.put(name, buf); - buf.flip(); + Object value = getAttribute(name); + if (value != null) + result.put(name, value); } return result;
--- a/overlays/nio2/openjdk/jdk/src/share/classes/sun/nio/fs/Cancellable.java Wed Feb 04 12:48:30 2009 +0000 +++ b/overlays/nio2/openjdk/jdk/src/share/classes/sun/nio/fs/Cancellable.java Thu Feb 05 19:03:06 2009 +0000 @@ -112,21 +112,24 @@ abstract void implRun() throws Throwable; /** - * Invokes the task in its own thread. If this (meaning the current) thread - * is interrupted then an attempt is make to cancel the background task by - * writting bits into the memory location that it is polling. On return, - * the interrupt status for this thread has been cleared. + * Invokes the given task in its own thread. If this (meaning the current) + * thread is interrupted then an attempt is make to cancel the background + * thread by writing into the memory location that it polls cooperatively. */ static void runInterruptibly(Cancellable task) throws ExecutionException { Thread t = new Thread(task); t.start(); + boolean cancelledByInterrupt = false; while (t.isAlive()) { try { t.join(); } catch (InterruptedException e) { + cancelledByInterrupt = true; task.cancel(); } } + if (cancelledByInterrupt) + Thread.currentThread().interrupt(); Throwable exc = task.exception(); if (exc != null) throw new ExecutionException(exc);
--- a/overlays/nio2/openjdk/jdk/src/windows/classes/sun/nio/fs/WindowsAclFileAttributeView.java Wed Feb 04 12:48:30 2009 +0000 +++ b/overlays/nio2/openjdk/jdk/src/windows/classes/sun/nio/fs/WindowsAclFileAttributeView.java Thu Feb 05 19:03:06 2009 +0000 @@ -117,8 +117,7 @@ // GetFileSecurity does not follow links so when following links we // need the final target - String path = followLinks ? WindowsLinkSupport.getFinalPath(file) : - file.getPathForWin32Calls(); + String path = WindowsLinkSupport.getFinalPath(file, followLinks); NativeBuffer buffer = getFileSecurity(path, OWNER_SECURITY_INFORMATION); try { // get the address of the SID @@ -142,8 +141,7 @@ // GetFileSecurity does not follow links so when following links we // need the final target - String path = followLinks ? WindowsLinkSupport.getFinalPath(file) : - file.getPathForWin32Calls(); + String path = WindowsLinkSupport.getFinalPath(file, followLinks); // ALLOW and DENY entries in DACL; // AUDIT entries in SACL (ignore for now as it requires privileges) @@ -170,8 +168,7 @@ // SetFileSecurity does not follow links so when following links we // need the final target - String path = followLinks ? WindowsLinkSupport.getFinalPath(file) : - file.getPathForWin32Calls(); + String path = WindowsLinkSupport.getFinalPath(file, followLinks); // ConvertStringSidToSid allocates memory for SID so must invoke // LocalFree to free it when we are done @@ -216,9 +213,7 @@ // SetFileSecurity does not follow links so when following links we // need the final target - String path = followLinks ? WindowsLinkSupport.getFinalPath(file) : - file.getPathForWin32Calls(); - + String path = WindowsLinkSupport.getFinalPath(file, followLinks); WindowsSecurityDescriptor sd = WindowsSecurityDescriptor.create(acl); try { SetFileSecurity(path, DACL_SECURITY_INFORMATION, sd.address());
--- a/overlays/nio2/openjdk/jdk/src/windows/classes/sun/nio/fs/WindowsChannelFactory.java Wed Feb 04 12:48:30 2009 +0000 +++ b/overlays/nio2/openjdk/jdk/src/windows/classes/sun/nio/fs/WindowsChannelFactory.java Thu Feb 05 19:03:06 2009 +0000 @@ -56,7 +56,76 @@ * Do not follow reparse points when opening an existing file. Do not fail * if the file is a reparse point. */ - static final OpenOption NOFOLLOW_REPARSEPOINT = new OpenOption() { }; + static final OpenOption OPEN_REPARSE_POINT = new OpenOption() { }; + + /** + * Represents the flags from a user-supplied set of open options. + */ + private static class Flags { + boolean read; + boolean write; + boolean append; + boolean truncateExisting; + boolean create; + boolean createNew; + boolean deleteOnClose; + boolean sparse; + boolean overlapped; + boolean sync; + boolean dsync; + + // non-standard + boolean shareRead = true; + boolean shareWrite = true; + boolean shareDelete = true; + boolean noFollowLinks; + boolean openReparsePoint; + + static Flags toFlags(Set<? extends OpenOption> options) { + Flags flags = new Flags(); + for (OpenOption option: options) { + if (!(option instanceof StandardOpenOption)) { + if (option == ExtendedOpenOption.NOSHARE_READ) { + flags.shareRead = false; + continue; + } + if (option == ExtendedOpenOption.NOSHARE_WRITE) { + flags.shareWrite = false; + continue; + } + if (option == ExtendedOpenOption.NOSHARE_DELETE) { + flags.shareDelete = false; + continue; + } + if (option == LinkOption.NOFOLLOW_LINKS) { + flags.noFollowLinks = true; + continue; + } + if (option == OPEN_REPARSE_POINT) { + flags.openReparsePoint = true; + continue; + } + if (option == null) + throw new NullPointerException(); + throw new UnsupportedOperationException("Unsupported open option"); + } + switch ((StandardOpenOption)option) { + case READ : flags.read = true; break; + case WRITE : flags.write = true; break; + case APPEND : flags.append = true; break; + case TRUNCATE_EXISTING : flags.truncateExisting = true; break; + case CREATE : flags.create = true; break; + case CREATE_NEW : flags.createNew = true; break; + case DELETE_ON_CLOSE : flags.deleteOnClose = true; break; + case SPARSE : flags.sparse = true; break; + case SYNC : flags.sync = true; break; + case DSYNC : flags.dsync = true; break; + default: throw new AssertionError("Should not get here"); + } + } + return flags; + } + } /** * Open/creates file, returning FileChannel to access the file @@ -72,50 +141,25 @@ long pSecurityDescriptor) throws WindowsException { - boolean reading = false; - boolean writing = false; - boolean append = false; - boolean trunc = false; + Flags flags = Flags.toFlags(options); - // check for invalid flags - for (OpenOption flag: options) { - if (flag == StandardOpenOption.READ) { - reading = true; continue; - } - if (flag == StandardOpenOption.WRITE) { - writing = true; continue; - } - if (flag == StandardOpenOption.APPEND) { - append = true; - writing = true; - continue; - } - if (flag == StandardOpenOption.TRUNCATE_EXISTING) { - trunc = true; continue; - } - if (flag == null) - throw new NullPointerException(); - if (!(flag instanceof StandardOpenOption) && - !(flag instanceof ExtendedOpenOption)) - { - throw new UnsupportedOperationException("Unsupported open option"); + // default is reading; append => writing + if (!flags.read && !flags.write) { + if (flags.append) { + flags.write = true; + } else { + flags.read = true; } } - // default is reading - if (!reading && !writing) { - reading = true; - } - - // check for invalid combinations - if (reading && append) + // validation + if (flags.read && flags.append) throw new IllegalArgumentException("READ + APPEND not allowed"); - if (append && trunc) + if (flags.append && flags.truncateExisting) throw new IllegalArgumentException("APPEND + TRUNCATE_EXISTING not allowed"); - FileDescriptor fdObj = open(pathForWindows, pathToCheck, reading, writing, - append, false, options, pSecurityDescriptor); - return FileChannelImpl.open(fdObj, reading, writing, null); + FileDescriptor fdObj = open(pathForWindows, pathToCheck, flags, pSecurityDescriptor); + return FileChannelImpl.open(fdObj, flags.read, flags.write, null); } /** @@ -135,38 +179,24 @@ ThreadPool pool) throws IOException { - boolean reading = false; - boolean writing = false; + Flags flags = Flags.toFlags(options); - // check for invalid flags - for (OpenOption flag: options) { - if (flag == StandardOpenOption.READ) { - reading = true; continue; - } - if (flag == StandardOpenOption.WRITE) { - writing = true; continue; - } - if (flag == null) - throw new NullPointerException(); - if (!(flag instanceof StandardOpenOption) && - !(flag instanceof ExtendedOpenOption)) - { - throw new UnsupportedOperationException("Unsupported open option"); - } - if (flag == StandardOpenOption.APPEND) - throw new UnsupportedOperationException("'APPEND' not supported"); + // Overlapped I/O required + flags.overlapped = true; + + // default is reading + if (!flags.read && !flags.write) { + flags.read = true; } - // default is reading - if (!reading && !writing) { - reading = true; - } + // validation + if (flags.append) + throw new UnsupportedOperationException("APPEND not allowed"); // open file for overlapped I/O FileDescriptor fdObj; try { - fdObj = open(pathForWindows, pathToCheck, reading, writing, false, - true, options, pSecurityDescriptor); + fdObj = open(pathForWindows, pathToCheck, flags, pSecurityDescriptor); } catch (WindowsException x) { x.rethrowAsIOException(pathForWindows); return null; @@ -174,7 +204,7 @@ // create the AsynchronousFileChannel try { - return WindowsAsynchronousFileChannelImpl.open(fdObj, reading, writing, pool); + return WindowsAsynchronousFileChannelImpl.open(fdObj, flags.read, flags.write, pool); } catch (IOException x) { // IOException is thrown if the file handle cannot be associated // with the completion port. All we can do is close the file. @@ -190,11 +220,7 @@ */ private static FileDescriptor open(String pathForWindows, String pathToCheck, - boolean reading, - boolean writing, - boolean append, - boolean overlapped, - Set<? extends OpenOption> options, + Flags flags, long pSecurityDescriptor) throws WindowsException { @@ -203,30 +229,30 @@ // map options int dwDesiredAccess = 0; - if (reading) + if (flags.read) dwDesiredAccess |= GENERIC_READ; - if (writing) - dwDesiredAccess |= (append) ? FILE_APPEND_DATA : GENERIC_WRITE; + if (flags.write) + dwDesiredAccess |= (flags.append) ? FILE_APPEND_DATA : GENERIC_WRITE; int dwShareMode = 0; - if (!options.contains(ExtendedOpenOption.NOSHARE_READ)) + if (flags.shareRead) dwShareMode |= FILE_SHARE_READ; - if (!options.contains(ExtendedOpenOption.NOSHARE_WRITE)) + if (flags.shareWrite) dwShareMode |= FILE_SHARE_WRITE; - if (!options.contains(ExtendedOpenOption.NOSHARE_DELETE)) + if (flags.shareDelete) dwShareMode |= FILE_SHARE_DELETE; int dwFlagsAndAttributes = FILE_ATTRIBUTE_NORMAL; int dwCreationDisposition = OPEN_EXISTING; - if (writing) { - if (options.contains(StandardOpenOption.CREATE_NEW)) { + if (flags.write) { + if (flags.createNew) { dwCreationDisposition = CREATE_NEW; // force create to fail if file is orphaned reparse point dwFlagsAndAttributes |= FILE_FLAG_OPEN_REPARSE_POINT; } else { - if (options.contains(StandardOpenOption.CREATE)) + if (flags.create) dwCreationDisposition = OPEN_ALWAYS; - if (options.contains(StandardOpenOption.TRUNCATE_EXISTING)) { + if (flags.truncateExisting) { // Windows doesn't have a creation disposition that exactly // corresponds to CREATE + TRUNCATE_EXISTING so we use // the OPEN_ALWAYS mode and then truncate the file. @@ -239,23 +265,21 @@ } } - if (options.contains(StandardOpenOption.DSYNC) || options.contains(StandardOpenOption.SYNC)) + if (flags.dsync || flags.sync) dwFlagsAndAttributes |= FILE_FLAG_WRITE_THROUGH; - if (overlapped) + if (flags.overlapped) dwFlagsAndAttributes |= FILE_FLAG_OVERLAPPED; - - boolean deleteOnClose = options.contains(StandardOpenOption.DELETE_ON_CLOSE); - if (deleteOnClose) + if (flags.deleteOnClose) dwFlagsAndAttributes |= FILE_FLAG_DELETE_ON_CLOSE; // NOFOLLOW_LINKS and NOFOLLOW_REPARSEPOINT mean open reparse point boolean okayToFollowLinks = true; if (dwCreationDisposition != CREATE_NEW && - (options.contains(LinkOption.NOFOLLOW_LINKS) || - options.contains(NOFOLLOW_REPARSEPOINT) || - deleteOnClose)) + (flags.noFollowLinks || + flags.openReparsePoint || + flags.deleteOnClose)) { - if (options.contains(LinkOption.NOFOLLOW_LINKS)) + if (flags.noFollowLinks) okayToFollowLinks = false; dwFlagsAndAttributes |= FILE_FLAG_OPEN_REPARSE_POINT; } @@ -264,11 +288,11 @@ if (pathToCheck != null) { SecurityManager sm = System.getSecurityManager(); if (sm != null) { - if (reading) + if (flags.read) sm.checkRead(pathToCheck); - if (writing) + if (flags.write) sm.checkWrite(pathToCheck); - if (deleteOnClose) + if (flags.deleteOnClose) sm.checkDelete(pathToCheck); } } @@ -308,9 +332,7 @@ } // make the file sparse if needed - if (dwCreationDisposition == CREATE_NEW && - options.contains(StandardOpenOption.SPARSE)) - { + if (dwCreationDisposition == CREATE_NEW && flags.sparse) { try { DeviceIoControlSetSparse(handle); } catch (WindowsException x) {
--- a/overlays/nio2/openjdk/jdk/src/windows/classes/sun/nio/fs/WindowsDirectoryStream.java Wed Feb 04 12:48:30 2009 +0000 +++ b/overlays/nio2/openjdk/jdk/src/windows/classes/sun/nio/fs/WindowsDirectoryStream.java Thu Feb 05 19:03:06 2009 +0000 @@ -62,16 +62,16 @@ this.dir = dir; this.filter = filter; - // Need to append * or \* to match entries in directory. - String search = dir.getPathForWin32Calls(); - char last = search.charAt(search.length() -1); - if (last == ':' || last == '\\') { - search += "*"; - } else { - search += "\\*"; - } + try { + // Need to append * or \* to match entries in directory. + String search = dir.getPathForWin32Calls(); + char last = search.charAt(search.length() -1); + if (last == ':' || last == '\\') { + search += "*"; + } else { + search += "\\*"; + } - try { FirstFile first = FindFirstFile(search); this.handle = first.handle(); this.firstName = first.name();
--- a/overlays/nio2/openjdk/jdk/src/windows/classes/sun/nio/fs/WindowsFileAttributeViews.java Wed Feb 04 12:48:30 2009 +0000 +++ b/overlays/nio2/openjdk/jdk/src/windows/classes/sun/nio/fs/WindowsFileAttributeViews.java Thu Feb 05 19:03:06 2009 +0000 @@ -226,9 +226,7 @@ // GetFileAttribtues & SetFileAttributes do not follow links so when // following links we need the final target - String path = followLinks ? WindowsLinkSupport.getFinalPath(file) : - file.getPathForWin32Calls(); - + String path = WindowsLinkSupport.getFinalPath(file, followLinks); try { int oldValue = GetFileAttributes(path); int newValue = oldValue;
--- a/overlays/nio2/openjdk/jdk/src/windows/classes/sun/nio/fs/WindowsFileCopy.java Wed Feb 04 12:48:30 2009 +0000 +++ b/overlays/nio2/openjdk/jdk/src/windows/classes/sun/nio/fs/WindowsFileCopy.java Thu Feb 05 19:03:06 2009 +0000 @@ -144,8 +144,8 @@ sm.checkPermission(new LinkPermission("symbolic")); } - final String sourcePath = source.getPathForWin32Calls(); - final String targetPath = target.getPathForWin32Calls(); + final String sourcePath = asWin32Path(source); + final String targetPath = asWin32Path(target); // if target exists then delete it. if (targetAttrs != null) { @@ -288,8 +288,8 @@ target.checkWrite(); } - String sourcePath = source.getPathForWin32Calls(); - String targetPath = target.getPathForWin32Calls(); + final String sourcePath = asWin32Path(source); + final String targetPath = asWin32Path(target); // atomic case if (atomicMove) { @@ -468,6 +468,16 @@ } } + + private static String asWin32Path(WindowsPath path) throws IOException { + try { + return path.getPathForWin32Calls(); + } catch (WindowsException x) { + x.rethrowAsIOException(path); + return null; + } + } + /** * Copy DACL/owner/group from source to target */ @@ -476,8 +486,7 @@ boolean followLinks) throws IOException { - String path = followLinks ? - WindowsLinkSupport.getFinalPath(source) : source.getPathForWin32Calls(); + String path = WindowsLinkSupport.getFinalPath(source, followLinks); // may need SeRestorePrivilege to set file owner WindowsSecurity.Privilege priv =
--- a/overlays/nio2/openjdk/jdk/src/windows/classes/sun/nio/fs/WindowsFileStore.java Wed Feb 04 12:48:30 2009 +0000 +++ b/overlays/nio2/openjdk/jdk/src/windows/classes/sun/nio/fs/WindowsFileStore.java Thu Feb 05 19:03:06 2009 +0000 @@ -84,11 +84,11 @@ // final target String target; if (file.getFileSystem().supportsLinks()) { - target = WindowsLinkSupport.getFinalPath(file); + target = WindowsLinkSupport.getFinalPath(file, true); } else { // file must exist WindowsFileAttributes.get(file, true); - target = file.toString(); + target = file.getPathForWin32Calls(); } String root = GetVolumePathName(target); return new WindowsFileStore(root, file.getPathForPermissionCheck());
--- a/overlays/nio2/openjdk/jdk/src/windows/classes/sun/nio/fs/WindowsFileSystemProvider.java Wed Feb 04 12:48:30 2009 +0000 +++ b/overlays/nio2/openjdk/jdk/src/windows/classes/sun/nio/fs/WindowsFileSystemProvider.java Thu Feb 05 19:03:06 2009 +0000 @@ -137,6 +137,9 @@ options, sd.address(), pool); + } catch (WindowsException x) { + x.rethrowAsIOException(file); + return null; } finally { if (sd != null) sd.release();
--- a/overlays/nio2/openjdk/jdk/src/windows/classes/sun/nio/fs/WindowsLinkSupport.java Wed Feb 04 12:48:30 2009 +0000 +++ b/overlays/nio2/openjdk/jdk/src/windows/classes/sun/nio/fs/WindowsLinkSupport.java Thu Feb 05 19:03:06 2009 +0000 @@ -66,13 +66,17 @@ * Returns the final path of a given path as a String. This should be used * prior to calling Win32 system calls that do not follow links. */ - static String getFinalPath(WindowsPath input) throws IOException { + static String getFinalPath(WindowsPath input, boolean followLinks) + throws IOException + { WindowsFileSystem fs = input.getFileSystem(); - if (!fs.supportsLinks()) - return input.getPathForWin32Calls(); - // if the file is not a sym link then return the path to access the file try { + // if not following links then don't need final path + if (!followLinks || !fs.supportsLinks()) + return input.getPathForWin32Calls(); + + // if file is a sym link then don't need final path if (!WindowsFileAttributes.get(input, false).isSymbolicLink()) { return input.getPathForWin32Calls(); }
--- a/overlays/nio2/openjdk/jdk/src/windows/classes/sun/nio/fs/WindowsNamedAttributeView.java Wed Feb 04 12:48:30 2009 +0000 +++ b/overlays/nio2/openjdk/jdk/src/windows/classes/sun/nio/fs/WindowsNamedAttributeView.java Thu Feb 05 19:03:06 2009 +0000 @@ -51,7 +51,7 @@ throw new NullPointerException("'name' is null"); return file + ":" + name; } - private String join(WindowsPath file, String name) { + private String join(WindowsPath file, String name) throws WindowsException { return join(file.getPathForWin32Calls(), name); } @@ -219,11 +219,11 @@ Set<OpenOption> opts = new HashSet<OpenOption>(); opts.add(READ); if (!followLinks) - opts.add(WindowsChannelFactory.NOFOLLOW_REPARSEPOINT); + opts.add(WindowsChannelFactory.OPEN_REPARSE_POINT); fc = WindowsChannelFactory .newFileChannel(join(file, name), null, opts, 0L); } catch (WindowsException x) { - x.rethrowAsIOException(join(file, name)); + x.rethrowAsIOException(join(file.getPathForPermissionCheck(), name)); } try { long size = fc.size(); @@ -246,11 +246,11 @@ Set<OpenOption> opts = new HashSet<OpenOption>(); opts.add(READ); if (!followLinks) - opts.add(WindowsChannelFactory.NOFOLLOW_REPARSEPOINT); + opts.add(WindowsChannelFactory.OPEN_REPARSE_POINT); fc = WindowsChannelFactory .newFileChannel(join(file, name), null, opts, 0L); } catch (WindowsException x) { - x.rethrowAsIOException(join(file, name)); + x.rethrowAsIOException(join(file.getPathForPermissionCheck(), name)); } // read to EOF (nothing we can do if I/O error occurs) @@ -300,7 +300,7 @@ try { Set<OpenOption> opts = new HashSet<OpenOption>(); if (!followLinks) - opts.add(WindowsChannelFactory.NOFOLLOW_REPARSEPOINT); + opts.add(WindowsChannelFactory.OPEN_REPARSE_POINT); opts.add(CREATE); opts.add(WRITE); opts.add(StandardOpenOption.TRUNCATE_EXISTING); @@ -309,7 +309,7 @@ named = WindowsChannelFactory .newFileChannel(join(file, name), null, opts, 0L); } catch (WindowsException x) { - x.rethrowAsIOException(join(file, name)); + x.rethrowAsIOException(join(file.getPathForPermissionCheck(), name)); } // write value (nothing we can do if I/O error occurs) try { @@ -331,8 +331,8 @@ if (System.getSecurityManager() != null) checkAccess(file.getPathForPermissionCheck(), false, true); - String toDelete = followLinks ? - join(WindowsLinkSupport.getFinalPath(file), name) : join(file, name); + String path = WindowsLinkSupport.getFinalPath(file, followLinks); + String toDelete = join(path, name); try { DeleteFile(toDelete); } catch (WindowsException x) {
--- a/overlays/nio2/openjdk/jdk/src/windows/classes/sun/nio/fs/WindowsPath.java Wed Feb 04 12:48:30 2009 +0000 +++ b/overlays/nio2/openjdk/jdk/src/windows/classes/sun/nio/fs/WindowsPath.java Thu Feb 05 19:03:06 2009 +0000 @@ -33,6 +33,7 @@ import java.net.URI; import java.security.AccessController; import java.util.*; +import java.lang.ref.WeakReference; import com.sun.nio.file.ExtendedWatchEventModifier; @@ -49,6 +50,15 @@ class WindowsPath extends AbstractPath { private static final Unsafe unsafe = Unsafe.getUnsafe(); + // The maximum path that does not require long path prefix. On Windows + // the maximum path is 260 minus 1 (NUL) but for directories it is 260 + // minus 12 minus 1 (to allow for the creation of a 8.3 file in the + // directory). + private static final int MAX_PATH = 247; + + // Maximum extended-length path + private static final int MAX_LONG_PATH = 32000; + // FIXME - eliminate this reference to reduce space private final WindowsFileSystem fs; @@ -59,18 +69,15 @@ // normalized path private final String path; + // the path to use in Win32 calls. This differs from path for relative + // paths and has a long path prefix for all paths longer than MAX_PATH. + private volatile WeakReference<String> pathForWin32Calls; + // offsets into name components (computed lazily) private volatile Integer[] offsets; - // resolved against file system's default directory - private final String resolved; - - // the path to use in calls to Windows (same as resolved path when less - // than 248 characters but differs for long paths) - private final String pathForWin32Calls; - // computed hash code (computed lazily, no need to be volatile) - private volatile int hash; + private int hash; /** @@ -85,56 +92,6 @@ this.type = type; this.root = root; this.path = path; - - // resolve path against file system's default directory - switch (type) { - case ABSOLUTE : - case UNC : - this.resolved = path; - break; - case RELATIVE : - String defaultDirectory = getFileSystem().defaultDirectory(); - if (defaultDirectory.endsWith("\\")) { - this.resolved = defaultDirectory + path; - } else { - this.resolved = defaultDirectory + "\\" + path; - } - break; - case DIRECTORY_RELATIVE: - String defaultRoot = getFileSystem().defaultRoot(); - this.resolved = defaultRoot + path.substring(1); - break; - case DRIVE_RELATIVE: - // Need to postpone resolving these types of paths as they can - // change for the case of removable media devices when media - // is inserted or removed. - this.resolved = path; - break; - default: - throw new AssertionError(); - } - - // Long paths need to have "." and ".." removed and be prefixed with \\?\ - // Note that it is okay to remove ".." even when it follows a link - - // for example, it is okay for foo/link/../bar to be changed to foo/bar. - // The reason is that Win32 APIs to access foo/link/../bar will access - // foo/bar anyway (which differs to Unix systems) - String ps = resolved; - if (ps.length() > 248) { - if (ps.length() > 32000) { - throw new InvalidPathException(ps, - "Cannot access file with path exceeding 32000 characters"); - } - try { - ps = GetFullPathName(ps); - } catch (WindowsException x) { - throw new AssertionError("GetFullPathName failed for '" + ps + - "' " + x.getMessage()); - } - ps = addPrefixIfNeeded(ps); - } - - this.pathForWin32Calls = ps; } /** @@ -165,12 +122,107 @@ // use this path for permission checks String getPathForPermissionCheck() { + return path; + } + + // use this path for Win32 calls + // This method will prefix long paths with \\?\ or \\?\UNC as required. + String getPathForWin32Calls() throws WindowsException { + // short absolute paths can be used directly + if (isAbsolute() && path.length() <= MAX_PATH) + return path; + + // return cached values if available + WeakReference<String> ref = pathForWin32Calls; + String resolved = (ref != null) ? ref.get() : null; + if (resolved != null) { + // Win32 path already available + return resolved; + } + + // resolve against default directory + resolved = getAbsolutePath(); + + // Long paths need to have "." and ".." removed and be prefixed with + // "\\?\". Note that it is okay to remove ".." even when it follows + // a link - for example, it is okay for foo/link/../bar to be changed + // to foo/bar. The reason is that Win32 APIs to access foo/link/../bar + // will access foo/bar anyway (which differs to Unix systems) + if (resolved.length() > MAX_PATH) { + if (resolved.length() > MAX_LONG_PATH) { + throw new WindowsException("Cannot access file with path exceeding " + + MAX_LONG_PATH + " characters"); + } + resolved = addPrefixIfNeeded(GetFullPathName(resolved)); + } + + // cache the resolved path (except drive relative paths as the working + // directory on removal media devices can change during the lifetime + // of the VM) + if (type != WindowsPathType.DRIVE_RELATIVE) { + synchronized (path) { + pathForWin32Calls = new WeakReference<String>(resolved); + } + } return resolved; } - // use this for calls into Windows (may have \\?\ or \\?\UNC prefix) - String getPathForWin32Calls() { - return pathForWin32Calls; + // return this path resolved against the file system's default directory + private String getAbsolutePath() throws WindowsException { + if (isAbsolute()) + return path; + + // Relative path ("foo" for example) + if (type == WindowsPathType.RELATIVE) { + String defaultDirectory = getFileSystem().defaultDirectory(); + if (defaultDirectory.endsWith("\\")) { + return defaultDirectory + path; + } else { + StringBuilder sb = + new StringBuilder(defaultDirectory.length() + path.length() + 1); + return sb.append(defaultDirectory).append('\\').append(path).toString(); + } + } + + // Directory relative path ("\foo" for example) + if (type == WindowsPathType.DIRECTORY_RELATIVE) { + String defaultRoot = getFileSystem().defaultRoot(); + return defaultRoot + path.substring(1); + } + + // Drive relative path ("C:foo" for example). + if (isSameDrive(root, getFileSystem().defaultRoot())) { + // relative to default directory + String remaining = path.substring(root.length()); + String defaultDirectory = getFileSystem().defaultDirectory(); + String result; + if (defaultDirectory.endsWith("\\")) { + result = defaultDirectory + remaining; + } else { + result = defaultDirectory + "\\" + remaining; + } + return result; + } else { + // relative to some other drive + String wd; + try { + int dt = GetDriveType(root + "\\"); + if (dt == DRIVE_UNKNOWN || dt == DRIVE_NO_ROOT_DIR) + throw new WindowsException(""); + wd = GetFullPathName(root + "."); + } catch (WindowsException x) { + throw new WindowsException("Unable to get working directory of drive '" + + Character.toUpperCase(root.charAt(0)) + "'"); + } + String result = wd; + if (wd.endsWith("\\")) { + result += path.substring(root.length()); + } else { + if (path.length() > root.length()) + result += "\\" + path.substring(root.length()); + } + return result; + } } // Add long path prefix to path if required @@ -727,9 +779,9 @@ */ private int getEffectiveAccess() throws IOException { // read security descriptor continaing ACL (symlinks are followed) - String fp = WindowsLinkSupport.getFinalPath(this); + String target = WindowsLinkSupport.getFinalPath(this, true); NativeBuffer aclBuffer = WindowsAclFileAttributeView - .getFileSecurity(fp, DACL_SECURITY_INFORMATION); + .getFileSecurity(target, DACL_SECURITY_INFORMATION); // retrieves DACL from security descriptor long pAcl = GetSecurityDescriptorDacl(aclBuffer.address()); @@ -1189,44 +1241,10 @@ sm.checkPropertyAccess("user.dir"); } - // result is the resolved path if the path is not drive-relative - if (type != WindowsPathType.DRIVE_RELATIVE) - return WindowsPath.createFromNormalizedPath(getFileSystem(), resolved); - - // if the path is drive-relative and is relative to a drive other - // than the drive of the default directory then resolve against the - // working directory of that drive. - if (!isSameDrive(root, getFileSystem().defaultRoot())) { - try { - int dt = GetDriveType(root + "\\"); - if (dt == DRIVE_UNKNOWN || dt == DRIVE_NO_ROOT_DIR) - throw new WindowsException(""); - String wd = GetFullPathName(root + "."); - String result = wd; - if (wd.endsWith("\\")) { - result += path.substring(root.length()); - } else { - if (path.length() > root.length()) - result += "\\" + path.substring(root.length()); - } - return WindowsPath.createFromNormalizedPath(getFileSystem(), result); - } catch (WindowsException x) { - IOException ioe = new IOException("Unable to get working " + - "directory of drive '" + - Character.toUpperCase(root.charAt(0)) + "'"); - throw new java.io.IOError(ioe); - } - } else { - // relative to default directory - String remaining = path.substring(root.length()); - String defaultDirectory = getFileSystem().defaultDirectory(); - String result; - if (defaultDirectory.endsWith("\\")) { - result = defaultDirectory + remaining; - } else { - result = defaultDirectory + "\\" + remaining; - } - return createFromNormalizedPath(getFileSystem(), result); + try { + return createFromNormalizedPath(getFileSystem(), getAbsolutePath()); + } catch (WindowsException x) { + throw new IOError(new IOException(x.getMessage())); } }
--- a/overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/Path/InterruptCopy.java Wed Feb 04 12:48:30 2009 +0000 +++ b/overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/Path/InterruptCopy.java Thu Feb 05 19:03:06 2009 +0000 @@ -90,8 +90,10 @@ source.copyTo(target, ExtendedCopyOption.INTERRUPTIBLE); throw new RuntimeException("Copy completed (this is not expected)"); } catch (IOException e) { + boolean interrupted = Thread.interrupted(); + if (!interrupted) + throw new RuntimeException("Interrupt status was not set"); System.out.println("Copy failed (this is expected)"); - e.printStackTrace(); } // copy source to target via task in thread pool, interrupting it after
--- a/overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/attribute/NamedAttributeView/Basic.java Wed Feb 04 12:48:30 2009 +0000 +++ b/overlays/nio2/openjdk/jdk/test/org/classpath/icedtea/java/nio/file/attribute/NamedAttributeView/Basic.java Thu Feb 05 19:03:06 2009 +0000 @@ -32,7 +32,8 @@ import java.nio.file.*; import static java.nio.file.LinkOption.*; import java.nio.file.attribute.*; -import java.util.Iterator; +import java.util.Arrays; +import java.util.Map; import java.util.Random; import java.io.IOException; @@ -44,6 +45,29 @@ private static final String ATTR_VALUE = "text/plain"; private static final String ATTR_VALUE2 = "text/html"; + static interface Task { + void run() throws Exception; + } + + static void tryCatch(Class<? extends Throwable> ex, Task task) { + boolean caught = false; + try { + task.run(); + } catch (Throwable x) { + if (ex.isAssignableFrom(x.getClass())) { + caught = true; + } else { + throw new RuntimeException(x); + } + } + if (!caught) + throw new RuntimeException(ex.getName() + " expected"); + } + + static void expectNullPointerException(Task task) { + tryCatch(NullPointerException.class, task); + } + static boolean hasAttribute(NamedAttributeView view, String attr) throws IOException { @@ -55,7 +79,7 @@ } static void test(Path file, LinkOption... options) throws IOException { - NamedAttributeView view = file + final NamedAttributeView view = file .getFileAttributeView(NamedAttributeView.class, options); ByteBuffer buf = rand.nextBoolean() ? ByteBuffer.allocate(100) : ByteBuffer.allocateDirect(100); @@ -82,11 +106,10 @@ throw new RuntimeException("Unexpected attribute value"); // Test: read with insufficient space - try { - view.read(ATTR_NAME, ByteBuffer.allocateDirect(size-1)); - throw new RuntimeException("Read expected to fail"); - } catch (IOException x) { - } + tryCatch(IOException.class, new Task() { + public void run() throws IOException { + view.read(ATTR_NAME, ByteBuffer.allocateDirect(1)); + }}); // Test: replace value buf.clear(); @@ -104,56 +127,97 @@ view.delete(ATTR_NAME); if (hasAttribute(view, ATTR_NAME)) throw new RuntimeException("Attribute name in list"); + + // Test: dynamic access + byte[] valueAsBytes = ATTR_VALUE.getBytes(); + view.setAttribute(ATTR_NAME, valueAsBytes); + byte[] actualAsBytes = (byte[])view.getAttribute(ATTR_NAME); + if (!Arrays.equals(valueAsBytes, actualAsBytes)) + throw new RuntimeException("Unexpected attribute value"); + Map<String,?> map = view.readAttributes(ATTR_NAME); + if (!Arrays.equals(valueAsBytes, (byte[])map.get(ATTR_NAME))) + throw new RuntimeException("Unexpected attribute value"); + map = view.readAttributes(ATTR_NAME, "*"); + if (!Arrays.equals(valueAsBytes, (byte[])map.get(ATTR_NAME))) + throw new RuntimeException("Unexpected attribute value"); + map = view.readAttributes("DoesNotExist"); + if (!map.isEmpty()) + throw new RuntimeException("Map expected to be empty"); } static void miscTests(Path file) throws IOException { - NamedAttributeView view = file + final NamedAttributeView view = file .getFileAttributeView(NamedAttributeView.class); view.write(ATTR_NAME, ByteBuffer.wrap(ATTR_VALUE.getBytes())); // NullPointerException - ByteBuffer buf = ByteBuffer.allocate(100); - try { - view.read(null, buf); - throw new RuntimeException("NPE expected"); - } catch (NullPointerException x) { } - try { - view.read(ATTR_NAME, null); - throw new RuntimeException("NPE expected"); - } catch (NullPointerException x) { } - try { - view.write(null, buf); - throw new RuntimeException("NPE expected"); - } catch (NullPointerException x) { } - try { - view.write(ATTR_NAME, null); - throw new RuntimeException("NPE expected"); - } catch (NullPointerException x) { } - try { - view.size(null); - throw new RuntimeException("NPE expected"); - } catch (NullPointerException x) { } - try { - view.delete(null); - throw new RuntimeException("NPE expected"); - } catch (NullPointerException x) { } + final ByteBuffer buf = ByteBuffer.allocate(100); + + expectNullPointerException(new Task() { + public void run() throws IOException { + view.read(null, buf); + }}); + expectNullPointerException(new Task() { + public void run() throws IOException { + view.read(ATTR_NAME, null); + }}); + expectNullPointerException(new Task() { + public void run() throws IOException { + view.write(null, buf); + }}); + expectNullPointerException(new Task() { + public void run() throws IOException { + view.write(ATTR_NAME, null); + }}); + expectNullPointerException(new Task() { + public void run() throws IOException { + view.size(null); + }}); + expectNullPointerException(new Task() { + public void run() throws IOException { + view.delete(null); + }}); + expectNullPointerException(new Task() { + public void run() throws IOException { + view.getAttribute(null); + }}); + expectNullPointerException(new Task() { + public void run() throws IOException { + view.setAttribute(ATTR_NAME, null); + }}); + expectNullPointerException(new Task() { + public void run() throws IOException { + view.setAttribute(null, new byte[0]); + }}); + expectNullPointerException(new Task() { + public void run() throws IOException { + view.readAttributes(null); + }}); + expectNullPointerException(new Task() { + public void run() throws IOException { + view.readAttributes("*", (String[])null); + }}); + expectNullPointerException(new Task() { + public void run() throws IOException { + view.readAttributes("*", ATTR_NAME, null); + }}); // Read-only buffer - buf = ByteBuffer.wrap(ATTR_VALUE.getBytes()).asReadOnlyBuffer(); - view.write(ATTR_NAME, buf); - buf.flip(); - try { - view.read(ATTR_NAME, buf); - throw new RuntimeException("IAE expected"); - } catch (IllegalArgumentException x) { } + tryCatch(IllegalArgumentException.class, new Task() { + public void run() throws IOException { + ByteBuffer buf = ByteBuffer.wrap(ATTR_VALUE.getBytes()).asReadOnlyBuffer(); + view.write(ATTR_NAME, buf); + buf.flip(); + view.read(ATTR_NAME, buf); + }}); // Zero bytes remaining - buf = ByteBuffer.allocateDirect(100); - buf.position(buf.capacity()); - try { - view.read(ATTR_NAME, buf); - throw new RuntimeException("IOE expected"); - } catch (IOException x) { } + tryCatch(IOException.class, new Task() { + public void run() throws IOException { + ByteBuffer buf = buf = ByteBuffer.allocateDirect(100); + buf.position(buf.capacity()); + view.read(ATTR_NAME, buf); + }}); } public static void main(String[] args) throws IOException {