2008-01-10 16:27:52 +03:00
/*
* Unix SMB / CIFS implementation .
* Utility functions to transfer files .
*
* Copyright ( C ) Jeremy Allison 2001 - 2002
* Copyright ( C ) Michael Adam 2008
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation ; either version 3 of the License , or
* ( at your option ) any later version .
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License
* along with this program . If not , see < http : //www.gnu.org/licenses/>.
*/
# include <includes.h>
2011-02-26 02:56:46 +03:00
# include "transfer_file.h"
2015-10-12 16:57:34 +03:00
# include "lib/util/sys_rw.h"
2008-01-10 16:27:52 +03:00
/****************************************************************************
Transfer some data between two fd ' s .
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
# ifndef TRANSFER_BUF_SIZE
# define TRANSFER_BUF_SIZE 65536
# endif
ssize_t transfer_file_internal ( void * in_file ,
void * out_file ,
size_t n ,
2015-04-27 13:16:16 +03:00
ssize_t ( * pread_fn ) ( void * , void * , size_t , off_t ) ,
ssize_t ( * pwrite_fn ) ( void * , const void * , size_t , off_t ) )
2008-01-10 16:27:52 +03:00
{
char * buf ;
size_t total = 0 ;
ssize_t read_ret ;
ssize_t write_ret ;
size_t num_to_read_thistime ;
size_t num_written = 0 ;
2015-04-27 13:16:16 +03:00
off_t offset = 0 ;
2008-01-10 16:27:52 +03:00
2012-12-18 20:21:14 +04:00
if ( n = = 0 ) {
return 0 ;
}
2008-01-10 16:27:52 +03:00
if ( ( buf = SMB_MALLOC_ARRAY ( char , TRANSFER_BUF_SIZE ) ) = = NULL ) {
return - 1 ;
}
2012-12-18 20:21:14 +04:00
do {
2008-01-10 16:27:52 +03:00
num_to_read_thistime = MIN ( ( n - total ) , TRANSFER_BUF_SIZE ) ;
2015-04-27 13:16:16 +03:00
read_ret = ( * pread_fn ) ( in_file , buf , num_to_read_thistime , offset ) ;
2008-01-10 16:27:52 +03:00
if ( read_ret = = - 1 ) {
DEBUG ( 0 , ( " transfer_file_internal: read failure. "
" Error = %s \n " , strerror ( errno ) ) ) ;
SAFE_FREE ( buf ) ;
return - 1 ;
}
if ( read_ret = = 0 ) {
break ;
}
num_written = 0 ;
while ( num_written < read_ret ) {
2015-04-27 13:16:16 +03:00
write_ret = ( * pwrite_fn ) ( out_file , buf + num_written ,
read_ret - num_written ,
offset + num_written ) ;
2008-01-10 16:27:52 +03:00
if ( write_ret = = - 1 ) {
DEBUG ( 0 , ( " transfer_file_internal: "
" write failure. Error = %s \n " ,
strerror ( errno ) ) ) ;
SAFE_FREE ( buf ) ;
return - 1 ;
}
if ( write_ret = = 0 ) {
return ( ssize_t ) total ;
}
num_written + = ( size_t ) write_ret ;
}
total + = ( size_t ) read_ret ;
2015-04-27 13:16:16 +03:00
offset + = ( off_t ) read_ret ;
2012-12-18 20:21:14 +04:00
} while ( total < n ) ;
2008-01-10 16:27:52 +03:00
SAFE_FREE ( buf ) ;
return ( ssize_t ) total ;
}
2015-04-27 13:16:16 +03:00
static ssize_t sys_pread_fn ( void * file , void * buf , size_t len , off_t offset )
2008-01-10 16:27:52 +03:00
{
int * fd = ( int * ) file ;
2015-04-27 13:16:16 +03:00
return sys_pread ( * fd , buf , len , offset ) ;
2008-01-10 16:27:52 +03:00
}
2015-04-27 13:16:16 +03:00
static ssize_t sys_pwrite_fn ( void * file , const void * buf , size_t len , off_t offset )
2008-01-10 16:27:52 +03:00
{
int * fd = ( int * ) file ;
2015-04-27 13:16:16 +03:00
return sys_pwrite ( * fd , buf , len , offset ) ;
2008-01-10 16:27:52 +03:00
}
2012-04-05 08:53:08 +04:00
off_t transfer_file ( int infd , int outfd , off_t n )
2008-01-10 16:27:52 +03:00
{
2012-04-05 08:53:08 +04:00
return ( off_t ) transfer_file_internal ( & infd , & outfd , ( size_t ) n ,
2015-04-27 13:16:16 +03:00
sys_pread_fn , sys_pwrite_fn ) ;
2008-01-10 16:27:52 +03:00
}