476{
477 using namespace XrdCl;
478
479
480
481
485 return 50;
487
488
489
490
493 if( config.Dlvl )
494 {
498 }
499
503
504 bool posc = false;
505 bool force = false;
506 bool coerce = false;
507 bool makedir = false;
508 bool dynSrc = false;
509 bool delegate = false;
510 bool preserveXAttr = false;
511 bool rmOnBadCksum = false;
512 bool continue_ = false;
513 bool recurse = false;
514 bool zipappend = false;
515 bool doserver = false;
516 std::string thirdParty = "none"s;
517 std::string thirdPartyMode = "pull"s;
518
519 const std::string thirdPartyTokenFile = config.tcpTokenFile ? config.tcpTokenFile : ""s;
520
530 {
531
532
533
534
536 delegate = true;
537 }
538 else
540
542 {
543 makedir = true;
544 recurse = true;
545 }
551
552 if( force && continue_ )
553 {
554 std::cerr << "Invalid argument combination: continue + force." << std::endl;
555 return 50;
556 }
557
558
559
560
561 std::string checkSumType;
562 std::string checkSumPreset;
563 std::string checkSumMode = "none";
565 {
566 checkSumMode = "end2end";
567 std::vector<std::string> ckSumParams;
569 if( ckSumParams.size() > 1 )
570 {
571 if( ckSumParams[1] == "print" )
572 {
573 checkSumMode = "target";
575 }
576 else
577 checkSumPreset = ckSumParams[1];
578 }
579 checkSumType = ckSumParams[0];
580 }
581
583 {
584 checkSumMode = "source";
585 std::vector<std::string> ckSumParams;
587 if( ckSumParams.size() == 2 )
588 {
589 checkSumMode = "source";
590 checkSumType = ckSumParams[0];
592 }
593 else
594 {
595 std::cerr << "Invalid parameter: " << config.CksVal << std::endl;
596 return 50;
597 }
598 }
599
600 if( !config.AddCksVal.empty() )
602
603
604
605
606 std::string zipFile;
607 bool zip = false;
609 {
610 zipFile = config.zipFile;
611 zip = true;
612 }
613
614
615
616
617 int nbSources = 0;
618 bool xcp = false;
620 {
621 nbSources = config.nSrcs;
622 xcp = true;
623 }
624
625
626
627
629
630
631 struct scope_exit {
633 } stopPostMaster;
634
635 if( config.nStrm != 0 )
636 env->
PutInt(
"SubStreamsPerChannel", config.nStrm + 1 );
637
638 if( config.Retry != -1 )
639 {
640 env->
PutInt(
"CpRetry", config.Retry );
641 env->
PutString(
"CpRetryPolicy", config.RetryPolicy );
642 }
643
645 env->
PutInt(
"NoTlsOK", 1 );
646
648 env->
PutInt(
"TlsNoData", 1 );
649
651 env->
PutInt(
"TlsMetalink", 1 );
652
654 env->
PutInt(
"ZipMtlnCksum", 1 );
655
656
657
658
659
660
661 if( !config.HttpHeaders.empty() )
662 {
663 std::string headers;
664 for( auto &header : config.HttpHeaders )
665 {
666 if( !headers.empty() ) headers += '\n';
667 headers += header;
668 }
669 env->
PutString(
"HttpHeaders", headers );
670 }
671
673 env->
GetInt(
"CPChunkSize", chunkSize );
674
676 env->
GetInt(
"XCpBlockSize", blockSize );
677
679 env->
GetInt(
"CPParallelChunks", parallelChunks );
680 if( parallelChunks < 1 ||
681 parallelChunks > std::numeric_limits<uint8_t>::max() )
682 {
683 std::cerr << "Can only handle between 1 and ";
684 std::cerr << (int)std::numeric_limits<uint8_t>::max();
685 std::cerr << " chunks in parallel. You asked for " << parallelChunks;
686 std::cerr << "." << std::endl;
687 return 50;
688 }
689
690 if( !preserveXAttr )
691 {
693 env->
GetInt(
"PreserveXAttrs", val );
694 if( val ) preserveXAttr = true;
695 }
696
697 log->
Dump(
AppMsg,
"Chunk size: %d, parallel chunks %d, streams: %d",
698 chunkSize, parallelChunks, config.nStrm + 1 );
699
700
701
702
703 std::vector<XrdCl::PropertyList*> resultVect;
704
705 std::string dest;
708 {
709 dest = "file://";
710
711
712 if( config.dstFile->Path[0] != '/' )
713 {
714 char buf[FILENAME_MAX];
715 char *cwd = getcwd( buf, FILENAME_MAX );
716 if( !cwd )
717 {
719 std::cerr << st.GetErrorMessage() << std::endl;
720 return st.GetShellCode();
721 }
722 dest += cwd;
723 dest += '/';
724 }
725 }
726 dest += config.dstFile->Path;
727
728
729
730
731
732
733
734
735 bool targetIsDir = false;
736 bool targetExists = false;
738 targetIsDir = true;
741 {
743 FileSystem fs( target );
745 XRootDStatus st = fs.Stat( target.GetPathWithParams(), statInfo );
747 {
749 targetIsDir = true;
750 targetExists = true;
751 }
753 {
754 int n = strlen(config.dstFile->Path);
755 if( config.dstFile->Path[n-1] == '/' )
756 targetIsDir = true;
757 }
759 {
761 std::cerr << st.
ToStr() << std::endl;
763 }
764
765 delete statInfo;
766 }
767
768 if( !targetIsDir && targetExists && !force && !recurse && !zipappend )
769 {
771
773 std::cerr <<
"Run: " << st.
ToStr() << std::endl;
775 }
776
777
778
779
780
783 {
784 std::cerr << "Multiple sources were given but target is not a directory.";
785 std::cerr << std::endl;
786 return 50;
787 }
788
789
790
791
792
793 bool remoteSrcIsDir = false;
797 {
798 URL source( config.srcFile->Path );
799 FileSystem *fs = new FileSystem( source );
801
802 XRootDStatus st = fs->Stat( source.GetPath(), statInfo );
804 {
805 remoteSrcIsDir = true;
806
807
808
809 delete config.srcFile;
810 std::string url = source.GetURL();
811 config.srcFile =
IndexRemote( fs, url, url.size() );
812 if ( !config.srcFile )
813 {
814 std::cerr << "Error indexing remote directory.";
815 return 50;
816 }
817 }
818
819 delete fs;
820 delete statInfo;
821 }
822
824
825
826
827 while( sourceFile )
828 {
830
831
832
833
836 std::string source = sourceFile->
Path;
838 {
839
840 if( source[0] == '/' )
841 source = "file://" + source;
842 else
843 {
844 char buf[FILENAME_MAX];
845 char *cwd = getcwd( buf, FILENAME_MAX );
846 if( !cwd )
847 {
851 }
852 source = "file://" + std::string( cwd ) + '/' + source;
853 }
854 }
855
857
858 std::string sourcePathObf = sourceFile->
Path;
859 std::string destPathObf = dest;
863 }
864 log->
Dump(
AppMsg,
"Processing source entry: %s, type %s, target file: %s, logLevel = %d",
866 destPathObf.c_str(), log->
GetLevel() );
867
868
869
870
871 std::string target = dest;
872
873
874 bool srcIsDir = false;
875
876 if( strncmp( sourceFile->
ProtName,
"file", 4 ) == 0 )
877 srcIsDir = std::string( sourceFile->
Path ).size() == size_t( sourceFile->
Doff + sourceFile->
Dlen );
878
879 else
880 srcIsDir = remoteSrcIsDir;
881
883 {
884
885 std::string srcDir( sourceFile->
Path, sourceFile->
Doff );
886
887 if( srcDir[srcDir.size() - 1] == '/' )
888 srcDir = srcDir.substr( 0, srcDir.size() - 1 );
889 size_t diroff = srcDir.rfind( '/' );
890
891 if( diroff == std::string::npos ) diroff = 0;
892 target += '/';
893 target += sourceFile->
Path + diroff;
894
895 target = target.substr( 0 , target.rfind('/') );
896 }
898
899 properties.
Set(
"source", source );
900 properties.
Set(
"target", target );
901 properties.
Set(
"force", force );
902 properties.
Set(
"posc", posc );
903 properties.
Set(
"coerce", coerce );
904 properties.
Set(
"makeDir", makedir );
905 properties.
Set(
"dynamicSource", dynSrc );
906 properties.
Set(
"thirdParty", thirdParty );
907 properties.
Set(
"thirdPartyMode", thirdPartyMode );
908 properties.
Set(
"checkSumMode", checkSumMode );
909 properties.
Set(
"checkSumType", checkSumType );
910 properties.
Set(
"checkSumPreset", checkSumPreset );
911 properties.
Set(
"chunkSize", chunkSize );
912 properties.
Set(
"parallelChunks", parallelChunks );
913 properties.
Set(
"zipArchive", zip );
914 properties.
Set(
"xcp", xcp );
915 properties.
Set(
"xcpBlockSize", blockSize );
916 properties.
Set(
"delegate", delegate );
917 properties.
Set(
"targetIsDir", targetIsDir );
918 properties.
Set(
"preserveXAttr", preserveXAttr );
919 properties.
Set(
"xrate", config.xRate );
920 properties.
Set(
"xrateThreshold", config.xRateThreshold );
921 properties.
Set(
"rmOnBadCksum", rmOnBadCksum );
922 properties.
Set(
"continue", continue_ );
923 properties.
Set(
"zipAppend", zipappend );
924 properties.
Set(
"addcksums", config.AddCksVal );
925 properties.
Set(
"doServer", doserver );
926
927 if( zip )
928 properties.
Set(
"zipSource", zipFile );
929
930 if( xcp )
931 properties.
Set(
"nbXcpSources", nbSources );
932
933 if( !thirdPartyTokenFile.empty() )
934 properties.
Set(
"thirdPartyTokenFile", thirdPartyTokenFile );
935
938 {
939 std::cerr << "AddJob " << source << " -> " << target << ": ";
940 std::cerr << st.
ToStr() << std::endl;
941 }
942 resultVect.push_back( results );
943 sourceFile = sourceFile->
Next;
944 }
945
946
947
948
950 processConfig.
Set(
"jobType",
"configuration" );
951 processConfig.
Set(
"parallel", config.Parallel );
952 process.
AddJob( processConfig, 0 );
953
954
955
956
959 {
961 std::cerr <<
"Prepare: " << st.
ToStr() << std::endl;
963 }
964
965 st = process.
Run( &progress );
967 {
968 if( resultVect.size() == 1 )
969 std::cerr <<
"Run: " << st.
ToStr() << std::endl;
970 else
971 {
972 std::vector<XrdCl::PropertyList*>::iterator it;
973 uint32_t i = 1;
974 uint32_t jobsRun = 0;
975 uint32_t errors = 0;
976 for( it = resultVect.begin(); it != resultVect.end(); ++it, ++i )
977 {
978 if( !(*it)->HasProperty( "status" ) )
979 continue;
980
983 {
984 std::cerr <<
"Job #" << i <<
": " << st.
ToStr();
985 ++errors;
986 }
987 ++jobsRun;
988 }
989 std::cerr << "Jobs total: " << resultVect.size();
990 std::cerr << ", run: " << jobsRun;
991 std::cerr << ", errors: " << errors << std::endl;
992 }
995 }
997 return 0;
998}
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 uint16_t errInvalidOp
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.