libzypp 17.31.23
zsyncparser.cc
Go to the documentation of this file.
1/*---------------------------------------------------------------------\
2| ____ _ __ __ ___ |
3| |__ / \ / / . \ . \ |
4| / / \ V /| _/ _/ |
5| / /__ | | | | | | |
6| /_____||_| |_| |_| |
7| |
8\---------------------------------------------------------------------*/
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
45{
46 filesize = off_t(-1);
47 blksize = 0;
48 sql = rsl = csl = 0;
49}
50
51static int
52hexstr2bytes(unsigned char *buf, const char *str, int buflen)
53{
54 int i;
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"));
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
118
119 size_t nblks = (filesize + blksize - 1) / blksize;
120 size_t i;
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>
188{
189 std::vector<Url> ret;
190 size_t i;
191 for (i = 0; i < urls.size(); i++)
192 ret.push_back(Url(urls[i]));
193 return ret;
194}
195
198{
199 return bl;
200}
201
202 } // namespace media
203} // namespace zypp
Base class for Exception.
Definition: Exception.h:146
Url manipulation class.
Definition: Url.h:92
const char * c_str() const
String representation.
Definition: Pathname.h:110
void setRsum(size_t blkno, int rsl, unsigned int rs, size_t rspad=0)
set / verify the (weak) rolling checksum over a single block
void setFileChecksum(std::string ctype, int cl, unsigned char *c)
set / verify the checksum over the whole file
void setRsumSequence(uint seq)
how many blocks in sequence need to have the correct checksums to be considered a match
size_t addBlock(off_t off, size_t size)
add a block with offset off and size size to the block list.
void setChecksum(size_t blkno, std::string cstype, int csl, unsigned char *cs, size_t cspad=0)
set / verify the (strong) checksum over a single block
void setFilesize(off_t newfilesize=off_t(-1))
set / return the size of the whole file
void parse(const Pathname &filename)
parse a file consisting of zlink data
Definition: zsyncparser.cc:77
MediaBlockList getBlockList()
return the block list from the parsed metalink data
Definition: zsyncparser.cc:197
std::vector< std::string > urls
Definition: zsyncparser.h:50
std::vector< Url > getUrls()
return the download urls from the parsed metalink data
Definition: zsyncparser.cc:187
String related utilities and Regular expression matching.
Definition: Env.h:23
bool ZYPP_METALINK_DEBUG()
Hack to circumvent the currently poor –root support.
UByteArray hexstr2bytes(std::string str)
bool strToBool(const C_Str &str, bool default_r)
Parse str into a bool depending on the default value.
Definition: String.h:429
Easy-to use interface to the ZYPP dependency resolver.
Definition: CodePitfalls.doc:2
#define c2h(c)
#define ZYPP_THROW(EXCPT)
Drops a logline and throws the Exception.
Definition: Exception.h:428
#define DBG
Definition: Logger.h:95
#define MIL
Definition: Logger.h:96