]> git.saurik.com Git - apt.git/commitdiff
* merged with mainline (doc fix)
authorMichael Vogt <egon@bottom>
Wed, 26 Apr 2006 11:31:58 +0000 (13:31 +0200)
committerMichael Vogt <egon@bottom>
Wed, 26 Apr 2006 11:31:58 +0000 (13:31 +0200)
19 files changed:
apt-pkg/acquire-item.cc
apt-pkg/acquire-item.h
apt-pkg/contrib/hashes.cc
apt-pkg/contrib/hashes.h
apt-pkg/contrib/sha256.cc [new file with mode: 0644]
apt-pkg/contrib/sha256.h [new file with mode: 0644]
apt-pkg/makefile
apt-pkg/tagfile.cc
configure.in
debian/NEWS.Debian
debian/changelog
doc/examples/configure-index
ftparchive/cachedb.cc
ftparchive/cachedb.h
ftparchive/writer.cc
ftparchive/writer.h
methods/http.cc
methods/makefile
methods/rred.cc [new file with mode: 0644]

index 1fa929aad659823994e4f7286df069095ae90ada..cbccfbfae40c794144919b1042528f7df0414612 100644 (file)
@@ -24,6 +24,8 @@
 #include <apt-pkg/strutl.h>
 #include <apt-pkg/fileutl.h>
 #include <apt-pkg/md5.h>
+#include <apt-pkg/sha1.h>
+#include <apt-pkg/tagfile.h>
 
 #include <apti18n.h>
     
@@ -31,6 +33,7 @@
 #include <unistd.h>
 #include <errno.h>
 #include <string>
+#include <sstream>
 #include <stdio.h>
                                                                        /*}}}*/
 
@@ -100,7 +103,8 @@ void pkgAcquire::Item::Done(string Message,unsigned long Size,string,
 {
    // We just downloaded something..
    string FileName = LookupTag(Message,"Filename");
-   if (Complete == false && FileName == DestFile)
+   // we only inform the Log class if it was actually not a local thing
+   if (Complete == false && !Local && FileName == DestFile)
    {
       if (Owner->Log != 0)
         Owner->Log->Fetched(Size,atoi(LookupTag(Message,"Resume-Point","0").c_str()));
@@ -131,14 +135,431 @@ void pkgAcquire::Item::Rename(string From,string To)
 }
                                                                        /*}}}*/
 
+
+// AcqDiffIndex::AcqDiffIndex - Constructor                    
+// ---------------------------------------------------------------------
+/* Get the DiffIndex file first and see if there are patches availabe 
+ * If so, create a pkgAcqIndexDiffs fetcher that will get and apply the
+ * patches. If anything goes wrong in that process, it will fall back to
+ * the original packages file
+ */
+pkgAcqDiffIndex::pkgAcqDiffIndex(pkgAcquire *Owner,
+                                string URI,string URIDesc,string ShortDesc,
+                                string ExpectedMD5)
+   : Item(Owner), RealURI(URI), ExpectedMD5(ExpectedMD5), Description(URIDesc)
+{
+   
+   Debug = _config->FindB("Debug::pkgAcquire::Diffs",false);
+
+   Desc.Description = URIDesc + "/DiffIndex";
+   Desc.Owner = this;
+   Desc.ShortDesc = ShortDesc;
+   Desc.URI = URI + ".diff/Index";
+
+   DestFile = _config->FindDir("Dir::State::lists") + "partial/";
+   DestFile += URItoFileName(URI) + string(".DiffIndex");
+
+   if(Debug)
+      std::clog << "pkgAcqDiffIndex: " << Desc.URI << std::endl;
+
+   // look for the current package file
+   CurrentPackagesFile = _config->FindDir("Dir::State::lists");
+   CurrentPackagesFile += URItoFileName(RealURI);
+
+   // FIXME: this file:/ check is a hack to prevent fetching
+   //        from local sources. this is really silly, and
+   //        should be fixed cleanly as soon as possible
+   if(!FileExists(CurrentPackagesFile) || 
+      Desc.URI.substr(0,strlen("file:/")) == "file:/")
+   {
+      // we don't have a pkg file or we don't want to queue
+      if(Debug)
+        std::clog << "No index file, local or canceld by user" << std::endl;
+      Failed("", NULL);
+      return;
+   }
+
+   if(Debug) 
+      std::clog << "pkgAcqIndexDiffs::pkgAcqIndexDiffs(): " 
+               << CurrentPackagesFile << std::endl;
+   
+   QueueURI(Desc);
+
+}
+
+// AcqIndex::Custom600Headers - Insert custom request headers          /*{{{*/
+// ---------------------------------------------------------------------
+/* The only header we use is the last-modified header. */
+string pkgAcqDiffIndex::Custom600Headers()
+{
+   string Final = _config->FindDir("Dir::State::lists");
+   Final += URItoFileName(RealURI) + string(".IndexDiff");
+   
+   if(Debug)
+      std::clog << "Custom600Header-IMS: " << Final << std::endl;
+
+   struct stat Buf;
+   if (stat(Final.c_str(),&Buf) != 0)
+      return "\nIndex-File: true";
+   
+   return "\nIndex-File: true\nLast-Modified: " + TimeRFC1123(Buf.st_mtime);
+}
+
+
+bool pkgAcqDiffIndex::ParseDiffIndex(string IndexDiffFile)
+{
+   if(Debug)
+      std::clog << "pkgAcqIndexDiffs::ParseIndexDiff() " << IndexDiffFile 
+               << std::endl;
+
+   pkgTagSection Tags;
+   string ServerSha1;
+   vector<DiffInfo> available_patches;
+   
+   FileFd Fd(IndexDiffFile,FileFd::ReadOnly);
+   pkgTagFile TF(&Fd);
+   if (_error->PendingError() == true)
+      return false;
+
+   if(TF.Step(Tags) == true)
+   {
+      string local_sha1;
+      bool found = false;
+      DiffInfo d;
+      string size;
+
+      string tmp = Tags.FindS("SHA1-Current");
+      std::stringstream ss(tmp);
+      ss >> ServerSha1;
+
+      FileFd fd(CurrentPackagesFile, FileFd::ReadOnly);
+      SHA1Summation SHA1;
+      SHA1.AddFD(fd.Fd(), fd.Size());
+      local_sha1 = string(SHA1.Result());
+
+      if(local_sha1 == ServerSha1) 
+      {
+        // we have the same sha1 as the server
+        if(Debug)
+           std::clog << "Package file is up-to-date" << std::endl;
+        // set found to true, this will queue a pkgAcqIndexDiffs with
+        // a empty availabe_patches
+        found = true;
+      } 
+      else 
+      {
+        if(Debug)
+           std::clog << "SHA1-Current: " << ServerSha1 << std::endl;
+
+        // check the historie and see what patches we need
+        string history = Tags.FindS("SHA1-History");     
+        std::stringstream hist(history);
+        while(hist >> d.sha1 >> size >> d.file) 
+        {
+           d.size = atoi(size.c_str());
+           // read until the first match is found
+           if(d.sha1 == local_sha1) 
+              found=true;
+           // from that point on, we probably need all diffs
+           if(found) 
+           {
+              if(Debug)
+                 std::clog << "Need to get diff: " << d.file << std::endl;
+              available_patches.push_back(d);
+           }
+        }
+      }
+
+      // no information how to get the patches, bail out
+      if(!found) 
+      {
+        if(Debug)
+           std::clog << "Can't find a patch in the index file" << std::endl;
+        // Failed will queue a big package file
+        Failed("", NULL);
+      } 
+      else 
+      {
+        // queue the diffs
+        new pkgAcqIndexDiffs(Owner, RealURI, Description, Desc.ShortDesc,
+                             ExpectedMD5, available_patches);
+        Complete = false;
+        Status = StatDone;
+        Dequeue();
+        return true;
+      }
+   }
+
+   return false;
+}
+
+void pkgAcqDiffIndex::Failed(string Message,pkgAcquire::MethodConfig *Cnf)
+{
+   if(Debug)
+      std::clog << "pkgAcqDiffIndex failed: " << Desc.URI << std::endl
+               << "Falling back to normal index file aquire" << std::endl;
+
+   new pkgAcqIndex(Owner, RealURI, Description, Desc.ShortDesc, 
+                  ExpectedMD5);
+
+   Complete = false;
+   Status = StatDone;
+   Dequeue();
+}
+
+void pkgAcqDiffIndex::Done(string Message,unsigned long Size,string Md5Hash,
+                          pkgAcquire::MethodConfig *Cnf)
+{
+   if(Debug)
+      std::clog << "pkgAcqDiffIndex::Done(): " << Desc.URI << std::endl;
+
+   Item::Done(Message,Size,Md5Hash,Cnf);
+
+   string FinalFile;
+   FinalFile = _config->FindDir("Dir::State::lists")+URItoFileName(RealURI);
+
+   // sucess in downloading the index
+   // rename the index
+   FinalFile += string(".IndexDiff");
+   if(Debug)
+      std::clog << "Renaming: " << DestFile << " -> " << FinalFile 
+               << std::endl;
+   Rename(DestFile,FinalFile);
+   chmod(FinalFile.c_str(),0644);
+   DestFile = FinalFile;
+
+   if(!ParseDiffIndex(DestFile))
+      return Failed("", NULL);
+
+   Complete = true;
+   Status = StatDone;
+   Dequeue();
+   return;
+}
+
+
+
+// AcqIndexDiffs::AcqIndexDiffs - Constructor                  
+// ---------------------------------------------------------------------
+/* The package diff is added to the queue. one object is constructed
+ * for each diff and the index
+ */
+pkgAcqIndexDiffs::pkgAcqIndexDiffs(pkgAcquire *Owner,
+                                  string URI,string URIDesc,string ShortDesc,
+                                  string ExpectedMD5, vector<DiffInfo> diffs)
+   : Item(Owner), RealURI(URI), ExpectedMD5(ExpectedMD5), 
+     available_patches(diffs)
+{
+   
+   DestFile = _config->FindDir("Dir::State::lists") + "partial/";
+   DestFile += URItoFileName(URI);
+
+   Debug = _config->FindB("Debug::pkgAcquire::Diffs",false);
+
+   Desc.Description = URIDesc;
+   Desc.Owner = this;
+   Desc.ShortDesc = ShortDesc;
+
+   if(available_patches.size() == 0) 
+   {
+      // we are done (yeah!)
+      Finish(true);
+   }
+   else
+   {
+      // get the next diff
+      State = StateFetchDiff;
+      QueueNextDiff();
+   }
+}
+
+
+void pkgAcqIndexDiffs::Failed(string Message,pkgAcquire::MethodConfig *Cnf)
+{
+   if(Debug)
+      std::clog << "pkgAcqIndexDiffs failed: " << Desc.URI << std::endl
+               << "Falling back to normal index file aquire" << std::endl;
+   new pkgAcqIndex(Owner, RealURI, Description,Desc.ShortDesc, 
+                  ExpectedMD5);
+   Finish();
+}
+
+
+// helper that cleans the item out of the fetcher queue
+void pkgAcqIndexDiffs::Finish(bool allDone)
+{
+   // we restore the original name, this is required, otherwise
+   // the file will be cleaned
+   if(allDone) 
+   {
+      DestFile = _config->FindDir("Dir::State::lists");
+      DestFile += URItoFileName(RealURI);
+
+      // do the final md5sum checking
+      MD5Summation sum;
+      FileFd Fd(DestFile, FileFd::ReadOnly);
+      sum.AddFD(Fd.Fd(), Fd.Size());
+      Fd.Close();
+      string MD5 = (string)sum.Result();
+
+      if (!ExpectedMD5.empty() && MD5 != ExpectedMD5)
+      {
+        Status = StatAuthError;
+        ErrorText = _("MD5Sum mismatch");
+        Rename(DestFile,DestFile + ".FAILED");
+        Dequeue();
+        return;
+      }
+
+      // this is for the "real" finish
+      Complete = true;
+      Status = StatDone;
+      Dequeue();
+      if(Debug)
+        std::clog << "\n\nallDone: " << DestFile << "\n" << std::endl;
+      return;
+   }
+
+   if(Debug)
+      std::clog << "Finishing: " << Desc.URI << std::endl;
+   Complete = false;
+   Status = StatDone;
+   Dequeue();
+   return;
+}
+
+
+
+bool pkgAcqIndexDiffs::QueueNextDiff()
+{
+
+   // calc sha1 of the just patched file
+   string FinalFile = _config->FindDir("Dir::State::lists");
+   FinalFile += URItoFileName(RealURI);
+
+   FileFd fd(FinalFile, FileFd::ReadOnly);
+   SHA1Summation SHA1;
+   SHA1.AddFD(fd.Fd(), fd.Size());
+   string local_sha1 = string(SHA1.Result());
+   if(Debug)
+      std::clog << "QueueNextDiff: " 
+               << FinalFile << " (" << local_sha1 << ")"<<std::endl;
+
+   // remove all patches until the next matching patch is found
+   // this requires the Index file to be ordered
+   for(vector<DiffInfo>::iterator I=available_patches.begin();
+       available_patches.size() > 0 && 
+         I != available_patches.end() &&
+         (*I).sha1 != local_sha1; 
+       I++) 
+   {
+      available_patches.erase(I);
+   }
+
+   // error checking and falling back if no patch was found
+   if(available_patches.size() == 0) 
+   { 
+      Failed("", NULL);
+      return false;
+   }
+
+   // queue the right diff
+   Desc.URI = string(RealURI) + ".diff/" + available_patches[0].file + ".gz";
+   Desc.Description = available_patches[0].file + string(".pdiff");
+
+   DestFile = _config->FindDir("Dir::State::lists") + "partial/";
+   DestFile += URItoFileName(RealURI + ".diff/" + available_patches[0].file);
+
+   if(Debug)
+      std::clog << "pkgAcqIndexDiffs::QueueNextDiff(): " << Desc.URI << std::endl;
+   
+   QueueURI(Desc);
+
+   return true;
+}
+
+
+
+void pkgAcqIndexDiffs::Done(string Message,unsigned long Size,string Md5Hash,
+                           pkgAcquire::MethodConfig *Cnf)
+{
+   if(Debug)
+      std::clog << "pkgAcqIndexDiffs::Done(): " << Desc.URI << std::endl;
+
+   Item::Done(Message,Size,Md5Hash,Cnf);
+
+   string FinalFile;
+   FinalFile = _config->FindDir("Dir::State::lists")+URItoFileName(RealURI);
+
+   // sucess in downloading a diff, enter ApplyDiff state
+   if(State == StateFetchDiff) 
+   {
+
+      if(Debug)
+        std::clog << "Sending to gzip method: " << FinalFile << std::endl;
+
+      string FileName = LookupTag(Message,"Filename");
+      State = StateUnzipDiff;
+      Local = true;
+      Desc.URI = "gzip:" + FileName;
+      DestFile += ".decomp";
+      QueueURI(Desc);
+      Mode = "gzip";
+      return;
+   } 
+
+   // sucess in downloading a diff, enter ApplyDiff state
+   if(State == StateUnzipDiff) 
+   {
+
+      // rred excepts the patch as $FinalFile.ed
+      Rename(DestFile,FinalFile+".ed");
+
+      if(Debug)
+        std::clog << "Sending to rred method: " << FinalFile << std::endl;
+
+      State = StateApplyDiff;
+      Local = true;
+      Desc.URI = "rred:" + FinalFile;
+      QueueURI(Desc);
+      Mode = "rred";
+      return;
+   } 
+
+
+   // success in download/apply a diff, queue next (if needed)
+   if(State == StateApplyDiff)
+   {
+      // remove the just applied patch
+      available_patches.erase(available_patches.begin());
+
+      // move into place
+      if(Debug) 
+      {
+        std::clog << "Moving patched file in place: " << std::endl
+                  << DestFile << " -> " << FinalFile << std::endl;
+      }
+      Rename(DestFile,FinalFile);
+
+      // see if there is more to download
+      if(available_patches.size() > 0) {
+        new pkgAcqIndexDiffs(Owner, RealURI, Description, Desc.ShortDesc,
+                             ExpectedMD5, available_patches);
+        return Finish();
+      } else 
+        return Finish(true);
+   }
+}
+
+
 // AcqIndex::AcqIndex - Constructor                                    /*{{{*/
 // ---------------------------------------------------------------------
 /* The package file is added to the queue and a second class is 
    instantiated to fetch the revision file */   
 pkgAcqIndex::pkgAcqIndex(pkgAcquire *Owner,
                         string URI,string URIDesc,string ShortDesc,
-                        string ExpectedMD5, string comprExt) :
-   Item(Owner), RealURI(URI), ExpectedMD5(ExpectedMD5)
+                        string ExpectedMD5, string comprExt)
+   Item(Owner), RealURI(URI), ExpectedMD5(ExpectedMD5)
 {
    Decompression = false;
    Erase = false;
@@ -601,9 +1022,14 @@ void pkgAcqMetaIndex::QueueIndexes(bool verify)
          }
       }
       
-      // Queue Packages file
-      new pkgAcqIndex(Owner, (*Target)->URI, (*Target)->Description,
-                      (*Target)->ShortDesc, ExpectedIndexMD5);
+      // Queue Packages file (either diff or full packages files, depending
+      // on the users option)
+      if(_config->FindB("Acquire::PDiffs",false) == false) 
+        new pkgAcqDiffIndex(Owner, (*Target)->URI, (*Target)->Description,
+                            (*Target)->ShortDesc, ExpectedIndexMD5);
+      else 
+        new pkgAcqIndex(Owner, (*Target)->URI, (*Target)->Description,
+                           (*Target)->ShortDesc, ExpectedIndexMD5);
    }
 }
 
index da1bea801d7310557691a9d2470ffa2bf033466b..3649d7a039bd2e92575ca6fa83954712cab1b88a 100644 (file)
@@ -82,6 +82,70 @@ class pkgAcquire::Item
    virtual ~Item();
 };
 
+// item for index diffs
+
+struct DiffInfo {
+   string file;
+   string sha1;
+   unsigned long size;
+};
+
+class pkgAcqDiffIndex : public pkgAcquire::Item
+{
+ protected:
+   bool Debug;
+   pkgAcquire::ItemDesc Desc;
+   string RealURI;
+   string ExpectedMD5;
+   string CurrentPackagesFile;
+   string Description;
+
+ public:
+   // Specialized action members
+   virtual void Failed(string Message,pkgAcquire::MethodConfig *Cnf);
+   virtual void Done(string Message,unsigned long Size,string Md5Hash,
+                    pkgAcquire::MethodConfig *Cnf);
+   virtual string DescURI() {return RealURI + "Index";};
+   virtual string Custom600Headers();
+
+   // helpers
+   bool ParseDiffIndex(string IndexDiffFile);
+   
+   pkgAcqDiffIndex(pkgAcquire *Owner,string URI,string URIDesc,
+                  string ShortDesct, string ExpectedMD5);
+};
+
+class pkgAcqIndexDiffs : public pkgAcquire::Item
+{
+   protected:
+   bool Debug;
+   pkgAcquire::ItemDesc Desc;
+   string RealURI;
+   string ExpectedMD5;
+
+   // this is the SHA-1 sum we expect after the patching
+   string Description;
+   vector<DiffInfo> available_patches;
+   enum {StateFetchIndex,StateFetchDiff,StateUnzipDiff,StateApplyDiff} State;
+
+   public:
+   
+   // Specialized action members
+   virtual void Failed(string Message,pkgAcquire::MethodConfig *Cnf);
+   virtual void Done(string Message,unsigned long Size,string Md5Hash,
+                    pkgAcquire::MethodConfig *Cnf);
+   virtual string DescURI() {return RealURI + "Index";};
+
+   // various helpers
+   bool QueueNextDiff();
+   bool ApplyDiff(string PatchFile);
+   void Finish(bool allDone=false);
+
+   pkgAcqIndexDiffs(pkgAcquire *Owner,string URI,string URIDesc,
+                   string ShortDesct, string ExpectedMD5,
+                   vector<DiffInfo> diffs=vector<DiffInfo>());
+};
+
 // Item class for index files
 class pkgAcqIndex : public pkgAcquire::Item
 {
index b17b9431989e59ffcab886c40ceff0205594578b..9b22a90d3321d24144c2c73761a6e2520471218e 100644 (file)
@@ -36,6 +36,7 @@ bool Hashes::AddFD(int Fd,unsigned long Size)
       Size -= Res;
       MD5.Add(Buf,Res);
       SHA1.Add(Buf,Res);
+      SHA256.Add(Buf,Res);
    }
    return true;
 }
index 40bbe00a02673edae48a0cd23f78cd018435de26..eefa7bf4147dd670e21df66eeb32e3353c0563ea 100644 (file)
@@ -19,6 +19,7 @@
 
 #include <apt-pkg/md5.h>
 #include <apt-pkg/sha1.h>
+#include <apt-pkg/sha256.h>
 
 #include <algorithm>
 
@@ -30,10 +31,11 @@ class Hashes
 
    MD5Summation MD5;
    SHA1Summation SHA1;
+   SHA256Summation SHA256;
    
    inline bool Add(const unsigned char *Data,unsigned long Size)
    {
-      return MD5.Add(Data,Size) && SHA1.Add(Data,Size);
+      return MD5.Add(Data,Size) && SHA1.Add(Data,Size) && SHA256.Add(Data,Size);
    };
    inline bool Add(const char *Data) {return Add((unsigned char *)Data,strlen(Data));};
    bool AddFD(int Fd,unsigned long Size);
diff --git a/apt-pkg/contrib/sha256.cc b/apt-pkg/contrib/sha256.cc
new file mode 100644 (file)
index 0000000..a4d258d
--- /dev/null
@@ -0,0 +1,421 @@
+/*
+ * Cryptographic API.
+ *
+ * SHA-256, as specified in
+ * http://csrc.nist.gov/cryptval/shs/sha256-384-512.pdf
+ *
+ * SHA-256 code by Jean-Luc Cooke <jlcooke@certainkey.com>.
+ *
+ * Copyright (c) Jean-Luc Cooke <jlcooke@certainkey.com>
+ * Copyright (c) Andrew McDonald <andrew@mcdonald.org.uk>
+ * Copyright (c) 2002 James Morris <jmorris@intercode.com.au>
+ *
+ * Ported from the Linux kernel to Apt by Anthony Towns <ajt@debian.org>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option) 
+ * any later version.
+ *
+ */
+#define SHA256_DIGEST_SIZE      32
+#define SHA256_HMAC_BLOCK_SIZE  64
+
+#define ror32(value,bits) (((value) >> (bits)) | ((value) << (32 - (bits))))
+
+#include <apt-pkg/sha256.h>
+#include <apt-pkg/strutl.h>
+#include <string.h>
+#include <unistd.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <arpa/inet.h>
+
+typedef uint32_t u32;
+typedef uint8_t  u8;
+
+static inline u32 Ch(u32 x, u32 y, u32 z)
+{
+        return z ^ (x & (y ^ z));
+}
+
+static inline u32 Maj(u32 x, u32 y, u32 z)
+{
+        return (x & y) | (z & (x | y));
+}
+
+#define e0(x)       (ror32(x, 2) ^ ror32(x,13) ^ ror32(x,22))
+#define e1(x)       (ror32(x, 6) ^ ror32(x,11) ^ ror32(x,25))
+#define s0(x)       (ror32(x, 7) ^ ror32(x,18) ^ (x >> 3))
+#define s1(x)       (ror32(x,17) ^ ror32(x,19) ^ (x >> 10))
+
+#define H0         0x6a09e667
+#define H1         0xbb67ae85
+#define H2         0x3c6ef372
+#define H3         0xa54ff53a
+#define H4         0x510e527f
+#define H5         0x9b05688c
+#define H6         0x1f83d9ab
+#define H7         0x5be0cd19
+
+static inline void LOAD_OP(int I, u32 *W, const u8 *input)
+{
+        W[I] = ntohl( ((u32*)(input))[I] );
+}
+
+static inline void BLEND_OP(int I, u32 *W)
+{
+        W[I] = s1(W[I-2]) + W[I-7] + s0(W[I-15]) + W[I-16];
+}
+
+static void sha256_transform(u32 *state, const u8 *input)
+{
+        u32 a, b, c, d, e, f, g, h, t1, t2;
+        u32 W[64];
+        int i;
+
+        /* load the input */
+        for (i = 0; i < 16; i++)
+                LOAD_OP(i, W, input);
+
+        /* now blend */
+        for (i = 16; i < 64; i++)
+                BLEND_OP(i, W);
+    
+        /* load the state into our registers */
+        a=state[0];  b=state[1];  c=state[2];  d=state[3];
+        e=state[4];  f=state[5];  g=state[6];  h=state[7];
+
+        /* now iterate */
+        t1 = h + e1(e) + Ch(e,f,g) + 0x428a2f98 + W[ 0];
+        t2 = e0(a) + Maj(a,b,c);    d+=t1;    h=t1+t2;
+        t1 = g + e1(d) + Ch(d,e,f) + 0x71374491 + W[ 1];
+        t2 = e0(h) + Maj(h,a,b);    c+=t1;    g=t1+t2;
+        t1 = f + e1(c) + Ch(c,d,e) + 0xb5c0fbcf + W[ 2];
+        t2 = e0(g) + Maj(g,h,a);    b+=t1;    f=t1+t2;
+        t1 = e + e1(b) + Ch(b,c,d) + 0xe9b5dba5 + W[ 3];
+        t2 = e0(f) + Maj(f,g,h);    a+=t1;    e=t1+t2;
+        t1 = d + e1(a) + Ch(a,b,c) + 0x3956c25b + W[ 4];
+        t2 = e0(e) + Maj(e,f,g);    h+=t1;    d=t1+t2;
+        t1 = c + e1(h) + Ch(h,a,b) + 0x59f111f1 + W[ 5];
+        t2 = e0(d) + Maj(d,e,f);    g+=t1;    c=t1+t2;
+        t1 = b + e1(g) + Ch(g,h,a) + 0x923f82a4 + W[ 6];
+        t2 = e0(c) + Maj(c,d,e);    f+=t1;    b=t1+t2;
+        t1 = a + e1(f) + Ch(f,g,h) + 0xab1c5ed5 + W[ 7];
+        t2 = e0(b) + Maj(b,c,d);    e+=t1;    a=t1+t2;
+
+        t1 = h + e1(e) + Ch(e,f,g) + 0xd807aa98 + W[ 8];
+        t2 = e0(a) + Maj(a,b,c);    d+=t1;    h=t1+t2;
+        t1 = g + e1(d) + Ch(d,e,f) + 0x12835b01 + W[ 9];
+        t2 = e0(h) + Maj(h,a,b);    c+=t1;    g=t1+t2;
+        t1 = f + e1(c) + Ch(c,d,e) + 0x243185be + W[10];
+        t2 = e0(g) + Maj(g,h,a);    b+=t1;    f=t1+t2;
+        t1 = e + e1(b) + Ch(b,c,d) + 0x550c7dc3 + W[11];
+        t2 = e0(f) + Maj(f,g,h);    a+=t1;    e=t1+t2;
+        t1 = d + e1(a) + Ch(a,b,c) + 0x72be5d74 + W[12];
+        t2 = e0(e) + Maj(e,f,g);    h+=t1;    d=t1+t2;
+        t1 = c + e1(h) + Ch(h,a,b) + 0x80deb1fe + W[13];
+        t2 = e0(d) + Maj(d,e,f);    g+=t1;    c=t1+t2;
+        t1 = b + e1(g) + Ch(g,h,a) + 0x9bdc06a7 + W[14];
+        t2 = e0(c) + Maj(c,d,e);    f+=t1;    b=t1+t2;
+        t1 = a + e1(f) + Ch(f,g,h) + 0xc19bf174 + W[15];
+        t2 = e0(b) + Maj(b,c,d);    e+=t1;    a=t1+t2;
+
+        t1 = h + e1(e) + Ch(e,f,g) + 0xe49b69c1 + W[16];
+        t2 = e0(a) + Maj(a,b,c);    d+=t1;    h=t1+t2;
+        t1 = g + e1(d) + Ch(d,e,f) + 0xefbe4786 + W[17];
+        t2 = e0(h) + Maj(h,a,b);    c+=t1;    g=t1+t2;
+        t1 = f + e1(c) + Ch(c,d,e) + 0x0fc19dc6 + W[18];
+        t2 = e0(g) + Maj(g,h,a);    b+=t1;    f=t1+t2;
+        t1 = e + e1(b) + Ch(b,c,d) + 0x240ca1cc + W[19];
+        t2 = e0(f) + Maj(f,g,h);    a+=t1;    e=t1+t2;
+        t1 = d + e1(a) + Ch(a,b,c) + 0x2de92c6f + W[20];
+        t2 = e0(e) + Maj(e,f,g);    h+=t1;    d=t1+t2;
+        t1 = c + e1(h) + Ch(h,a,b) + 0x4a7484aa + W[21];
+        t2 = e0(d) + Maj(d,e,f);    g+=t1;    c=t1+t2;
+        t1 = b + e1(g) + Ch(g,h,a) + 0x5cb0a9dc + W[22];
+        t2 = e0(c) + Maj(c,d,e);    f+=t1;    b=t1+t2;
+        t1 = a + e1(f) + Ch(f,g,h) + 0x76f988da + W[23];
+        t2 = e0(b) + Maj(b,c,d);    e+=t1;    a=t1+t2;
+
+        t1 = h + e1(e) + Ch(e,f,g) + 0x983e5152 + W[24];
+        t2 = e0(a) + Maj(a,b,c);    d+=t1;    h=t1+t2;
+        t1 = g + e1(d) + Ch(d,e,f) + 0xa831c66d + W[25];
+        t2 = e0(h) + Maj(h,a,b);    c+=t1;    g=t1+t2;
+        t1 = f + e1(c) + Ch(c,d,e) + 0xb00327c8 + W[26];
+        t2 = e0(g) + Maj(g,h,a);    b+=t1;    f=t1+t2;
+        t1 = e + e1(b) + Ch(b,c,d) + 0xbf597fc7 + W[27];
+        t2 = e0(f) + Maj(f,g,h);    a+=t1;    e=t1+t2;
+        t1 = d + e1(a) + Ch(a,b,c) + 0xc6e00bf3 + W[28];
+        t2 = e0(e) + Maj(e,f,g);    h+=t1;    d=t1+t2;
+        t1 = c + e1(h) + Ch(h,a,b) + 0xd5a79147 + W[29];
+        t2 = e0(d) + Maj(d,e,f);    g+=t1;    c=t1+t2;
+        t1 = b + e1(g) + Ch(g,h,a) + 0x06ca6351 + W[30];
+        t2 = e0(c) + Maj(c,d,e);    f+=t1;    b=t1+t2;
+        t1 = a + e1(f) + Ch(f,g,h) + 0x14292967 + W[31];
+        t2 = e0(b) + Maj(b,c,d);    e+=t1;    a=t1+t2;
+
+        t1 = h + e1(e) + Ch(e,f,g) + 0x27b70a85 + W[32];
+        t2 = e0(a) + Maj(a,b,c);    d+=t1;    h=t1+t2;
+        t1 = g + e1(d) + Ch(d,e,f) + 0x2e1b2138 + W[33];
+        t2 = e0(h) + Maj(h,a,b);    c+=t1;    g=t1+t2;
+        t1 = f + e1(c) + Ch(c,d,e) + 0x4d2c6dfc + W[34];
+        t2 = e0(g) + Maj(g,h,a);    b+=t1;    f=t1+t2;
+        t1 = e + e1(b) + Ch(b,c,d) + 0x53380d13 + W[35];
+        t2 = e0(f) + Maj(f,g,h);    a+=t1;    e=t1+t2;
+        t1 = d + e1(a) + Ch(a,b,c) + 0x650a7354 + W[36];
+        t2 = e0(e) + Maj(e,f,g);    h+=t1;    d=t1+t2;
+        t1 = c + e1(h) + Ch(h,a,b) + 0x766a0abb + W[37];
+        t2 = e0(d) + Maj(d,e,f);    g+=t1;    c=t1+t2;
+        t1 = b + e1(g) + Ch(g,h,a) + 0x81c2c92e + W[38];
+        t2 = e0(c) + Maj(c,d,e);    f+=t1;    b=t1+t2;
+        t1 = a + e1(f) + Ch(f,g,h) + 0x92722c85 + W[39];
+        t2 = e0(b) + Maj(b,c,d);    e+=t1;    a=t1+t2;
+
+        t1 = h + e1(e) + Ch(e,f,g) + 0xa2bfe8a1 + W[40];
+        t2 = e0(a) + Maj(a,b,c);    d+=t1;    h=t1+t2;
+        t1 = g + e1(d) + Ch(d,e,f) + 0xa81a664b + W[41];
+        t2 = e0(h) + Maj(h,a,b);    c+=t1;    g=t1+t2;
+        t1 = f + e1(c) + Ch(c,d,e) + 0xc24b8b70 + W[42];
+        t2 = e0(g) + Maj(g,h,a);    b+=t1;    f=t1+t2;
+        t1 = e + e1(b) + Ch(b,c,d) + 0xc76c51a3 + W[43];
+        t2 = e0(f) + Maj(f,g,h);    a+=t1;    e=t1+t2;
+        t1 = d + e1(a) + Ch(a,b,c) + 0xd192e819 + W[44];
+        t2 = e0(e) + Maj(e,f,g);    h+=t1;    d=t1+t2;
+        t1 = c + e1(h) + Ch(h,a,b) + 0xd6990624 + W[45];
+        t2 = e0(d) + Maj(d,e,f);    g+=t1;    c=t1+t2;
+        t1 = b + e1(g) + Ch(g,h,a) + 0xf40e3585 + W[46];
+        t2 = e0(c) + Maj(c,d,e);    f+=t1;    b=t1+t2;
+        t1 = a + e1(f) + Ch(f,g,h) + 0x106aa070 + W[47];
+        t2 = e0(b) + Maj(b,c,d);    e+=t1;    a=t1+t2;
+
+        t1 = h + e1(e) + Ch(e,f,g) + 0x19a4c116 + W[48];
+        t2 = e0(a) + Maj(a,b,c);    d+=t1;    h=t1+t2;
+        t1 = g + e1(d) + Ch(d,e,f) + 0x1e376c08 + W[49];
+        t2 = e0(h) + Maj(h,a,b);    c+=t1;    g=t1+t2;
+        t1 = f + e1(c) + Ch(c,d,e) + 0x2748774c + W[50];
+        t2 = e0(g) + Maj(g,h,a);    b+=t1;    f=t1+t2;
+        t1 = e + e1(b) + Ch(b,c,d) + 0x34b0bcb5 + W[51];
+        t2 = e0(f) + Maj(f,g,h);    a+=t1;    e=t1+t2;
+        t1 = d + e1(a) + Ch(a,b,c) + 0x391c0cb3 + W[52];
+        t2 = e0(e) + Maj(e,f,g);    h+=t1;    d=t1+t2;
+        t1 = c + e1(h) + Ch(h,a,b) + 0x4ed8aa4a + W[53];
+        t2 = e0(d) + Maj(d,e,f);    g+=t1;    c=t1+t2;
+        t1 = b + e1(g) + Ch(g,h,a) + 0x5b9cca4f + W[54];
+        t2 = e0(c) + Maj(c,d,e);    f+=t1;    b=t1+t2;
+        t1 = a + e1(f) + Ch(f,g,h) + 0x682e6ff3 + W[55];
+        t2 = e0(b) + Maj(b,c,d);    e+=t1;    a=t1+t2;
+
+        t1 = h + e1(e) + Ch(e,f,g) + 0x748f82ee + W[56];
+        t2 = e0(a) + Maj(a,b,c);    d+=t1;    h=t1+t2;
+        t1 = g + e1(d) + Ch(d,e,f) + 0x78a5636f + W[57];
+        t2 = e0(h) + Maj(h,a,b);    c+=t1;    g=t1+t2;
+        t1 = f + e1(c) + Ch(c,d,e) + 0x84c87814 + W[58];
+        t2 = e0(g) + Maj(g,h,a);    b+=t1;    f=t1+t2;
+        t1 = e + e1(b) + Ch(b,c,d) + 0x8cc70208 + W[59];
+        t2 = e0(f) + Maj(f,g,h);    a+=t1;    e=t1+t2;
+        t1 = d + e1(a) + Ch(a,b,c) + 0x90befffa + W[60];
+        t2 = e0(e) + Maj(e,f,g);    h+=t1;    d=t1+t2;
+        t1 = c + e1(h) + Ch(h,a,b) + 0xa4506ceb + W[61];
+        t2 = e0(d) + Maj(d,e,f);    g+=t1;    c=t1+t2;
+        t1 = b + e1(g) + Ch(g,h,a) + 0xbef9a3f7 + W[62];
+        t2 = e0(c) + Maj(c,d,e);    f+=t1;    b=t1+t2;
+        t1 = a + e1(f) + Ch(f,g,h) + 0xc67178f2 + W[63];
+        t2 = e0(b) + Maj(b,c,d);    e+=t1;    a=t1+t2;
+
+        state[0] += a; state[1] += b; state[2] += c; state[3] += d;
+        state[4] += e; state[5] += f; state[6] += g; state[7] += h;
+
+        /* clear any sensitive info... */
+        a = b = c = d = e = f = g = h = t1 = t2 = 0;
+        memset(W, 0, 64 * sizeof(u32));
+}
+
+SHA256Summation::SHA256Summation()
+{
+        Sum.state[0] = H0;
+        Sum.state[1] = H1;
+        Sum.state[2] = H2;
+        Sum.state[3] = H3;
+        Sum.state[4] = H4;
+        Sum.state[5] = H5;
+        Sum.state[6] = H6;
+        Sum.state[7] = H7;
+        Sum.count[0] = Sum.count[1] = 0;
+        memset(Sum.buf, 0, sizeof(Sum.buf));
+        Done = false;
+}
+
+bool SHA256Summation::Add(const u8 *data, unsigned long len)
+{
+        struct sha256_ctx *sctx = &Sum;
+        unsigned int i, index, part_len;
+
+        if (Done) return false;
+
+        /* Compute number of bytes mod 128 */
+        index = (unsigned int)((sctx->count[0] >> 3) & 0x3f);
+
+        /* Update number of bits */
+        if ((sctx->count[0] += (len << 3)) < (len << 3)) {
+                sctx->count[1]++;
+                sctx->count[1] += (len >> 29);
+        }
+
+        part_len = 64 - index;
+
+        /* Transform as many times as possible. */
+        if (len >= part_len) {
+                memcpy(&sctx->buf[index], data, part_len);
+                sha256_transform(sctx->state, sctx->buf);
+
+                for (i = part_len; i + 63 < len; i += 64)
+                        sha256_transform(sctx->state, &data[i]);
+                index = 0;
+        } else {
+                i = 0;
+        }
+
+        /* Buffer remaining input */
+        memcpy(&sctx->buf[index], &data[i], len-i);
+
+        return true;
+}
+
+SHA256SumValue SHA256Summation::Result()
+{
+   struct sha256_ctx *sctx = &Sum;
+   if (!Done) {
+        u8 bits[8];
+        unsigned int index, pad_len, t;
+        static const u8 padding[64] = { 0x80, };
+
+        /* Save number of bits */
+        t = sctx->count[0];
+        bits[7] = t; t >>= 8;
+        bits[6] = t; t >>= 8;
+        bits[5] = t; t >>= 8;
+        bits[4] = t;
+        t = sctx->count[1];
+        bits[3] = t; t >>= 8;
+        bits[2] = t; t >>= 8;
+        bits[1] = t; t >>= 8;
+        bits[0] = t;
+
+        /* Pad out to 56 mod 64. */
+        index = (sctx->count[0] >> 3) & 0x3f;
+        pad_len = (index < 56) ? (56 - index) : ((64+56) - index);
+        Add(padding, pad_len);
+
+        /* Append length (before padding) */
+        Add(bits, 8);
+   }
+
+   Done = true;
+
+   /* Store state in digest */
+
+   SHA256SumValue res;
+   u8 *out = res.Sum;
+
+   int i, j;
+   unsigned int t;
+   for (i = j = 0; i < 8; i++, j += 4) {
+      t = sctx->state[i];
+      out[j+3] = t; t >>= 8;
+      out[j+2] = t; t >>= 8;
+      out[j+1] = t; t >>= 8;
+      out[j  ] = t;
+   }
+
+   return res;
+}
+
+// SHA256SumValue::SHA256SumValue - Constructs the sum from a string   /*{{{*/
+// ---------------------------------------------------------------------
+/* The string form of a SHA256 is a 64 character hex number */
+SHA256SumValue::SHA256SumValue(string Str)
+{
+   memset(Sum,0,sizeof(Sum));
+   Set(Str);
+}
+
+                                                                       /*}}}*/
+// SHA256SumValue::SHA256SumValue - Default constructor                /*{{{*/
+// ---------------------------------------------------------------------
+/* Sets the value to 0 */
+SHA256SumValue::SHA256SumValue()
+{
+   memset(Sum,0,sizeof(Sum));
+}
+
+                                                                       /*}}}*/
+// SHA256SumValue::Set - Set the sum from a string                     /*{{{*/
+// ---------------------------------------------------------------------
+/* Converts the hex string into a set of chars */
+bool SHA256SumValue::Set(string Str)
+{
+   return Hex2Num(Str,Sum,sizeof(Sum));
+}
+                                                                       /*}}}*/
+// SHA256SumValue::Value - Convert the number into a string            /*{{{*/
+// ---------------------------------------------------------------------
+/* Converts the set of chars into a hex string in lower case */
+string SHA256SumValue::Value() const
+{
+   char Conv[16] =
+      { '0','1','2','3','4','5','6','7','8','9','a','b',
+      'c','d','e','f'
+   };
+   char Result[65];
+   Result[64] = 0;
+
+   // Convert each char into two letters
+   int J = 0;
+   int I = 0;
+   for (; I != 64; J++,I += 2)
+   {
+      Result[I] = Conv[Sum[J] >> 4];
+      Result[I + 1] = Conv[Sum[J] & 0xF];
+   }
+
+   return string(Result);
+}
+
+
+
+// SHA256SumValue::operator == - Comparator                            /*{{{*/
+// ---------------------------------------------------------------------
+/* Call memcmp on the buffer */
+bool SHA256SumValue::operator == (const SHA256SumValue & rhs) const
+{
+   return memcmp(Sum,rhs.Sum,sizeof(Sum)) == 0;
+}
+                                                                       /*}}}*/
+
+
+// SHA256Summation::AddFD - Add content of file into the checksum      /*{{{*/
+// ---------------------------------------------------------------------
+/* */
+bool SHA256Summation::AddFD(int Fd,unsigned long Size)
+{
+   unsigned char Buf[64 * 64];
+   int Res = 0;
+   int ToEOF = (Size == 0);
+   while (Size != 0 || ToEOF)
+   {
+      unsigned n = sizeof(Buf);
+      if (!ToEOF) n = min(Size,(unsigned long)n);
+      Res = read(Fd,Buf,n);
+      if (Res < 0 || (!ToEOF && (unsigned) Res != n)) // error, or short read
+         return false;
+      if (ToEOF && Res == 0) // EOF
+         break;
+      Size -= Res;
+      Add(Buf,Res);
+   }
+   return true;
+}
+                                                                       /*}}}*/
+
diff --git a/apt-pkg/contrib/sha256.h b/apt-pkg/contrib/sha256.h
new file mode 100644 (file)
index 0000000..9e88f5e
--- /dev/null
@@ -0,0 +1,75 @@
+// -*- mode: cpp; mode: fold -*-
+// Description                                                          /*{{{*/
+// $Id: sha1.h,v 1.3 2001/05/07 05:05:47 jgg Exp $
+/* ######################################################################
+
+   SHA256SumValue - Storage for a SHA-256 hash.
+   SHA256Summation - SHA-256 Secure Hash Algorithm.
+   
+   This is a C++ interface to a set of SHA256Sum functions, that mirrors
+   the equivalent MD5 & SHA1 classes. 
+
+   ##################################################################### */
+                                                                        /*}}}*/
+#ifndef APTPKG_SHA256_H
+#define APTPKG_SHA256_H
+
+#ifdef __GNUG__
+#pragma interface "apt-pkg/sha256.h"
+#endif 
+
+#include <string>
+#include <algorithm>
+#include <stdint.h>
+
+using std::string;
+using std::min;
+
+class SHA256Summation;
+
+class SHA256SumValue
+{
+   friend class SHA256Summation;
+   unsigned char Sum[32];
+   
+   public:
+
+   // Accessors
+   bool operator ==(const SHA256SumValue &rhs) const; 
+   string Value() const;
+   inline void Value(unsigned char S[32])
+         {for (int I = 0; I != sizeof(Sum); I++) S[I] = Sum[I];};
+   inline operator string() const {return Value();};
+   bool Set(string Str);
+   inline void Set(unsigned char S[32]) 
+         {for (int I = 0; I != sizeof(Sum); I++) Sum[I] = S[I];};
+
+   SHA256SumValue(string Str);
+   SHA256SumValue();
+};
+
+struct sha256_ctx {
+    uint32_t count[2];
+    uint32_t state[8];
+    uint8_t buf[128];
+};
+
+class SHA256Summation
+{
+   struct sha256_ctx Sum;
+
+   bool Done;
+
+   public:
+
+   bool Add(const unsigned char *inbuf,unsigned long inlen);
+   inline bool Add(const char *Data) {return Add((unsigned char *)Data,strlen(Data));};
+   bool AddFD(int Fd,unsigned long Size);
+   inline bool Add(const unsigned char *Beg,const unsigned char *End) 
+                  {return Add(Beg,End-Beg);};
+   SHA256SumValue Result();
+   
+   SHA256Summation();
+};
+
+#endif
index 0e6aecc65c26e6a231f824d0921c729a9b4a5d4e..7e5feae53b4b11082c1d3973bab0772c5ce7085d 100644 (file)
@@ -21,11 +21,11 @@ APT_DOMAIN:=libapt-pkg$(MAJOR)
 # Source code for the contributed non-core things
 SOURCE = contrib/mmap.cc contrib/error.cc contrib/strutl.cc \
          contrib/configuration.cc contrib/progress.cc contrib/cmndline.cc \
-        contrib/md5.cc contrib/sha1.cc contrib/hashes.cc \
+        contrib/md5.cc contrib/sha1.cc contrib/sha256.cc contrib/hashes.cc \
         contrib/cdromutl.cc contrib/crc-16.cc \
         contrib/fileutl.cc 
 HEADERS = mmap.h error.h configuration.h fileutl.h  cmndline.h \
-         md5.h crc-16.h cdromutl.h strutl.h sptr.h sha1.h hashes.h
+         md5.h crc-16.h cdromutl.h strutl.h sptr.h sha1.h sha256.h hashes.h
 
 # Source code for the core main library
 SOURCE+= pkgcache.cc version.cc depcache.cc \
index dc1ba3f9e991fe3aafcad402d36fd1ead5cb912e..fc020436ca37345e1e062be8d9d8371a60e52afd 100644 (file)
@@ -342,7 +342,8 @@ static const char *iTFRewritePackageOrder[] = {
                           "Filename",
                           "Size",
                           "MD5Sum",
-                          "SHA1Sum",
+                          "SHA1",
+                          "SHA256",
                            "MSDOS-Filename",   // Obsolete
                           "Description",
                           0};
index 4c5583a0f5e7fd692399d01b882728fb5df8fb15..2c4bbcb6fb3c8206df0b1d232a23a29eabddcad3 100644 (file)
@@ -18,7 +18,7 @@ AC_CONFIG_AUX_DIR(buildlib)
 AC_CONFIG_HEADER(include/config.h:buildlib/config.h.in include/apti18n.h:buildlib/apti18n.h.in)
 
 dnl -- SET THIS TO THE RELEASE VERSION --
-AC_DEFINE_UNQUOTED(VERSION,"0.6.43.4")
+AC_DEFINE_UNQUOTED(VERSION,"0.6.44")
 PACKAGE="apt"
 AC_DEFINE_UNQUOTED(PACKAGE,"$PACKAGE")
 AC_SUBST(PACKAGE)
index db04b1e919e256a474a6bee895886c23e834b9ce..f44d1966b82037589f3dfa6d3de078b36a8b3263 100644 (file)
@@ -1,3 +1,11 @@
+apt (0.6.44) unstable; urgency=low
+
+  * apt-ftparchive --db now uses Berkeley DB_BTREE instead of DB_HASH. 
+    If you use a database created by an older version of apt, delete 
+    it and allow it to be recreated the next time.
+
+ -- Michael Vogt <mvo@debian.org>  Wed, 26 Apr 2006 12:57:53 +0200
+
 apt (0.5.25) unstable; urgency=low
 
   * apt-ftparchive --db now uses Berkeley DB version 4.2.  If used with a
index 00b46eb22b7023fa1ab2676ed794ae22f0c75d53..6d2a7173aed240fc336b95039b373dc6762373e7 100644 (file)
@@ -1,10 +1,15 @@
 apt (0.6.44) unstable; urgency=low
 
   * apt-pkg/acquire.cc: don't show ETA if it is 0 or absurdely large
+  * apt-pkg/contrib/sha256.{cc,h},hashes.{cc,h}: support for sha256 
+    (thanks to Anthony Towns)
+  * ftparchive/cachedb.{cc,h},writer.{cc,h}: optimizations 
+    (thanks to Anthony Towns)
+  * apt pdiff support from experimental merged
+  * apt-pkg/deb/dpkgpm.cc: wording fixes (thanks to Matt Zimmerman)
   * apt-pkg/deb/dpkgpm.cc: 
     - wording fixes (thanks to Matt Zimmerman)
-    - fix error in dpkg interaction (closes: #364513, 
-      thanks to Martin Dickopp)
+    - fix error in dpkg interaction (closes: #364513, thanks to Martin Dickopp)
   * apt-pkg/tagfile.{cc,h}:
     - use MMap to read the entries (thanks to Zephaniah E. Hull for the
       patch) Closes: #350025
@@ -14,7 +19,7 @@ apt (0.6.44) unstable; urgency=low
     - fix documentation for "SrcPackages" -> "Sources" 
       (thanks to Bart Martens for the patch, closes: #307756)
 
- -- Michael Vogt <michael.vogt@ubuntu.com>  Tue, 25 Apr 2006 09:34:20 +0200
+ -- Michael Vogt <mvo@debian.org>  Sun,  2 Apr 2006 16:41:54 +0200
 
 apt (0.6.43.3) unstable; urgency=low
 
index 9e851d7533f7ede88e1c2049d9ddb83a56fa2f84..7346ba9bb4324b4ea14c63fd498b769efbc5f3cd 100644 (file)
@@ -104,6 +104,8 @@ Acquire
   Queue-Mode "host";       // host|access
   Retries "0";
   Source-Symlinks "true";
+
+  PDiffs "true";     // try to get the IndexFile diffs
   
   // HTTP method configuration
   http 
index 9e93dff0520946658c3bd8ee03da1cf62a3db2c5..0e6078642ad4833b6aa4bb200096774032389e33 100644 (file)
@@ -19,6 +19,8 @@
 #include <apti18n.h>
 #include <apt-pkg/error.h>
 #include <apt-pkg/md5.h>
+#include <apt-pkg/sha1.h>
+#include <apt-pkg/sha256.h>
 #include <apt-pkg/strutl.h>
 #include <apt-pkg/configuration.h>
     
@@ -54,7 +56,7 @@ bool CacheDB::ReadyDB(string DB)
       return true;
 
    db_create(&Dbp, NULL, 0);
-   if ((err = Dbp->open(Dbp, NULL, DB.c_str(), NULL, DB_HASH,
+   if ((err = Dbp->open(Dbp, NULL, DB.c_str(), NULL, DB_BTREE,
                         (ReadOnly?DB_RDONLY:DB_CREATE),
                         0644)) != 0)
    {
@@ -67,6 +69,12 @@ bool CacheDB::ReadyDB(string DB)
                             (ReadOnly?DB_RDONLY:DB_CREATE), 0644);
 
       }
+      // the database format has changed from DB_HASH to DB_BTREE in 
+      // apt 0.6.44
+      if (err == EINVAL)
+      {
+        _error->Error(_("DB format is invalid. If you upgraded from a older version of apt, please remove and re-create the database."));
+      }
       if (err)
       {
           Dbp = 0;
@@ -79,48 +87,123 @@ bool CacheDB::ReadyDB(string DB)
    return true;
 }
                                                                        /*}}}*/
-// CacheDB::SetFile - Select a file to be working with                 /*{{{*/
+// CacheDB::OpenFile - Open the filei                                  /*{{{*/
+// ---------------------------------------------------------------------
+/* */
+bool CacheDB::OpenFile()
+{
+       Fd = new FileFd(FileName,FileFd::ReadOnly);
+       if (_error->PendingError() == true)
+       {
+               delete Fd;
+               Fd = NULL;
+               return false;
+       }
+       return true;
+}
+                                                                       /*}}}*/
+// CacheDB::GetFileStat - Get stats from the file                      /*{{{*/
+// ---------------------------------------------------------------------
+/* This gets the size from the database if it's there.  If we need
+ * to look at the file, also get the mtime from the file. */
+bool CacheDB::GetFileStat()
+{
+       if ((CurStat.Flags & FlSize) == FlSize)
+       {
+               /* Already worked out the file size */
+       }
+       else
+       {
+               /* Get it from the file. */
+               if (Fd == NULL && OpenFile() == false)
+               {
+                       return false;
+               }
+               // Stat the file
+               struct stat St;
+               if (fstat(Fd->Fd(),&St) != 0)
+               {
+                       return _error->Errno("fstat",
+                               _("Failed to stat %s"),FileName.c_str());
+               }
+               CurStat.FileSize = St.st_size;
+               CurStat.mtime = htonl(St.st_mtime);
+               CurStat.Flags |= FlSize;
+       }
+       return true;
+}
+                                                                       /*}}}*/
+// CacheDB::GetCurStat - Set the CurStat variable.                     /*{{{*/
 // ---------------------------------------------------------------------
-/* All future actions will be performed against this file */
-bool CacheDB::SetFile(string FileName,struct stat St,FileFd *Fd)
+/* Sets the CurStat variable.  Either to 0 if no database is used
+ * or to the value in the database if one is used */
+bool CacheDB::GetCurStat()
 {
-   delete DebFile;
-   DebFile = 0;
-   this->FileName = FileName;
-   this->Fd = Fd;
-   this->FileStat = St;
-   FileStat = St;   
    memset(&CurStat,0,sizeof(CurStat));
    
-   Stats.Bytes += St.st_size;
-   Stats.Packages++;
-   
-   if (DBLoaded == false)
-      return true;
+       if (DBLoaded)
+       {
+               /* First see if thre is anything about it
+                  in the database */
 
+               /* Get the flags (and mtime) */
    InitQuery("st");
-   
    // Ensure alignment of the returned structure
    Data.data = &CurStat;
    Data.ulen = sizeof(CurStat);
    Data.flags = DB_DBT_USERMEM;
-   // Lookup the stat info and confirm the file is unchanged
-   if (Get() == true)
-   {
-      if (CurStat.mtime != htonl(St.st_mtime))
+               if (Get() == false)
       {
-        CurStat.mtime = htonl(St.st_mtime);
         CurStat.Flags = 0;
-        _error->Warning(_("File date has changed %s"),FileName.c_str());
       }      
+               CurStat.Flags = ntohl(CurStat.Flags);
+               CurStat.FileSize = ntohl(CurStat.FileSize);
    }      
-   else
+       return true;
+}
+                                                                       /*}}}*/
+// CacheDB::GetFileInfo - Get all the info about the file              /*{{{*/
+// ---------------------------------------------------------------------
+bool CacheDB::GetFileInfo(string FileName, bool DoControl, bool DoContents,
+                               bool GenContentsOnly, 
+                               bool DoMD5, bool DoSHA1, bool DoSHA256)
+{
+       this->FileName = FileName;
+
+       if (GetCurStat() == false)
    {
-      CurStat.mtime = htonl(St.st_mtime);
-      CurStat.Flags = 0;
+               return false;
    }   
-   CurStat.Flags = ntohl(CurStat.Flags);
    OldStat = CurStat;
+       
+       if (GetFileStat() == false)
+       {
+               delete Fd;
+               Fd = NULL;
+               return false;   
+       }
+
+       Stats.Bytes += CurStat.FileSize;
+       Stats.Packages++;
+
+       if (DoControl && LoadControl() == false
+               || DoContents && LoadContents(GenContentsOnly) == false
+               || DoMD5 && GetMD5(false) == false
+               || DoSHA1 && GetSHA1(false) == false
+               || DoSHA256 && GetSHA256(false) == false)
+       {
+               delete Fd;
+               Fd = NULL;
+               delete DebFile;
+               DebFile = NULL;
+               return false;   
+       }
+
+       delete Fd;
+       Fd = NULL;
+       delete DebFile;
+       DebFile = NULL;
+
    return true;
 }
                                                                        /*}}}*/
@@ -139,6 +222,10 @@ bool CacheDB::LoadControl()
       CurStat.Flags &= ~FlControl;
    }
    
+   if (Fd == NULL && OpenFile() == false)
+   {
+      return false;
+   }
    // Create a deb instance to read the archive
    if (DebFile == 0)
    {
@@ -183,6 +270,10 @@ bool CacheDB::LoadContents(bool GenOnly)
       CurStat.Flags &= ~FlContents;
    }
    
+   if (Fd == NULL && OpenFile() == false)
+   {
+      return false;
+   }
    // Create a deb instance to read the archive
    if (DebFile == 0)
    {
@@ -201,10 +292,37 @@ bool CacheDB::LoadContents(bool GenOnly)
    return true;
 }
                                                                        /*}}}*/
+
+static string bytes2hex(uint8_t *bytes, size_t length) {
+   char space[65];
+   if (length * 2 > sizeof(space) - 1) length = (sizeof(space) - 1) / 2;
+   for (size_t i = 0; i < length; i++)
+      snprintf(&space[i*2], 3, "%02x", bytes[i]);
+   return string(space);
+}
+
+static inline unsigned char xdig2num(char dig) {
+   if (isdigit(dig)) return dig - '0';
+   if ('a' <= dig && dig <= 'f') return dig - 'a' + 10;
+   if ('A' <= dig && dig <= 'F') return dig - 'A' + 10;
+   return 0;
+}
+
+static void hex2bytes(uint8_t *bytes, const char *hex, int length) {
+   while (length-- > 0) {
+      *bytes = 0;
+      if (isxdigit(hex[0]) && isxdigit(hex[1])) {
+         *bytes = xdig2num(hex[0]) * 16 + xdig2num(hex[1]);
+         hex += 2;
+      }
+      bytes++;
+   } 
+}
+
 // CacheDB::GetMD5 - Get the MD5 hash                                  /*{{{*/
 // ---------------------------------------------------------------------
 /* */
-bool CacheDB::GetMD5(string &MD5Res,bool GenOnly)
+bool CacheDB::GetMD5(bool GenOnly)
 {
    // Try to read the control information out of the DB.
    if ((CurStat.Flags & FlMD5) == FlMD5)
@@ -212,28 +330,88 @@ bool CacheDB::GetMD5(string &MD5Res,bool GenOnly)
       if (GenOnly == true)
         return true;
       
-      InitQuery("m5");
-      if (Get() == true)
-      {
-        MD5Res = string((char *)Data.data,Data.size);
+      MD5Res = bytes2hex(CurStat.MD5, sizeof(CurStat.MD5));
         return true;
       }
-      CurStat.Flags &= ~FlMD5;
-   }
    
-   Stats.MD5Bytes += FileStat.st_size;
+   Stats.MD5Bytes += CurStat.FileSize;
         
+   if (Fd == NULL && OpenFile() == false)
+   {
+      return false;
+   }
    MD5Summation MD5;
-   if (Fd->Seek(0) == false || MD5.AddFD(Fd->Fd(),FileStat.st_size) == false)
+   if (Fd->Seek(0) == false || MD5.AddFD(Fd->Fd(),CurStat.FileSize) == false)
       return false;
    
    MD5Res = MD5.Result();
-   InitQuery("m5");
-   if (Put(MD5Res.c_str(),MD5Res.length()) == true)
+   hex2bytes(CurStat.MD5, MD5Res.data(), sizeof(CurStat.MD5));
       CurStat.Flags |= FlMD5;
    return true;
 }
                                                                        /*}}}*/
+// CacheDB::GetSHA1 - Get the SHA1 hash                                        /*{{{*/
+// ---------------------------------------------------------------------
+/* */
+bool CacheDB::GetSHA1(bool GenOnly)
+{
+   // Try to read the control information out of the DB.
+   if ((CurStat.Flags & FlSHA1) == FlSHA1)
+   {
+      if (GenOnly == true)
+        return true;
+
+      SHA1Res = bytes2hex(CurStat.SHA1, sizeof(CurStat.SHA1));
+      return true;
+   }
+   
+   Stats.SHA1Bytes += CurStat.FileSize;
+        
+   if (Fd == NULL && OpenFile() == false)
+   {
+      return false;
+   }
+   SHA1Summation SHA1;
+   if (Fd->Seek(0) == false || SHA1.AddFD(Fd->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 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;
+   }
+   
+   Stats.SHA256Bytes += CurStat.FileSize;
+        
+   if (Fd == NULL && OpenFile() == false)
+   {
+      return false;
+   }
+   SHA256Summation SHA256;
+   if (Fd->Seek(0) == false || SHA256.AddFD(Fd->Fd(),CurStat.FileSize) == false)
+      return false;
+   
+   SHA256Res = SHA256.Result();
+   hex2bytes(CurStat.SHA256, SHA256Res.data(), sizeof(CurStat.SHA256));
+   CurStat.Flags |= FlSHA256;
+   return true;
+}
+                                                                       /*}}}*/
 // CacheDB::Finish - Write back the cache structure                    /*{{{*/
 // ---------------------------------------------------------------------
 /* */
@@ -246,9 +424,12 @@ bool CacheDB::Finish()
    
    // Write the stat information
    CurStat.Flags = htonl(CurStat.Flags);
+   CurStat.FileSize = htonl(CurStat.FileSize);
    InitQuery("st");
    Put(&CurStat,sizeof(CurStat));
    CurStat.Flags = ntohl(CurStat.Flags);
+   CurStat.FileSize = ntohl(CurStat.FileSize);
+
    return true;
 }
                                                                        /*}}}*/
@@ -278,7 +459,6 @@ bool CacheDB::Clean()
       {
         if (stringcmp((char *)Key.data,Colon,"st") == 0 ||
             stringcmp((char *)Key.data,Colon,"cn") == 0 ||
-            stringcmp((char *)Key.data,Colon,"m5") == 0 ||
             stringcmp((char *)Key.data,Colon,"cl") == 0)
         {
            if (FileExists(string(Colon+1,(const char *)Key.data+Key.size)) == true)
index 1b043e1aa33aad8f319f826f89bc2b10e50e9628..afa22213ae5c55b504b1d3d2523c4b28eed28058 100644 (file)
@@ -44,7 +44,7 @@ class CacheDB
       memset(&Key,0,sizeof(Key));
       memset(&Data,0,sizeof(Data));
       Key.data = TmpKey;
-      Key.size = snprintf(TmpKey,sizeof(TmpKey),"%s:%s",Type,FileName.c_str());
+      Key.size = snprintf(TmpKey,sizeof(TmpKey),"%s:%s",FileName.c_str(), Type);
    }
    
    inline bool Get() 
@@ -64,19 +64,31 @@ class CacheDB
       }
       return true;
    }
+   bool OpenFile();
+   bool GetFileStat();
+   bool GetCurStat();
+   bool LoadControl();
+   bool LoadContents(bool GenOnly);
+   bool GetMD5(bool GenOnly);
+   bool GetSHA1(bool GenOnly);
+   bool GetSHA256(bool GenOnly);
    
    // Stat info stored in the DB, Fixed types since it is written to disk.
-   enum FlagList {FlControl = (1<<0),FlMD5=(1<<1),FlContents=(1<<2)};
+   enum FlagList {FlControl = (1<<0),FlMD5=(1<<1),FlContents=(1<<2),
+       FlSize=(1<<3), FlSHA1=(1<<4), FlSHA256=(1<<5)};
    struct StatStore
    {
-      time_t   mtime;          
       uint32_t Flags;
+      uint32_t mtime;          
+      uint32_t FileSize;
+      uint8_t  MD5[16];
+      uint8_t  SHA1[20];
+      uint8_t  SHA256[32];
    } CurStat;
    struct StatStore OldStat;
    
    // 'set' state
    string FileName;
-   struct stat FileStat;
    FileFd *Fd;
    debDebFile *DebFile;
    
@@ -85,34 +97,42 @@ class CacheDB
    // Data collection helpers
    debDebFile::MemControlExtract Control;
    ContentsExtract Contents;
+   string MD5Res;
+   string SHA1Res;
+   string SHA256Res;
    
    // Runtime statistics
    struct Stats
    {
       double Bytes;
       double MD5Bytes;
+      double SHA1Bytes;
+      double SHA256Bytes;
       unsigned long Packages;
       unsigned long Misses;  
       unsigned long DeLinkBytes;
       
-      inline void Add(const Stats &S) {Bytes += S.Bytes; MD5Bytes += S.MD5Bytes;
+      inline void Add(const Stats &S) {
+        Bytes += S.Bytes; MD5Bytes += S.MD5Bytes; SHA1Bytes += S.SHA1Bytes; 
+        SHA256Bytes += S.SHA256Bytes;
         Packages += S.Packages; Misses += S.Misses; DeLinkBytes += S.DeLinkBytes;};
-      Stats() : Bytes(0), MD5Bytes(0), Packages(0), Misses(0), DeLinkBytes(0) {};
+      Stats() : Bytes(0), MD5Bytes(0), SHA1Bytes(0), SHA256Bytes(0), Packages(0), Misses(0), DeLinkBytes(0) {};
    } Stats;
    
    bool ReadyDB(string DB);
    inline bool DBFailed() {return Dbp != 0 && DBLoaded == false;};
    inline bool Loaded() {return DBLoaded == true;};
    
+   inline off_t GetFileSize(void) {return CurStat.FileSize;}
+   
    bool SetFile(string FileName,struct stat St,FileFd *Fd);
-   bool LoadControl();
-   bool LoadContents(bool GenOnly);
-   bool GetMD5(string &MD5Res,bool GenOnly);
+   bool GetFileInfo(string FileName, bool DoControl, bool DoContents,
+                  bool GenContentsOnly, bool DoMD5, bool DoSHA1, bool DoSHA256);
    bool Finish();   
    
    bool Clean();
    
-   CacheDB(string DB) : Dbp(0), DebFile(0) {ReadyDB(DB);};
+   CacheDB(string DB) : Dbp(0), Fd(NULL), DebFile(0) {ReadyDB(DB);};
    ~CacheDB() {ReadyDB(string()); delete DebFile;};
 };
     
index fc9ea27d7e52af22d10f5a8d8b46e6c21edead2e..ea242d6af13623f47c2abd165beb6b7910e79023 100644 (file)
@@ -23,6 +23,7 @@
 #include <apt-pkg/configuration.h>
 #include <apt-pkg/md5.h>
 #include <apt-pkg/sha1.h>
+#include <apt-pkg/sha256.h>
 #include <apt-pkg/deblistparser.h>
 
 #include <sys/types.h>
@@ -70,7 +71,7 @@ FTWScanner::FTWScanner()
 // ---------------------------------------------------------------------
 /* This is the FTW scanner, it processes each directory element in the 
    directory tree. */
-int FTWScanner::Scanner(const char *File,const struct stat *sb,int Flag)
+int FTWScanner::ScannerFTW(const char *File,const struct stat *sb,int Flag)
 {
    if (Flag == FTW_DNR)
    {
@@ -85,6 +86,14 @@ int FTWScanner::Scanner(const char *File,const struct stat *sb,int Flag)
    if (Flag != FTW_F)
       return 0;
 
+   return ScannerFile(File, true);
+}
+                                                                       /*}}}*/
+// FTWScanner::ScannerFile - File Scanner                              /*{{{*/
+// ---------------------------------------------------------------------
+/* */
+int FTWScanner::ScannerFile(const char *File, bool ReadLink)
+{
    const char *LastComponent = strrchr(File, '/');
    if (LastComponent == NULL)
       LastComponent = File;
@@ -105,7 +114,8 @@ int FTWScanner::Scanner(const char *File,const struct stat *sb,int Flag)
       given are not links themselves. */
    char Jnk[2];
    Owner->OriginalPath = File;
-   if (Owner->RealPath != 0 && readlink(File,Jnk,sizeof(Jnk)) != -1 &&
+   if (ReadLink && Owner->RealPath != 0 &&
+       readlink(File,Jnk,sizeof(Jnk)) != -1 &&
        realpath(File,Owner->RealPath) != 0)
       Owner->DoPackage(Owner->RealPath);
    else
@@ -154,7 +164,7 @@ bool FTWScanner::RecursiveScan(string Dir)
    
    // Do recursive directory searching
    Owner = this;
-   int Res = ftw(Dir.c_str(),Scanner,30);
+   int Res = ftw(Dir.c_str(),ScannerFTW,30);
    
    // Error treewalking?
    if (Res != 0)
@@ -209,12 +219,14 @@ bool FTWScanner::LoadFileList(string Dir,string File)
         FileName = Line;
       }
       
+#if 0
       struct stat St;
       int Flag = FTW_F;
       if (stat(FileName,&St) != 0)
         Flag = FTW_NS;
+#endif
 
-      if (Scanner(FileName,&St,Flag) != 0)
+      if (ScannerFile(FileName, false) != 0)
         break;
    }
   
@@ -227,7 +239,7 @@ bool FTWScanner::LoadFileList(string Dir,string File)
 /* */
 bool FTWScanner::Delink(string &FileName,const char *OriginalPath,
                        unsigned long &DeLinkBytes,
-                       struct stat &St)
+                       off_t FileSize)
 {
    // See if this isn't an internaly prefix'd file name.
    if (InternalPrefix.empty() == false &&
@@ -243,7 +255,7 @@ bool FTWScanner::Delink(string &FileName,const char *OriginalPath,
         
         NewLine(1);
         ioprintf(c1out, _(" DeLink %s [%s]\n"), (OriginalPath + InternalPrefix.length()),
-                   SizeToStr(St.st_size).c_str());
+                   SizeToStr(FileSize).c_str());
         c1out << flush;
         
         if (NoLinkAct == false)
@@ -269,7 +281,7 @@ bool FTWScanner::Delink(string &FileName,const char *OriginalPath,
            }       
         }
         
-        DeLinkBytes += St.st_size;
+        DeLinkBytes += FileSize;
         if (DeLinkBytes/1024 >= DeLinkLimit)
            ioprintf(c1out, _(" DeLink limit of %sB hit.\n"), SizeToStr(DeLinkBytes).c_str());      
       }
@@ -295,6 +307,8 @@ PackagesWriter::PackagesWriter(string DB,string Overrides,string ExtOverrides,
    
    // Process the command line options
    DoMD5 = _config->FindB("APT::FTPArchive::MD5",true);
+   DoSHA1 = _config->FindB("APT::FTPArchive::SHA1",true);
+   DoSHA256 = _config->FindB("APT::FTPArchive::SHA256",true);
    DoContents = _config->FindB("APT::FTPArchive::Contents",true);
    NoOverride = _config->FindB("APT::FTPArchive::NoOverrideMsg",false);
 
@@ -343,29 +357,19 @@ bool FTWScanner::SetExts(string Vals)
 // PackagesWriter::DoPackage - Process a single package                        /*{{{*/
 // ---------------------------------------------------------------------
 /* This method takes a package and gets its control information and 
-   MD5 then writes out a control record with the proper fields rewritten
-   and the path/size/hash appended. */
+   MD5, SHA1 and SHA256 then writes out a control record with the proper fields 
+   rewritten and the path/size/hash appended. */
 bool PackagesWriter::DoPackage(string FileName)
 {      
-   // Open the archive
-   FileFd F(FileName,FileFd::ReadOnly);
-   if (_error->PendingError() == true)
-      return false;
-   
-   // Stat the file for later
-   struct stat St;
-   if (fstat(F.Fd(),&St) != 0)
-      return _error->Errno("fstat",_("Failed to stat %s"),FileName.c_str());
-
    // Pull all the data we need form the DB
-   string MD5Res;
-   if (Db.SetFile(FileName,St,&F) == false ||
-       Db.LoadControl() == false ||
-       (DoContents == true && Db.LoadContents(true) == false) ||
-       (DoMD5 == true && Db.GetMD5(MD5Res,false) == false))
+   if (Db.GetFileInfo(FileName, true, DoContents, true, DoMD5, DoSHA1, DoSHA256) 
+                 == false)
+   {
       return false;
+   }
 
-   if (Delink(FileName,OriginalPath,Stats.DeLinkBytes,St) == false)
+   off_t FileSize = Db.GetFileSize();
+   if (Delink(FileName,OriginalPath,Stats.DeLinkBytes,FileSize) == false)
       return false;
    
    // Lookup the overide information
@@ -400,7 +404,7 @@ bool PackagesWriter::DoPackage(string FileName)
    }
 
    char Size[40];
-   sprintf(Size,"%lu",St.st_size);
+   sprintf(Size,"%lu", (unsigned long) FileSize);
    
    // Strip the DirStrip prefix from the FileName and add the PathPrefix
    string NewFileName;
@@ -420,7 +424,9 @@ bool PackagesWriter::DoPackage(string FileName)
 
    unsigned int End = 0;
    SetTFRewriteData(Changes[End++], "Size", Size);
-   SetTFRewriteData(Changes[End++], "MD5sum", MD5Res.c_str());
+   SetTFRewriteData(Changes[End++], "MD5sum", Db.MD5Res.c_str());
+   SetTFRewriteData(Changes[End++], "SHA1", Db.SHA1Res.c_str());
+   SetTFRewriteData(Changes[End++], "SHA256", Db.SHA256Res.c_str());
    SetTFRewriteData(Changes[End++], "Filename", NewFileName.c_str());
    SetTFRewriteData(Changes[End++], "Priority", OverItem->Priority.c_str());
    SetTFRewriteData(Changes[End++], "Status", 0);
@@ -491,6 +497,10 @@ SourcesWriter::SourcesWriter(string BOverrides,string SOverrides,
    else
       NoOverride = true;
 
+   // WTF?? The logic above: if we can't read binary overrides, don't even try
+   // reading source overrides. if we can read binary overrides, then say there
+   // are no overrides. THIS MAKES NO SENSE! -- ajt@d.o, 2006/02/28
+
    if (ExtOverrides.empty() == false)
       SOver.ReadExtraOverride(ExtOverrides);
    
@@ -607,12 +617,14 @@ bool SourcesWriter::DoPackage(string FileName)
    }
    
    auto_ptr<Override::Item> SOverItem(SOver.GetItem(Tags.FindS("Source")));
-   const auto_ptr<Override::Item> autoSOverItem(SOverItem);
+   // const auto_ptr<Override::Item> autoSOverItem(SOverItem);
    if (SOverItem.get() == 0)
    {
+      ioprintf(c1out, _("  %s has no source override entry\n"), Tags.FindS("Source").c_str());
       SOverItem = auto_ptr<Override::Item>(BOver.GetItem(Tags.FindS("Source")));
       if (SOverItem.get() == 0)
       {
+        ioprintf(c1out, _("  %s has no binary override entry either\n"), Tags.FindS("Source").c_str());
         SOverItem = auto_ptr<Override::Item>(new Override::Item);
         *SOverItem = *OverItem;
       }
@@ -657,7 +669,7 @@ bool SourcesWriter::DoPackage(string FileName)
          realpath(OriginalPath.c_str(),RealPath) != 0)
       {
         string RP = RealPath;
-        if (Delink(RP,OriginalPath.c_str(),Stats.DeLinkBytes,St) == false)
+        if (Delink(RP,OriginalPath.c_str(),Stats.DeLinkBytes,St.st_size) == false)
            return false;
       }
    }
@@ -727,26 +739,14 @@ ContentsWriter::ContentsWriter(string DB) :
    determine what the package name is. */
 bool ContentsWriter::DoPackage(string FileName,string Package)
 {
-   // Open the archive
-   FileFd F(FileName,FileFd::ReadOnly);
-   if (_error->PendingError() == true)
-      return false;
-   
-   // Stat the file for later
-   struct stat St;
-   if (fstat(F.Fd(),&St) != 0)
-      return _error->Errno("fstat","Failed too stat %s",FileName.c_str());
-
-   // Ready the DB
-   if (Db.SetFile(FileName,St,&F) == false || 
-       Db.LoadContents(false) == false)
+   if (!Db.GetFileInfo(FileName, Package.empty(), true, false, false, false, false))
+   {
       return false;
+   }
 
    // Parse the package name
    if (Package.empty() == true)
    {
-      if (Db.LoadControl() == false)
-        return false;
       Package = Db.Control.Section.FindS("Package");
    }
 
@@ -896,6 +896,11 @@ bool ReleaseWriter::DoPackage(string FileName)
    SHA1.AddFD(fd.Fd(), fd.Size());
    CheckSums[NewFileName].SHA1 = SHA1.Result();
 
+   fd.Seek(0);
+   SHA256Summation SHA256;
+   SHA256.AddFD(fd.Fd(), fd.Size());
+   CheckSums[NewFileName].SHA256 = SHA256.Result();
+
    fd.Close();
    
    return true;
@@ -927,5 +932,16 @@ void ReleaseWriter::Finish()
               (*I).second.size,
               (*I).first.c_str());
    }
+
+   fprintf(Output, "SHA256:\n");
+   for(map<string,struct CheckSum>::iterator I = CheckSums.begin();
+       I != CheckSums.end();
+       ++I)
+   {
+      fprintf(Output, " %s %16ld %s\n",
+              (*I).second.SHA256.c_str(),
+              (*I).second.size,
+              (*I).first.c_str());
+   }
 }
 
index 16d014ef895647417409c3a63ba7f62e3b3f5dda..1d47d57ec8062b4f5e519644154f084096c76ec1 100644 (file)
@@ -45,10 +45,11 @@ class FTWScanner
    bool NoLinkAct;
    
    static FTWScanner *Owner;
-   static int Scanner(const char *File,const struct stat *sb,int Flag);
+   static int ScannerFTW(const char *File,const struct stat *sb,int Flag);
+   static int ScannerFile(const char *File, bool ReadLink);
 
    bool Delink(string &FileName,const char *OriginalPath,
-              unsigned long &Bytes,struct stat &St);
+              unsigned long &Bytes,off_t FileSize);
 
    inline void NewLine(unsigned Priority)
    {
@@ -84,6 +85,8 @@ class PackagesWriter : public FTWScanner
 
    // Some flags
    bool DoMD5;
+   bool DoSHA1;
+   bool DoSHA256;
    bool NoOverride;
    bool DoContents;
 
@@ -170,6 +173,7 @@ protected:
    {
       string MD5;
       string SHA1;
+      string SHA256;
       // Limited by FileFd::Size()
       unsigned long size;
       ~CheckSum() {};
index 341de94e37ab046c3e2a1360bdd16f0f96a5c7dc..cb63ada499f9df866f96f143a0eec53608fbf7ad 100644 (file)
@@ -58,7 +58,6 @@ unsigned long PipelineDepth = 10;
 unsigned long TimeOut = 120;
 bool Debug = false;
 
-
 unsigned long CircleBuf::BwReadLimit=0;
 unsigned long CircleBuf::BwTickReadData=0;
 struct timeval CircleBuf::BwReadTick={0,0};
index 1e3b1ef850b128f8fd97ec77c7442cced44a0e34..d0b5a28c0210cadb478b2cb78a315b11943c2891 100644 (file)
@@ -59,6 +59,13 @@ LIB_MAKES = apt-pkg/makefile
 SOURCE = ftp.cc rfc2553emu.cc connect.cc
 include $(PROGRAM_H)
 
+# The rred method
+PROGRAM=rred
+SLIBS = -lapt-pkg $(SOCKETLIBS)
+LIB_MAKES = apt-pkg/makefile
+SOURCE = rred.cc
+include $(PROGRAM_H)
+
 # The rsh method
 PROGRAM=rsh
 SLIBS = -lapt-pkg
diff --git a/methods/rred.cc b/methods/rred.cc
new file mode 100644 (file)
index 0000000..6fa57f3
--- /dev/null
@@ -0,0 +1,262 @@
+#include <apt-pkg/fileutl.h>
+#include <apt-pkg/error.h>
+#include <apt-pkg/acquire-method.h>
+#include <apt-pkg/strutl.h>
+#include <apt-pkg/hashes.h>
+
+#include <sys/stat.h>
+#include <unistd.h>
+#include <utime.h>
+#include <stdio.h>
+#include <errno.h>
+#include <apti18n.h>
+
+/* this method implements a patch functionality similar to "patch --ed" that is
+ * used by the "tiffany" incremental packages download stuff. it differs from 
+ * "ed" insofar that it is way more restricted (and therefore secure). in the
+ * moment only the "c", "a" and "d" commands of ed are implemented (diff 
+ * doesn't output any other). additionally the records must be reverse sorted 
+ * by line number and may not overlap (diff *seems* to produce this kind of 
+ * output). 
+ * */
+
+const char *Prog;
+
+class RredMethod : public pkgAcqMethod
+{
+   bool Debug;
+   // the size of this doesn't really matter (except for performance)    
+   const static int BUF_SIZE = 1024;
+   // the ed commands
+   enum Mode {MODE_CHANGED, MODE_DELETED, MODE_ADDED};
+   // return values
+   enum State {ED_OK, ED_ORDERING, ED_PARSER, ED_FAILURE};
+   // this applies a single hunk, it uses a tail recursion to 
+   // reverse the hunks in the file
+   int ed_rec(FILE *ed_cmds, FILE *in_file, FILE *out_file, int line, 
+      char *buffer, unsigned int bufsize, Hashes *hash);
+   // apply a patch file
+   int ed_file(FILE *ed_cmds, FILE *in_file, FILE *out_file, Hashes *hash);
+   // the methods main method
+   virtual bool Fetch(FetchItem *Itm);
+   
+   public:
+   
+   RredMethod() : pkgAcqMethod("1.1",SingleInstance | SendConfig) {};
+};
+
+int RredMethod::ed_rec(FILE *ed_cmds, FILE *in_file, FILE *out_file, int line, 
+      char *buffer, unsigned int bufsize, Hashes *hash) {
+   int pos;
+   int startline;
+   int stopline;
+   int mode;
+   int written;
+   char *idx;
+
+   /* get the current command and parse it*/
+   if (fgets(buffer, bufsize, ed_cmds) == NULL) {
+      return line;
+   }
+   startline = strtol(buffer, &idx, 10);
+   if (startline < line) {
+      return ED_ORDERING;
+   }
+   if (*idx == ',') {
+      idx++;
+      stopline = strtol(idx, &idx, 10);
+   }
+   else {
+      stopline = startline;
+   }
+   if (*idx == 'c') {
+      mode = MODE_CHANGED;
+          if (Debug == true) {
+                  std::clog << "changing from line " << startline 
+                            << " to " << stopline << std::endl;
+          }
+   }
+   else if (*idx == 'a') {
+      mode = MODE_ADDED;
+          if (Debug == true) {
+                  std::clog << "adding after line " << startline << std::endl;
+          }
+   }
+   else if (*idx == 'd') {
+      mode = MODE_DELETED;
+          if (Debug == true) {
+                  std::clog << "deleting from line " << startline 
+                            <<  " to " << stopline << std::endl;
+          }
+   }
+   else {
+      return ED_PARSER;
+   }
+   /* get the current position */
+   pos = ftell(ed_cmds);
+   /* if this is add or change then go to the next full stop */
+   if ((mode == MODE_CHANGED) || (mode == MODE_ADDED)) {
+      do {
+         fgets(buffer, bufsize, ed_cmds);
+         while ((strlen(buffer) == (bufsize - 1)) 
+               && (buffer[bufsize - 2] != '\n')) {
+            fgets(buffer, bufsize, ed_cmds);
+            buffer[0] = ' ';
+         }
+      } while (strncmp(buffer, ".", 1) != 0);
+   }
+   /* do the recursive call */
+   line = ed_rec(ed_cmds, in_file, out_file, line, buffer, bufsize, 
+         hash);
+   /* pass on errors */
+   if (line < 0) {
+      return line;
+   }
+   /* apply our hunk */
+   fseek(ed_cmds, pos, SEEK_SET); 
+   /* first wind to the current position */
+   if (mode != MODE_ADDED) {
+      startline -= 1;
+   }
+   while (line < startline) {
+      fgets(buffer, bufsize, in_file);
+      written = fwrite(buffer, 1, strlen(buffer), out_file);
+      hash->Add((unsigned char*)buffer, written);
+      while ((strlen(buffer) == (bufsize - 1)) 
+            && (buffer[bufsize - 2] != '\n')) {
+         fgets(buffer, bufsize, in_file);
+         written = fwrite(buffer, 1, strlen(buffer), out_file);
+         hash->Add((unsigned char*)buffer, written);
+      }
+      line++;
+   }
+   /* include from ed script */
+   if ((mode == MODE_ADDED) || (mode == MODE_CHANGED)) {
+      do {
+         fgets(buffer, bufsize, ed_cmds);
+         if (strncmp(buffer, ".", 1) != 0) {
+            written = fwrite(buffer, 1, strlen(buffer), out_file);
+            hash->Add((unsigned char*)buffer, written);
+            while ((strlen(buffer) == (bufsize - 1)) 
+                  && (buffer[bufsize - 2] != '\n')) {
+               fgets(buffer, bufsize, ed_cmds);
+               written = fwrite(buffer, 1, strlen(buffer), out_file);
+               hash->Add((unsigned char*)buffer, written);
+            }
+         }
+         else {
+            break;
+         }
+      } while (1);
+   }
+   /* ignore the corresponding number of lines from input */
+   if ((mode == MODE_DELETED) || (mode == MODE_CHANGED)) {
+      while (line < stopline) {
+         fgets(buffer, bufsize, in_file);
+         while ((strlen(buffer) == (bufsize - 1)) 
+               && (buffer[bufsize - 2] != '\n')) {
+            fgets(buffer, bufsize, in_file);
+         }
+         line++;
+      }
+   }
+   return line;
+}
+
+int RredMethod::ed_file(FILE *ed_cmds, FILE *in_file, FILE *out_file, 
+      Hashes *hash) {
+   char buffer[BUF_SIZE];
+   int result;
+   int written;
+   
+   /* we do a tail recursion to read the commands in the right order */
+   result = ed_rec(ed_cmds, in_file, out_file, 0, buffer, BUF_SIZE, 
+         hash);
+   
+   /* read the rest from infile */
+   if (result > 0) {
+      while (fgets(buffer, BUF_SIZE, in_file) != NULL) {
+         written = fwrite(buffer, 1, strlen(buffer), out_file);
+         hash->Add((unsigned char*)buffer, written);
+      }
+   }
+   else {
+      return ED_FAILURE;
+   }
+   return ED_OK;
+}
+
+
+bool RredMethod::Fetch(FetchItem *Itm)
+{
+   Debug = _config->FindB("Debug::pkgAcquire::RRed",false);
+   URI Get = Itm->Uri;
+   string Path = Get.Host + Get.Path; // To account for relative paths
+   // Path contains the filename to patch
+   FetchResult Res;
+   Res.Filename = Itm->DestFile;
+   URIStart(Res);
+   // Res.Filename the destination filename
+
+   if (Debug == true) 
+      std::clog << "Patching " << Path << " with " << Path 
+         << ".ed and putting result into " << Itm->DestFile << std::endl;
+   // Open the source and destination files (the d'tor of FileFd will do 
+   // the cleanup/closing of the fds)
+   FileFd From(Path,FileFd::ReadOnly);
+   FileFd Patch(Path+".ed",FileFd::ReadOnly);
+   FileFd To(Itm->DestFile,FileFd::WriteEmpty);   
+   To.EraseOnFailure();
+   if (_error->PendingError() == true)
+      return false;
+   
+   Hashes Hash;
+   FILE* fFrom = fdopen(From.Fd(), "r");
+   FILE* fPatch = fdopen(Patch.Fd(), "r");
+   FILE* fTo = fdopen(To.Fd(), "w");
+   // now do the actual patching
+   if (ed_file(fPatch, fFrom, fTo, &Hash) != ED_OK) {
+     _error->Errno("rred", _("Could not patch file"));  
+      return false;
+   }
+
+   // write out the result
+   fflush(fFrom);
+   fflush(fPatch);
+   fflush(fTo);
+   From.Close();
+   Patch.Close();
+   To.Close();
+
+   // Transfer the modification times
+   struct stat Buf;
+   if (stat(Path.c_str(),&Buf) != 0)
+      return _error->Errno("stat",_("Failed to stat"));
+
+   struct utimbuf TimeBuf;
+   TimeBuf.actime = Buf.st_atime;
+   TimeBuf.modtime = Buf.st_mtime;
+   if (utime(Itm->DestFile.c_str(),&TimeBuf) != 0)
+      return _error->Errno("utime",_("Failed to set modification time"));
+
+   if (stat(Itm->DestFile.c_str(),&Buf) != 0)
+      return _error->Errno("stat",_("Failed to stat"));
+
+   // return done
+   Res.LastModified = Buf.st_mtime;
+   Res.Size = Buf.st_size;
+   Res.TakeHashes(Hash);
+   URIDone(Res);
+
+   return true;
+}
+
+int main(int argc, char *argv[])
+{
+   RredMethod Mth;
+
+   Prog = strrchr(argv[0],'/');
+   Prog++;
+   
+   return Mth.Run();
+}