10#if ENABLE_ZCHUNK_COMPRESSION
15#include <zypp-core/AutoDispose.h>
30 std::ifstream dFile( file.
c_str() );
31 if ( !dFile.is_open() )
34 constexpr std::string_view magic(
"\0ZCK1", 5);
36 std::array< char, magic.size() > lead;
38 dFile.read( lead.data(), lead.size() );
39 return ( magic == std::string_view( lead.data(), lead.size()) );
42 DLZckHeadState::DLZckHeadState( std::vector<Url> &&mirrors, std::shared_ptr<Request> &&oldReq, DownloadPrivate &parent )
43 : BasicDownloaderStateBase(
std::move(oldReq), parent )
45 _fileMirrors = std::move(mirrors);
46 MIL <<
"About to enter DlZckHeadState for url " << parent._spec.url() << std::endl;
49 DLZckHeadState::DLZckHeadState( std::vector<Url> &&mirrors, DownloadPrivate &parent )
50 : BasicDownloaderStateBase( parent )
52 _fileMirrors = std::move(mirrors);
53 MIL <<
"About to enter DlZckHeadState for url " << parent._spec.url() << std::endl;
57 bool DLZckHeadState::initializeRequest(std::shared_ptr<Request> &r )
59 BasicDownloaderStateBase::initializeRequest( r );
61 const auto &s = stateMachine()._spec;
62 if ( s.headerSize() == 0 ) {
63 ERR <<
"Downloading the zck header was requested, but headersize is zero." << std::endl;
67 std::shared_ptr<zypp::Digest> digest;
68 NetworkRequest::CheckSumBytes sum;
70 const auto &headerSum = s.headerChecksum();
72 digest = std::make_shared<zypp::Digest>();
73 if ( !digest->create( headerSum->type() ) ) {
74 ERR <<
"Unknown header checksum type " << headerSum->type() << std::endl;
77 sum = zypp::Digest::hexStringToUByteArray( headerSum->checksum() );
80 r->addRequestRange( 0, s.headerSize(), digest, sum );
84 void DLZckHeadState::gotFinished()
86 if ( isZchunkFile( stateMachine()._spec.targetPath() ) )
87 return BasicDownloaderStateBase::gotFinished();
88 failed (
"Downloaded header is not a zchunk header");
91 std::shared_ptr<DLZckState> DLZckHeadState::transitionToDlZckState()
93 MIL_MEDIA <<
"Downloaded the header of size: " << _request->downloadedByteCount() << std::endl;
94 return std::make_shared<DLZckState>( std::move(_fileMirrors), stateMachine() );
97 DLZckState::DLZckState(std::vector<Url> &&mirrors, DownloadPrivate &parent)
98 : RangeDownloaderBaseState(
std::move(mirrors), parent )
100 MIL_MEDIA <<
"About to enter DLZckState for url " << parent._spec.url() << std::endl;
103 void DLZckState::enter()
105 auto &sm = stateMachine();
106 const auto &spec = sm._spec;
111 _failedRanges.clear();
114 _fileSize = spec.expectedFileSize();
116 zypp::AutoFD src_fd = open( spec.deltaFile().asString().c_str(), O_RDONLY);
124 if(!zck_init_read(zck_src, src_fd))
125 return setFailed (
zypp::str::Format(
"Unable to open %1%: %2%") % spec.deltaFile() % zck_get_error(zck_src) );
127 zypp::AutoFD target_fd = open( spec.targetPath().asString().c_str(), O_RDWR);
129 return setFailed (
zypp::str::Format(
"Unable to open %1%") % spec.targetPath() );
135 if(!zck_init_read(zckTarget, target_fd))
136 return setFailed (
zypp::str::Format(
"Unable to open %1%: %2%") % spec.targetPath() % zck_get_error(zckTarget) );
139 switch ( zck_find_valid_chunks(zckTarget) ) {
141 return setFailed (
zypp::str::Format(
"Unable to open %1%: %2%") % spec.targetPath() % zck_get_error(zckTarget) );
143 return setFinished();
146 const auto srcHashType = zck_get_chunk_hash_type( zckTarget );
147 const auto targetHashType = zck_get_chunk_hash_type( zckTarget );
149 const size_t fLen = zck_get_length( zckTarget );
150 if ( _fileSize > 0 ) {
152 if ( _fileSize != fLen ) {
153 return setFailed( NetworkRequestErrorPrivate::customError(
154 NetworkRequestError::ExceededMaxLen,
155 zypp::str::Format(
"Zchunk header reports a different filesize than what was expected ( Zck: %1% != Exp: %2%).") % fLen % _fileSize )
162 const auto maxConns = sm._requestDispatcher->maximumConcurrentConnections();
163 if ( sm._spec.preferredChunkSize() == 0 ) {
164 const auto autoBlkSize = makeBlksize( _fileSize );
165 if ( maxConns == -1 ) {
166 _preferredChunkSize = autoBlkSize;
168 _preferredChunkSize = _fileSize / maxConns;
169 if ( _preferredChunkSize < autoBlkSize )
170 _preferredChunkSize = autoBlkSize;
176 _preferredChunkSize = sm._spec.preferredChunkSize();
179 if( srcHashType != targetHashType )
180 return setFailed (
zypp::str::Format(
"ERROR: Chunk hash types don't match. Source Hash: %1% vs Target Hash: %2%")
181 % zck_hash_name_from_type ( srcHashType )
182 % zck_hash_name_from_type ( targetHashType ) );
184 if(!zck_copy_chunks( zck_src, zckTarget ))
185 return setFailed (
zypp::str::Format(
"Unable to copy chunks from deltafile.") );
188 zck_reset_failed_chunks( zckTarget );
192 _downloadedMultiByteCount = _fileSize;
194 auto chunk = zck_get_first_chunk( zckTarget );
197 if ( zck_get_chunk_valid( chunk ) == 1 )
201 UByteArray chksumVec = zypp::Digest::hexStringToUByteArray( std::string_view( zckDigest.value() ) );
202 std::string chksumName;
203 std::optional<size_t> chksumCompareLen;
205 switch ( targetHashType ) {
206 case ZCK_HASH_SHA1: {
210 case ZCK_HASH_SHA256: {
214 case ZCK_HASH_SHA512: {
218 case ZCK_HASH_SHA512_128: {
222 chksumCompareLen = chksumVec.size();
226 return setFailed (
zypp::str::Format(
"Unsupported chunk hash type: %1%.") % zck_hash_name_from_type( targetHashType ) );
230 const auto s =
static_cast<off_t
>( zck_get_chunk_start( chunk ) );
231 const auto l =
static_cast<size_t>( zck_get_chunk_comp_size ( chunk ) );
233 MIL_MEDIA <<
"Downloading block " << s <<
" with length " << l <<
" checksum " << zckDigest.value() <<
" type " << chksumName << std::endl;
235 _ranges.push_back( Block{
238 .chksumtype = chksumName,
239 .chksumVec = std::move( chksumVec ),
240 .chksumCompareLen = std::move(chksumCompareLen)
244 _downloadedMultiByteCount -= l;
246 }
while ( (chunk = zck_get_next_chunk( chunk )) );
248 ensureDownloadsRunning();
251 void DLZckState::exit()
253 cancelAll( NetworkRequestError() );
256 std::shared_ptr<FinishedState> DLZckState::transitionToFinished()
258 return std::make_shared<FinishedState>( std::move(_error), stateMachine() );
261 void DLZckState::setFinished()
263 const auto &spec = stateMachine()._spec;
265 zypp::AutoFD target_fd = open( spec.targetPath().asString().c_str(), O_RDONLY );
267 return setFailed (
zypp::str::Format(
"Unable to open %1%") % spec.targetPath() );
273 if(!zck_init_read(zckTarget, target_fd))
274 return setFailed (
zypp::str::Format(
"Unable to open %1%: %2%") % spec.targetPath() % zck_get_error(zckTarget) );
278 const auto res = zck_validate_checksums( zckTarget );
279 if ( res == 0 || res == -1 ) {
280 if( zck_is_error(
nullptr) ) {
281 std::string err = zck_get_error(NULL);
282 zck_clear_error(NULL);
283 return setFailed( std::move(err) );
285 if( zck_is_error(zckTarget) )
286 return setFailed( zck_get_error(zckTarget) );
287 return setFailed(
"zck_validate_checksums returned a unknown error." );
291 RangeDownloaderBaseState::setFinished();
Reference counted access to a Tp object calling a custom Dispose function when the last AutoDispose h...
Store and operate with byte count.
static const Unit M
1024^2 Byte
static const std::string & sha512()
sha512
static const std::string & sha1()
sha1
static const std::string & sha256()
sha256
const char * c_str() const
String representation.
AutoDispose<int> calling ::close