From 243b2a381f4a12939d91084ecf100ee6d3dcb007 Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Wed, 4 Jun 2014 12:39:36 +0200 Subject: Add compat mode for old (32bit FileSize) CacheDB (LP: #1274466) --- ftparchive/cachedb.cc | 69 ++++++++++++++++++--- ftparchive/cachedb.h | 20 +++++- test/integration/cachedb-lp1274466-old-format.db | Bin 0 -> 8192 bytes test/integration/deb-lp1274466-cachedb.deb | Bin 0 -> 1270 bytes .../test-apt-ftparchive-cachedb-lp1274466 | 51 +++++++++++++++ 5 files changed, 129 insertions(+), 11 deletions(-) create mode 100644 test/integration/cachedb-lp1274466-old-format.db create mode 100644 test/integration/deb-lp1274466-cachedb.deb create mode 100755 test/integration/test-apt-ftparchive-cachedb-lp1274466 diff --git a/ftparchive/cachedb.cc b/ftparchive/cachedb.cc index 12eac20d8..0901492f7 100644 --- a/ftparchive/cachedb.cc +++ b/ftparchive/cachedb.cc @@ -99,7 +99,7 @@ bool CacheDB::ReadyDB(std::string const &DB) return _error->Error(_("Unable to open DB file %s: %s"),DB.c_str(), db_strerror(err)); } } - + DBFile = DB; DBLoaded = true; return true; @@ -185,6 +185,45 @@ bool CacheDB::GetFileStat(bool const &doStat) 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; } /*}}}*/ @@ -198,19 +237,29 @@ bool CacheDB::GetCurStat() 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); } diff --git a/ftparchive/cachedb.h b/ftparchive/cachedb.h index edb8594bf..29d710d2c 100644 --- a/ftparchive/cachedb.h +++ b/ftparchive/cachedb.h @@ -85,8 +85,12 @@ class CacheDB bool OpenDebFile(); void CloseDebFile(); - bool GetFileStat(bool const &doStat = false); + // GetCurStat needs some compat code, see lp #1274466) + bool GetCurStatCompatOldFormat(); + bool GetCurStatCompatNewFormat(); bool GetCurStat(); + + bool GetFileStat(bool const &doStat = false); bool LoadControl(); bool LoadContents(bool const &GenOnly); bool LoadSource(); @@ -101,6 +105,20 @@ class CacheDB FlSHA512=(1<<6), FlSource=(1<<7), }; + // the on-disk format changed (FileSize increased to 64bit) in + // commit 650faab0 which will lead to corruption with old caches + struct StatStoreOldFormat + { + uint32_t Flags; + uint32_t mtime; + uint32_t FileSize; + uint8_t MD5[16]; + uint8_t SHA1[20]; + uint8_t SHA256[32]; + } CurStatOldFormat; + + // WARNING: this struct is read/written to the DB so do not change the + // layout of the fields (see lp #1274466), only append to it struct StatStore { uint32_t Flags; diff --git a/test/integration/cachedb-lp1274466-old-format.db b/test/integration/cachedb-lp1274466-old-format.db new file mode 100644 index 000000000..88da5f1ee Binary files /dev/null and b/test/integration/cachedb-lp1274466-old-format.db differ diff --git a/test/integration/deb-lp1274466-cachedb.deb b/test/integration/deb-lp1274466-cachedb.deb new file mode 100644 index 000000000..43d7ee6f1 Binary files /dev/null and b/test/integration/deb-lp1274466-cachedb.deb differ diff --git a/test/integration/test-apt-ftparchive-cachedb-lp1274466 b/test/integration/test-apt-ftparchive-cachedb-lp1274466 new file mode 100755 index 000000000..211740a53 --- /dev/null +++ b/test/integration/test-apt-ftparchive-cachedb-lp1274466 @@ -0,0 +1,51 @@ +#!/bin/sh +set -e + + +# +# main() +# +TESTDIR=$(readlink -f $(dirname $0)) +. $TESTDIR/framework +setupenvironment +configarchitecture "i386" + +# gather the db and the deb, ensure mtime is not modfied as its saved in the DB +cp -p $TESTDIR/deb-lp1274466-cachedb.deb foo_1_i386.deb +cp $TESTDIR/cachedb-lp1274466-old-format.db old-format.db + +# verify that the format is different +testsuccess aptftparchive --db new-format.db packages . +db_dump new-format.db > new-format.dump +db_dump old-format.db > old-format.dump +testfailure diff -u old-format.dump new-format.dump + +# ensure the new format as the sha512 +testsuccess grep 7da58ff901a40ecf42a730dc33198b182e9ba9ec98799fc2c2b6fabeeee40cc12a0e7cadb4b66764235c56e1009dbfe8a9a566fb1eedf47a992d1fff2cc3332c new-format.dump +# but the old format does not +testfailure grep 7da58ff901a40ecf42a730dc33198b182e9ba9ec98799fc2c2b6fabeeee40cc12a0e7cadb4b66764235c56e1009dbfe8a9a566fb1eedf47a992d1fff2cc3332c old-format.dump + +# regression test for corruption with previous generation of cachedb +testequal "Package: foo +Priority: optional +Section: others +Installed-Size: 29 +Maintainer: Joe Sixpack +Architecture: i386 +Version: 1 +Filename: ./foo_1_i386.deb +Size: 1270 +MD5sum: 85d0e908c1a897700e2c5dea72d7e3c0 +SHA1: 858b09169032b7925a0e463f46b6634243fc40ce +SHA256: 3750a2c9c6b5beee7f307564be3d51d3ec7cbb78fa4f0b47f84a7c41477bff59 +SHA512: 7da58ff901a40ecf42a730dc33198b182e9ba9ec98799fc2c2b6fabeeee40cc12a0e7cadb4b66764235c56e1009dbfe8a9a566fb1eedf47a992d1fff2cc3332c +Description: an autogenerated dummy foo=1/test + If you find such a package installed on your system, + something went horribly wrong! They are autogenerated + und used only by testcases and surf no other proposeā€¦ +" aptftparchive --db old-format.db packages . + +# ensure that the db is updated +db_dump old-format.db > old-format.dump +testsuccess diff -u old-format.dump new-format.dump + -- cgit v1.2.3