Skip to content

Commit

Permalink
Fix unhandled UnsupportedOperationException in Fallocate
Browse files Browse the repository at this point in the history
  • Loading branch information
torusrxxx committed Nov 30, 2024
1 parent ed64823 commit c6f7e9b
Showing 1 changed file with 35 additions and 15 deletions.
50 changes: 35 additions & 15 deletions src/freenet/support/io/Fallocate.java
Original file line number Diff line number Diff line change
Expand Up @@ -38,49 +38,69 @@ private Fallocate(FileChannel channel, int fd, long final_filesize) {
}

public static Fallocate forChannel(FileChannel channel, long final_filesize) {
return new Fallocate(channel, getDescriptor(channel), final_filesize);
try {
return new Fallocate(channel, getDescriptor(channel), final_filesize);
} catch (final UnsupportedOperationException exception) {
// File descriptor is not supported: fd is null and unavailable
return new Fallocate(channel, 0, final_filesize);
}
}

public static Fallocate forChannel(FileChannel channel, FileDescriptor fd, long final_filesize) {
return new Fallocate(channel, getDescriptor(fd), final_filesize);
try {
return new Fallocate(channel, getDescriptor(fd), final_filesize);
} catch (final UnsupportedOperationException exception) {
// File descriptor is not supported: fd is null and unavailable
return new Fallocate(channel, 0, final_filesize);
}
}

public Fallocate fromOffset(long offset) {
public Fallocate fromOffset(long offset) throws IllegalArgumentException {
if(offset < 0 || offset > final_filesize) throw new IllegalArgumentException();
this.offset = offset;
return this;
}

public Fallocate keepSize() {
public Fallocate keepSize() throws UnsupportedOperationException {
requireLinux("fallocate keep size");
mode |= FALLOC_FL_KEEP_SIZE;
return this;
}

private void requireLinux(String feature) {
private void requireLinux(String feature) throws UnsupportedOperationException {
if (!IS_LINUX) {
throwUnsupported(feature);
}
}

private void throwUnsupported(String feature) {
private void throwUnsupported(String feature) throws UnsupportedOperationException {
throw new UnsupportedOperationException(feature + " is not supported on this file system");
}

public void execute() throws IOException {
int errno = 0;
boolean isUnsupported = false;
if (IS_LINUX) {
final int result = FallocateHolder.fallocate(fd, mode, offset, final_filesize-offset);
errno = result == 0 ? 0 : Native.getLastError();
} else if (IS_POSIX) {
errno = FallocateHolderPOSIX.posix_fallocate(fd, offset, final_filesize-offset);
if (fd != 0) {
if (IS_LINUX) {
final int result = FallocateHolder.fallocate(fd, mode, offset, final_filesize-offset);
errno = result == 0 ? 0 : Native.getLastError();
} else if (IS_POSIX) {
errno = FallocateHolderPOSIX.posix_fallocate(fd, offset, final_filesize-offset);
} else {
isUnsupported = true;
}
} else {
isUnsupported = true;
// fd is null and unavailable
if (Platform.isWindows()) {
// Windows do not create sparse files by default, so just write a byte at the end.
channel.write(ByteBuffer.allocate(1), final_filesize - 1);
} else {
isUnsupported = true;
}
}

if (isUnsupported || errno != 0) {
Logger.normal(this, "fallocate() failed; using legacy method; errno="+errno);
Logger.normal(this, "fallocate() failed; using legacy method; errno=" + errno);
legacyFill(channel, final_filesize, offset);
}
}
Expand All @@ -101,7 +121,7 @@ private static class FallocateHolderPOSIX {
private static native int posix_fallocate(int fd, long offset, long length);
}

private static int getDescriptor(FileChannel channel) {
private static int getDescriptor(FileChannel channel) throws UnsupportedOperationException {
try {
// sun.nio.ch.FileChannelImpl declares private final java.io.FileDescriptor fd
final Field field = channel.getClass().getDeclaredField("fd");
Expand All @@ -112,7 +132,7 @@ private static int getDescriptor(FileChannel channel) {
}
}

private static int getDescriptor(FileDescriptor descriptor) {
private static int getDescriptor(FileDescriptor descriptor) throws UnsupportedOperationException {
try {
// Oracle java.io.FileDescriptor declares private int fd
final Field field = descriptor.getClass().getDeclaredField(IS_ANDROID ? "descriptor" : "fd");
Expand Down

0 comments on commit c6f7e9b

Please sign in to comment.