Skip to content

Commit

Permalink
8325382: (fc) FileChannel.transferTo throws IOException when position…
Browse files Browse the repository at this point in the history
… equals size

Reviewed-by: bpb
Backport-of: 6b7c9718d68f30f47a163042d6e205945b9ff365
  • Loading branch information
TheRealMDoerr committed Jun 3, 2024
1 parent 88c366c commit e4ac1a4
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 14 deletions.
22 changes: 10 additions & 12 deletions src/java.base/share/classes/sun/nio/ch/FileChannelImpl.java
Original file line number Diff line number Diff line change
@@ -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.
*
* This code is free software; you can redistribute it and/or modify it
Expand Down Expand Up @@ -759,20 +759,18 @@ public long transferTo(long position, long count,
if (position > sz)
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
// which advertise zero size such as those in Linux /proc
if (sz > 0) {
// Attempt a direct transfer, if the kernel supports it, limiting
// the number of bytes according to which platform
// Now sz > 0 and position <= sz so remaining >= 0 and
// 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());
long n;
if ((n = transferToDirectly(position, icount, target)) >= 0)
Expand Down
33 changes: 31 additions & 2 deletions test/jdk/java/nio/channels/FileChannel/Transfer.java
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -22,7 +22,7 @@
*/

/* @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)
* @library ..
* @library /test/lib
Expand All @@ -48,11 +48,13 @@
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.nio.channels.spi.SelectorProvider;
import java.nio.file.Files;
import java.util.Random;
import java.util.concurrent.TimeUnit;

import jdk.test.lib.RandomFactory;

import org.testng.Assert;
import org.testng.annotations.Test;

public class Transfer {
Expand Down Expand Up @@ -158,6 +160,33 @@ public void testReadableByteChannel() throws Exception {
}
}

@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
public void xferTest02() throws Exception { // for bug 4482726
byte[] srcData = new byte[5000];
Expand Down

1 comment on commit e4ac1a4

@openjdk-notifier
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.