#include <apt-pkg/fileutl.h>
#include <apt-pkg/debfile.h>
#include <apt-pkg/gpgv.h>
+#include <apt-pkg/hashes.h>
#include <netinet/in.h> // htonl, etc
#include <ctype.h>
#include <stddef.h>
#include <sys/stat.h>
+#include <strings.h>
#include "cachedb.h"
#include <apti18n.h>
/*}}}*/
+CacheDB::CacheDB(std::string const &DB)
+ : Dbp(0), Fd(NULL), DebFile(0)
+{
+ TmpKey[0]='\0';
+ ReadyDB(DB);
+}
+
+CacheDB::~CacheDB()
+{
+ ReadyDB();
+ delete DebFile;
+ CloseFile();
+}
+
// CacheDB::ReadyDB - Ready the DB2 /*{{{*/
// ---------------------------------------------------------------------
/* This opens the DB2 file for caching package information */
return _error->Error(_("Unable to open DB file %s: %s"),DB.c_str(), db_strerror(err));
}
}
-
+
DBFile = DB;
DBLoaded = true;
return true;
/* */
bool CacheDB::OpenFile()
{
- // its open already
- if(Fd && Fd->Name() == this->FileName)
- return true;
-
- // a different file is open, close it first
- if(Fd && Fd->Name() != this->FileName)
- CloseFile();
+ // always close existing file first
+ CloseFile();
// open a new file
Fd = new FileFd(FileName,FileFd::ReadOnly);
// CacheDB::OpenDebFile - Open a debfile /*{{{*/
bool CacheDB::OpenDebFile()
{
- // debfile is already open
- if(DebFile && &DebFile->GetFile() == Fd)
- return true;
-
- // a different debfile is open, close it first
- if(DebFile && &DebFile->GetFile() != Fd)
- CloseDebFile();
+ // always close existing file first
+ CloseDebFile();
// first open the fd, then pass it to the debDebFile
if(OpenFile() == false)
CurStat.mtime = htonl(St.st_mtime);
CurStat.Flags |= FlSize;
+ return true;
+}
+ /*}}}*/
+// CacheDB::GetCurStatCompatOldFormat /*{{{*/
+// ---------------------------------------------------------------------
+/* Read the old (32bit FileSize) StateStore format from disk */
+bool CacheDB::GetCurStatCompatOldFormat()
+{
+ InitQueryStats();
+ Data.data = &CurStatOldFormat;
+ Data.flags = DB_DBT_USERMEM;
+ Data.ulen = sizeof(CurStatOldFormat);
+ if (Get() == false)
+ {
+ CurStat.Flags = 0;
+ } else {
+ CurStat.Flags = CurStatOldFormat.Flags;
+ CurStat.mtime = CurStatOldFormat.mtime;
+ CurStat.FileSize = CurStatOldFormat.FileSize;
+ memcpy(CurStat.MD5, CurStatOldFormat.MD5, sizeof(CurStat.MD5));
+ memcpy(CurStat.SHA1, CurStatOldFormat.SHA1, sizeof(CurStat.SHA1));
+ memcpy(CurStat.SHA256, CurStatOldFormat.SHA256, sizeof(CurStat.SHA256));
+ }
+ return true;
+}
+ /*}}}*/
+// CacheDB::GetCurStatCompatOldFormat /*{{{*/
+// ---------------------------------------------------------------------
+/* Read the new (64bit FileSize) StateStore format from disk */
+bool CacheDB::GetCurStatCompatNewFormat()
+{
+ InitQueryStats();
+ Data.data = &CurStat;
+ Data.flags = DB_DBT_USERMEM;
+ Data.ulen = sizeof(CurStat);
+ if (Get() == false)
+ {
+ CurStat.Flags = 0;
+ }
return true;
}
/*}}}*/
if (DBLoaded)
{
- /* First see if there is anything about it
- in the database */
-
- /* Get the flags (and mtime) */
+ // do a first query to just get the size of the data on disk
InitQueryStats();
- // Ensure alignment of the returned structure
Data.data = &CurStat;
- Data.ulen = sizeof(CurStat);
Data.flags = DB_DBT_USERMEM;
- if (Get() == false)
+ Data.ulen = 0;
+ Get();
+
+ if (Data.size == 0)
{
- CurStat.Flags = 0;
- }
+ // nothing needs to be done, we just have not data for this deb
+ }
+ // check if the record is written in the old format (32bit filesize)
+ else if(Data.size == sizeof(CurStatOldFormat))
+ {
+ GetCurStatCompatOldFormat();
+ }
+ else if(Data.size == sizeof(CurStat))
+ {
+ GetCurStatCompatNewFormat();
+ } else {
+ return _error->Error("Cache record size mismatch (%ul)", Data.size);
+ }
+
CurStat.Flags = ntohl(CurStat.Flags);
CurStat.FileSize = ntohl(CurStat.FileSize);
}
/*}}}*/
// CacheDB::GetFileInfo - Get all the info about the file /*{{{*/
// ---------------------------------------------------------------------
-bool CacheDB::GetFileInfo(std::string const &FileName, bool const &DoControl,
- bool const &DoContents,
- bool const &GenContentsOnly,
- bool const &DoSource,
- bool const &DoMD5, bool const &DoSHA1,
- bool const &DoSHA256, bool const &DoSHA512,
+bool CacheDB::GetFileInfo(std::string const &FileName, bool const &DoControl, bool const &DoContents,
+ bool const &GenContentsOnly, bool const DoSource, unsigned int const DoHashes,
bool const &checkMtime)
{
- bool result = true;
this->FileName = FileName;
if (GetCurStat() == false)
OldStat = CurStat;
if (GetFileStat(checkMtime) == false)
- return false;
+ return false;
/* if mtime changed, update CurStat from disk */
if (checkMtime == true && OldStat.mtime != CurStat.mtime)
CurStat.Flags = FlSize;
Stats.Bytes += CurStat.FileSize;
- Stats.Packages++;
+ ++Stats.Packages;
if ((DoControl && LoadControl() == false)
- || (DoContents && LoadContents(GenContentsOnly) == false)
- || (DoSource && LoadSource() == false)
- || (DoMD5 && GetMD5(false) == false)
- || (DoSHA1 && GetSHA1(false) == false)
- || (DoSHA256 && GetSHA256(false) == false)
- || (DoSHA512 && GetSHA512(false) == false) )
+ || (DoContents && LoadContents(GenContentsOnly) == false)
+ || (DoSource && LoadSource() == false)
+ || (DoHashes != 0 && GetHashes(false, DoHashes) == false)
+ )
{
- result = false;
+ return false;
}
-
- return result;
+
+ return true;
}
/*}}}*/
-
-bool CacheDB::LoadSource()
+bool CacheDB::LoadSource() /*{{{*/
{
// Try to read the control information out of the DB.
if ((CurStat.Flags & FlSource) == FlSource)
if (Dsc.Read(FileName) == false)
return false;
- if (Dsc.Data == 0)
+ if (Dsc.Length == 0)
return _error->Error(_("Failed to read .dsc"));
-
+
// Write back the control information
InitQuerySource();
- if (Put(Dsc.Data, Dsc.Length) == true)
+ if (Put(Dsc.Data.c_str(), Dsc.Length) == true)
CurStat.Flags |= FlSource;
return true;
}
-
+ /*}}}*/
// CacheDB::LoadControl - Load Control information /*{{{*/
// ---------------------------------------------------------------------
/* */
return true;
}
/*}}}*/
-
+// CacheDB::GetHashes - Get the hashs /*{{{*/
static std::string bytes2hex(uint8_t *bytes, size_t length) {
char buf[3];
std::string space;
bytes++;
}
}
-
-// CacheDB::GetMD5 - Get the MD5 hash /*{{{*/
-// ---------------------------------------------------------------------
-/* */
-bool CacheDB::GetMD5(bool const &GenOnly)
+bool CacheDB::GetHashes(bool const GenOnly, unsigned int const DoHashes)
{
- // Try to read the control information out of the DB.
- if ((CurStat.Flags & FlMD5) == FlMD5)
- {
- if (GenOnly == true)
- return true;
-
- MD5Res = bytes2hex(CurStat.MD5, sizeof(CurStat.MD5));
- return true;
- }
-
- Stats.MD5Bytes += CurStat.FileSize;
-
- if (OpenFile() == false)
- return false;
+ unsigned int FlHashes = DoHashes & (Hashes::MD5SUM | Hashes::SHA1SUM | Hashes::SHA256SUM | Hashes::SHA512SUM);
+ HashesList.clear();
- MD5Summation MD5;
- if (Fd->Seek(0) == false || MD5.AddFD(*Fd, CurStat.FileSize) == false)
- return false;
-
- MD5Res = MD5.Result();
- hex2bytes(CurStat.MD5, MD5Res.data(), sizeof(CurStat.MD5));
- CurStat.Flags |= FlMD5;
- return true;
-}
- /*}}}*/
-// CacheDB::GetSHA1 - Get the SHA1 hash /*{{{*/
-// ---------------------------------------------------------------------
-/* */
-bool CacheDB::GetSHA1(bool const &GenOnly)
-{
- // Try to read the control information out of the DB.
- if ((CurStat.Flags & FlSHA1) == FlSHA1)
+ if (FlHashes != 0)
{
- if (GenOnly == true)
- return true;
+ if (OpenFile() == false)
+ return false;
- SHA1Res = bytes2hex(CurStat.SHA1, sizeof(CurStat.SHA1));
- return true;
- }
-
- Stats.SHA1Bytes += CurStat.FileSize;
-
- if (OpenFile() == false)
- return false;
+ Hashes hashes(FlHashes);
+ if (Fd->Seek(0) == false || hashes.AddFD(*Fd, CurStat.FileSize) == false)
+ return false;
- SHA1Summation SHA1;
- if (Fd->Seek(0) == false || SHA1.AddFD(*Fd, CurStat.FileSize) == false)
- return false;
-
- SHA1Res = SHA1.Result();
- hex2bytes(CurStat.SHA1, SHA1Res.data(), sizeof(CurStat.SHA1));
- CurStat.Flags |= FlSHA1;
- return true;
-}
- /*}}}*/
-// CacheDB::GetSHA256 - Get the SHA256 hash /*{{{*/
-// ---------------------------------------------------------------------
-/* */
-bool CacheDB::GetSHA256(bool const &GenOnly)
-{
- // Try to read the control information out of the DB.
- if ((CurStat.Flags & FlSHA256) == FlSHA256)
- {
- if (GenOnly == true)
- return true;
-
- SHA256Res = bytes2hex(CurStat.SHA256, sizeof(CurStat.SHA256));
- return true;
+ HashStringList hl = hashes.GetHashStringList();
+ for (HashStringList::const_iterator hs = hl.begin(); hs != hl.end(); ++hs)
+ {
+ HashesList.push_back(*hs);
+ if (strcasecmp(hs->HashType().c_str(), "SHA512") == 0)
+ {
+ Stats.SHA512Bytes += CurStat.FileSize;
+ hex2bytes(CurStat.SHA512, hs->HashValue().data(), sizeof(CurStat.SHA512));
+ CurStat.Flags |= FlSHA512;
+ }
+ else if (strcasecmp(hs->HashType().c_str(), "SHA256") == 0)
+ {
+ Stats.SHA256Bytes += CurStat.FileSize;
+ hex2bytes(CurStat.SHA256, hs->HashValue().data(), sizeof(CurStat.SHA256));
+ CurStat.Flags |= FlSHA256;
+ }
+ else if (strcasecmp(hs->HashType().c_str(), "SHA1") == 0)
+ {
+ Stats.SHA1Bytes += CurStat.FileSize;
+ hex2bytes(CurStat.SHA1, hs->HashValue().data(), sizeof(CurStat.SHA1));
+ CurStat.Flags |= FlSHA1;
+ }
+ else if (strcasecmp(hs->HashType().c_str(), "MD5Sum") == 0)
+ {
+ Stats.MD5Bytes += CurStat.FileSize;
+ hex2bytes(CurStat.MD5, hs->HashValue().data(), sizeof(CurStat.MD5));
+ CurStat.Flags |= FlMD5;
+ }
+ else if (strcasecmp(hs->HashType().c_str(), "Checksum-FileSize") == 0)
+ {
+ // we store it in a different field already
+ }
+ else
+ return _error->Error("Got unknown unrequested hashtype %s", hs->HashType().c_str());
+ }
}
-
- Stats.SHA256Bytes += CurStat.FileSize;
-
- if (OpenFile() == false)
- return false;
-
- SHA256Summation SHA256;
- if (Fd->Seek(0) == false || SHA256.AddFD(*Fd, CurStat.FileSize) == false)
- return false;
-
- SHA256Res = SHA256.Result();
- hex2bytes(CurStat.SHA256, SHA256Res.data(), sizeof(CurStat.SHA256));
- CurStat.Flags |= FlSHA256;
- return true;
-}
- /*}}}*/
-// CacheDB::GetSHA256 - Get the SHA256 hash /*{{{*/
-// ---------------------------------------------------------------------
-/* */
-bool CacheDB::GetSHA512(bool const &GenOnly)
-{
- // Try to read the control information out of the DB.
- if ((CurStat.Flags & FlSHA512) == FlSHA512)
- {
- if (GenOnly == true)
- return true;
-
- SHA512Res = bytes2hex(CurStat.SHA512, sizeof(CurStat.SHA512));
+ if (GenOnly == true)
return true;
- }
-
- Stats.SHA512Bytes += CurStat.FileSize;
-
- if (OpenFile() == false)
- return false;
- SHA512Summation SHA512;
- if (Fd->Seek(0) == false || SHA512.AddFD(*Fd, CurStat.FileSize) == false)
- return false;
-
- SHA512Res = SHA512.Result();
- hex2bytes(CurStat.SHA512, SHA512Res.data(), sizeof(CurStat.SHA512));
- CurStat.Flags |= FlSHA512;
- return true;
+ bool ret = true;
+#define PUSH_BACK_HASH(FLAG, TYPE, VALUE) \
+ if ((CurStat.Flags & FLAG) == FLAG) \
+ ret &= HashesList.push_back(HashString(TYPE, bytes2hex(VALUE, sizeof(VALUE))));
+ PUSH_BACK_HASH(FlMD5, "MD5Sum", CurStat.MD5);
+ PUSH_BACK_HASH(FlSHA1, "SHA1", CurStat.SHA1);
+ PUSH_BACK_HASH(FlSHA256, "SHA256", CurStat.SHA256);
+ PUSH_BACK_HASH(FlSHA512, "SHA512", CurStat.SHA512);
+ return ret;
}
/*}}}*/
// CacheDB::Finish - Write back the cache structure /*{{{*/
if (CurStat.Flags == OldStat.Flags &&
CurStat.mtime == OldStat.mtime)
return true;
-
+
// Write the stat information
CurStat.Flags = htonl(CurStat.Flags);
CurStat.FileSize = htonl(CurStat.FileSize);