libzypp 17.31.7
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 {
29 namespace media {
30
32{
33 filesize = off_t(-1);
34 blksize = 0;
35 sql = rsl = csl = 0;
36}
37
38static int
39hexstr2bytes(unsigned char *buf, const char *str, int buflen)
40{
41 int i;
42 for (i = 0; i < buflen; i++)
43 {
44#define c2h(c) (((c)>='0' && (c)<='9') ? ((c)-'0') \
45 : ((c)>='a' && (c)<='f') ? ((c)-('a'-10)) \
46 : ((c)>='A' && (c)<='F') ? ((c)-('A'-10)) \
47 : -1)
48 int v = c2h(*str);
49 str++;
50 if (v < 0)
51 return 0;
52 buf[i] = v;
53 v = c2h(*str);
54 str++;
55 if (v < 0)
56 return 0;
57 buf[i] = (buf[i] << 4) | v;
58#undef c2h
59 }
60 return buflen;
61}
62
63void
64ZsyncParser::parse( const Pathname &filename )
65{
66 char buf[4096];
67
68 std::ifstream is(filename.c_str());
69 if (!is)
70 ZYPP_THROW(Exception("ZsyncParser: no such file"));
71 is.exceptions(std::ifstream::eofbit | std::ifstream::failbit | std::ifstream::badbit);
72 off_t filesize = off_t(-1);
73 while (is.good())
74 {
75 is.getline(buf, sizeof(buf));
76 if (!*buf)
77 break;
78 if (!strncmp(buf, "Length: ", 8))
79 filesize = (off_t)strtoull(buf + 8, 0, 10);
80 else if (!strncmp(buf, "Hash-Lengths: ", 14))
81 (void)sscanf(buf + 14, "%d,%d,%d", &sql, &rsl, &csl);
82 else if (!strncmp(buf, "Blocksize: ", 11))
83 blksize = atoi(buf + 11);
84 else if (!strncmp(buf, "URL: http://", 12) || !strncmp(buf, "URL: https://", 13) || !strncmp(buf, "URL: ftp://", 11) || !strncmp(buf, "URL: tftp://", 12) )
85 urls.push_back(buf + 5);
86 else if (!strncmp(buf, "SHA-1: ", 7))
87 {
88 unsigned char sha1[20];
89 if (hexstr2bytes(sha1, buf + 7, 20) == 20)
90 bl.setFileChecksum("SHA1", 20, sha1);
91 }
92 }
93 if (filesize == off_t(-1))
94 ZYPP_THROW(Exception("Parse Error"));
95 if (blksize <= 0 || (blksize & (blksize - 1)) != 0)
96 ZYPP_THROW(Exception("Parse Error: illegal block size"));
98
99 if (filesize)
100 {
101 if (csl < 3 || csl > 16 || rsl < 1 || rsl > 4 || sql < 1 || sql > 2)
102 ZYPP_THROW(Exception("Parse Error: illegal hash lengths"));
103
105
106 size_t nblks = (filesize + blksize - 1) / blksize;
107 size_t i;
108 off_t off = 0;
109 size_t size = blksize;
110 for (i = 0; i < nblks; i++)
111 {
112 if (i == nblks - 1)
113 {
114 size = filesize % blksize;
115 if (!size)
116 size = blksize;
117 }
118 size_t blkno = bl.addBlock(off, size);
119 unsigned char rp[16];
120 rp[0] = rp[1] = rp[2] = rp[3] = 0;
121 try {
122 is.read((char *)rp + 4 - rsl, rsl);
123 } catch ( const std::exception &e ) {
124 if ( !is.good() ) {
125 if (is.bad())
126 throw zypp::Exception( "I/O error while reading" );
127 else if (is.eof())
128 throw zypp::Exception( "End of file reached unexpectedly" );
129 else if (is.fail())
130 throw zypp::Exception( "Non-integer data encountered" );
131 else
132 throw zypp::Exception( "Unknown IO err" );
133 }
134 }
135
136 bl.setRsum(blkno, rsl, rp[0] << 24 | rp[1] << 16 | rp[2] << 8 | rp[3], blksize);
137 try {
138 is.read((char *)rp, csl);
139 } catch ( const std::exception &e ) {
140 if ( !is.good() ) {
141 if (is.bad())
142 throw zypp::Exception( "I/O error while reading" );
143 else if (is.eof())
144 throw zypp::Exception( "End of file reached unexpectedly" );
145 else if (is.fail())
146 throw zypp::Exception( "Non-integer data encountered" );
147 else
148 throw zypp::Exception( "Unknown IO err" );
149 }
150 }
151 if ( !is.good() ) {
152 if (is.bad())
153 throw zypp::Exception( "I/O error while reading" );
154 else if (is.eof())
155 throw zypp::Exception( "End of file reached unexpectedly" );
156 else if (is.fail())
157 throw zypp::Exception( "Non-integer data encountered" );
158 else
159 throw zypp::Exception( "Unknown IO err" );
160 }
161 bl.setChecksum(blkno, "MD4", csl, rp, blksize);
162 off += size;
163 }
164 }
165 is.close();
166}
167
168std::vector<Url>
170{
171 std::vector<Url> ret;
172 size_t i;
173 for (i = 0; i < urls.size(); i++)
174 ret.push_back(Url(urls[i]));
175 return ret;
176}
177
180{
181 return bl;
182}
183
184 } // namespace media
185} // 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:64
MediaBlockList getBlockList()
return the block list from the parsed metalink data
Definition: zsyncparser.cc:179
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:169
String related utilities and Regular expression matching.
UByteArray hexstr2bytes(std::string str)
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