mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-26 14:24:46 +02:00
8233451: (fs) Files.newInputStream() cannot be used with character special files
Reviewed-by: alanb
This commit is contained in:
parent
002de86081
commit
de92fe3757
8 changed files with 415 additions and 31 deletions
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2001, 2023, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
|
@ -38,6 +38,7 @@ import java.nio.channels.WritableByteChannel;
|
|||
import java.util.Arrays;
|
||||
import java.util.Objects;
|
||||
import jdk.internal.util.ArraysSupport;
|
||||
import jdk.internal.vm.annotation.Stable;
|
||||
|
||||
/**
|
||||
* An InputStream that reads bytes from a channel.
|
||||
|
@ -53,6 +54,10 @@ class ChannelInputStream extends InputStream {
|
|||
private byte[] bs; // Invoker's previous array
|
||||
private byte[] b1;
|
||||
|
||||
// if isOther is true, then the file being read is not a regular file,
|
||||
// nor a directory, nor a symbolic link, hence possibly not seekable
|
||||
private @Stable Boolean isOther;
|
||||
|
||||
/**
|
||||
* Initialize a ChannelInputStream that reads from the given channel.
|
||||
*/
|
||||
|
@ -60,6 +65,17 @@ class ChannelInputStream extends InputStream {
|
|||
this.ch = ch;
|
||||
}
|
||||
|
||||
private boolean isOther() throws IOException {
|
||||
Boolean isOther = this.isOther;
|
||||
if (isOther == null) {
|
||||
if (ch instanceof FileChannelImpl fci)
|
||||
this.isOther = isOther = fci.isOther();
|
||||
else
|
||||
this.isOther = isOther = Boolean.FALSE;
|
||||
}
|
||||
return isOther;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads a sequence of bytes from the channel into the given buffer.
|
||||
*/
|
||||
|
@ -105,7 +121,8 @@ class ChannelInputStream extends InputStream {
|
|||
|
||||
@Override
|
||||
public byte[] readAllBytes() throws IOException {
|
||||
if (!(ch instanceof SeekableByteChannel sbc))
|
||||
if (!(ch instanceof SeekableByteChannel sbc) ||
|
||||
(ch instanceof FileChannelImpl fci && isOther()))
|
||||
return super.readAllBytes();
|
||||
|
||||
long length = sbc.size();
|
||||
|
@ -156,7 +173,8 @@ class ChannelInputStream extends InputStream {
|
|||
if (len == 0)
|
||||
return new byte[0];
|
||||
|
||||
if (!(ch instanceof SeekableByteChannel sbc))
|
||||
if (!(ch instanceof SeekableByteChannel sbc) ||
|
||||
(ch instanceof FileChannelImpl fci && isOther()))
|
||||
return super.readNBytes(len);
|
||||
|
||||
long length = sbc.size();
|
||||
|
@ -192,7 +210,9 @@ class ChannelInputStream extends InputStream {
|
|||
@Override
|
||||
public int available() throws IOException {
|
||||
// special case where the channel is to a file
|
||||
if (ch instanceof SeekableByteChannel sbc) {
|
||||
if (ch instanceof FileChannelImpl fci) {
|
||||
return fci.available();
|
||||
} else if (ch instanceof SeekableByteChannel sbc) {
|
||||
long rem = Math.max(0, sbc.size() - sbc.position());
|
||||
return (rem > Integer.MAX_VALUE) ? Integer.MAX_VALUE : (int)rem;
|
||||
}
|
||||
|
@ -202,7 +222,8 @@ class ChannelInputStream extends InputStream {
|
|||
@Override
|
||||
public synchronized long skip(long n) throws IOException {
|
||||
// special case where the channel is to a file
|
||||
if (ch instanceof SeekableByteChannel sbc) {
|
||||
if (ch instanceof SeekableByteChannel sbc &&
|
||||
!(ch instanceof FileChannelImpl fci && isOther())) {
|
||||
long pos = sbc.position();
|
||||
long newPos;
|
||||
if (n > 0) {
|
||||
|
@ -224,7 +245,8 @@ class ChannelInputStream extends InputStream {
|
|||
public long transferTo(OutputStream out) throws IOException {
|
||||
Objects.requireNonNull(out, "out");
|
||||
|
||||
if (ch instanceof FileChannel fc) {
|
||||
if (ch instanceof FileChannel fc &&
|
||||
!(fc instanceof FileChannelImpl fci && isOther())) {
|
||||
// FileChannel -> SocketChannel
|
||||
if (out instanceof SocketOutputStream sos) {
|
||||
SocketChannelImpl sc = sos.channel();
|
||||
|
|
|
@ -454,6 +454,7 @@ public class FileChannelImpl
|
|||
}
|
||||
return bytesWritten;
|
||||
}
|
||||
|
||||
// -- Other operations --
|
||||
|
||||
@Override
|
||||
|
@ -529,6 +530,49 @@ public class FileChannelImpl
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an estimate of the number of remaining bytes that can be read
|
||||
* from this channel without blocking.
|
||||
*/
|
||||
int available() throws IOException {
|
||||
ensureOpen();
|
||||
synchronized (positionLock) {
|
||||
int a = -1;
|
||||
int ti = -1;
|
||||
try {
|
||||
beginBlocking();
|
||||
ti = threads.add();
|
||||
if (!isOpen())
|
||||
return -1;
|
||||
a = nd.available(fd);
|
||||
} finally {
|
||||
threads.remove(ti);
|
||||
endBlocking(a > -1);
|
||||
}
|
||||
return a;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tells whether the channel represents something other than a regular
|
||||
* file, directory, or symbolic link.
|
||||
*/
|
||||
boolean isOther() throws IOException {
|
||||
ensureOpen();
|
||||
int ti = -1;
|
||||
Boolean isOther = null;
|
||||
try {
|
||||
beginBlocking();
|
||||
ti = threads.add();
|
||||
if (!isOpen())
|
||||
return false;
|
||||
return isOther = nd.isOther(fd);
|
||||
} finally {
|
||||
threads.remove(ti);
|
||||
endBlocking(isOther != null);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public FileChannel truncate(long newSize) throws IOException {
|
||||
ensureOpen();
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2007, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2007, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
|
@ -49,6 +49,10 @@ abstract class FileDispatcher extends NativeDispatcher {
|
|||
|
||||
abstract long size(FileDescriptor fd) throws IOException;
|
||||
|
||||
abstract int available(FileDescriptor fd) throws IOException;
|
||||
|
||||
abstract boolean isOther(FileDescriptor fd) throws IOException;
|
||||
|
||||
abstract int lock(FileDescriptor fd, boolean blocking, long pos, long size,
|
||||
boolean shared) throws IOException;
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue