Use sendfile if EXDEV received from rename call

master
Am1GO 2014-09-29 14:21:30 +04:00
parent 7c2205a3e0
commit a761c0078a
1 changed files with 34 additions and 2 deletions

36
file.cc
View File

@ -7,6 +7,10 @@
#include <cerrno>
#include <cstring>
#include <sys/sendfile.h>
#include <sys/types.h>
#include <fcntl.h>
#include "file.hh"
enum
@ -38,8 +42,36 @@ void File::erase( std::string const & filename ) throw( exCantErase )
void File::rename( std::string const & from,
std::string const & to ) throw( exCantRename )
{
if ( ::rename( from.c_str(), to.c_str() ) != 0 )
throw exCantRename( from + " to " + to );
int res = 0;
res = ::rename( from.c_str(), to.c_str() );
if ( 0 != res )
{
if ( EXDEV == errno )
{
int read_fd;
int write_fd;
struct stat stat_buf;
off_t offset = 0;
/* Open the input file. */
read_fd = ::open( from.c_str(), O_RDONLY );
/* Stat the input file to obtain its size. */
fstat( read_fd, &stat_buf );
/* Open the output file for writing, with the same permissions as the
source file. */
write_fd = ::open( to.c_str(), O_WRONLY | O_CREAT, stat_buf.st_mode );
/* Blast the bytes from one file to the other. */
if ( -1 == sendfile(write_fd, read_fd, &offset, stat_buf.st_size) )
throw exCantRename( from + " to " + to );
/* Close up. */
::close( read_fd );
::close( write_fd );
File::erase ( from );
}
else
throw exCantRename( from + " to " + to );
}
}
void File::open( char const * filename, OpenMode mode ) throw( exCantOpen )