#include #ifndef _GNU_SOURCE #define _GNU_SOURCE #endif #include #include #include struct MyFds { int fdin; int fdout; int readpipe; int writepipe; loff_t size; MyFds(int p_fdin, int p_fdout, int p_readpipe, int p_writepipe, loff_t p_size) : fdin(p_fdin), fdout(p_fdout), readpipe(p_readpipe), writepipe(p_writepipe), size(p_size) { }; }; static void * splicecopywriter(void * threadparam) { const MyFds * fds = (const MyFds *) threadparam; std::cout << "In writer thread " << std::endl; loff_t offset = 0; size_t bytesleft = fds->size; int splices=0; while (bytesleft > 0) { splices ++; ssize_t bytes = splice(fds->readpipe, (loff_t *) 0, fds->fdout, & offset, bytesleft, 0 /* flags */ ); if (bytes == -1) { break; } bytesleft -= bytes; } int spliceerr = errno; std::cout << "writer:splices= " << splices << " errno=" << spliceerr << std::endl; std::cout << "still in writer thread " << std::endl; return (void *) 0; } static int splicecopyreader(const MyFds *fds) { loff_t offset = 0; size_t bytesleft = fds->size; int splices = 0; while (bytesleft > 0) { splices ++; ssize_t bytes = splice(fds->fdin, &offset, fds->writepipe, (loff_t *) 0, (size_t) fds->size, 0 /* flags */ ); if (bytes == -1) { break; } bytesleft -= bytes; } int spliceerr = errno; std::cout << "reader: splices=" << splices << " errno=" << spliceerr << std::endl; close(fds->writepipe); } static int splicecopypipes(const MyFds *fds) { // Main thread reads from disc and into pipe; // writerthread reads from pipe and on to disc. pthread_t writerthread; int res = pthread_create(&writerthread, (const pthread_attr_t *) 0, splicecopywriter, (void *) fds); std::cout << "In main thread" << std::endl; splicecopyreader(fds); int threadres; pthread_join(writerthread, (void **) (& threadres) ); std::cout << "Joined" << std::endl; return threadres; } static int splicecopyfd(int fdin, int fdout) { // Work out how big it is struct stat st; if (fstat(fdin, &st) != 0) { std::cerr << "Stat failed" << std::endl; return 3; } int pipes[2]; if (pipe(pipes) != 0) { std::cerr << "Pipe failed" << std::endl; return 4; } int readpipe = pipes[0]; int writepipe = pipes[1]; MyFds fds(fdin, fdout, readpipe, writepipe, st.st_size); int res = splicecopypipes(&fds); close(pipes[0]); close(pipes[1]); return res; } static int splicecopy(const char *srcfile, const char *destfile) { int fdin = open(srcfile, O_RDONLY); if (-1 == fdin) { std::cerr << "Failed to open src file" << std::endl; return 1; } int fdout = open(destfile, O_WRONLY | O_CREAT, 0644); if (-1 == fdout) { close(fdin); std::cerr << "Failed to open dest file" << std::endl; return 2; } int res = splicecopyfd(fdin, fdout); close(fdin); close(fdout); return res; } int main(int argc, const char * argv[]) { if (argc < 3) { std::cerr << "Source and destination required" << std::endl; return 1; } const char *srcfile = argv[1]; const char *destfile = argv[2]; return splicecopy(srcfile,destfile); }