libzypp
10.5.0
|
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