//------------------------------------------------------------------------------ // Copyright (c) 2011-2014 by European Organization for Nuclear Research (CERN) // Author: Michal Simon //------------------------------------------------------------------------------ // This file is part of the XRootD software suite. // // XRootD is free software: you can redistribute it and/or modify // it under the terms of the GNU Lesser General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // XRootD is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU Lesser General Public License // along with XRootD. If not, see . // // In applying this licence, CERN does not waive the privileges and immunities // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. //------------------------------------------------------------------------------ #ifndef SRC_XRDZIP_XRDZIPEOCD_HH_ #define SRC_XRDZIP_XRDZIPEOCD_HH_ #include "XrdZip/XrdZipUtils.hh" #include "XrdZip/XrdZipLFH.hh" #include "XrdZip/XrdZipCDFH.hh" #include #include namespace XrdZip { //--------------------------------------------------------------------------- // A data structure representing the End of Central Directory record //--------------------------------------------------------------------------- struct EOCD { inline static const char* Find( const char *buffer, uint64_t size ) { for( ssize_t offset = size - eocdBaseSize; offset >= 0; --offset ) { uint32_t signature = to( buffer + offset ); if( signature == eocdSign ) return buffer + offset; } return 0; } //------------------------------------------------------------------------- //! Constructor from buffer //------------------------------------------------------------------------- EOCD( const char *buffer, uint32_t maxSize = 0 ) { nbDisk = *reinterpret_cast( buffer + 4 ); nbDiskCd = *reinterpret_cast( buffer + 6 ); nbCdRecD = *reinterpret_cast( buffer + 8 ); nbCdRec = *reinterpret_cast( buffer + 10 ); cdSize = *reinterpret_cast( buffer + 12 ); cdOffset = *reinterpret_cast( buffer + 16 ); commentLength = *reinterpret_cast( buffer + 20 ); if(maxSize > 0 && (uint32_t)(eocdBaseSize + commentLength) > maxSize) throw bad_data(); comment = std::string( buffer + 22, commentLength ); eocdSize = eocdBaseSize + commentLength; useZip64= false; } //------------------------------------------------------------------------- //! Constructor from last LFH + CDFH //------------------------------------------------------------------------- EOCD( uint64_t cdoff, uint32_t cdcnt, uint32_t cdsize ): nbDisk( 0 ), nbDiskCd( 0 ), commentLength( 0 ), useZip64( false ) { if( cdcnt >= ovrflw::value ) { nbCdRecD = ovrflw::value; nbCdRec = ovrflw::value; } else { nbCdRecD = cdcnt; nbCdRec = cdcnt; } cdSize = cdsize; if( cdoff >= ovrflw::value ) { cdOffset = ovrflw::value; useZip64 = true; } else cdOffset = cdoff; eocdSize = eocdBaseSize + commentLength; } //------------------------------------------------------------------------- //! Serialize the object into a buffer //------------------------------------------------------------------------- void Serialize( buffer_t &buffer ) { copy_bytes( eocdSign, buffer ); copy_bytes( nbDisk, buffer ); copy_bytes( nbDiskCd, buffer ); copy_bytes( nbCdRecD, buffer ); copy_bytes( nbCdRec, buffer ); copy_bytes( cdSize, buffer ); copy_bytes( cdOffset, buffer ); copy_bytes( commentLength, buffer ); std::copy( comment.begin(), comment.end(), std::back_inserter( buffer ) ); } //------------------------------------------------------------------------- //! Convert the EOCD into a string for logging purposes //------------------------------------------------------------------------- std::string ToString() { std::stringstream ss; ss << "{nbDisk=" << nbDisk; ss << ";nbDiskCd=" << nbDiskCd; ss << ";nbCdRecD=" << nbCdRecD; ss << ";nbCdRec=" << nbCdRec; ss << ";cdSize" << cdSize; ss << ";cdOffset=" << cdOffset; ss << ";commentLength=" << commentLength; ss << ";comment=" << comment << '}'; return ss.str(); } uint16_t nbDisk; //< number of this disk uint16_t nbDiskCd; //< number of the disk with the start of the central directory uint16_t nbCdRecD; //< total number of entries in the central directory on this disk uint16_t nbCdRec; //< total number of entries in the central directory uint32_t cdSize; //< size of the central directory uint32_t cdOffset; //< offset of start of central directory uint16_t commentLength; //< comment length std::string comment; //< user comment uint16_t eocdSize; //< size of the record bool useZip64; //< true if ZIP64 format is to be used, false otherwise //------------------------------------------------------------------------- // the End of Central Directory signature //------------------------------------------------------------------------- static const uint32_t eocdSign = 0x06054b50; static const uint16_t eocdBaseSize = 22; static const uint16_t maxCommentLength = 65535; }; } #endif /* SRC_XRDZIP_XRDZIPEOCD_HH_ */