libzypp: zypp-curl/parser/zsyncparser.cc Source File

libzypp 17.38.6

zsyncparser.cc
Go to the documentation of this file.
1/*---------------------------------------------------------------------\
2| ____ _ __ __ ___ |
3| |__ / \ / / . \ . \ |
4| / / \ V /| _/ _/ |
5| / /__ | | | | | | |
6| /_____||_| |_| |_| |
7| |
8\---------------------------------------------------------------------*/
12
13#include "zsyncparser.h"
14#include <zypp-core/base/Logger.h>
15
16#include <sys/types.h>
17#include <stdio.h>
18#include <stdlib.h>
19#include <string.h>
20
21#include <vector>
22#include <iostream>
23#include <fstream>
24
25using std::endl;
26using namespace zypp::base;
27
28namespace zypp::env
29{
31 inline bool ZYPP_METALINK_DEBUG()
32 {
33 static bool val = [](){
34 const char * env = getenv("ZYPP_METALINK_DEBUG");
35 return( env && zypp::str::strToBool( env, true ) );
36 }();
37 return val;
38 }
39}
40
41namespace zypp {
42 namespace media {
43
44ZsyncParser::ZsyncParser()
45{
46 filesize = off_t(-1);
47 blksize = 0;
48 sql = rsl = csl = 0;
49}
50
51static int
52 hexstr2bytes(unsigned char *buf, const char *str, int buflen)
53{
54 int i = 0;
55 for (i = 0; i < buflen; i++)
56 {
57#define c2h(c) (((c)>='0' && (c)<='9') ? ((c)-'0') \
58 : ((c)>='a' && (c)<='f') ? ((c)-('a'-10)) \
59 : ((c)>='A' && (c)<='F') ? ((c)-('A'-10)) \
60 : -1)
61 int v = c2h(*str);
62 str++;
63 if (v < 0)
64 return 0;
65 buf[i] = v;
66 v = c2h(*str);
67 str++;
68 if (v < 0)
69 return 0;
70 buf[i] = (buf[i] << 4) | v;
71#undef c2h
72 }
73 return buflen;
74}
75
76void
77ZsyncParser::parse( const Pathname &filename )
78{
79 char buf[4096];
80
81 std::ifstream is(filename.c_str());
82 if (!is)
83 ZYPP_THROW(Exception("ZsyncParser: no such file"));
84 is.exceptions(std::ifstream::eofbit | std::ifstream::failbit | std::ifstream::badbit);
85 off_t filesize = off_t(-1);
86 while (is.good())
87 {
88 is.getline(buf, sizeof(buf));
89 if (!*buf)
90 break;
91 if (!strncmp(buf, "Length: ", 8))
92 filesize = (off_t)strtoull(buf + 8, 0, 10);
93 else if (!strncmp(buf, "Hash-Lengths: ", 14))
94 (void)sscanf(buf + 14, "%d,%d,%d", &sql, &rsl, &csl);
95 else if (!strncmp(buf, "Blocksize: ", 11))
96 blksize = atoi(buf + 11);
97 else if (!strncmp(buf, "URL: http://", 12) || !strncmp(buf, "URL: https://", 13) || !strncmp(buf, "URL: ftp://", 11) || !strncmp(buf, "URL: tftp://", 12) )
98 urls.push_back(buf + 5);
99 else if (!strncmp(buf, "SHA-1: ", 7))
100 {
101 unsigned char sha1[20];
102 if (hexstr2bytes(sha1, buf + 7, 20) == 20)
103 bl.setFileChecksum("SHA1", 20, sha1);
104 }
105 }
106 if (filesize == off_t(-1))
107 ZYPP_THROW(Exception("Parse Error"));
108 if (blksize <= 0 || (blksize & (blksize - 1)) != 0)
109 ZYPP_THROW(Exception("Parse Error: illegal block size"));
110 bl.setFilesize(filesize);
111
112 if (filesize)
113 {
114 if (csl < 3 || csl > 16 || rsl < 1 || rsl > 4 || sql < 1 || sql > 2)
115 ZYPP_THROW(Exception("Parse Error: illegal hash lengths"));
116
117 bl.setRsumSequence( sql );
118
119 size_t nblks = (filesize + blksize - 1) / blksize;
120 size_t i = 0;
121 off_t off = 0;
122 size_t size = blksize;
123 for (i = 0; i < nblks; i++)
124 {
125 if (i == nblks - 1)
126 {
127 size = filesize % blksize;
128 if (!size)
129 size = blksize;
130 }
131 size_t blkno = bl.addBlock(off, size);
132 unsigned char rp[16];
133 rp[0] = rp[1] = rp[2] = rp[3] = 0;
134 try {
135 is.read((char *)rp + 4 - rsl, rsl);
136 } catch ( const std::exception &e ) {
137 if ( !is.good() ) {
138 if (is.bad())
139 throw zypp::Exception( "I/O error while reading" );
140 else if (is.eof())
141 throw zypp::Exception( "End of file reached unexpectedly" );
142 else if (is.fail())
143 throw zypp::Exception( "Non-integer data encountered" );
144 else
145 throw zypp::Exception( "Unknown IO err" );
146 }
147 }
148
149 bl.setRsum(blkno, rsl, rp[0] << 24 | rp[1] << 16 | rp[2] << 8 | rp[3], blksize);
150 try {
151 is.read((char *)rp, csl);
152 } catch ( const std::exception &e ) {
153 if ( !is.good() ) {
154 if (is.bad())
155 throw zypp::Exception( "I/O error while reading" );
156 else if (is.eof())
157 throw zypp::Exception( "End of file reached unexpectedly" );
158 else if (is.fail())
159 throw zypp::Exception( "Non-integer data encountered" );
160 else
161 throw zypp::Exception( "Unknown IO err" );
162 }
163 }
164 if ( !is.good() ) {
165 if (is.bad())
166 throw zypp::Exception( "I/O error while reading" );
167 else if (is.eof())
168 throw zypp::Exception( "End of file reached unexpectedly" );
169 else if (is.fail())
170 throw zypp::Exception( "Non-integer data encountered" );
171 else
172 throw zypp::Exception( "Unknown IO err" );
173 }
174 bl.setChecksum(blkno, "MD4", csl, rp, blksize);
175 off += size;
176 }
177 }
178 is.close();
179 MIL << "Parsed " << urls.size() << " mirrors from " << filename << std::endl;
180 if ( env::ZYPP_METALINK_DEBUG() ) {
181 for ( const auto &url : urls )
182 DBG << "- " << url << std::endl;
183 }
184}
185
186std::vector<Url>
187ZsyncParser::getUrls()
188{
189 std::vector<Url> ret;
190 size_t i = 0;
191 for (i = 0; i < urls.size(); i++)
192 ret.push_back(Url(urls[i]));
193 return ret;
194}
195
196 MediaBlockList
197ZsyncParser::getBlockList()
198{
199 return bl;
200}
201
202 } // namespace media
203} // namespace zypp
ZYPP_THROW
#define ZYPP_THROW(EXCPT)
Drops a logline and throws the Exception.
Definition Exception.h:459
Logger.h
DBG
#define DBG
Definition Logger.h:102
MIL
#define MIL
Definition Logger.h:103
zypp::Exception
Base class for Exception.
Definition Exception.h:153
zypp::Url
Url manipulation class.
Definition Url.h:93
zypp::filesystem::Pathname
Pathname.
Definition Pathname.h:48
zypp::filesystem::Pathname::c_str
const char * c_str() const
String representation.
Definition Pathname.h:113
zypp::media::MediaBlockList
Definition mediablocklist.h:36
zypp::media::ZsyncParser::parse
void parse(const Pathname &filename)
parse a file consisting of zlink data
Definition zsyncparser.cc:77
zypp::media::ZsyncParser::blksize
size_t blksize
Definition zsyncparser.h:45
zypp::media::ZsyncParser::getBlockList
MediaBlockList getBlockList()
return the block list from the parsed metalink data
Definition zsyncparser.cc:197
zypp::media::ZsyncParser::filesize
off_t filesize
Definition zsyncparser.h:44
zypp::media::ZsyncParser::urls
std::vector< std::string > urls
Definition zsyncparser.h:50
zypp::media::ZsyncParser::sql
int sql
Definition zsyncparser.h:46
zypp::media::ZsyncParser::ZsyncParser
ZsyncParser()
Definition zsyncparser.cc:44
zypp::media::ZsyncParser::bl
MediaBlockList bl
Definition zsyncparser.h:49
zypp::media::ZsyncParser::csl
int csl
Definition zsyncparser.h:48
zypp::media::ZsyncParser::getUrls
std::vector< Url > getUrls()
return the download urls from the parsed metalink data
Definition zsyncparser.cc:187
zypp::media::ZsyncParser::rsl
int rsl
Definition zsyncparser.h:47
str
String related utilities and Regular expression matching.
zypp::base
Definition Random.cc:7
zypp::env
Namespace intended to collect all environment variables we use.
Definition RepoVariables.cc:34
zypp::env::ZYPP_METALINK_DEBUG
bool ZYPP_METALINK_DEBUG()
Hack to circumvent the currently poor –root support.
Definition metalinkparser.cc:30
zypp::media
Definition MediaNetworkRequestExecutor.h:22
zypp::media::hexstr2bytes
UByteArray hexstr2bytes(const std::string &str)
Definition metalinkparser.cc:353
zypp::str::strToBool
bool strToBool(const C_Str &str, bool default_r)
Parse str into a bool depending on the default value.
Definition String.h:500
zypp::url
Url details namespace.
Definition UrlBase.cc:58
zypp
Easy-to use interface to the ZYPP dependency resolver.
Definition CodePitfalls.doc:2
string.h
c2h
#define c2h(c)
zsyncparser.h