472{
473 using namespace XrdCl;
474
475
476
477
481 return 50;
483
484
485
486
488 Log *log = DefaultEnv::GetLog();
489 if( config.Dlvl )
490 {
491 if( config.Dlvl == 1 ) log->
SetLevel( Log::InfoMsg );
492 else if( config.Dlvl == 2 ) log->
SetLevel( Log::DebugMsg );
493 else if( config.Dlvl == 3 ) log->
SetLevel( Log::DumpMsg );
494 }
495
499
500 bool posc = false;
501 bool force = false;
502 bool coerce = false;
503 bool makedir = false;
504 bool dynSrc = false;
505 bool delegate = false;
506 bool preserveXAttr = false;
507 bool rmOnBadCksum = false;
508 bool continue_ = false;
509 bool recurse = false;
510 bool zipappend = false;
511 bool doserver = false;
512 std::string thirdParty = "none";
513
522 {
523
524
525
526
527 DlgEnv::Instance().Enable();
528 delegate = true;
529 }
530 else
531 DlgEnv::Instance().Disable();
532
534 {
535 makedir = true;
536 recurse = true;
537 }
543
544 if( force && continue_ )
545 {
546 std::cerr << "Invalid argument combination: continue + force." << std::endl;
547 return 50;
548 }
549
550
551
552
553 std::string checkSumType;
554 std::string checkSumPreset;
555 std::string checkSumMode = "none";
557 {
558 checkSumMode = "end2end";
559 std::vector<std::string> ckSumParams;
560 Utils::splitString( ckSumParams, config.CksVal, ":" );
561 if( ckSumParams.size() > 1 )
562 {
563 if( ckSumParams[1] == "print" )
564 {
565 checkSumMode = "target";
567 }
568 else
569 checkSumPreset = ckSumParams[1];
570 }
571 checkSumType = ckSumParams[0];
572 }
573
575 {
576 checkSumMode = "source";
577 std::vector<std::string> ckSumParams;
578 Utils::splitString( ckSumParams, config.CksVal, ":" );
579 if( ckSumParams.size() == 2 )
580 {
581 checkSumMode = "source";
582 checkSumType = ckSumParams[0];
584 }
585 else
586 {
587 std::cerr << "Invalid parameter: " << config.CksVal << std::endl;
588 return 50;
589 }
590 }
591
592 if( !config.AddCksVal.empty() )
594
595
596
597
598 std::string zipFile;
599 bool zip = false;
601 {
602 zipFile = config.zipFile;
603 zip = true;
604 }
605
606
607
608
609 int nbSources = 0;
610 bool xcp = false;
612 {
613 nbSources = config.nSrcs;
614 xcp = true;
615 }
616
617
618
619
621
622
623 struct scope_exit {
625 } stopPostMaster;
626
627 if( config.nStrm != 0 )
628 env->
PutInt(
"SubStreamsPerChannel", config.nStrm + 1 );
629
630 if( config.Retry != -1 )
631 {
632 env->
PutInt(
"CpRetry", config.Retry );
633 env->
PutString(
"CpRetryPolicy", config.RetryPolicy );
634 }
635
637 env->
PutInt(
"NoTlsOK", 1 );
638
640 env->
PutInt(
"TlsNoData", 1 );
641
643 env->
PutInt(
"TlsMetalink", 1 );
644
646 env->
PutInt(
"ZipMtlnCksum", 1 );
647
649 env->
GetInt(
"CPChunkSize", chunkSize );
650
652 env->
GetInt(
"XCpBlockSize", blockSize );
653
655 env->
GetInt(
"CPParallelChunks", parallelChunks );
656 if( parallelChunks < 1 ||
657 parallelChunks > std::numeric_limits<uint8_t>::max() )
658 {
659 std::cerr << "Can only handle between 1 and ";
660 std::cerr << (int)std::numeric_limits<uint8_t>::max();
661 std::cerr << " chunks in parallel. You asked for " << parallelChunks;
662 std::cerr << "." << std::endl;
663 return 50;
664 }
665
666 if( !preserveXAttr )
667 {
669 env->
GetInt(
"PreserveXAttrs", val );
670 if( val ) preserveXAttr = true;
671 }
672
673 log->
Dump( AppMsg,
"Chunk size: %d, parallel chunks %d, streams: %d",
674 chunkSize, parallelChunks, config.nStrm + 1 );
675
676
677
678
679 std::vector<XrdCl::PropertyList*> resultVect;
680
681 std::string dest;
684 {
685 dest = "file://";
686
687
688 if( config.dstFile->Path[0] != '/' )
689 {
690 char buf[FILENAME_MAX];
691 char *cwd = getcwd( buf, FILENAME_MAX );
692 if( !cwd )
693 {
695 std::cerr << st.GetErrorMessage() << std::endl;
696 return st.GetShellCode();
697 }
698 dest += cwd;
699 dest += '/';
700 }
701 }
702 dest += config.dstFile->Path;
703
704
705
706
707
708
709
710
711 bool targetIsDir = false;
712 bool targetExists = false;
714 targetIsDir = true;
717 {
721 XRootDStatus st = fs.Stat( target.GetPathWithParams(), statInfo );
723 {
724 if( statInfo->
TestFlags( StatInfo::IsDir ) )
725 targetIsDir = true;
726 targetExists = true;
727 }
729 {
730 int n = strlen(config.dstFile->Path);
731 if( config.dstFile->Path[n-1] == '/' )
732 targetIsDir = true;
733 }
735 {
736 log->
Error( AppMsg,
"%s (destination)", st.
ToString().c_str() );
737 std::cerr << st.
ToStr() << std::endl;
739 }
740
741 delete statInfo;
742 }
743
744 if( !targetIsDir && targetExists && !force && !recurse && !zipappend )
745 {
747
748 log->
Error( AppMsg,
"%s (destination)", st.
ToString().c_str() );
749 std::cerr <<
"Run: " << st.
ToStr() << std::endl;
751 }
752
753
754
755
756
759 {
760 std::cerr << "Multiple sources were given but target is not a directory.";
761 std::cerr << std::endl;
762 return 50;
763 }
764
765
766
767
768
769 bool remoteSrcIsDir = false;
772 {
773 URL source( config.srcFile->Path );
776
779 {
780 remoteSrcIsDir = true;
781
782
783
784 delete config.srcFile;
785 std::string url = source.GetURL();
786 config.srcFile =
IndexRemote( fs, url, url.size() );
787 if ( !config.srcFile )
788 {
789 std::cerr << "Error indexing remote directory.";
790 return 50;
791 }
792 }
793
794 delete fs;
795 delete statInfo;
796 }
797
799
800
801
802 while( sourceFile )
803 {
805
806
807
808
811 std::string source = sourceFile->
Path;
813 {
814
815 if( source[0] == '/' )
816 source = "file://" + source;
817 else
818 {
819 char buf[FILENAME_MAX];
820 char *cwd = getcwd( buf, FILENAME_MAX );
821 if( !cwd )
822 {
826 }
827 source = "file://" + std::string( cwd ) + '/' + source;
828 }
829 }
830
832
833 std::string sourcePathObf = sourceFile->
Path;
834 std::string destPathObf = dest;
838 }
839 log->
Dump( AppMsg,
"Processing source entry: %s, type %s, target file: %s, logLevel = %d",
841 destPathObf.c_str(), log->
GetLevel() );
842
843
844
845
846 std::string target = dest;
847
848
849 bool srcIsDir = false;
850
851 if( strncmp( sourceFile->
ProtName,
"file", 4 ) == 0 )
852 srcIsDir = std::string( sourceFile->
Path ).size() == size_t( sourceFile->
Doff + sourceFile->
Dlen );
853
854 else
855 srcIsDir = remoteSrcIsDir;
856
858 {
859
860 std::string srcDir( sourceFile->
Path, sourceFile->
Doff );
861
862 if( srcDir[srcDir.size() - 1] == '/' )
863 srcDir = srcDir.substr( 0, srcDir.size() - 1 );
864 size_t diroff = srcDir.rfind( '/' );
865
866 if( diroff == std::string::npos ) diroff = 0;
867 target += '/';
868 target += sourceFile->
Path + diroff;
869
870 target = target.substr( 0 , target.rfind('/') );
871 }
873
874 properties.
Set(
"source", source );
875 properties.
Set(
"target", target );
876 properties.
Set(
"force", force );
877 properties.
Set(
"posc", posc );
878 properties.
Set(
"coerce", coerce );
879 properties.
Set(
"makeDir", makedir );
880 properties.
Set(
"dynamicSource", dynSrc );
881 properties.
Set(
"thirdParty", thirdParty );
882 properties.
Set(
"checkSumMode", checkSumMode );
883 properties.
Set(
"checkSumType", checkSumType );
884 properties.
Set(
"checkSumPreset", checkSumPreset );
885 properties.
Set(
"chunkSize", chunkSize );
886 properties.
Set(
"parallelChunks", parallelChunks );
887 properties.
Set(
"zipArchive", zip );
888 properties.
Set(
"xcp", xcp );
889 properties.
Set(
"xcpBlockSize", blockSize );
890 properties.
Set(
"delegate", delegate );
891 properties.
Set(
"targetIsDir", targetIsDir );
892 properties.
Set(
"preserveXAttr", preserveXAttr );
893 properties.
Set(
"xrate", config.xRate );
894 properties.
Set(
"xrateThreshold", config.xRateThreshold );
895 properties.
Set(
"rmOnBadCksum", rmOnBadCksum );
896 properties.
Set(
"continue", continue_ );
897 properties.
Set(
"zipAppend", zipappend );
898 properties.
Set(
"addcksums", config.AddCksVal );
899 properties.
Set(
"doServer", doserver );
900
901 if( zip )
902 properties.
Set(
"zipSource", zipFile );
903
904 if( xcp )
905 properties.
Set(
"nbXcpSources", nbSources );
906
907
910 {
911 std::cerr << "AddJob " << source << " -> " << target << ": ";
912 std::cerr << st.
ToStr() << std::endl;
913 }
914 resultVect.push_back( results );
915 sourceFile = sourceFile->
Next;
916 }
917
918
919
920
922 processConfig.
Set(
"jobType",
"configuration" );
923 processConfig.
Set(
"parallel", config.Parallel );
924 process.
AddJob( processConfig, 0 );
925
926
927
928
931 {
933 std::cerr <<
"Prepare: " << st.
ToStr() << std::endl;
935 }
936
937 st = process.
Run( &progress );
939 {
940 if( resultVect.size() == 1 )
941 std::cerr <<
"Run: " << st.
ToStr() << std::endl;
942 else
943 {
944 std::vector<XrdCl::PropertyList*>::iterator it;
945 uint16_t i = 1;
946 uint16_t jobsRun = 0;
947 uint16_t errors = 0;
948 for( it = resultVect.begin(); it != resultVect.end(); ++it, ++i )
949 {
950 if( !(*it)->HasProperty( "status" ) )
951 continue;
952
955 {
956 std::cerr <<
"Job #" << i <<
": " << st.
ToStr();
957 ++errors;
958 }
959 ++jobsRun;
960 }
961 std::cerr << "Jobs total: " << resultVect.size();
962 std::cerr << ", run: " << jobsRun;
963 std::cerr << ", errors: " << errors << std::endl;
964 }
967 }
969 return 0;
970}
bool AllOptionsSupported(XrdCpConfig *config)
const char * FileType2String(XrdCpFile::PType type)
void ProcessCommandLineEnv(XrdCpConfig *config)
void CleanUpResults(std::vector< XrdCl::PropertyList * > &results)
XrdCpFile * IndexRemote(XrdCl::FileSystem *fs, std::string basePath, long dirOffset)
void AdjustFileInfo(XrdCpFile *file)
uint32_t CountSources(XrdCpFile *file)
void AppendCGI(std::string &url, const char *newCGI)
std::string obfuscateAuth(const std::string &input)
void PrintAdditionalCheckSum(bool print)
void PrintSourceCheckSum(bool print)
void PrintProgressBar(bool print)
void PrintTargetCheckSum(bool print)
static int mapError(int rc)
Copy the data from one point to another.
XRootDStatus Run(CopyProgressHandler *handler)
Run the copy jobs.
XRootDStatus AddJob(const PropertyList &properties, PropertyList *results)
static PostMaster * GetPostMaster()
Get default post master.
static Env * GetEnv()
Get default client environment.
bool PutInt(const std::string &key, int value)
bool PutString(const std::string &key, const std::string &value)
bool GetInt(const std::string &key, int &value)
Send file/filesystem queries to an XRootD cluster.
XRootDStatus Stat(const std::string &path, ResponseHandler *handler, uint16_t timeout=0) XRD_WARN_UNUSED_RESULT
void SetLevel(LogLevel level)
Set the level of the messages that should be sent to the destination.
LogLevel GetLevel() const
Get the log level.
void Dump(uint64_t topic, const char *format,...)
Print a dump message.
bool Stop()
Stop the postmaster.
A key-value pair map storing both keys and values as strings.
void Set(const std::string &name, const Item &value)
std::string ToStr() const
Convert to string.
const int DefaultCPChunkSize
const int DefaultCPParallelChunks
const int DefaultXCpBlockSize
const int DefaultPreserveXAttrs
std::string ToString() const
Create a string representation.
uint32_t errNo
Errno, if any.
int GetShellCode() const
Get the status code that may be returned to the shell.
static const uint64_t DoZipMtlnCksum
static const uint64_t DoNoPbar
static const uint64_t DoCoerce
static const uint64_t DoForce
static const uint64_t DoRmOnBadCksum
static const uint64_t DoNoTlsOK
static const uint64_t DoTpc
static const uint64_t DoCksum
static const uint64_t DoCksrc
static const uint64_t DoTpcDlgt
static const uint64_t DoZip
static const uint64_t DoContinue
static const uint64_t DoRecurse
static const uint64_t DoZipAppend
static const uint64_t DoDynaSrc
static const uint64_t DoSources
static const uint64_t DoXAttr
static const uint64_t DoTlsMLF
static const int optRmtRec
static const uint64_t DoPath
static const uint64_t DoPosc
static const uint64_t DoTpcOnly
static const uint64_t DoTlsNoData
static const uint64_t DoServer