libzypp  17.31.31
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 
25 using std::endl;
26 using namespace zypp::base;
27 
28 namespace 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 
41 namespace zypp {
42  namespace media {
43 
44 ZsyncParser::ZsyncParser()
45 {
46  filesize = off_t(-1);
47  blksize = 0;
48  sql = rsl = csl = 0;
49 }
50 
51 static int
52 hexstr2bytes(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 
76 void
77 ZsyncParser::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;
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 
186 std::vector<Url>
187 ZsyncParser::getUrls()
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 
197 ZsyncParser::getBlockList()
198 {
199  return bl;
200 }
201 
202  } // namespace media
203 } // namespace zypp
#define MIL
Definition: Logger.h:96
Definition: Env.h:22
bool ZYPP_METALINK_DEBUG()
Hack to circumvent the currently poor –root support.
#define ZYPP_THROW(EXCPT)
Drops a logline and throws the Exception.
Definition: Exception.h:428
#define c2h(c)
const char * c_str() const
String representation.
Definition: Pathname.h:110
String related utilities and Regular expression matching.
Base class for Exception.
Definition: Exception.h:145
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:1
Url manipulation class.
Definition: Url.h:91
static int hexstr2bytes(unsigned char *buf, const char *str, int buflen)
Definition: zsyncparser.cc:52
#define DBG
Definition: Logger.h:95