]> git.saurik.com Git - apt.git/commitdiff
WIP local deb install
authorMichael Vogt <mvo@ubuntu.com>
Fri, 25 Apr 2014 22:00:51 +0000 (00:00 +0200)
committerMichael Vogt <mvo@ubuntu.com>
Mon, 28 Apr 2014 07:59:33 +0000 (09:59 +0200)
12 files changed:
apt-pkg/acquire-item.cc
apt-pkg/contrib/fileutl.cc
apt-pkg/contrib/fileutl.h
apt-pkg/deb/debindexfile.cc
apt-pkg/deb/debindexfile.h
apt-pkg/deb/deblistparser.cc
apt-pkg/deb/deblistparser.h
apt-pkg/deb/debmetaindex.cc
apt-pkg/deb/debmetaindex.h
apt-pkg/deb/debrecords.h
apt-pkg/sourcelist.h
apt-private/private-install.cc

index 30743addf0a85a0e1b8319b190f6ff10e818d2f4..22b77cbda310eda13c6d4f01eca272c5114c8318 100644 (file)
@@ -2084,7 +2084,8 @@ void pkgAcqArchive::Done(string Message,unsigned long long Size,string CalcHash,
    }
    
    // Check the hash
    }
    
    // Check the hash
-   if(ExpectedHash.toStr() != CalcHash)
+   // FIXME: could this empty() check impose *any* sort of security issue?
+   if(ExpectedHash.empty() == false && ExpectedHash.toStr() != CalcHash)
    {
       RenameOnError(HashSumMismatch);
       return;
    {
       RenameOnError(HashSumMismatch);
       return;
index de73a7fd8a8f9e593d3301e6db76aff30bab5e22..655dcdac774c168dea45eeae4c0b26f55c44826f 100644 (file)
@@ -1920,7 +1920,6 @@ bool FileFd::Close()
    {
       if ((Flags & Compressed) != Compressed && iFd > 0 && close(iFd) != 0)
         Res &= _error->Errno("close",_("Problem closing the file %s"), FileName.c_str());
    {
       if ((Flags & Compressed) != Compressed && iFd > 0 && close(iFd) != 0)
         Res &= _error->Errno("close",_("Problem closing the file %s"), FileName.c_str());
-
       if (d != NULL)
       {
         Res &= d->CloseDown(FileName);
       if (d != NULL)
       {
         Res &= d->CloseDown(FileName);
@@ -2047,6 +2046,31 @@ std::string GetTempDir()
    return string(tmpdir);
 }
 
    return string(tmpdir);
 }
 
+FileFd* GetTempFile(std::string const &Prefix, bool ImmediateUnlink)
+{
+   char fn[512];
+   FileFd *Fd = new FileFd();
+
+   std::string tempdir = GetTempDir();
+   snprintf(fn, sizeof(fn), "%s/%s.XXXXXX", 
+            tempdir.c_str(), Prefix.c_str());
+   int fd = mkstemp(fn);
+   if(ImmediateUnlink)
+      unlink(fn);
+   if (fd < 0) 
+   {
+      _error->Errno("GetTempFile",_("Unable to mkstemp %s"), fn);
+      return NULL;
+   }
+   if (!Fd->OpenDescriptor(fd, FileFd::WriteOnly, FileFd::None, true))
+   {
+      _error->Errno("GetTempFile",_("Unable to write to %s"),fn);
+      return NULL;
+   }
+
+   return Fd;
+}
+
 bool Rename(std::string From, std::string To)
 {
    if (rename(From.c_str(),To.c_str()) != 0)
 bool Rename(std::string From, std::string To)
 {
    if (rename(From.c_str(),To.c_str()) != 0)
index cc1a98eae02c227b47962dff72421baf0e3f5e6d..fb01531fd6704c517801c432ddd48304abae14f3 100644 (file)
@@ -168,6 +168,8 @@ time_t GetModificationTime(std::string const &Path);
 bool Rename(std::string From, std::string To);
 
 std::string GetTempDir();
 bool Rename(std::string From, std::string To);
 
 std::string GetTempDir();
+FileFd* GetTempFile(std::string const &Prefix = "", 
+                    bool ImmediateUnlink = true);
 
 /** \brief Ensure the existence of the given Path
  *
 
 /** \brief Ensure the existence of the given Path
  *
index eee758b7a124d388ac1d1fe1c9cb84c38d6fe806..f9864c67bc33df58c3d7e5b56a3969416ac73569 100644 (file)
@@ -30,6 +30,7 @@
 #include <apt-pkg/pkgcachegen.h>
 #include <apt-pkg/pkgrecords.h>
 #include <apt-pkg/srcrecords.h>
 #include <apt-pkg/pkgcachegen.h>
 #include <apt-pkg/pkgrecords.h>
 #include <apt-pkg/srcrecords.h>
+#include <apt-pkg/sptr.h>
 
 #include <stdio.h>
 #include <iostream>
 
 #include <stdio.h>
 #include <iostream>
@@ -667,6 +668,95 @@ APT_CONST bool debStatusIndex::Exists() const
 }
                                                                        /*}}}*/
 
 }
                                                                        /*}}}*/
 
+// debDebPkgFile - Single .deb file                                    /*{{{*/
+// ---------------------------------------------------------------------
+debDebPkgFileIndex::debDebPkgFileIndex(std::string DebFile)
+   : pkgIndexFile(true), DebFile(DebFile)
+{
+   // FIXME: we need to os.normpath(DebFile) here, this is a lame workaround
+   DebFileFullPath = SafeGetCWD() + DebFile;
+}
+
+std::string debDebPkgFileIndex::ArchiveURI(std::string /*File*/) const
+{
+   return "file:" + DebFileFullPath;
+}
+
+bool debDebPkgFileIndex::Exists() const
+{
+   return FileExists(DebFile);
+}
+bool debDebPkgFileIndex::Merge(pkgCacheGenerator& Gen, OpProgress* Prog) const
+{
+   if(Prog)
+      Prog->SubProgress(0, "Reading deb file");
+
+   // get the control data out of the deb file vid dpkg -I
+   // ... can I haz libdpkg?
+   string cmd;
+   // FIXME: shell injection
+   strprintf(cmd, "dpkg -I %s control", DebFile.c_str());
+   FILE *p = popen(cmd.c_str(), "r");
+   if (p == NULL)
+      return _error->Error("popen failed");
+   // FIXME: static buffer
+   char buf[8*1024];
+   size_t n = fread(buf, 1, sizeof(buf)-1, p);
+   if (n == 0)
+      return _error->Errno("popen", "Failed to read dpkg pipe");
+   pclose(p);
+
+   // now write the control data to a tempfile
+   SPtr<FileFd> DebControl = GetTempFile("deb-file-" + DebFile);
+   if(DebControl == NULL)
+      return false;
+   DebControl->Write(buf, n);
+   // append size of the file
+   FileFd Fd(DebFile, FileFd::ReadOnly);
+   string Size;
+   strprintf(Size, "Size: %llu\n", Fd.Size());
+   DebControl->Write(Size.c_str(), Size.size());
+   // and rewind for the listparser
+   DebControl->Seek(0);
+
+   // and give it to the list parser
+   debDebFileParser Parser(DebControl, DebFile);
+   if(Gen.SelectFile(DebFile, "local", *this) == false)
+      return _error->Error("Problem with SelectFile %s", DebFile.c_str());
+
+   pkgCache::PkgFileIterator File = Gen.GetCurFile();
+   File->Size = DebControl->Size();
+   File->mtime = DebControl->ModificationTime();
+   
+   if (Gen.MergeList(Parser) == false)
+      return _error->Error("Problem with MergeLister for %s", DebFile.c_str());
+
+   return true;
+}
+pkgCache::PkgFileIterator debDebPkgFileIndex::FindInCache(pkgCache &Cache) const
+{
+   // FIXME: we could simply always return pkgCache::PkgFileIterator(Cache);
+   //        to indicate its never in the cache which will force a Merge()
+   pkgCache::PkgFileIterator File = Cache.FileBegin();
+   for (; File.end() == false; ++File)
+   {
+       if (File.FileName() == NULL || DebFile != File.FileName())
+        continue;
+
+       return File;
+   }
+   
+   return File;
+}
+unsigned long debDebPkgFileIndex::Size() const
+{
+   struct stat buf;
+   if(stat(DebFile.c_str(), &buf) != 0)
+      return 0;
+   return buf.st_size;
+}
+                                                                       /*}}}*/
+
 // Index File types for Debian                                         /*{{{*/
 class debIFTypeSrc : public pkgIndexFile::Type
 {
 // Index File types for Debian                                         /*{{{*/
 class debIFTypeSrc : public pkgIndexFile::Type
 {
@@ -699,10 +789,20 @@ class debIFTypeStatus : public pkgIndexFile::Type
    };
    debIFTypeStatus() {Label = "Debian dpkg status file";};
 };
    };
    debIFTypeStatus() {Label = "Debian dpkg status file";};
 };
+class debIFTypeDebPkgFile : public pkgIndexFile::Type
+{
+   public:
+   virtual pkgRecords::Parser *CreatePkgParser(pkgCache::PkgFileIterator File) const 
+   {
+      return new debDebFileRecordParser(File.FileName(),*File.Cache());
+   };
+   debIFTypeDebPkgFile() {Label = "deb Package file";};
+};
 static debIFTypeSrc _apt_Src;
 static debIFTypePkg _apt_Pkg;
 static debIFTypeTrans _apt_Trans;
 static debIFTypeStatus _apt_Status;
 static debIFTypeSrc _apt_Src;
 static debIFTypePkg _apt_Pkg;
 static debIFTypeTrans _apt_Trans;
 static debIFTypeStatus _apt_Status;
+static debIFTypeDebPkgFile _apt_DebPkgFile;
 
 const pkgIndexFile::Type *debSourcesIndex::GetType() const
 {
 
 const pkgIndexFile::Type *debSourcesIndex::GetType() const
 {
@@ -720,5 +820,8 @@ const pkgIndexFile::Type *debStatusIndex::GetType() const
 {
    return &_apt_Status;
 }
 {
    return &_apt_Status;
 }
-
+const pkgIndexFile::Type *debDebPkgFileIndex::GetType() const
+{
+   return &_apt_DebPkgFile;
+}
                                                                        /*}}}*/
                                                                        /*}}}*/
index 017c69a0a907c67c36ad35f66128945dd1beef5a..69754e79d469490a3fee43eca7dc35014ce98f03 100644 (file)
@@ -164,4 +164,35 @@ class debSourcesIndex : public pkgIndexFile
    virtual ~debSourcesIndex() {};
 };
 
    virtual ~debSourcesIndex() {};
 };
 
+class debDebPkgFileIndex : public pkgIndexFile
+{
+ private:
+   void *d;
+   std::string DebFile;
+   std::string DebFileFullPath;
+
+ public:
+   virtual const Type *GetType() const APT_CONST;
+
+   virtual std::string Describe(bool /*Short*/) const {
+      return DebFile;
+   }
+
+   // Interface for the Cache Generator
+   virtual bool Exists() const;
+   virtual bool HasPackages() const {
+      return true;
+   };
+   virtual unsigned long Size() const;
+   virtual bool Merge(pkgCacheGenerator &Gen,OpProgress *Prog) const;
+   virtual pkgCache::PkgFileIterator FindInCache(pkgCache &Cache) const;
+
+   // Interface for acquire
+   virtual std::string ArchiveURI(std::string /*File*/) const;
+
+   debDebPkgFileIndex(std::string DebFile);
+   virtual ~debDebPkgFileIndex() {};
+   
+};
+
 #endif
 #endif
index a1bcfb710432cc44facf49fd394cb231f8b4c319..d5e3ccb655db9cfccbfdb4da64350c9845d6f5c7 100644 (file)
@@ -959,3 +959,23 @@ bool debListParser::SameVersion(unsigned short const Hash,         /*{{{*/
 }
                                                                        /*}}}*/
 #endif
 }
                                                                        /*}}}*/
 #endif
+
+
+debDebFileParser::debDebFileParser(FileFd *File, std::string const &DebFile)
+   : debListParser(File, ""), DebFile(DebFile)
+{
+}
+
+bool debDebFileParser::UsePackage(pkgCache::PkgIterator &Pkg,
+                                  pkgCache::VerIterator &Ver)
+{
+   bool res = debListParser::UsePackage(Pkg, Ver);
+   // we use the full file path as a provides so that the file is found
+   // by its name
+   if(NewProvidesAllArch(Ver, DebFile, Ver.VerStr()) == false)
+      return false;
+   return res;
+}
+
+
+
index baace79fe1f632f5bb25f565afba015a3e4061fb..92ec048b1086fa727a6fcdb1237a972197456435 100644 (file)
@@ -56,7 +56,8 @@ class debListParser : public pkgCacheGenerator::ListParser
    bool ParseProvides(pkgCache::VerIterator &Ver);
    bool NewProvidesAllArch(pkgCache::VerIterator &Ver, std::string const &Package, std::string const &Version);
    static bool GrabWord(std::string Word,WordList *List,unsigned char &Out);
    bool ParseProvides(pkgCache::VerIterator &Ver);
    bool NewProvidesAllArch(pkgCache::VerIterator &Ver, std::string const &Package, std::string const &Version);
    static bool GrabWord(std::string Word,WordList *List,unsigned char &Out);
-   
+   APT_HIDDEN unsigned char ParseMultiArch(bool const showErrors);
+
    public:
 
    static unsigned char GetPrio(std::string Str);
    public:
 
    static unsigned char GetPrio(std::string Str);
@@ -101,9 +102,17 @@ class debListParser : public pkgCacheGenerator::ListParser
 
    debListParser(FileFd *File, std::string const &Arch = "");
    virtual ~debListParser() {};
 
    debListParser(FileFd *File, std::string const &Arch = "");
    virtual ~debListParser() {};
+};
 
 
-   private:
-   APT_HIDDEN unsigned char ParseMultiArch(bool const showErrors);
+class debDebFileParser : public debListParser
+{
+ private:
+   std::string DebFile;
+
+ public:
+   debDebFileParser(FileFd *File, std::string const &DebFile);
+   virtual bool UsePackage(pkgCache::PkgIterator &Pkg,
+                          pkgCache::VerIterator &Ver);
 };
 
 #endif
 };
 
 #endif
index 6fd12add8f3589cf02fdb1fd84b596e70f7986b4..67da592d68cd4224eef66e85366a0ea71aa24000 100644 (file)
@@ -471,6 +471,15 @@ class debSLTypeDebian : public pkgSourceList::Type
    }
 };
 
    }
 };
 
+debDebFileMetaIndex::debDebFileMetaIndex(std::string const &DebFile)
+   : metaIndex(DebFile, "local-uri", "deb-dist"), DebFile(DebFile)
+{
+   DebIndex = new debDebPkgFileIndex(DebFile);
+   Indexes = new vector<pkgIndexFile *>();
+   Indexes->push_back(DebIndex);
+}
+
+
 class debSLTypeDeb : public debSLTypeDebian
 {
    public:
 class debSLTypeDeb : public debSLTypeDebian
 {
    public:
index 2286fa8b2c88e63bb376e7eeb4ca783464432545..0e70bba87d0986da01a067fec374fdfb7f166abf 100644 (file)
@@ -18,6 +18,7 @@
 
 class pkgAcquire;
 class pkgIndexFile;
 
 class pkgAcquire;
 class pkgIndexFile;
+class debDebPkgFileIndex;
 
 class debReleaseIndex : public metaIndex {
    public:
 
 class debReleaseIndex : public metaIndex {
    public:
@@ -71,4 +72,27 @@ class debReleaseIndex : public metaIndex {
    void PushSectionEntry(const debSectionEntry *Entry);
 };
 
    void PushSectionEntry(const debSectionEntry *Entry);
 };
 
+class debDebFileMetaIndex : public metaIndex
+{
+ private:
+   std::string DebFile;
+   debDebPkgFileIndex *DebIndex;
+ public:
+   virtual std::string ArchiveURI(std::string const& /*File*/) const {
+      return DebFile;
+   }
+   virtual bool GetIndexes(pkgAcquire* /*Owner*/, const bool& /*GetAll=false*/) const {
+      return true;
+   }
+   virtual std::vector<pkgIndexFile *> *GetIndexFiles() {
+      return Indexes;
+   }
+   virtual bool IsTrusted() const {
+      return true;
+   }
+   debDebFileMetaIndex(std::string const &DebFile);
+   virtual ~debDebFileMetaIndex() {};
+
+};
+
 #endif
 #endif
index bdac6c90b8c8883f779e68f8d78780a56bf573c1..d572bc5c20b5605cafc775dfb99aabad2a1771a3 100644 (file)
@@ -29,17 +29,16 @@ class debRecordParser : public pkgRecords::Parser
 {
    /** \brief dpointer placeholder (for later in case we need it) */
    void *d;
 {
    /** \brief dpointer placeholder (for later in case we need it) */
    void *d;
-
+   
+ protected:
    FileFd File;
    pkgTagFile Tags;
    pkgTagSection Section;
    
    FileFd File;
    pkgTagFile Tags;
    pkgTagSection Section;
    
-   protected:
-   
    virtual bool Jump(pkgCache::VerFileIterator const &Ver);
    virtual bool Jump(pkgCache::DescFileIterator const &Desc);
    
    virtual bool Jump(pkgCache::VerFileIterator const &Ver);
    virtual bool Jump(pkgCache::DescFileIterator const &Desc);
    
  public:
+ public:
 
    // These refer to the archive file for the Version
    virtual std::string FileName();
 
    // These refer to the archive file for the Version
    virtual std::string FileName();
@@ -66,4 +65,15 @@ class debRecordParser : public pkgRecords::Parser
    virtual ~debRecordParser() {};
 };
 
    virtual ~debRecordParser() {};
 };
 
+// custom record parser that reads deb files directly
+class debDebFileRecordParser : public debRecordParser
+{
+ public:
+   virtual std::string FileName() {
+      return File.Name();
+   }
+   debDebFileRecordParser(std::string FileName,pkgCache &Cache)
+      : debRecordParser(FileName, Cache) {};
+};
+
 #endif
 #endif
index 9df0c1d7419c3fbd46e38fef1d113fbd8e06b067..4943dd32acb93f50ca075f3de6fd184b745a22b9 100644 (file)
@@ -116,6 +116,11 @@ class pkgSourceList
    // query last-modified time
    time_t GetLastModifiedTime();
 
    // query last-modified time
    time_t GetLastModifiedTime();
 
+   // Add custom metaIndex (e.g. local files)
+   void Add(metaIndex *mi) {
+      SrcList.push_back(mi);
+   }
+
    pkgSourceList();
    pkgSourceList(std::string File);
    ~pkgSourceList();      
    pkgSourceList();
    pkgSourceList(std::string File);
    ~pkgSourceList();      
index 107ed398e30f6a9dbe7a639d636fa5b9b927a967..40165af31161f1f6df529c8dcf50441fe4bf00ff 100644 (file)
 #include <apt-pkg/macros.h>
 #include <apt-pkg/packagemanager.h>
 #include <apt-pkg/pkgcache.h>
 #include <apt-pkg/macros.h>
 #include <apt-pkg/packagemanager.h>
 #include <apt-pkg/pkgcache.h>
+#include <apt-pkg/sourcelist.h>
+
+// FIXME: include of deb specific header
+#include <apt-pkg/debmetaindex.h>
 
 #include <errno.h>
 #include <stdlib.h>
 
 #include <errno.h>
 #include <stdlib.h>
@@ -669,10 +673,23 @@ bool DoCacheManipulationFromCommandLine(CommandLine &CmdL, CacheFile &Cache,
 bool DoInstall(CommandLine &CmdL)
 {
    CacheFile Cache;
 bool DoInstall(CommandLine &CmdL)
 {
    CacheFile Cache;
+   // first check for local pkgs and add them to the cache
+   for (const char **I = CmdL.FileList; *I != 0; I++)
+   {
+      if(FileExists(*I))
+      {
+         // FIMXE: direct usage of .deb specific stuff
+         metaIndex *mi = new debDebFileMetaIndex(*I);
+         pkgSourceList *sources = Cache.GetSourceList();
+         sources->Add(mi);
+      }
+   }
+
+   // then open the cache
    if (Cache.OpenForInstall() == false || 
        Cache.CheckDeps(CmdL.FileSize() != 1) == false)
       return false;
    if (Cache.OpenForInstall() == false || 
        Cache.CheckDeps(CmdL.FileSize() != 1) == false)
       return false;
-
+   
    std::map<unsigned short, APT::VersionSet> verset;
 
    if(!DoCacheManipulationFromCommandLine(CmdL, Cache, verset))
    std::map<unsigned short, APT::VersionSet> verset;
 
    if(!DoCacheManipulationFromCommandLine(CmdL, Cache, verset))