diff --git a/docs/man/xrdfs.1 b/docs/man/xrdfs.1 index ca53cd7d173..c9c7abce89e 100644 --- a/docs/man/xrdfs.1 +++ b/docs/man/xrdfs.1 @@ -30,7 +30,7 @@ Modify permissions of the \fIpath\fR. Permission string example: \fIrwxr-x--x\fR .RE -\fBls\fR \fI[-l]\fR \fI[-u]\fR \fI[-R]\fR \fI[-D]\fR \fI[-Z]\fR \fI[dirname]\fR +\fBls\fR \fI[-l]\fR \fI[-u]\fR \fI[-R]\fR \fI[-D]\fR \fI[-Z]\fR \fI[-C]\fR \fI[dirname]\fR .RS 3 Get directory listing. .br @@ -43,6 +43,8 @@ Get directory listing. \fI-D\fR show duplicate entries .br \fI-Z\fR check if file is a ZIP archive and if yes list its content +.br +\fI-C\fR checksum every entry .RE \fBlocate\fR \fI[-n]\fR \fI[-r]\fR \fI[-d]\fR \fI[-m]\fR \fI[-i]\fR \fI[-p]\fR \fI\fR diff --git a/src/XrdCl/XrdClFS.cc b/src/XrdCl/XrdClFS.cc index 60ae29e23a5..e779f3a2647 100644 --- a/src/XrdCl/XrdClFS.cc +++ b/src/XrdCl/XrdClFS.cc @@ -210,10 +210,10 @@ XRootDStatus DoCD( FileSystem *fs, //------------------------------------------------------------------------------ // Helper function to calculate number of digits in a number //------------------------------------------------------------------------------ -int nbDigits( uint64_t nb ) +uint32_t nbDigits( uint64_t nb ) { if( nb == 0 ) return 1; - return int( log10( double(nb) ) + 1); + return uint32_t( log10( double(nb) ) + 1); } //------------------------------------------------------------------------------ @@ -230,6 +230,7 @@ XRootDStatus DoLS( FileSystem *fs, uint32_t argc = args.size(); bool stats = false; bool showUrls = false; + bool hascks = false; std::string path; DirListFlags::Flags flags = DirListFlags::Locate | DirListFlags::Merge; @@ -262,6 +263,13 @@ XRootDStatus DoLS( FileSystem *fs, // check if file is a ZIP archive if yes list content flags |= DirListFlags::Zip; } + else if( args[i] == "-C" ) + { + // query checksum for each entry in the directory + hascks = true; + stats = true; + flags |= DirListFlags::Cksm; + } else path = args[i]; } @@ -302,7 +310,7 @@ XRootDStatus DoLS( FileSystem *fs, std::cerr << "incomplete." << std::endl; } - uint32_t ownerwidth = 0, groupwidth = 0, sizewidth = 0; + uint32_t ownerwidth = 0, groupwidth = 0, sizewidth = 0, ckswidth = 0; DirectoryList::Iterator it; for( it = list->Begin(); it != list->End() && stats; ++it ) { @@ -313,6 +321,8 @@ XRootDStatus DoLS( FileSystem *fs, groupwidth = info->GetGroup().size(); if( sizewidth < nbDigits( info->GetSize() ) ) sizewidth = nbDigits( info->GetSize() ); + if( ckswidth < info->GetChecksum().size() ) + ckswidth = info->GetChecksum().size(); } //---------------------------------------------------------------------------- @@ -340,6 +350,8 @@ XRootDStatus DoLS( FileSystem *fs, std::cout << " " << std::setw( ownerwidth ) << info->GetOwner(); std::cout << " " << std::setw( groupwidth ) << info->GetGroup(); std::cout << " " << std::setw( sizewidth ) << info->GetSize(); + if( info->HasChecksum() ) + std::cout << " " << std::setw( sizewidth ) << info->GetChecksum(); std::cout << " " << info->GetModTimeAsString() << " "; } else @@ -1776,13 +1788,14 @@ XRootDStatus PrintHelp( FileSystem *, Env *, printf( " Modify permissions. Permission string example:\n" ); printf( " rwxr-x--x\n\n" ); - printf( " ls [-l] [-u] [-R] [-D] [-Z] [dirname]\n" ); + printf( " ls [-l] [-u] [-R] [-D] [-Z] [-C] [dirname]\n" ); printf( " Get directory listing.\n" ); printf( " -l stat every entry and pring long listing\n" ); printf( " -u print paths as URLs\n" ); printf( " -R list subdirectories recursively\n" ); printf( " -D show duplicate entries" ); - printf( " -Z if a ZIP archive list its content\n\n" ); + printf( " -Z if a ZIP archive list its content\n" ); + printf( " -C checksum every entry\n\n" ); printf( " locate [-n] [-r] [-d] [-m] [-i] [-p] \n" ); printf( " Get the locations of the path.\n" ); diff --git a/src/XrdCl/XrdClFileSystem.cc b/src/XrdCl/XrdClFileSystem.cc index 0ba89f79068..b2e2b887a41 100644 --- a/src/XrdCl/XrdClFileSystem.cc +++ b/src/XrdCl/XrdClFileSystem.cc @@ -1651,6 +1651,9 @@ namespace XrdCl if( ( flags & DirListFlags::Stat ) || ( flags & DirListFlags::Recursive ) ) req->options[0] = kXR_dstat; + if( ( flags & DirListFlags::Cksm ) ) + req->options[0] = kXR_dstat | kXR_dcksm; + if( flags & DirListFlags::Recursive ) handler = new RecursiveDirListHandler( *pImpl->pUrl, url.GetPath(), flags, handler, timeout ); diff --git a/src/XrdCl/XrdClFileSystem.hh b/src/XrdCl/XrdClFileSystem.hh index 9b87ea8e35f..47d5939df48 100644 --- a/src/XrdCl/XrdClFileSystem.hh +++ b/src/XrdCl/XrdClFileSystem.hh @@ -161,7 +161,8 @@ namespace XrdCl Recursive = 4, //!< Do a recursive listing Merge = 8, //!< Merge duplicates Chunked = 16, //!< Serve chunked results for better performance - Zip = 32 //!< List content of ZIP files + Zip = 32, //!< List content of ZIP files + Cksm = 64 //!< Get checksum for every entry }; }; XRDOUC_ENUM_OPERATORS( DirListFlags::Flags ) diff --git a/src/XrdCl/XrdClXRootDResponses.cc b/src/XrdCl/XrdClXRootDResponses.cc index 1c18645f940..9d096665896 100644 --- a/src/XrdCl/XrdClXRootDResponses.cc +++ b/src/XrdCl/XrdClXRootDResponses.cc @@ -109,9 +109,9 @@ namespace XrdCl struct StatInfoImpl { StatInfoImpl() : pSize( 0 ), pFlags( 0 ), pModifyTime( 0 ), - pChangeTime( 0 ), pAccessTime( 0 ), pExtended( false ) + pChangeTime( 0 ), pAccessTime( 0 ), + pExtended( false ), pHasCksum( false ) { - } StatInfoImpl( const StatInfoImpl & pimpl ) : pId( pimpl.pId ), @@ -123,7 +123,8 @@ namespace XrdCl pMode( pimpl.pMode ), pOwner( pimpl.pOwner ), pGroup( pimpl.pGroup ), - pExtended( pimpl.pExtended ) + pExtended( pimpl.pExtended ), + pHasCksum( pimpl.pHasCksum ) { } @@ -165,7 +166,7 @@ namespace XrdCl return false; } - if( chunks.size() == 9 ) + if( chunks.size() >= 9 ) { pChangeTime = ::strtoll( chunks[4].c_str(), &result, 0 ); if( *result != 0 ) @@ -191,6 +192,16 @@ namespace XrdCl pExtended = true; } + // after the extended stat information, we might have the checksum + if( chunks.size() >= 10 ) + { + if( ( chunks[9] == "[" ) && ( chunks[11] == "]" ) ) + { + pHasCksum = true; + pCksum = chunks[10]; + } + } + return true; } @@ -205,6 +216,8 @@ namespace XrdCl std::string pGroup; bool pExtended; + bool pHasCksum; + std::string pCksum; }; //---------------------------------------------------------------------------- @@ -390,6 +403,14 @@ namespace XrdCl return pImpl->pGroup; } + //------------------------------------------------------------------------ + //! Get checksum + //------------------------------------------------------------------------ + const std::string& StatInfo::GetChecksum() const + { + return pImpl->pCksum; + } + //------------------------------------------------------------------------ //! Parse server response and fill up the object //------------------------------------------------------------------------ @@ -398,6 +419,14 @@ namespace XrdCl return pImpl->pExtended; } + //------------------------------------------------------------------------ + //! Has checksum + //------------------------------------------------------------------------ + bool StatInfo::HasChecksum() const + { + return pImpl->pHasCksum; + } + //---------------------------------------------------------------------------- // StatInfo constructor //---------------------------------------------------------------------------- diff --git a/src/XrdCl/XrdClXRootDResponses.hh b/src/XrdCl/XrdClXRootDResponses.hh index 8f9d6533b6c..8e0ec44e400 100644 --- a/src/XrdCl/XrdClXRootDResponses.hh +++ b/src/XrdCl/XrdClXRootDResponses.hh @@ -512,16 +512,26 @@ namespace XrdCl //------------------------------------------------------------------------ const std::string& GetGroup() const; + //------------------------------------------------------------------------ + //! Get checksum + //------------------------------------------------------------------------ + const std::string& GetChecksum() const; + //------------------------------------------------------------------------ //! Parse server response and fill up the object //------------------------------------------------------------------------ bool ParseServerResponse( const char *data ); //------------------------------------------------------------------------ - //! Parse server response and fill up the object + //! Has extended stat information //------------------------------------------------------------------------ bool ExtendedFormat() const; + //------------------------------------------------------------------------ + //! Has checksum + //------------------------------------------------------------------------ + bool HasChecksum() const; + private: static inline std::string TimeToString( uint64_t time )