|
||||
File indexing completed on 2025-01-18 10:15:37
0001 //------------------------------------------------------------------------------ 0002 // Copyright (c) 2011-2014 by European Organization for Nuclear Research (CERN) 0003 // Author: Michal Simon <michal.simon@cern.ch> 0004 //------------------------------------------------------------------------------ 0005 // This file is part of the XRootD software suite. 0006 // 0007 // XRootD is free software: you can redistribute it and/or modify 0008 // it under the terms of the GNU Lesser General Public License as published by 0009 // the Free Software Foundation, either version 3 of the License, or 0010 // (at your option) any later version. 0011 // 0012 // XRootD is distributed in the hope that it will be useful, 0013 // but WITHOUT ANY WARRANTY; without even the implied warranty of 0014 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 0015 // GNU General Public License for more details. 0016 // 0017 // You should have received a copy of the GNU Lesser General Public License 0018 // along with XRootD. If not, see <http://www.gnu.org/licenses/>. 0019 // 0020 // In applying this licence, CERN does not waive the privileges and immunities 0021 // granted to it by virtue of its status as an Intergovernmental Organization 0022 // or submit itself to any jurisdiction. 0023 //------------------------------------------------------------------------------ 0024 0025 #ifndef SRC_XRDZIP_XRDZIPARCHIVE_HH_ 0026 #define SRC_XRDZIP_XRDZIPARCHIVE_HH_ 0027 0028 #include "XrdCl/XrdClFile.hh" 0029 #include "XrdCl/XrdClResponseJob.hh" 0030 #include "XrdCl/XrdClJobManager.hh" 0031 #include "XrdCl/XrdClDefaultEnv.hh" 0032 #include "XrdCl/XrdClPostMaster.hh" 0033 #include "XrdZip/XrdZipEOCD.hh" 0034 #include "XrdZip/XrdZipCDFH.hh" 0035 #include "XrdZip/XrdZipZIP64EOCD.hh" 0036 #include "XrdZip/XrdZipLFH.hh" 0037 #include "XrdCl/XrdClZipCache.hh" 0038 0039 #include <memory> 0040 #include <unordered_map> 0041 0042 //----------------------------------------------------------------------------- 0043 // Forward declaration needed for friendship 0044 //----------------------------------------------------------------------------- 0045 namespace XrdEc{ class StrmWriter; class Reader; template<bool> class OpenOnlyImpl; }; 0046 class MicroTest; 0047 class XrdEcTests; 0048 0049 namespace XrdCl 0050 { 0051 using namespace XrdZip; 0052 0053 //--------------------------------------------------------------------------- 0054 // ZipArchive provides following functionalities: 0055 // - parsing of existing ZIP archive 0056 // - reading data from existing ZIP archive 0057 // - appending data to existing ZIP archive 0058 // - querying stat info and checksum for given file in ZIP archive 0059 //--------------------------------------------------------------------------- 0060 class ZipArchive 0061 { 0062 friend class XrdEc::StrmWriter; 0063 friend class XrdEc::Reader; 0064 template<bool> 0065 friend class XrdEc::OpenOnlyImpl; 0066 friend class ::MicroTest; 0067 friend class ::XrdEcTests; 0068 0069 template<typename RSP> 0070 friend XRootDStatus ReadFromImpl( ZipArchive&, const std::string&, uint64_t, uint32_t, void*, ResponseHandler*, uint16_t ); 0071 0072 public: 0073 //----------------------------------------------------------------------- 0074 //! Constructor 0075 //----------------------------------------------------------------------- 0076 ZipArchive( bool enablePlugIns = true ); 0077 0078 //----------------------------------------------------------------------- 0079 //! Destructor 0080 //----------------------------------------------------------------------- 0081 virtual ~ZipArchive(); 0082 0083 //----------------------------------------------------------------------- 0084 //! Open ZIP Archive (and parse the Central Directory) 0085 //! 0086 //! @param url : the URL of the ZIP archive 0087 //! @param flags : open flags to be used when openning the file 0088 //! @param handler : user callback 0089 //! @param timeout : operation timeout 0090 //! @return : the status of the operation 0091 //----------------------------------------------------------------------- 0092 XRootDStatus OpenArchive( const std::string &url, 0093 OpenFlags::Flags flags, 0094 ResponseHandler *handler, 0095 uint16_t timeout = 0 ); 0096 0097 //----------------------------------------------------------------------- 0098 //! Open a file within the ZIP Archive 0099 //! 0100 //! @param fn : file name to be opened 0101 //! @param flags : open flags (either 'Read' or 'New | Write') 0102 //! @param size : file size (to be included in the LFH) 0103 //! @param crc32 : file crc32 (to be included in the LFH) 0104 //! @return : the status of the operation 0105 //----------------------------------------------------------------------- 0106 XRootDStatus OpenFile( const std::string &fn, 0107 OpenFlags::Flags flags = OpenFlags::None, 0108 uint64_t size = 0, 0109 uint32_t crc32 = 0 ); 0110 0111 //----------------------------------------------------------------------- 0112 //! Read data from an open file 0113 //! 0114 //! @param offset : offset within the file to read at 0115 //! @param size : number of bytes to be read 0116 //! @param buffer : the buffer for the data 0117 //! @param handler : user callback 0118 //! @param timeout : operation timeout 0119 //! @return : the status of the operation 0120 //----------------------------------------------------------------------- 0121 inline 0122 XRootDStatus Read( uint64_t offset, 0123 uint32_t size, 0124 void *buffer, 0125 ResponseHandler *handler, 0126 uint16_t timeout = 0 ) 0127 { 0128 if( openfn.empty() ) return XRootDStatus( stError, errInvalidOp ); 0129 return ReadFrom( openfn, offset, size, buffer, handler, timeout ); 0130 } 0131 0132 //----------------------------------------------------------------------- 0133 //! PgRead data from an open file 0134 //! 0135 //! @param offset : offset within the file to read at 0136 //! @param size : number of bytes to be read 0137 //! @param buffer : the buffer for the data 0138 //! @param handler : user callback 0139 //! @param timeout : operation timeout 0140 //! @return : the status of the operation 0141 //----------------------------------------------------------------------- 0142 inline 0143 XRootDStatus PgRead( uint64_t offset, 0144 uint32_t size, 0145 void *buffer, 0146 ResponseHandler *handler, 0147 uint16_t timeout = 0 ) 0148 { 0149 if( openfn.empty() ) return XRootDStatus( stError, errInvalidOp ); 0150 return PgReadFrom( openfn, offset, size, buffer, handler, timeout ); 0151 } 0152 0153 //----------------------------------------------------------------------- 0154 //! Read data from a given file 0155 //! 0156 //! @param fn : the name of the file from which we are going to read 0157 //! @param offset : offset within the file to read at 0158 //! @param size : number of bytes to be read 0159 //! @param buffer : the buffer for the data 0160 //! @param handler : user callback 0161 //! @param timeout : operation timeout 0162 //! @return : the status of the operation 0163 //----------------------------------------------------------------------- 0164 XRootDStatus ReadFrom( const std::string &fn, 0165 uint64_t offset, 0166 uint32_t size, 0167 void *buffer, 0168 ResponseHandler *handler, 0169 uint16_t timeout = 0 ); 0170 0171 //----------------------------------------------------------------------- 0172 //! PgRead data from a given file 0173 //! 0174 //! @param fn : the name of the file from which we are going to read 0175 //! @param offset : offset within the file to read at 0176 //! @param size : number of bytes to be read 0177 //! @param buffer : the buffer for the data 0178 //! @param handler : user callback 0179 //! @param timeout : operation timeout 0180 //! @return : the status of the operation 0181 //----------------------------------------------------------------------- 0182 XRootDStatus PgReadFrom( const std::string &fn, 0183 uint64_t offset, 0184 uint32_t size, 0185 void *buffer, 0186 ResponseHandler *handler, 0187 uint16_t timeout = 0 ); 0188 0189 //----------------------------------------------------------------------- 0190 //! Append data to a new file 0191 //! 0192 //! @param size : number of bytes to be appended 0193 //! @param buffer : the buffer with the data to be appended 0194 //! @param handler : user callback 0195 //! @param timeout : operation timeout 0196 //! @return : the status of the operation 0197 //----------------------------------------------------------------------- 0198 inline XRootDStatus Write( uint32_t size, 0199 const void *buffer, 0200 ResponseHandler *handler, 0201 uint16_t timeout = 0 ) 0202 { 0203 if( openstage != Done || openfn.empty() ) 0204 return XRootDStatus( stError, errInvalidOp, 0, "Archive not opened." ); 0205 0206 return WriteImpl( size, buffer, handler, timeout ); 0207 } 0208 0209 //----------------------------------------------------------------------- 0210 //! Update the metadata of the currently open file 0211 //! 0212 //! @param crc32 : the crc32 checksum 0213 //! @return : the status of the operation 0214 //----------------------------------------------------------------------- 0215 XRootDStatus UpdateMetadata( uint32_t crc32 ); 0216 0217 //----------------------------------------------------------------------- 0218 //! Create a new file in the ZIP archive and append the data 0219 //! 0220 //! @param fn : the name of the new file to be created 0221 //! @param crc32 : the crc32 of the file 0222 //! @param size : the size of the file 0223 //! @param buffer : the buffer with the data 0224 //! @param handler : user callback 0225 //! @param timeout : operation timeout 0226 //! @return : the status of the operation 0227 //----------------------------------------------------------------------- 0228 XRootDStatus AppendFile( const std::string &fn, 0229 uint32_t crc32, 0230 uint32_t size, 0231 const void *buffer, 0232 ResponseHandler *handler, 0233 uint16_t timeout = 0 ); 0234 0235 //----------------------------------------------------------------------- 0236 //! Get stat info for given file 0237 //! 0238 //! @param fn : the name of the file 0239 //! @param info : output parameter 0240 //! @return : the status of the operation 0241 //----------------------------------------------------------------------- 0242 inline XRootDStatus Stat( const std::string &fn, StatInfo *&info ) 0243 { // make sure archive has been opened and CD has been parsed 0244 if( openstage != Done ) 0245 return XRootDStatus( stError, errInvalidOp ); 0246 // make sure the file is part of the archive 0247 auto cditr = cdmap.find( fn ); 0248 if( cditr == cdmap.end() ) 0249 return XRootDStatus( stError, errNotFound ); 0250 // create the result 0251 info = make_stat( fn ); 0252 if (info) 0253 return XRootDStatus(); 0254 else // have difficult to access the openned archive. 0255 return XRootDStatus( stError, errNotFound ); 0256 } 0257 0258 //----------------------------------------------------------------------- 0259 //! Get stat info for an open file 0260 //! 0261 //! @param info : output parameter 0262 //! @return : the status of the operation 0263 //----------------------------------------------------------------------- 0264 inline XRootDStatus Stat( StatInfo *&info ) 0265 { 0266 if( openfn.empty() ) 0267 return XRootDStatus( stError, errInvalidOp ); 0268 return Stat( openfn, info ); 0269 } 0270 0271 //----------------------------------------------------------------------- 0272 //! Get crc32 for a given file 0273 //! 0274 //! @param fn : file name 0275 //! @param cksum : output parameter 0276 //! @return : the status of the operation 0277 //----------------------------------------------------------------------- 0278 inline XRootDStatus GetCRC32( const std::string &fn, uint32_t &cksum ) 0279 { // make sure archive has been opened and CD has been parsed 0280 if( openstage != Done ) 0281 return XRootDStatus( stError, errInvalidOp ); 0282 // make sure the file is part of the archive 0283 auto cditr = cdmap.find( fn ); 0284 if( cditr == cdmap.end() ) 0285 return XRootDStatus( stError, errNotFound ); 0286 cksum = cdvec[cditr->second]->ZCRC32; 0287 return XRootDStatus(); 0288 } 0289 0290 inline XRootDStatus GetOffset( const std::string &fn, uint64_t &offset){ 0291 if( openstage != XrdCl::ZipArchive::Done || !archive.IsOpen() ) 0292 return XrdCl::XRootDStatus( XrdCl::stError, XrdCl::errInvalidOp ); 0293 0294 auto cditr = cdmap.find( fn ); 0295 if( cditr == cdmap.end() ) 0296 return XrdCl::XRootDStatus( XrdCl::stError, XrdCl::errNotFound, 0297 XrdCl::errNotFound, "File not found." ); 0298 0299 XrdCl::CDFH *cdfh = cdvec[cditr->second].get(); 0300 0301 // check if the file is compressed, for now we only support uncompressed and inflate/deflate compression 0302 if( cdfh->compressionMethod != 0 && cdfh->compressionMethod != Z_DEFLATED ) 0303 return XrdCl::XRootDStatus( XrdCl::stError, XrdCl::errNotSupported, 0304 0, "The compression algorithm is not supported!" ); 0305 0306 // Now the problem is that at the beginning of our 0307 // file there is the Local-file-header, which size 0308 // is not known because of the variable size 'extra' 0309 // field, so we need to know the offset of the next 0310 // record and shift it by the file size. 0311 // The next record is either the next LFH (next file) 0312 // or the start of the Central-directory. 0313 uint64_t cdOffset = zip64eocd ? zip64eocd->cdOffset : eocd->cdOffset; 0314 uint64_t nextRecordOffset = ( cditr->second + 1 < cdvec.size() ) ? 0315 XrdCl::CDFH::GetOffset( *cdvec[cditr->second + 1] ) : cdOffset; 0316 uint64_t filesize = cdfh->compressedSize; 0317 if( filesize == std::numeric_limits<uint32_t>::max() && cdfh->extra ) 0318 filesize = cdfh->extra->compressedSize; 0319 uint16_t descsize = cdfh->HasDataDescriptor() ? 0320 XrdCl::DataDescriptor::GetSize( cdfh->IsZIP64() ) : 0; 0321 offset = nextRecordOffset - filesize - descsize; 0322 return XrdCl::XRootDStatus(); 0323 } 0324 0325 //----------------------------------------------------------------------- 0326 //! Create the central directory at the end of ZIP archive and close it 0327 // 0328 //! @param handler : user callback 0329 //! @param timeout : operation timeout 0330 //! @return : the status of the operation 0331 //----------------------------------------------------------------------- 0332 XRootDStatus CloseArchive( ResponseHandler *handler, 0333 uint16_t timeout = 0 ); 0334 0335 //----------------------------------------------------------------------- 0336 //! Close an open file within the ZIP archive 0337 //! @return : the status of the operation 0338 //----------------------------------------------------------------------- 0339 inline XRootDStatus CloseFile() 0340 { 0341 if( openstage != Done || openfn.empty() ) 0342 return XRootDStatus( stError, errInvalidOp, 0343 0, "Archive not opened." ); 0344 openfn.clear(); 0345 lfh.reset(); 0346 return XRootDStatus(); 0347 } 0348 0349 //----------------------------------------------------------------------- 0350 //! List files in the ZIP archive 0351 //! @return : the status of the operation 0352 //----------------------------------------------------------------------- 0353 XRootDStatus List( DirectoryList *&list ); 0354 0355 //----------------------------------------------------------------------- 0356 //! @return : true if ZIP archive has been successfully opened 0357 //----------------------------------------------------------------------- 0358 inline bool IsOpen() 0359 { 0360 return openstage == Done; 0361 } 0362 0363 //------------------------------------------------------------------------ 0364 //! Check if the underlying file is using an encrypted connection 0365 //------------------------------------------------------------------------ 0366 inline bool IsSecure() 0367 { 0368 return archive.IsSecure(); 0369 } 0370 0371 //----------------------------------------------------------------------- 0372 //! Set property on the underlying File object 0373 //----------------------------------------------------------------------- 0374 inline bool SetProperty( const std::string &name, const std::string &value ) 0375 { 0376 return archive.SetProperty( name, value ); 0377 } 0378 0379 //----------------------------------------------------------------------- 0380 //! Get property on the underlying File object 0381 //----------------------------------------------------------------------- 0382 inline bool GetProperty( const std::string &name, std::string &value ) 0383 { 0384 return archive.GetProperty( name, value ); 0385 } 0386 0387 //----------------------------------------------------------------------- 0388 //! Get the underlying File object 0389 //----------------------------------------------------------------------- 0390 inline File& GetFile() 0391 { 0392 return archive; 0393 } 0394 0395 private: 0396 0397 //----------------------------------------------------------------------- 0398 //! Append data to a new file, implementation 0399 //! 0400 //! @param size : number of bytes to be appended 0401 //! @param buffer : the buffer with the data to be appended 0402 //! @param handler : user callback 0403 //! @param timeout : operation timeout 0404 //! @return : the status of the operation 0405 //----------------------------------------------------------------------- 0406 XRootDStatus WriteImpl( uint32_t size, 0407 const void *buffer, 0408 ResponseHandler *handler, 0409 uint16_t timeout ); 0410 0411 //----------------------------------------------------------------------- 0412 //! Open the ZIP archive in read-only mode without parsing the central 0413 //! directory. 0414 //! 0415 //! @param url : url of the ZIP archive 0416 //! @param handler : user callback 0417 //! @param timeout : operation timeout 0418 //! @return : operation status 0419 //----------------------------------------------------------------------- 0420 XRootDStatus OpenOnly( const std::string &url, 0421 bool update, 0422 ResponseHandler *handler, 0423 uint16_t timeout = 0 ); 0424 0425 //----------------------------------------------------------------------- 0426 //! Get a buffer with central directory of the ZIP archive 0427 //! 0428 //! @return : buffer with central directory 0429 //----------------------------------------------------------------------- 0430 buffer_t GetCD(); 0431 0432 //----------------------------------------------------------------------- 0433 //! Set central directory for the ZIP archive 0434 //! 0435 //! @param buffer : a buffer with the central directory to be set 0436 //----------------------------------------------------------------------- 0437 void SetCD( const buffer_t &buffer ); 0438 0439 //----------------------------------------------------------------------- 0440 //! Package a response into AnyObject (erase the type) 0441 //! 0442 //! @param rsp : the response to be packaged 0443 //! @return : AnyObject with the response 0444 //----------------------------------------------------------------------- 0445 template<typename Response> 0446 inline static AnyObject* PkgRsp( Response *rsp ) 0447 { 0448 if( !rsp ) return nullptr; 0449 AnyObject *pkg = new AnyObject(); 0450 pkg->Set( rsp ); 0451 return pkg; 0452 } 0453 0454 //----------------------------------------------------------------------- 0455 //! Free status and response 0456 //----------------------------------------------------------------------- 0457 template<typename Response> 0458 inline static void Free( XRootDStatus *st, Response *rsp ) 0459 { 0460 delete st; 0461 delete rsp; 0462 } 0463 0464 //----------------------------------------------------------------------- 0465 //! Schedule a user callback to be executed in the thread-pool with given 0466 //! status and response. 0467 //! 0468 //! @param handler : user callback to be scheduled 0469 //! @param st : status to be passed to the callback 0470 //! @param rsp : response to be passed to the callback 0471 //----------------------------------------------------------------------- 0472 template<typename Response> 0473 inline static void Schedule( ResponseHandler *handler, XRootDStatus *st, Response *rsp = nullptr ) 0474 { 0475 if( !handler ) return Free( st, rsp ); 0476 ResponseJob *job = new ResponseJob( handler, st, PkgRsp( rsp ), 0 ); 0477 DefaultEnv::GetPostMaster()->GetJobManager()->QueueJob( job ); 0478 } 0479 0480 //----------------------------------------------------------------------- 0481 //! Create a StatInfo object from ZIP archive stat info and the file size. 0482 //! 0483 //! @param starch : ZIP archive stat info 0484 //! @param size : file size 0485 //! @return : StatInfo object 0486 //----------------------------------------------------------------------- 0487 inline static StatInfo* make_stat( const StatInfo &starch, uint64_t size ) 0488 { 0489 StatInfo *info = new StatInfo( starch ); 0490 uint32_t flags = info->GetFlags(); 0491 info->SetFlags( flags & ( ~StatInfo::IsWritable ) ); // make sure it is not listed as writable 0492 info->SetSize( size ); 0493 return info; 0494 } 0495 0496 //----------------------------------------------------------------------- 0497 //! Create a StatInfo object for a given file within the ZIP archive. 0498 //! 0499 //! @param fn : file name 0500 //! @return : StatInfo object for the given file 0501 //----------------------------------------------------------------------- 0502 inline StatInfo* make_stat( const std::string &fn ) 0503 { 0504 StatInfo *infoptr = 0; 0505 XRootDStatus st = archive.Stat( false, infoptr ); 0506 if (!st.IsOK()) return nullptr; 0507 std::unique_ptr<StatInfo> stinfo( infoptr ); 0508 auto itr = cdmap.find( fn ); 0509 if( itr == cdmap.end() ) return nullptr; 0510 size_t index = itr->second; 0511 uint64_t uncompressedSize = cdvec[index]->uncompressedSize; 0512 if( cdvec[index]->extra && uncompressedSize == std::numeric_limits<uint32_t>::max() ) 0513 uncompressedSize = cdvec[index]->extra->uncompressedSize; 0514 return make_stat( *stinfo, uncompressedSize ); 0515 } 0516 0517 //----------------------------------------------------------------------- 0518 //! Allocate new XRootDStatus object 0519 //----------------------------------------------------------------------- 0520 inline static XRootDStatus* make_status( const XRootDStatus &status = XRootDStatus() ) 0521 { 0522 return new XRootDStatus( status ); 0523 } 0524 0525 //----------------------------------------------------------------------- 0526 //! Clear internal ZipArchive objects 0527 //----------------------------------------------------------------------- 0528 inline void Clear() 0529 { 0530 buffer.reset(); 0531 eocd.reset(); 0532 cdvec.clear(); 0533 cdmap.clear(); 0534 zip64eocd.reset(); 0535 openstage = None; 0536 } 0537 0538 //----------------------------------------------------------------------- 0539 //! Stages of opening and parsing a ZIP archive 0540 //----------------------------------------------------------------------- 0541 enum OpenStages 0542 { 0543 None = 0, //< opening/parsing not started 0544 HaveEocdBlk, //< we have the End of Central Directory record 0545 HaveZip64EocdlBlk, //< we have the ZIP64 End of Central Directory locator record 0546 HaveZip64EocdBlk, //< we have the ZIP64 End of Central Directory record 0547 HaveCdRecords, //< we have Central Directory records 0548 Done, //< we are done parsing the Central Directory 0549 Error, //< opening/parsing failed 0550 NotParsed //< the ZIP archive has been opened but Central Directory is not parsed 0551 }; 0552 0553 //----------------------------------------------------------------------- 0554 //! LFH of a newly appended file (in case it needs to be overwritten) 0555 //----------------------------------------------------------------------- 0556 struct NewFile 0557 { 0558 NewFile( uint64_t offset, std::unique_ptr<LFH> lfh ) : offset( offset ), 0559 lfh( std::move( lfh ) ), 0560 overwrt( false ) 0561 { 0562 } 0563 0564 NewFile( NewFile && nf ) : offset( nf.offset ), 0565 lfh( std::move( nf.lfh ) ), 0566 overwrt( nf.overwrt ) 0567 { 0568 } 0569 0570 uint64_t offset; // the offset of the LFH of the file 0571 std::unique_ptr<LFH> lfh; // LFH of the file 0572 bool overwrt; // if true the LFH needs to be overwritten on close 0573 }; 0574 0575 //----------------------------------------------------------------------- 0576 //! Type that maps file name to its cache 0577 //----------------------------------------------------------------------- 0578 typedef std::unordered_map<std::string, ZipCache> zipcache_t; 0579 typedef std::unordered_map<std::string, NewFile> new_files_t; 0580 0581 File archive; //> File object for handling the ZIP archive 0582 uint64_t archsize; //> size of the ZIP archive 0583 bool cdexists; //> true if Central Directory exists, false otherwise 0584 bool updated; //> true if the ZIP archive has been updated, false otherwise 0585 std::unique_ptr<char[]> buffer; //> buffer for keeping the data to be parsed or raw data 0586 std::unique_ptr<EOCD> eocd; //> End of Central Directory record 0587 cdvec_t cdvec; //> vector of Central Directory File Headers 0588 cdmap_t cdmap; //> mapping of file name to CDFH index 0589 uint64_t cdoff; //> Central Directory offset 0590 uint32_t orgcdsz; //> original CD size 0591 uint32_t orgcdcnt; //> original number CDFH records 0592 buffer_t orgcdbuf; //> buffer with the original CDFH records 0593 std::unique_ptr<ZIP64_EOCD> zip64eocd; //> ZIP64 End of Central Directory record 0594 OpenStages openstage; //> stage of opening / parsing a ZIP archive 0595 std::string openfn; //> file name of opened file 0596 zipcache_t zipcache; //> cache for inflating compressed data 0597 std::unique_ptr<LFH> lfh; //> Local File Header record for the newly appended file 0598 bool ckpinit; //> a flag indicating whether a checkpoint has been initialized 0599 new_files_t newfiles; //> all newly appended files 0600 }; 0601 0602 } /* namespace XrdZip */ 0603 0604 #endif /* SRC_XRDZIP_XRDZIPARCHIVE_HH_ */
[ Source navigation ] | [ Diff markup ] | [ Identifier search ] | [ general search ] |
This page was automatically generated by the 2.3.7 LXR engine. The LXR team |