diff options
author | Michael Vogt <mvo@ubuntu.com> | 2014-11-06 08:55:06 +0100 |
---|---|---|
committer | Michael Vogt <mvo@ubuntu.com> | 2014-11-06 08:55:06 +0100 |
commit | 9397ea947c23c0957a683152360909810340abce (patch) | |
tree | 6b29e35b9ef602c15d0aab20eefdec3138eb4692 /apt-pkg/contrib | |
parent | 87ecd6a2d719aeaeedd99dd500b467e966376f1c (diff) | |
parent | 6e2261d0f250406058d66b360080aa986953ae19 (diff) |
Merge remote-tracking branch 'upstream/debian/experimental' into feature/no-more-acquire-guessing
Conflicts:
apt-pkg/acquire-item.cc
Diffstat (limited to 'apt-pkg/contrib')
-rw-r--r-- | apt-pkg/contrib/hashes.cc | 32 | ||||
-rw-r--r-- | apt-pkg/contrib/hashes.h | 4 | ||||
-rw-r--r-- | apt-pkg/contrib/strutl.cc | 124 |
3 files changed, 95 insertions, 65 deletions
diff --git a/apt-pkg/contrib/hashes.cc b/apt-pkg/contrib/hashes.cc index 417982343..55180c642 100644 --- a/apt-pkg/contrib/hashes.cc +++ b/apt-pkg/contrib/hashes.cc @@ -29,7 +29,7 @@ const char * HashString::_SupportedHashes[] = { - "SHA512", "SHA256", "SHA1", "MD5Sum", NULL + "SHA512", "SHA256", "SHA1", "MD5Sum", "Checksum-FileSize", NULL }; HashString::HashString() @@ -111,6 +111,8 @@ std::string HashString::GetHashForFile(std::string filename) const /*{{{*/ SHA512.AddFD(Fd); fileHash = (std::string)SHA512.Result(); } + else if (strcasecmp(Type.c_str(), "Checksum-FileSize") == 0) + strprintf(fileHash, "%llu", Fd.FileSize()); Fd.Close(); return fileHash; @@ -147,7 +149,13 @@ bool HashStringList::usable() const /*{{{*/ return false; std::string const forcedType = _config->Find("Acquire::ForceHash", ""); if (forcedType.empty() == true) - return true; + { + // FileSize alone isn't usable + for (std::vector<HashString>::const_iterator hs = list.begin(); hs != list.end(); ++hs) + if (hs->HashType() != "Checksum-FileSize") + return true; + return false; + } return find(forcedType) != NULL; } /*}}}*/ @@ -201,6 +209,9 @@ bool HashStringList::VerifyFile(std::string filename) const /*{{{*/ HashString const * const hs = find(NULL); if (hs == NULL || hs->VerifyFile(filename) == false) return false; + HashString const * const hsf = find("Checksum-FileSize"); + if (hsf != NULL && hsf->VerifyFile(filename) == false) + return false; return true; } /*}}}*/ @@ -235,6 +246,14 @@ bool HashStringList::operator!=(HashStringList const &other) const } /*}}}*/ +// PrivateHashes /*{{{*/ +class PrivateHashes { +public: + unsigned long long FileSize; + + PrivateHashes() : FileSize(0) {} +}; + /*}}}*/ // Hashes::Add* - Add the contents of data or FD /*{{{*/ bool Hashes::Add(const unsigned char * const Data,unsigned long long const Size, unsigned int const Hashes) { @@ -254,6 +273,7 @@ bool Hashes::Add(const unsigned char * const Data,unsigned long long const Size, #if __GNUC__ >= 4 #pragma GCC diagnostic pop #endif + d->FileSize += Size; return Res; } bool Hashes::AddFD(int const Fd,unsigned long long Size, unsigned int const Hashes) @@ -314,15 +334,17 @@ HashStringList Hashes::GetHashStringList() #if __GNUC__ >= 4 #pragma GCC diagnostic pop #endif + std::string SizeStr; + strprintf(SizeStr, "%llu", d->FileSize); + hashes.push_back(HashString("Checksum-FileSize", SizeStr)); return hashes; } #if __GNUC__ >= 4 #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wdeprecated-declarations" - #pragma GCC diagnostic ignored "-Wsuggest-attribute=const" #endif -Hashes::Hashes() {} -Hashes::~Hashes() {} +Hashes::Hashes() { d = new PrivateHashes(); } +Hashes::~Hashes() { delete d; } #if __GNUC__ >= 4 #pragma GCC diagnostic pop #endif diff --git a/apt-pkg/contrib/hashes.h b/apt-pkg/contrib/hashes.h index caeba006d..e2e213855 100644 --- a/apt-pkg/contrib/hashes.h +++ b/apt-pkg/contrib/hashes.h @@ -161,10 +161,10 @@ class HashStringList std::vector<HashString> list; }; +class PrivateHashes; class Hashes { - /** \brief dpointer placeholder */ - void *d; + PrivateHashes *d; public: /* those will disappear in the future as it is hard to add new ones this way. diff --git a/apt-pkg/contrib/strutl.cc b/apt-pkg/contrib/strutl.cc index aad358a55..ebf9c9ea6 100644 --- a/apt-pkg/contrib/strutl.cc +++ b/apt-pkg/contrib/strutl.cc @@ -779,86 +779,94 @@ string TimeRFC1123(time_t Date) In particular: this reads blocks from the input until it believes that it's run out of input text. Each block is terminated by a - double newline ('\n' followed by '\n'). As noted below, there is a - bug in this code: it assumes that all the blocks have been read if - it doesn't see additional text in the buffer after the last one is - parsed, which will cause it to lose blocks if the last block - coincides with the end of the buffer. + double newline ('\n' followed by '\n'). */ bool ReadMessages(int Fd, vector<string> &List) { char Buffer[64000]; - char *End = Buffer; // Represents any left-over from the previous iteration of the // parse loop. (i.e., if a message is split across the end // of the buffer, it goes here) string PartialMessage; - - while (1) - { - int Res = read(Fd,End,sizeof(Buffer) - (End-Buffer)); + + do { + int const Res = read(Fd, Buffer, sizeof(Buffer)); if (Res < 0 && errno == EINTR) continue; - - // Process is dead, this is kind of bad.. + + // process we read from has died if (Res == 0) return false; - + // No data - if (Res < 0 && errno == EAGAIN) + if (Res < 0 && (errno == EAGAIN || errno == EWOULDBLOCK)) return true; if (Res < 0) return false; - - End += Res; - - // Look for the end of the message - for (char *I = Buffer; I + 1 < End; I++) + + // extract the message(s) from the buffer + char const *Start = Buffer; + char const * const End = Buffer + Res; + + char const * NL = (char const *) memchr(Start, '\n', End - Start); + if (NL == NULL) { - if (I[1] != '\n' || - (I[0] != '\n' && strncmp(I, "\r\n\r\n", 4) != 0)) - continue; - - // Pull the message out - string Message(Buffer,I-Buffer); - PartialMessage += Message; - - // Fix up the buffer - for (; I < End && (*I == '\n' || *I == '\r'); ++I); - End -= I-Buffer; - memmove(Buffer,I,End-Buffer); - I = Buffer; - - List.push_back(PartialMessage); - PartialMessage.clear(); + // end of buffer: store what we have so far and read new data in + PartialMessage.append(Start, End - Start); + Start = End; } - if (End != Buffer) - { - // If there's text left in the buffer, store it - // in PartialMessage and throw the rest of the buffer - // away. This allows us to handle messages that - // are longer than the static buffer size. - PartialMessage += string(Buffer, End); - End = Buffer; - } else - { - // BUG ALERT: if a message block happens to end at a - // multiple of 64000 characters, this will cause it to - // terminate early, leading to a badly formed block and - // probably crashing the method. However, this is the only - // way we have to find the end of the message block. I have - // an idea of how to fix this, but it will require changes - // to the protocol (essentially to mark the beginning and - // end of the block). - // - // -- dburrows 2008-04-02 - return true; - } + ++NL; + + if (PartialMessage.empty() == false && Start < End) + { + // if we start with a new line, see if the partial message we have ended with one + // so that we properly detect records ending between two read() runs + // cases are: \n|\n , \r\n|\r\n and \r\n\r|\n + // the case \r|\n\r\n is handled by the usual double-newline handling + if ((NL - Start) == 1 || ((NL - Start) == 2 && *Start == '\r')) + { + if (APT::String::Endswith(PartialMessage, "\n") || APT::String::Endswith(PartialMessage, "\r\n\r")) + { + PartialMessage.erase(PartialMessage.find_last_not_of("\r\n") + 1); + List.push_back(PartialMessage); + PartialMessage.clear(); + while (NL < End && (*NL == '\n' || *NL == '\r')) ++NL; + Start = NL; + } + } + } + + while (Start < End) { + char const * NL2 = (char const *) memchr(NL, '\n', End - NL); + if (NL2 == NULL) + { + // end of buffer: store what we have so far and read new data in + PartialMessage.append(Start, End - Start); + break; + } + ++NL2; + + // did we find a double newline? + if ((NL2 - NL) == 1 || ((NL2 - NL) == 2 && *NL == '\r')) + { + PartialMessage.append(Start, NL2 - Start); + PartialMessage.erase(PartialMessage.find_last_not_of("\r\n") + 1); + List.push_back(PartialMessage); + PartialMessage.clear(); + while (NL2 < End && (*NL2 == '\n' || *NL2 == '\r')) ++NL2; + Start = NL2; + } + NL = NL2; + } + + // we have read at least one complete message and nothing left + if (PartialMessage.empty() == true) + return true; if (WaitFd(Fd) == false) return false; - } + } while (true); } /*}}}*/ // MonthConv - Converts a month string into a number /*{{{*/ |