libzypp  17.31.8
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 {
29  namespace media {
30 
31 ZsyncParser::ZsyncParser()
32 {
33  filesize = off_t(-1);
34  blksize = 0;
35  sql = rsl = csl = 0;
36 }
37 
38 static int
39 hexstr2bytes(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 
63 void
64 ZsyncParser::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"));
97  bl.setFilesize(filesize);
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 
104  bl.setRsumSequence( sql );
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 
168 std::vector<Url>
169 ZsyncParser::getUrls()
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 
179 ZsyncParser::getBlockList()
180 {
181  return bl;
182 }
183 
184  } // namespace media
185 } // namespace zypp
#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
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:39