libzypp  10.5.0
ZsyncParser.cc
Go to the documentation of this file.
00001 /*---------------------------------------------------------------------\
00002 |                          ____ _   __ __ ___                          |
00003 |                         |__  / \ / / . \ . \                         |
00004 |                           / / \ V /|  _/  _/                         |
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))
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   } // namespace media
00145 } // namespace zypp
00146