8325382: (fc) FileChannel.transferTo throws IOException when position equals size

Reviewed-by: alanb
This commit is contained in:
Brian Burkhalter 2024-02-13 15:53:29 +00:00
parent 13d9e8ff38
commit 6b7c9718d6
2 changed files with 41 additions and 14 deletions

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2000, 2023, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2000, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -857,20 +857,18 @@ public class FileChannelImpl
if (position > sz) if (position > sz)
return 0; return 0;
// Now position <= sz so remaining >= 0 and
// remaining == 0 if and only if sz == 0
long remaining = sz - position;
// Adjust count only if remaining > 0, i.e.,
// sz > position which means sz > 0
if (remaining > 0 && remaining < count)
count = remaining;
// System calls supporting fast transfers might not work on files // System calls supporting fast transfers might not work on files
// which advertise zero size such as those in Linux /proc // which advertise zero size such as those in Linux /proc
if (sz > 0) { if (sz > 0) {
// Attempt a direct transfer, if the kernel supports it, limiting // Now sz > 0 and position <= sz so remaining >= 0 and
// the number of bytes according to which platform // remaining == 0 if and only if sz == position
long remaining = sz - position;
if (remaining >= 0 && remaining < count)
count = remaining;
// Attempt a direct transfer, if the kernel supports it,
// limiting the number of bytes according to which platform
int icount = (int) Math.min(count, nd.maxDirectTransferSize()); int icount = (int) Math.min(count, nd.maxDirectTransferSize());
long n; long n;
if ((n = transferToDirect(position, icount, target)) >= 0) if ((n = transferToDirect(position, icount, target)) >= 0)

View file

@ -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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -22,7 +22,7 @@
*/ */
/* @test /* @test
* @bug 4434723 4482726 4559072 4795550 5081340 5103988 6984545 * @bug 4434723 4482726 4559072 4795550 5081340 5103988 6984545 8325382
* @summary Test FileChannel.transferFrom and transferTo (use -Dseed=X to set PRNG seed) * @summary Test FileChannel.transferFrom and transferTo (use -Dseed=X to set PRNG seed)
* @library .. * @library ..
* @library /test/lib * @library /test/lib
@ -48,11 +48,13 @@ import java.nio.channels.Pipe;
import java.nio.channels.ServerSocketChannel; import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel; import java.nio.channels.SocketChannel;
import java.nio.channels.spi.SelectorProvider; import java.nio.channels.spi.SelectorProvider;
import java.nio.file.Files;
import java.util.Random; import java.util.Random;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import jdk.test.lib.RandomFactory; import jdk.test.lib.RandomFactory;
import org.testng.Assert;
import org.testng.annotations.Test; import org.testng.annotations.Test;
public class Transfer { public class Transfer {
@ -158,6 +160,33 @@ public class Transfer {
} }
} }
@Test
public void transferToNoThrow() throws IOException { // for bug 8325382
File source = File.createTempFile("before", "after");
source.deleteOnExit();
CharSequence csq = "Reality is greater than the sum of its parts.";
Files.writeString(source.toPath(), csq);
final long length = csq.length();
Assert.assertEquals(source.length(), length);
File target = File.createTempFile("before", "after");
target.deleteOnExit();
try (FileInputStream in = new FileInputStream(source);
FileOutputStream out = new FileOutputStream(target);
FileChannel chSource = in.getChannel();
FileChannel chTarget = out.getChannel()) {
// The count of bytes requested to transfer must exceed
// FileChannelImpl.MAPPED_TRANSFER_THRESHOLD which is
// currently 16384
long n = chSource.transferTo(length, 16385, chTarget);
// At the end of the input so no bytes should be transferred
Assert.assertEquals(n, 0);
}
}
@Test @Test
public void xferTest02() throws Exception { // for bug 4482726 public void xferTest02() throws Exception { // for bug 4482726
byte[] srcData = new byte[5000]; byte[] srcData = new byte[5000];