package sun.nio.fs;
import java.nio.file.*;
import static java.nio.file.StandardOpenOption.*;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.io.IOException;
import java.util.*;
import jdk.internal.misc.Unsafe;
import static sun.nio.fs.WindowsNativeDispatcher.*;
import static sun.nio.fs.WindowsConstants.*;
class WindowsUserDefinedFileAttributeView
extends AbstractUserDefinedFileAttributeView
{
private static final Unsafe unsafe = Unsafe.getUnsafe();
private String join(String file, String name) {
if (name == null)
throw new NullPointerException("'name' is null");
return file + ":" + name;
}
private String join(WindowsPath file, String name) throws WindowsException {
return join(file.getPathForWin32Calls(), name);
}
private final WindowsPath file;
private final boolean followLinks;
WindowsUserDefinedFileAttributeView(WindowsPath file, boolean followLinks) {
this.file = file;
this.followLinks = followLinks;
}
private List<String> () throws IOException {
List<String> list = new ArrayList<>();
try {
FirstStream first = FindFirstStream(file.getPathForWin32Calls());
if (first != null) {
long handle = first.handle();
try {
String name = first.name();
if (!name.equals("::$DATA")) {
String[] segs = name.split(":");
list.add(segs[1]);
}
while ((name = FindNextStream(handle)) != null) {
String[] segs = name.split(":");
list.add(segs[1]);
}
} finally {
FindClose(handle);
}
}
} catch (WindowsException x) {
x.rethrowAsIOException(file);
}
return Collections.unmodifiableList(list);
}
@Override
public List<String> list() throws IOException {
if (System.getSecurityManager() != null)
checkAccess(file.getPathForPermissionCheck(), true, false);
return listUsingStreamEnumeration();
}
@Override
public int size(String name) throws IOException {
if (System.getSecurityManager() != null)
checkAccess(file.getPathForPermissionCheck(), true, false);
FileChannel fc = null;
try {
Set<OpenOption> opts = new HashSet<>();
opts.add(READ);
if (!followLinks)
opts.add(WindowsChannelFactory.OPEN_REPARSE_POINT);
fc = WindowsChannelFactory
.newFileChannel(join(file, name), null, opts, 0L);
} catch (WindowsException x) {
x.rethrowAsIOException(join(file.getPathForPermissionCheck(), name));
}
try {
long size = fc.size();
if (size > Integer.MAX_VALUE)
throw new ArithmeticException("Stream too large");
return (int)size;
} finally {
fc.close();
}
}
@Override
public int read(String name, ByteBuffer dst) throws IOException {
if (System.getSecurityManager() != null)
checkAccess(file.getPathForPermissionCheck(), true, false);
FileChannel fc = null;
try {
Set<OpenOption> opts = new HashSet<>();
opts.add(READ);
if (!followLinks)
opts.add(WindowsChannelFactory.OPEN_REPARSE_POINT);
fc = WindowsChannelFactory
.newFileChannel(join(file, name), null, opts, 0L);
} catch (WindowsException x) {
x.rethrowAsIOException(join(file.getPathForPermissionCheck(), name));
}
try {
if (fc.size() > dst.remaining())
throw new IOException("Stream too large");
int total = 0;
while (dst.hasRemaining()) {
int n = fc.read(dst);
if (n < 0)
break;
total += n;
}
return total;
} finally {
fc.close();
}
}
@Override
public int write(String name, ByteBuffer src) throws IOException {
if (System.getSecurityManager() != null)
checkAccess(file.getPathForPermissionCheck(), false, true);
long handle = -1L;
try {
int flags = FILE_FLAG_BACKUP_SEMANTICS;
if (!followLinks)
flags |= FILE_FLAG_OPEN_REPARSE_POINT;
handle = CreateFile(file.getPathForWin32Calls(),
GENERIC_READ,
(FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE),
OPEN_EXISTING,
flags);
} catch (WindowsException x) {
x.rethrowAsIOException(file);
}
try {
Set<OpenOption> opts = new HashSet<>();
if (!followLinks)
opts.add(WindowsChannelFactory.OPEN_REPARSE_POINT);
opts.add(CREATE);
opts.add(WRITE);
opts.add(StandardOpenOption.TRUNCATE_EXISTING);
FileChannel named = null;
try {
named = WindowsChannelFactory
.newFileChannel(join(file, name), null, opts, 0L);
} catch (WindowsException x) {
x.rethrowAsIOException(join(file.getPathForPermissionCheck(), name));
}
try {
int rem = src.remaining();
while (src.hasRemaining()) {
named.write(src);
}
return rem;
} finally {
named.close();
}
} finally {
CloseHandle(handle);
}
}
@Override
public void delete(String name) throws IOException {
if (System.getSecurityManager() != null)
checkAccess(file.getPathForPermissionCheck(), false, true);
String path = WindowsLinkSupport.getFinalPath(file, followLinks);
String toDelete = join(path, name);
try {
DeleteFile(toDelete);
} catch (WindowsException x) {
x.rethrowAsIOException(toDelete);
}
}
}