Skip to content
This repository has been archived by the owner on Mar 5, 2021. It is now read-only.

Commit

Permalink
#96: Possible fix for truncated files
Browse files Browse the repository at this point in the history
Actually the transferTo method must be called in a loop as it seems not
to be guaranteed that all content is transferred in one call.
  • Loading branch information
ctron committed Apr 6, 2017
1 parent 28dc5eb commit 19c3360
Showing 1 changed file with 60 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
*
* Contributors:
* IBH SYSTEMS GmbH - initial API and implementation
* Red Hat Inc - fix issue #96
*******************************************************************************/
package org.eclipse.packagedrone.utils.rpm.build;

Expand Down Expand Up @@ -97,7 +98,7 @@ private void checkNotFinished ()
}
}

private void debug ( final String fmt, final Object... args )
private static void debug ( final String fmt, final Object... args )
{
logger.debug ( String.format ( fmt, args ) );
}
Expand Down Expand Up @@ -219,7 +220,7 @@ private void finish () throws IOException

// set signature data

final Header<RpmSignatureTag> signature = new Header<RpmSignatureTag> ();
final Header<RpmSignatureTag> signature = new Header<> ();

// process signatures

Expand All @@ -244,9 +245,9 @@ private void finish () throws IOException

try ( ReadableByteChannel payloadChannel = this.payloadProvider.openChannel () )
{
if ( payloadChannel instanceof FileChannel )
if ( payloadChannel instanceof FileChannel && !isForceCopy () )
{
final long count = ( (FileChannel)payloadChannel ).transferTo ( 0, Long.MAX_VALUE, this.file );
final long count = copyFileChannel ( (FileChannel)payloadChannel, this.file );
debug ( "transfered - %s", count );
}
else
Expand All @@ -259,6 +260,61 @@ private void finish () throws IOException
debug ( "end - offset: %s", this.file.position () );
}

/**
* Check of in-JVM copy should be forced over
* {@link FileChannel#transferTo(long, long, java.nio.channels.WritableByteChannel)}
*
* @return {@code true} if copying should be forced, {@code false}
* otherwise. Defaults to {@code false}.
*/
private static boolean isForceCopy ()
{
return Boolean.getBoolean ( "org.eclipse.packagedrone.utils.rpm.build.RpmWriter.forceCopy" );
}

private static long copyFileChannel ( final FileChannel fileChannel, final FileChannel file ) throws IOException
{
long remaning = fileChannel.size ();
long position = 0;

while ( remaning > 0 )
{
// transfer next chunk

final long rc = fileChannel.transferTo ( position, remaning, file );

// check for negative result

if ( rc < 0 )
{
throw new IOException ( String.format ( "Failed to transfer bytes: rc = %s", rc ) );
}

debug ( "transferTo - position: %s, size: %s => rc: %s", position, remaning, rc );

// we should never get zero back, but check anyway

if ( rc == 0 )
{
break;
}

// update state

position += rc;
remaning -= rc;
}

// final check if we got it all

if ( remaning > 0 )
{
throw new IOException ( "Failed to transfer full content" );
}

return position;
}

private void processSignatures ( final Header<RpmSignatureTag> signature ) throws IOException
{
// init
Expand Down

0 comments on commit 19c3360

Please sign in to comment.