486{
487 using namespace XrdCl;
488
489
490
491
495 return 50;
497
498
499
500
503 if( config.Dlvl )
504 {
508 }
509
513
514 bool posc = false;
515 bool force = false;
516 bool coerce = false;
517 bool makedir = false;
518 bool dynSrc = false;
519 bool delegate = false;
520 bool preserveXAttr = false;
521 bool rmOnBadCksum = false;
522 bool continue_ = false;
523 bool zipappend = false;
524 bool doserver = false;
525 std::string thirdParty = "none"s;
526 std::string thirdPartyMode = "pull"s;
527
528 const std::string thirdPartyTokenFile = config.tcpTokenFile ? config.tcpTokenFile : ""s;
529
539 {
540
541
542
543
545 delegate = true;
546 }
547 else
549
556
557 if( force && continue_ )
558 {
559 std::cerr << "Invalid argument combination: continue + force." << std::endl;
560 return 50;
561 }
562
563
564
565
566 std::string checkSumType;
567 std::string checkSumPreset;
568 std::string checkSumMode = "none";
570 {
571 checkSumMode = "end2end";
572 std::vector<std::string> ckSumParams;
574 if( ckSumParams.size() > 1 )
575 {
576 if( ckSumParams[1] == "print" )
577 {
578 checkSumMode = "target";
580 }
581 else
582 checkSumPreset = ckSumParams[1];
583 }
584 checkSumType = ckSumParams[0];
585 }
586
588 {
589 checkSumMode = "source";
590 std::vector<std::string> ckSumParams;
592 if( ckSumParams.size() == 2 )
593 {
594 checkSumMode = "source";
595 checkSumType = ckSumParams[0];
597 }
598 else
599 {
600 std::cerr << "Invalid parameter: " << config.CksVal << std::endl;
601 return 50;
602 }
603 }
604
605 if( !config.AddCksVal.empty() )
607
608
609
610
611 std::string zipFile;
612 bool zip = false;
614 {
615 zipFile = config.zipFile;
616 zip = true;
617 }
618
619
620
621
622 int nbSources = 0;
623 bool xcp = false;
625 {
626 nbSources = config.nSrcs;
627 xcp = true;
628 }
629
630
631
632
634
635
636 struct scope_exit {
638 } stopPostMaster;
639
640 if( config.nStrm != 0 )
641 env->
PutInt(
"SubStreamsPerChannel", config.nStrm + 1 );
642
643 if( config.Retry != -1 )
644 {
645 env->
PutInt(
"CpRetry", config.Retry );
646 env->
PutString(
"CpRetryPolicy", config.RetryPolicy );
647 }
648
650 env->
PutInt(
"NoTlsOK", 1 );
651
653 env->
PutInt(
"TlsNoData", 1 );
654
656 env->
PutInt(
"TlsMetalink", 1 );
657
659 env->
PutInt(
"ZipMtlnCksum", 1 );
660
661
662
663
664
665
666 if( !config.HttpHeaders.empty() )
667 {
668 std::string headers;
669 for( auto &header : config.HttpHeaders )
670 {
671 if( !headers.empty() ) headers += '\n';
672 headers += header;
673 }
674 env->
PutString(
"HttpHeaders", headers );
675 }
676
678 env->
GetInt(
"CPChunkSize", chunkSize );
679
681 env->
GetInt(
"XCpBlockSize", blockSize );
682
684 env->
GetInt(
"CPParallelChunks", parallelChunks );
685 if( parallelChunks < 1 ||
686 parallelChunks > std::numeric_limits<uint8_t>::max() )
687 {
688 std::cerr << "Can only handle between 1 and ";
689 std::cerr << (int)std::numeric_limits<uint8_t>::max();
690 std::cerr << " chunks in parallel. You asked for " << parallelChunks;
691 std::cerr << "." << std::endl;
692 return 50;
693 }
694
695 if( !preserveXAttr )
696 {
698 env->
GetInt(
"PreserveXAttrs", val );
699 if( val ) preserveXAttr = true;
700 }
701
702 log->
Dump(
AppMsg,
"Chunk size: %d, parallel chunks %d, streams: %d",
703 chunkSize, parallelChunks, config.nStrm + 1 );
704
705
706
707
708 std::vector<XrdCl::PropertyList*> resultVect;
709
710 std::string dest;
713 {
714 dest = "file://";
715
716
717 if( config.dstFile->Path[0] != '/' )
718 {
719 char buf[FILENAME_MAX];
720 char *cwd = getcwd( buf, FILENAME_MAX );
721 if( !cwd )
722 {
724 std::cerr << st.GetErrorMessage() << std::endl;
725 return st.GetShellCode();
726 }
727 dest += cwd;
728 dest += '/';
729 }
730 }
731 dest += config.dstFile->Path;
732
733
734
735
736
737
739 if( !targetIsDir &&
745 {
747 const std::string path = target.GetPath();
748 if( !path.empty() )
749 targetIsDir = path.back() == '/';
750 else
751 {
752 const std::string spec = config.dstFile->Path;
753 const size_t query = spec.find( '?' );
754 const size_t end = query == std::string::npos ? spec.size() : query;
755 targetIsDir = end > 0 && spec[end - 1] == '/';
756 }
757 }
758
759
760
762 {
763 for(
XrdCpFile *file = config.srcFile; file; file = file->
Next )
764 {
765 if( strncmp( file->ProtName, "file", 4 ) == 0 &&
766 std::string( file->Path ).size() == size_t( file->Doff + file->Dlen ) )
767 {
768 targetIsDir = true;
769 break;
770 }
771 }
772 }
773
774
775
776
777 if( !targetIsDir &&
780 {
782 FileSystem fs( target );
784 XRootDStatus st = fs.Stat( target.GetPathWithParams(), statInfo );
786 targetIsDir = true;
788 {
790 std::cerr << st.
ToStr() << std::endl;
791 delete statInfo;
793 }
794 delete statInfo;
795 }
796
797
798
799
800
803 {
804 std::cerr << "Multiple sources were given but target is not a directory.";
805 std::cerr << std::endl;
806 return 50;
807 }
808
809
810
811
812
813 bool remoteSrcIsDir = false;
817 {
818 URL source( config.srcFile->Path );
819 FileSystem *fs = new FileSystem( source );
821
822 XRootDStatus st = fs->Stat( source.GetPath(), statInfo );
824 {
825 remoteSrcIsDir = true;
826
827 targetIsDir = true;
828
829
830
831 delete config.srcFile;
832 std::string url = source.GetURL();
833 config.srcFile =
IndexRemote( fs, url, url.size() );
834 if ( !config.srcFile )
835 {
836 std::cerr << "Error indexing remote directory.";
837 return 50;
838 }
839 }
840
841 delete fs;
842 delete statInfo;
843 }
844
846
847
848
849 while( sourceFile )
850 {
852
853
854
855
858 std::string source = sourceFile->
Path;
860 {
861
862 if( source[0] == '/' )
863 source = "file://" + source;
864 else
865 {
866 char buf[FILENAME_MAX];
867 char *cwd = getcwd( buf, FILENAME_MAX );
868 if( !cwd )
869 {
873 }
874 source = "file://" + std::string( cwd ) + '/' + source;
875 }
876 }
877
879
880 std::string sourcePathObf = sourceFile->
Path;
881 std::string destPathObf = dest;
885 }
886 log->
Dump(
AppMsg,
"Processing source entry: %s, type %s, target file: %s, logLevel = %d",
888 destPathObf.c_str(), log->
GetLevel() );
889
890
891
892
893 std::string target = dest;
894
895
896 bool srcIsDir = false;
897
898 if( strncmp( sourceFile->
ProtName,
"file", 4 ) == 0 )
899 srcIsDir = std::string( sourceFile->
Path ).size() == size_t( sourceFile->
Doff + sourceFile->
Dlen );
900
901 else
902 srcIsDir = remoteSrcIsDir;
903
905 {
906
907 std::string srcDir( sourceFile->
Path, sourceFile->
Doff );
908
909 if( !srcDir.empty() && srcDir.back() == '/' )
910 srcDir.pop_back();
911 size_t diroff = srcDir.rfind( '/' );
912
913
914
915 if( diroff == std::string::npos )
916 diroff = 0;
917 else
918 ++diroff;
919 if( target.empty() || target.back() != '/' )
920 target += '/';
921 target += sourceFile->
Path + diroff;
922
923 target = target.substr( 0 , target.rfind('/') );
924 }
926
927 properties.
Set(
"source", source );
928 properties.
Set(
"target", target );
929 properties.
Set(
"force", force );
930 properties.
Set(
"posc", posc );
931 properties.
Set(
"coerce", coerce );
932 properties.
Set(
"makeDir", makedir );
933 properties.
Set(
"dynamicSource", dynSrc );
934 properties.
Set(
"thirdParty", thirdParty );
935 properties.
Set(
"thirdPartyMode", thirdPartyMode );
936 properties.
Set(
"checkSumMode", checkSumMode );
937 properties.
Set(
"checkSumType", checkSumType );
938 properties.
Set(
"checkSumPreset", checkSumPreset );
939 properties.
Set(
"chunkSize", chunkSize );
940 properties.
Set(
"parallelChunks", parallelChunks );
941 properties.
Set(
"zipArchive", zip );
942 properties.
Set(
"xcp", xcp );
943 properties.
Set(
"xcpBlockSize", blockSize );
944 properties.
Set(
"delegate", delegate );
945 properties.
Set(
"targetIsDir", targetIsDir );
946 properties.
Set(
"preserveXAttr", preserveXAttr );
947 properties.
Set(
"xrate", config.xRate );
948 properties.
Set(
"xrateThreshold", config.xRateThreshold );
949 properties.
Set(
"rmOnBadCksum", rmOnBadCksum );
950 properties.
Set(
"continue", continue_ );
951 properties.
Set(
"zipAppend", zipappend );
952 properties.
Set(
"addcksums", config.AddCksVal );
953 properties.
Set(
"doServer", doserver );
954
955 if( zip )
956 properties.
Set(
"zipSource", zipFile );
957
958 if( xcp )
959 properties.
Set(
"nbXcpSources", nbSources );
960
961 if( !thirdPartyTokenFile.empty() )
962 properties.
Set(
"thirdPartyTokenFile", thirdPartyTokenFile );
963
966 {
967 std::cerr << "AddJob " << source << " -> " << target << ": ";
968 std::cerr << st.
ToStr() << std::endl;
969 }
970 resultVect.push_back( results );
971 sourceFile = sourceFile->
Next;
972 }
973
974
975
976
978 processConfig.
Set(
"jobType",
"configuration" );
979 processConfig.
Set(
"parallel", config.Parallel );
980 process.
AddJob( processConfig, 0 );
981
982
983
984
987 {
989 std::cerr <<
"Prepare: " << st.
ToStr() << std::endl;
991 }
992
993 st = process.
Run( &progress );
995 {
996 if( resultVect.size() == 1 )
997 std::cerr <<
"Run: " << st.
ToStr() << std::endl;
998 else
999 {
1000 std::vector<XrdCl::PropertyList*>::iterator it;
1001 uint32_t i = 1;
1002 uint32_t jobsRun = 0;
1003 uint32_t errors = 0;
1004 for( it = resultVect.begin(); it != resultVect.end(); ++it, ++i )
1005 {
1006 if( !(*it)->HasProperty( "status" ) )
1007 continue;
1008
1011 {
1012 std::cerr <<
"Job #" << i <<
": " << st.
ToStr();
1013 ++errors;
1014 }
1015 ++jobsRun;
1016 }
1017 std::cerr << "Jobs total: " << resultVect.size();
1018 std::cerr << ", run: " << jobsRun;
1019 std::cerr << ", errors: " << errors << std::endl;
1020 }
1023 }
1025 return 0;
1026}
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.
static DlgEnv & Instance()
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)
@ DebugMsg
print debug info
@ DumpMsg
print details of the request and responses
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)
static void splitString(Container &result, const std::string &input, const std::string &delimiter)
Split a string.
std::string ToStr() const
Convert to string.
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 DoTpcModePush
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
const int DefaultCPChunkSize
const uint16_t stError
An error occurred that could potentially be retried.
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.