summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Vogt <mvo@ubuntu.com>2014-04-26 00:00:51 +0200
committerMichael Vogt <mvo@ubuntu.com>2014-04-28 09:59:33 +0200
commit0d29b9d4368284782862c7b507c47002b79ddb27 (patch)
treebcf0fa5d55cce7eba85f20235648d1728b104924
parenta298a1dc595c548e6c10b48b8e69d987e5be1c42 (diff)
WIP local deb install
-rw-r--r--apt-pkg/acquire-item.cc3
-rw-r--r--apt-pkg/contrib/fileutl.cc26
-rw-r--r--apt-pkg/contrib/fileutl.h2
-rw-r--r--apt-pkg/deb/debindexfile.cc105
-rw-r--r--apt-pkg/deb/debindexfile.h31
-rw-r--r--apt-pkg/deb/deblistparser.cc20
-rw-r--r--apt-pkg/deb/deblistparser.h15
-rw-r--r--apt-pkg/deb/debmetaindex.cc9
-rw-r--r--apt-pkg/deb/debmetaindex.h24
-rw-r--r--apt-pkg/deb/debrecords.h18
-rw-r--r--apt-pkg/sourcelist.h5
-rw-r--r--apt-private/private-install.cc19
12 files changed, 266 insertions, 11 deletions
diff --git a/apt-pkg/acquire-item.cc b/apt-pkg/acquire-item.cc
index 30743addf..22b77cbda 100644
--- a/apt-pkg/acquire-item.cc
+++ b/apt-pkg/acquire-item.cc
@@ -2084,7 +2084,8 @@ void pkgAcqArchive::Done(string Message,unsigned long long Size,string CalcHash,
}
// 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;
diff --git a/apt-pkg/contrib/fileutl.cc b/apt-pkg/contrib/fileutl.cc
index de73a7fd8..655dcdac7 100644
--- a/apt-pkg/contrib/fileutl.cc
+++ b/apt-pkg/contrib/fileutl.cc
@@ -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 (d != NULL)
{
Res &= d->CloseDown(FileName);
@@ -2047,6 +2046,31 @@ std::string GetTempDir()
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)
diff --git a/apt-pkg/contrib/fileutl.h b/apt-pkg/contrib/fileutl.h
index cc1a98eae..fb01531fd 100644
--- a/apt-pkg/contrib/fileutl.h
+++ b/apt-pkg/contrib/fileutl.h
@@ -168,6 +168,8 @@ time_t GetModificationTime(std::string const &Path);
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
*
diff --git a/apt-pkg/deb/debindexfile.cc b/apt-pkg/deb/debindexfile.cc
index eee758b7a..f9864c67b 100644
--- a/apt-pkg/deb/debindexfile.cc
+++ b/apt-pkg/deb/debindexfile.cc
@@ -30,6 +30,7 @@
#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>
@@ -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
{
@@ -699,10 +789,20 @@ class debIFTypeStatus : public pkgIndexFile::Type
};
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 debIFTypeDebPkgFile _apt_DebPkgFile;
const pkgIndexFile::Type *debSourcesIndex::GetType() const
{
@@ -720,5 +820,8 @@ const pkgIndexFile::Type *debStatusIndex::GetType() const
{
return &_apt_Status;
}
-
+const pkgIndexFile::Type *debDebPkgFileIndex::GetType() const
+{
+ return &_apt_DebPkgFile;
+}
/*}}}*/
diff --git a/apt-pkg/deb/debindexfile.h b/apt-pkg/deb/debindexfile.h
index 017c69a0a..69754e79d 100644
--- a/apt-pkg/deb/debindexfile.h
+++ b/apt-pkg/deb/debindexfile.h
@@ -164,4 +164,35 @@ class debSourcesIndex : public pkgIndexFile
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
diff --git a/apt-pkg/deb/deblistparser.cc b/apt-pkg/deb/deblistparser.cc
index a1bcfb710..d5e3ccb65 100644
--- a/apt-pkg/deb/deblistparser.cc
+++ b/apt-pkg/deb/deblistparser.cc
@@ -959,3 +959,23 @@ bool debListParser::SameVersion(unsigned short const Hash, /*{{{*/
}
/*}}}*/
#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;
+}
+
+
+
diff --git a/apt-pkg/deb/deblistparser.h b/apt-pkg/deb/deblistparser.h
index baace79fe..92ec048b1 100644
--- a/apt-pkg/deb/deblistparser.h
+++ b/apt-pkg/deb/deblistparser.h
@@ -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);
-
+ APT_HIDDEN unsigned char ParseMultiArch(bool const showErrors);
+
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() {};
+};
- 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
diff --git a/apt-pkg/deb/debmetaindex.cc b/apt-pkg/deb/debmetaindex.cc
index 6fd12add8..67da592d6 100644
--- a/apt-pkg/deb/debmetaindex.cc
+++ b/apt-pkg/deb/debmetaindex.cc
@@ -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:
diff --git a/apt-pkg/deb/debmetaindex.h b/apt-pkg/deb/debmetaindex.h
index 2286fa8b2..0e70bba87 100644
--- a/apt-pkg/deb/debmetaindex.h
+++ b/apt-pkg/deb/debmetaindex.h
@@ -18,6 +18,7 @@
class pkgAcquire;
class pkgIndexFile;
+class debDebPkgFileIndex;
class debReleaseIndex : public metaIndex {
public:
@@ -71,4 +72,27 @@ class debReleaseIndex : public metaIndex {
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
diff --git a/apt-pkg/deb/debrecords.h b/apt-pkg/deb/debrecords.h
index bdac6c90b..d572bc5c2 100644
--- a/apt-pkg/deb/debrecords.h
+++ b/apt-pkg/deb/debrecords.h
@@ -29,17 +29,16 @@ class debRecordParser : public pkgRecords::Parser
{
/** \brief dpointer placeholder (for later in case we need it) */
void *d;
-
+
+ protected:
FileFd File;
pkgTagFile Tags;
pkgTagSection Section;
- protected:
-
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();
@@ -66,4 +65,15 @@ class debRecordParser : public pkgRecords::Parser
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
diff --git a/apt-pkg/sourcelist.h b/apt-pkg/sourcelist.h
index 9df0c1d74..4943dd32a 100644
--- a/apt-pkg/sourcelist.h
+++ b/apt-pkg/sourcelist.h
@@ -116,6 +116,11 @@ class pkgSourceList
// 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();
diff --git a/apt-private/private-install.cc b/apt-private/private-install.cc
index 107ed398e..40165af31 100644
--- a/apt-private/private-install.cc
+++ b/apt-private/private-install.cc
@@ -19,6 +19,10 @@
#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>
@@ -669,10 +673,23 @@ bool DoCacheManipulationFromCommandLine(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;
-
+
std::map<unsigned short, APT::VersionSet> verset;
if(!DoCacheManipulationFromCommandLine(CmdL, Cache, verset))