ZsyncParser.cc
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00013 #include "zypp/media/ZsyncParser.h"
00014 #include "zypp/base/Logger.h"
00015
00016 #include <sys/types.h>
00017 #include <stdio.h>
00018 #include <stdlib.h>
00019 #include <string.h>
00020
00021 #include <vector>
00022 #include <iostream>
00023 #include <fstream>
00024
00025 using namespace std;
00026 using namespace zypp::base;
00027
00028 namespace zypp {
00029 namespace media {
00030
00031 ZsyncParser::ZsyncParser()
00032 {
00033 filesize = off_t(-1);
00034 blksize = 0;
00035 sql = rsl = csl = 0;
00036 }
00037
00038 static int
00039 hexstr2bytes(unsigned char *buf, const char *str, int buflen)
00040 {
00041 int i;
00042 for (i = 0; i < buflen; i++)
00043 {
00044 #define c2h(c) (((c)>='0' && (c)<='9') ? ((c)-'0') \
00045 : ((c)>='a' && (c)<='f') ? ((c)-('a'-10)) \
00046 : ((c)>='A' && (c)<='F') ? ((c)-('A'-10)) \
00047 : -1)
00048 int v = c2h(*str);
00049 str++;
00050 if (v < 0)
00051 return 0;
00052 buf[i] = v;
00053 v = c2h(*str);
00054 str++;
00055 if (v < 0)
00056 return 0;
00057 buf[i] = (buf[i] << 4) | v;
00058 #undef c2h
00059 }
00060 return buflen;
00061 }
00062
00063 void
00064 ZsyncParser::parse(string filename)
00065 {
00066 char buf[4096];
00067
00068 std::ifstream is(filename.c_str());
00069 if (!is)
00070 ZYPP_THROW(Exception("ZsyncParser: no such file"));
00071 is.exceptions(ifstream::eofbit | ifstream::failbit | ifstream::badbit);
00072 off_t filesize = off_t(-1);
00073 while (is.good())
00074 {
00075 is.getline(buf, sizeof(buf));
00076 if (!*buf)
00077 break;
00078 if (!strncmp(buf, "Length: ", 8))
00079 filesize = (off_t)strtoull(buf + 8, 0, 10);
00080 else if (!strncmp(buf, "Hash-Lengths: ", 14))
00081 (void)sscanf(buf + 14, "%d,%d,%d", &sql, &rsl, &csl);
00082 else if (!strncmp(buf, "Blocksize: ", 11))
00083 blksize = atoi(buf + 11);
00084 else if (!strncmp(buf, "URL: http://", 12) || !strncmp(buf, "URL: https://", 13) || !strncmp(buf, "URL: ftp://", 11) || !strncmp(buf, "URL: tftp://", 12) )
00085 urls.push_back(buf + 5);
00086 else if (!strncmp(buf, "SHA-1: ", 7))
00087 {
00088 unsigned char sha1[20];
00089 if (hexstr2bytes(sha1, buf + 7, 20) == 20)
00090 bl.setFileChecksum("SHA1", 20, sha1);
00091 }
00092 }
00093 if (filesize == off_t(-1))
00094 ZYPP_THROW(Exception("Parse Error"));
00095 if (blksize <= 0 || (blksize & (blksize - 1)) != 0)
00096 ZYPP_THROW(Exception("Parse Error: illegal block size"));
00097 bl.setFilesize(filesize);
00098
00099 if (filesize)
00100 {
00101 if (csl < 3 || csl > 16 || rsl < 1 || rsl > 4 || sql < 1 || sql > 2)
00102 ZYPP_THROW(Exception("Parse Error: illegal hash lengths"));
00103 size_t nblks = (filesize + blksize - 1) / blksize;
00104 size_t i;
00105 off_t off = 0;
00106 size_t size = blksize;
00107 for (i = 0; i < nblks; i++)
00108 {
00109 if (i == nblks - 1)
00110 {
00111 size = filesize % blksize;
00112 if (!size)
00113 size = blksize;
00114 }
00115 size_t blkno = bl.addBlock(off, size);
00116 unsigned char rp[16];
00117 rp[0] = rp[1] = rp[2] = rp[3] = 0;
00118 is.read((char *)rp + 4 - rsl, rsl);
00119 bl.setRsum(blkno, rsl, rp[0] << 24 | rp[1] << 16 | rp[2] << 8 | rp[3], blksize);
00120 is.read((char *)rp, csl);
00121 bl.setChecksum(blkno, "MD4", csl, rp, blksize);
00122 off += size;
00123 }
00124 }
00125 is.close();
00126 }
00127
00128 std::vector<Url>
00129 ZsyncParser::getUrls()
00130 {
00131 std::vector<Url> ret;
00132 size_t i;
00133 for (i = 0; i < urls.size(); i++)
00134 ret.push_back(Url(urls[i]));
00135 return ret;
00136 }
00137
00138 MediaBlockList
00139 ZsyncParser::getBlockList()
00140 {
00141 return bl;
00142 }
00143
00144 }
00145 }
00146