libzypp  11.13.5
ZsyncParser.cc
Go to the documentation of this file.
1 /*---------------------------------------------------------------------\
2 | ____ _ __ __ ___ |
3 | |__ / \ / / . \ . \ |
4 | / / \ V /| _/ _/ |
5 | / /__ | | | | | | |
6 | /_____||_| |_| |_| |
7 | |
8 \---------------------------------------------------------------------*/
13 #include "zypp/media/ZsyncParser.h"
14 #include "zypp/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 namespace std;
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(string 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(ifstream::eofbit | ifstream::failbit | 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  size_t nblks = (filesize + blksize - 1) / blksize;
104  size_t i;
105  off_t off = 0;
106  size_t size = blksize;
107  for (i = 0; i < nblks; i++)
108  {
109  if (i == nblks - 1)
110  {
111  size = filesize % blksize;
112  if (!size)
113  size = blksize;
114  }
115  size_t blkno = bl.addBlock(off, size);
116  unsigned char rp[16];
117  rp[0] = rp[1] = rp[2] = rp[3] = 0;
118  is.read((char *)rp + 4 - rsl, rsl);
119  bl.setRsum(blkno, rsl, rp[0] << 24 | rp[1] << 16 | rp[2] << 8 | rp[3], blksize);
120  is.read((char *)rp, csl);
121  bl.setChecksum(blkno, "MD4", csl, rp, blksize);
122  off += size;
123  }
124  }
125  is.close();
126 }
127 
128 std::vector<Url>
129 ZsyncParser::getUrls()
130 {
131  std::vector<Url> ret;
132  size_t i;
133  for (i = 0; i < urls.size(); i++)
134  ret.push_back(Url(urls[i]));
135  return ret;
136 }
137 
139 ZsyncParser::getBlockList()
140 {
141  return bl;
142 }
143 
144  } // namespace media
145 } // namespace zypp
146