14 #include <sys/types.h> 18 #include <arpa/inet.h> 27 #include <zypp/base/Logger.h> 29 #include <zypp-core/zyppng/base/private/linuxhelpers_p.h> 30 #include <zypp-curl/parser/MetaLinkParser> 32 #include <zypp/ManagedFile.h> 34 #include <zypp-curl/auth/CurlAuthData> 41 #undef CURLVERSION_AT_LEAST 42 #define CURLVERSION_AT_LEAST(M,N,O) LIBCURL_VERSION_NUM >= ((((M)<<8)+(N))<<8)+(O) 170 bool recheckChecksum( off_t blockIdx );
175 void disableCompetition();
181 void adddnsfd( std::vector<GPollFD> &waitFds );
182 void dnsevent(
const std::vector<GPollFD> &waitFds );
187 bool _competing =
false;
196 size_t _datasize = 0;
198 double _starttime = 0;
199 size_t _datareceived = 0;
202 double _avgspeed = 0;
203 double _maxspeed = 0;
205 double _sleepuntil = 0;
213 size_t writefunction (
char *ptr, std::optional<off_t> offset,
size_t bytes )
override;
214 size_t headerfunction (
char *ptr,
size_t bytes )
override;
215 bool beginRange ( off_t range, std::string &cancelReason )
override;
216 bool finishedRange ( off_t range,
bool validated, std::string &cancelReason )
override;
231 void run(std::vector<Url> &urllist);
232 static ByteCount makeBlksize( uint maxConns,
size_t filesize );
253 CURLM *_multi =
nullptr;
255 std::list< std::unique_ptr<multifetchworker> >
_workers;
256 bool _stealing =
false;
257 bool _havenewjob =
false;
262 size_t _activeworkers = 0;
263 size_t _lookupworkers = 0;
264 size_t _sleepworkers = 0;
265 double _minsleepuntil = 0;
266 bool _finished =
false;
268 off_t _totalsize = 0;
269 off_t _fetchedsize = 0;
270 off_t _fetchedgoodsize = 0;
272 double _starttime = 0;
273 double _lastprogress = 0;
275 double _lastperiodstart = 0;
276 double _lastperiodfetched = 0;
277 double _periodavg = 0;
281 double _connect_timeout = 0;
282 double _maxspeed = 0;
294 #if _POSIX_C_SOURCE >= 199309L 296 if ( clock_gettime( CLOCK_MONOTONIC, &ts) )
298 return ts.tv_sec + ts.tv_nsec / 1000000000.;
301 if (gettimeofday(&tv, NULL))
303 return tv.tv_sec + tv.tv_usec / 1000000.;
308 multifetchworker::writefunction(
char *ptr, std::optional<off_t> offset,
size_t bytes)
311 return bytes ? 0 : 1;
316 _datareceived += bytes;
318 _request->_lastprogress = now;
320 const auto &currRange = _multiByteHandler->currentRange();
324 auto &stripeDesc = _request->_requiredStripes[_stripe];
325 if ( !_request->_fp || stripeDesc.blockStates[ _rangeToStripeBlock[*currRange] ] == Stripe::FINALIZED ) {
333 const auto &blk = _blocks[*currRange];
334 off_t seekTo = blk.start + blk.bytesWritten;
336 if ( ftell( _request->_fp ) != seekTo ) {
338 if (fseeko(_request->_fp, seekTo, SEEK_SET))
339 return bytes ? 0 : 1;
342 size_t cnt = fwrite(ptr, 1, bytes, _request->_fp);
343 _request->_fetchedsize += cnt;
347 bool multifetchworker::beginRange ( off_t workerRangeOff, std::string &cancelReason )
349 auto &stripeDesc = _request->_requiredStripes[_stripe];
350 auto stripeRangeOff = _rangeToStripeBlock[workerRangeOff];
351 const auto &currRangeState = stripeDesc.blockStates[stripeRangeOff];
353 if ( currRangeState == Stripe::FINALIZED ){
354 cancelReason =
"Cancelled because stripe block is already finalized";
356 WAR <<
"#" << _workerno <<
": trying to start a range ("<<stripeRangeOff<<
"["<< _blocks[workerRangeOff].start <<
" : "<<_blocks[workerRangeOff].len<<
"]) that was already finalized, cancelling. Stealing was: " << _request->_stealing << endl;
359 stripeDesc.blockStates[stripeRangeOff] = currRangeState == Stripe::PENDING ? Stripe::FETCH : Stripe::COMPETING;
363 bool multifetchworker::finishedRange ( off_t workerRangeOff,
bool validated, std::string &cancelReason )
365 auto &stripeDesc = _request->_requiredStripes[_stripe];
366 auto stripeRangeOff = _rangeToStripeBlock[workerRangeOff];
367 const auto &currRangeState = stripeDesc.blockStates[stripeRangeOff];
371 cancelReason =
"Block failed to validate";
375 if ( currRangeState == Stripe::FETCH ) {
377 stripeDesc.blockStates[stripeRangeOff] = Stripe::FINALIZED;
378 _request->_fetchedgoodsize += _blocks[workerRangeOff].len;
381 if ( recheckChecksum ( workerRangeOff ) ) {
382 stripeDesc.blockStates[stripeRangeOff] = Stripe::FINALIZED;
383 _request->_fetchedgoodsize += _blocks[workerRangeOff].len;
387 WAR <<
"#" << _workerno <<
": Broken data in COMPETING block, requesting refetch. Stealing is: " << _request->_stealing << endl;
388 stripeDesc.blockStates[stripeRangeOff] = Stripe::REFETCH;
395 multifetchworker::headerfunction(
char *p,
size_t bytes )
398 if (l > 9 && !strncasecmp(p,
"Location:", 9)) {
399 std::string line(p + 9, l - 9);
400 if (line[l - 10] ==
'\r')
401 line.erase(l - 10, 1);
402 XXX <<
"#" << _workerno <<
": redirecting to" << line << endl;
406 const auto &repSize = _multiByteHandler->reportedFileSize ();
407 if ( repSize && *repSize != _request->_filesize ) {
408 XXX <<
"#" << _workerno <<
": filesize mismatch" << endl;
410 strncpy(_curlError,
"filesize mismatch", CURL_ERROR_SIZE);
420 , _maxspeed( request._maxspeed )
421 , _request ( &request )
427 XXX <<
"reused worker from pool" << endl;
431 strncpy(
_curlError,
"curl_easy_init failed", CURL_ERROR_SIZE);
447 curl_easy_cleanup(
_curl);
450 strncpy(
_curlError,
"curl_easy_setopt failed", CURL_ERROR_SIZE);
453 curl_easy_setopt(
_curl, CURLOPT_PRIVATE,
this);
466 if (use_auth.empty())
467 use_auth =
"digest,basic";
469 if( auth != CURLAUTH_NONE)
471 XXX <<
"#" <<
_workerno <<
": Enabling HTTP authentication methods: " << use_auth
472 <<
" (CURLOPT_HTTPAUTH=" << auth <<
")" << std::endl;
473 curl_easy_setopt(
_curl, CURLOPT_HTTPAUTH, auth);
488 #if CURLVERSION_AT_LEAST(7,15,5) 489 curl_easy_setopt(
_curl, CURLOPT_MAX_RECV_SPEED_LARGE, (curl_off_t)0);
491 curl_easy_setopt(
_curl, CURLOPT_PRIVATE, (
void *)0);
492 curl_easy_setopt(
_curl, CURLOPT_WRITEFUNCTION, (
void *)0);
493 curl_easy_setopt(
_curl, CURLOPT_WRITEDATA, (
void *)0);
494 curl_easy_setopt(
_curl, CURLOPT_HEADERFUNCTION, (
void *)0);
495 curl_easy_setopt(
_curl, CURLOPT_HEADERDATA, (
void *)0);
499 curl_easy_cleanup(
_curl);
506 while (waitpid(
_pid, &status, 0) == -1)
523 const char *s = getenv(name.c_str());
524 return s && *s ? true :
false;
540 if (inet_pton(AF_INET, host.c_str(), addrbuf) == 1)
542 if (inet_pton(AF_INET6, host.c_str(), addrbuf) == 1)
553 if (schemeproxy !=
"http_proxy")
555 std::transform(schemeproxy.begin(), schemeproxy.end(), schemeproxy.begin(), ::toupper);
560 XXX <<
"checking DNS lookup of " << host << endl;
565 strncpy(
_curlError,
"DNS pipe creation failed", CURL_ERROR_SIZE);
569 if (
_pid == pid_t(-1))
575 strncpy(
_curlError,
"DNS checker fork failed", CURL_ERROR_SIZE);
582 struct addrinfo *ai, aihints;
583 memset(&aihints, 0,
sizeof(aihints));
584 aihints.ai_family = PF_UNSPEC;
585 int tstsock = socket(PF_INET6, SOCK_DGRAM | SOCK_CLOEXEC, 0);
587 aihints.ai_family = PF_INET;
590 aihints.ai_socktype = SOCK_STREAM;
591 aihints.ai_flags = AI_CANONNAME;
594 alarm(connecttimeout);
595 signal(SIGALRM, SIG_DFL);
596 if (getaddrinfo(host.c_str(), NULL, &aihints, &ai))
614 .events = G_IO_IN | G_IO_HUP | G_IO_ERR,
622 bool hasEvent =
std::any_of( waitFds.begin (), waitFds.end(),[
this](
const GPollFD &waitfd ){
623 return ( waitfd.fd ==
_dnspipe && waitfd.revents != 0 );
629 while (waitpid(
_pid, &status, 0) == -1)
640 if (!WIFEXITED(status))
643 strncpy(
_curlError,
"DNS lookup failed", CURL_ERROR_SIZE);
647 int exitcode = WEXITSTATUS(status);
648 XXX <<
"#" <<
_workerno <<
": DNS lookup returned " << exitcode << endl;
652 strncpy(
_curlError,
"DNS lookup failed", CURL_ERROR_SIZE);
666 auto &blk =
_blocks[workerRangeIdx];
682 size_t cnt = l >
sizeof(buf) ?
sizeof(buf) : l;
692 blk._digest = std::move(newDig);
707 std::optional<zypp::Digest> digest;
708 std::optional<size_t> relDigLen;
709 std::optional<size_t> blkSumPad;
714 relDigLen = sum.size( );
726 std::move(relDigLen),
727 std::move(blkSumPad) );
734 XXX <<
"start stealing!" << endl;
748 if (worker->
_pass == -1)
815 XXX <<
"#" <<
_workerno <<
": going to sleep for " << sl * 1000 <<
" ms" << endl;
872 for ( uint i = 0; i < stripeDesc.blocks.size(); i++ ) {
892 DBG <<
"#" <<
_workerno <<
"Done adding blocks to download, going to download: " <<
_blocks.size() <<
" nr of block with " <<
_datasize <<
" nr of bytes" << std::endl;
903 bool hadRangeFail =
_multiByteHandler->lastError() == MultiByteHandler::Code::RangeFail;
909 if ( hadRangeFail ) {
916 curl_easy_reset(
_curl );
941 strncpy(
_curlError,
"curl_multi_add_handle failed", CURL_ERROR_SIZE );
955 , _filename(filename)
959 , _blklist(
std::move(blklist))
960 , _filesize(filesize)
963 , _timeout(context->_settings.timeout())
964 , _connect_timeout(context->_settings.connectTimeout())
965 , _maxspeed(context->_settings.maxDownloadSpeed())
966 , _maxworkers(context->_settings.maxConcurrentConnections())
993 currStripeSize += blk.
size;
1008 std::vector<Url>::iterator urliter = urllist.begin();
1010 struct CurlMuliSockHelper {
1012 curl_multi_setopt( _parent._multi, CURLMOPT_SOCKETFUNCTION, socketcb );
1013 curl_multi_setopt( _parent._multi, CURLMOPT_SOCKETDATA,
this );
1014 curl_multi_setopt( _parent._multi, CURLMOPT_TIMERFUNCTION, timercb );
1015 curl_multi_setopt( _parent._multi, CURLMOPT_TIMERDATA,
this );
1018 ~CurlMuliSockHelper() {
1019 curl_multi_setopt( _parent._multi, CURLMOPT_SOCKETFUNCTION,
nullptr );
1020 curl_multi_setopt( _parent._multi, CURLMOPT_SOCKETDATA,
nullptr );
1021 curl_multi_setopt( _parent._multi, CURLMOPT_TIMERFUNCTION,
nullptr );
1022 curl_multi_setopt( _parent._multi, CURLMOPT_TIMERDATA,
nullptr );
1025 static int socketcb (CURL * easy, curl_socket_t s,
int what, CurlMuliSockHelper *userp,
void *sockp ) {
1026 auto it = std::find_if( userp->socks.begin(), userp->socks.end(), [&](
const GPollFD &fd){
return fd.fd == s; });
1028 if ( what == CURL_POLL_REMOVE ) {
1029 if ( it == userp->socks.end() ) {
1030 WAR <<
"Ignoring unknown socket in static_socketcb" << std::endl;
1033 userp->socks.erase(it);
1035 }
else if ( what == CURL_POLL_IN ) {
1036 events = G_IO_IN | G_IO_HUP | G_IO_ERR;
1037 }
else if ( what == CURL_POLL_OUT ) {
1038 events = G_IO_OUT | G_IO_ERR;
1039 }
else if ( what == CURL_POLL_INOUT ) {
1040 events = G_IO_IN | G_IO_OUT | G_IO_HUP | G_IO_ERR;
1043 if ( it != userp->socks.end() ) {
1044 it->events = events;
1047 userp->socks.push_back(
1060 static int timercb( CURLM *,
long timeout_ms, CurlMuliSockHelper *thatPtr ) {
1063 if ( timeout_ms == -1 )
1064 thatPtr->timeout_ms.reset();
1066 thatPtr->timeout_ms = timeout_ms;
1071 std::vector<GPollFD> socks;
1072 std::optional<long> timeout_ms = 0;
1073 } _curlHelper(*
this) ;
1077 CURLMcode mcode = curl_multi_socket_action(
_multi, CURL_SOCKET_TIMEOUT, 0, &handles );
1078 if (mcode != CURLM_OK)
1084 std::vector<GPollFD> waitFds;
1089 XXX <<
"finished!" << endl;
1096 _workers.push_back(std::make_unique<multifetchworker>(workerno++, *
this, *urliter));
1113 WAR <<
"No more active workers!" << endl;
1115 for (
auto workeriter =
_workers.begin(); workeriter !=
_workers.end(); ++workeriter)
1125 for (
auto workeriter =
_workers.begin(); workeriter !=
_workers.end(); ++workeriter)
1126 (*workeriter)->adddnsfd( waitFds );
1133 for (
auto workeriter =
_workers.begin(); workeriter !=
_workers.end(); ++workeriter) {
1147 timeoutMs = sl * 1000;
1150 if ( _curlHelper.timeout_ms.has_value() )
1151 timeoutMs = std::min<long>( timeoutMs, _curlHelper.timeout_ms.value() );
1153 dnsFdCount = waitFds.size();
1154 waitFds.insert( waitFds.end(), _curlHelper.socks.begin(), _curlHelper.socks.end() );
1156 int r = zyppng::eintrSafeCall( g_poll, waitFds.data(), waitFds.size(), timeoutMs );
1160 for (
auto workeriter =
_workers.begin(); workeriter !=
_workers.end(); ++workeriter)
1165 (*workeriter)->
dnsevent( waitFds );
1175 CURLMcode mcode = curl_multi_socket_action(
_multi, CURL_SOCKET_TIMEOUT, 0, &handles );
1176 if (mcode != CURLM_OK)
1179 for (
int sock = dnsFdCount; sock < waitFds.size(); sock++ ) {
1180 const auto &waitFd = waitFds[sock];
1181 if ( waitFd.revents == 0 )
1185 if ( (waitFd.revents & G_IO_HUP) == G_IO_HUP
1186 || (waitFd.revents & G_IO_IN) == G_IO_IN ) {
1187 ev = CURL_CSELECT_IN;
1189 if ( (waitFd.revents & G_IO_OUT) == G_IO_OUT ) {
1190 ev |= CURL_CSELECT_OUT;
1192 if ( (waitFd.revents & G_IO_ERR) == G_IO_ERR ) {
1193 ev |= CURL_CSELECT_ERR;
1197 CURLMcode mcode = curl_multi_socket_action(
_multi, waitFd.fd, ev, &runn );
1198 if (mcode != CURLM_OK)
1219 for (
auto workeriter =
_workers.begin(); workeriter !=
_workers.end(); ++workeriter)
1228 XXX <<
"#" << worker->
_workerno <<
": sleep done, wake up" << endl;
1238 while ((msg = curl_multi_info_read(
_multi, &nqueue)) != 0)
1240 if (msg->msg != CURLMSG_DONE)
1242 CURL *easy = msg->easy_handle;
1243 CURLcode cc = msg->data.result;
1246 if (curl_easy_getinfo(easy, CURLINFO_PRIVATE, &worker) != CURLE_OK)
1257 curl_multi_remove_handle(
_multi, easy);
1259 const auto &setWorkerBroken = [&](
const std::string &
str = {} ){
1261 if ( !
str.empty () )
1272 WAR <<
"#" << worker->
_workerno <<
": has no multibyte handler, this is a bug" << endl;
1273 setWorkerBroken(
"Multibyte handler error");
1282 WAR <<
"#" << worker->
_workerno <<
": still has work to do or can recover from a error, continuing the job!" << endl;
1293 if ( cc != CURLE_OK ) {
1299 WAR <<
"#" << worker->
_workerno <<
": failed, but was set to discard, reusing for new requests" << endl;
1318 bool done = std::all_of( wrkerStripe.blockStates.begin(), wrkerStripe.blockStates.begin(), [](
const Stripe::RState s ) {
return s ==
Stripe::FINALIZED; } );
1321 std::for_each( wrkerStripe.blockStates.begin(), wrkerStripe.blockStates.begin(), [](
Stripe::RState &s ) {
1334 int maxworkerno = 0;
1336 for (
auto workeriter =
_workers.begin(); workeriter !=
_workers.end(); ++workeriter)
1351 double ratio = worker->
_avgspeed / maxavg;
1354 ratio = ratio * ratio;
1357 XXX <<
"#" << worker->
_workerno <<
": too slow ("<< ratio <<
", " << worker->
_avgspeed <<
", #" << maxworkerno <<
": " << maxavg <<
"), going to sleep for " << ratio * 1000 <<
" ms" << endl;
1378 #if CURLVERSION_AT_LEAST(7,15,5) 1379 curl_easy_setopt(worker->
_curl, CURLOPT_MAX_RECV_SPEED_LARGE, (curl_off_t)(avg));
1411 WAR <<
"overall result" << endl;
1412 for (
auto workeriter =
_workers.begin(); workeriter !=
_workers.end(); ++workeriter)
1430 MIL <<
"MediaMultiCurl::MediaMultiCurl(" << url_r <<
", " << attach_point_hint_r <<
")" << endl;
1444 curl_multi_cleanup(
_multi);
1447 std::map<std::string, CURL *>::iterator it;
1450 CURL *easy = it->second;
1453 curl_easy_cleanup(easy);
1469 for (; sl; sl = sl->next)
1487 if ( curl_easy_getinfo(
_curl, CURLINFO_PRIVATE, &fp ) != CURLE_OK || !fp )
1489 if ( ftell( fp ) == 0 )
1494 long httpReturnCode = 0;
1495 if (curl_easy_getinfo(
_curl, CURLINFO_RESPONSE_CODE, &httpReturnCode ) != CURLE_OK || httpReturnCode == 0)
1499 bool ismetalink =
false;
1500 if (curl_easy_getinfo(
_curl, CURLINFO_CONTENT_TYPE, &ptr) == CURLE_OK && ptr)
1502 std::string ct = std::string(ptr);
1503 if (ct.find(
"application/x-zsync") == 0 || ct.find(
"application/metalink+xml") == 0 || ct.find(
"application/metalink4+xml") == 0)
1506 if (!ismetalink && dlnow < 256)
1515 DBG <<
"looks_like_meta_file: " << ismetalink << endl;
1534 DBG <<
"assert_dir " << dest.
dirname() <<
" failed" << endl;
1544 ERR <<
"out of memory for temp file name" << endl;
1548 AutoFD tmp_fd { ::mkostemp( buf, O_CLOEXEC ) };
1551 ERR <<
"mkstemp failed for file '" << destNew <<
"'" << endl;
1556 file = ::fdopen( tmp_fd,
"we" );
1559 ERR <<
"fopen failed for file '" << destNew <<
"'" << endl;
1562 tmp_fd.resetDispose();
1565 DBG <<
"dest: " << dest << endl;
1566 DBG <<
"temp: " << destNew << endl;
1571 curl_easy_setopt(
_curl, CURLOPT_TIMECONDITION, CURL_TIMECOND_IFMODSINCE);
1572 curl_easy_setopt(
_curl, CURLOPT_TIMEVALUE, (
long)
PathInfo(target).mtime());
1576 curl_easy_setopt(
_curl, CURLOPT_TIMECONDITION, CURL_TIMECOND_NONE);
1577 curl_easy_setopt(
_curl, CURLOPT_TIMEVALUE, 0L);
1583 curl_easy_setopt(
_curl, CURLOPT_PRIVATE, (*file) );
1590 curl_easy_setopt(
_curl, CURLOPT_TIMECONDITION, CURL_TIMECOND_NONE);
1591 curl_easy_setopt(
_curl, CURLOPT_TIMEVALUE, 0L);
1593 curl_easy_setopt(
_curl, CURLOPT_PRIVATE, (
void *)0);
1596 curl_easy_setopt(
_curl, CURLOPT_TIMECONDITION, CURL_TIMECOND_NONE);
1597 curl_easy_setopt(
_curl, CURLOPT_TIMEVALUE, 0L);
1599 curl_easy_setopt(
_curl, CURLOPT_PRIVATE, (
void *)0);
1600 long httpReturnCode = 0;
1601 CURLcode infoRet = curl_easy_getinfo(
_curl, CURLINFO_RESPONSE_CODE, &httpReturnCode);
1602 if (infoRet == CURLE_OK)
1605 if ( httpReturnCode == 304
1608 DBG <<
"not modified: " <<
PathInfo(dest) << endl;
1614 WAR <<
"Could not get the response code." << endl;
1620 if (curl_easy_getinfo(
_curl, CURLINFO_CONTENT_TYPE, &ptr) == CURLE_OK && ptr)
1622 std::string ct = std::string(ptr);
1623 if (ct.find(
"application/x-zsync") == 0 )
1625 else if (ct.find(
"application/metalink+xml") == 0 || ct.find(
"application/metalink4+xml") == 0)
1639 bool userabort =
false;
1645 std::vector<Url> urls;
1648 parser.
parse( destNew );
1665 XXX <<
"With no blocks" << std::endl;
1672 XXX <<
"No filesize in metalink file and no expected filesize, aborting multicurl." << std::endl;
1677 Disabling
this workaround
for now, since we now
do zip ranges into bigger requests
1688 file = fopen((*destNew).c_str(),
"w+e");
1693 XXX <<
"reusing blocks from file " << target << endl;
1699 XXX <<
"reusing blocks from file " << failedFile << endl;
1707 XXX <<
"reusing blocks from file " <<
df << endl;
1717 userabort = ex.
errstr() ==
"User abort";
1728 WAR<<
"Failed to multifetch file " << ex <<
" falling back to single Curl download!" << std::endl;
1729 if (
PathInfo(destNew).size() >= 63336)
1738 file = fopen((*destNew).c_str(),
"w+e");
1750 ERR <<
"Failed to chmod file " << destNew << endl;
1757 ERR <<
"Fclose failed for file '" << destNew <<
"'" << endl;
1761 if (
rename( destNew, dest ) != 0 )
1763 ERR <<
"Rename failed" << endl;
1766 destNew.resetDispose();
1774 if (filesize == off_t(-1) && blklist.haveFilesize())
1775 filesize = blklist.getFilesize();
1776 if (!blklist.haveBlocks() && filesize != 0) {
1777 if ( filesize == -1 ) {
1782 MIL <<
"Generate blocklist, since there was none in the metalink file." << std::endl;
1787 while ( currOff < filesize ) {
1789 auto blksize = filesize - currOff ;
1790 if ( blksize > prefSize )
1793 blklist.addBlock( currOff, blksize );
1797 XXX <<
"Generated blocklist: " << std::endl << blklist << std::endl <<
" End blocklist " << std::endl;
1800 if (filesize == 0 || !blklist.numBlocks()) {
1809 _multi = curl_multi_init();
1815 std::vector<Url> myurllist;
1816 for (std::vector<Url>::iterator urliter = urllist->begin(); urliter != urllist->end(); ++urliter)
1820 std::string scheme = urliter->getScheme();
1821 if (scheme ==
"http" || scheme ==
"https" || scheme ==
"ftp" || scheme ==
"tftp")
1831 if (!myurllist.size())
1832 myurllist.push_back(baseurl);
1841 if (fseeko(fp, off_t(0), SEEK_SET))
1847 while ((l = fread(buf, 1,
sizeof(buf), fp)) > 0)
1855 return _dnsok.find(host) ==
_dnsok.end() ? false :
true;
1877 curl_easy_cleanup(oldeasy);
std::string getScheme() const
Returns the scheme name of the URL.
int assert_dir(const Pathname &path, unsigned mode)
Like 'mkdir -p'.
The CurlMultiPartHandler class.
#define ZYPP_THROW(EXCPT)
Drops a logline and throws the Exception.
static ZConfig & instance()
Singleton ctor.
zypp::Url propagateQueryParams(zypp::Url url_r, const zypp::Url &template_r)
Compute Message Digests (MD5, SHA1 etc)
Store and operate with byte count.
static Range make(size_t start, size_t len=0, std::optional< zypp::Digest > &&digest={}, CheckSumBytes &&expectedChkSum=CheckSumBytes(), std::any &&userData=std::any(), std::optional< size_t > digestCompareLen={}, std::optional< size_t > _dataBlockPadding={})
Pathname extend(const std::string &r) const
Append string r to the last component of the path.
String related utilities and Regular expression matching.
AutoDispose< const Pathname > ManagedFile
A Pathname plus associated cleanup code to be executed when path is no longer needed.
static const Unit MB
1000^2 Byte
AutoDispose<int> calling ::close
std::optional< KeyManagerCtx > _context
#define ZYPP_RETHROW(EXCPT)
Drops a logline and rethrows, updating the CodeLocation.
std::string asString() const
Returns a default string representation of the Url object.
int unlink(const Pathname &path)
Like 'unlink'.
const std::string & asString() const
String representation.
int rename(const Pathname &oldpath, const Pathname &newpath)
Like 'rename'.
bool isExist() const
Return whether valid stat info exists.
Pathname repoCachePath() const
Path where the caches are kept (/var/cache/zypp)
Pathname dirname() const
Return all but the last component od this path.
int hardlinkCopy(const Pathname &oldpath, const Pathname &newpath)
Create newpath as hardlink or copy of oldpath.
std::string numstring(char n, int w=0)
std::string asString(unsigned field_width_r=0, unsigned unit_width_r=1) const
Auto selected Unit and precision.
void resetDispose()
Set no dispose function.
Pathname absolutename() const
Return this path, adding a leading '/' if relative.
Base class for Exception.
bool any_of(const Container &c, Fnc &&cb)
std::string getHost(EEncoding eflag=zypp::url::E_DECODED) const
Returns the hostname or IP from the URL authority.
static const Unit K
1024 Byte
Wrapper class for ::stat/::lstat.
AutoDispose<FILE*> calling ::fclose
AutoDispose< void * > _state
mode_t applyUmaskTo(mode_t mode_r)
Modify mode_r according to the current umask ( mode_r & ~getUmask() ).
Digest clone() const
Returns a clone of the current Digest and returns it.
Easy-to use interface to the ZYPP dependency resolver.
bool update(const char *bytes, size_t len)
feed data into digest computation algorithm
ByteCount df(const Pathname &path_r)
Report free disk space on a mounted file system.