Browse Source

WIP local deb install

debian/1.8.y
Michael Vogt 8 years ago
parent
commit
0d29b9d436
  1. 3
      apt-pkg/acquire-item.cc
  2. 26
      apt-pkg/contrib/fileutl.cc
  3. 2
      apt-pkg/contrib/fileutl.h
  4. 105
      apt-pkg/deb/debindexfile.cc
  5. 31
      apt-pkg/deb/debindexfile.h
  6. 20
      apt-pkg/deb/deblistparser.cc
  7. 15
      apt-pkg/deb/deblistparser.h
  8. 9
      apt-pkg/deb/debmetaindex.cc
  9. 24
      apt-pkg/deb/debmetaindex.h
  10. 18
      apt-pkg/deb/debrecords.h
  11. 5
      apt-pkg/sourcelist.h
  12. 19
      apt-private/private-install.cc

3
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;

26
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)

2
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
*

105
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;
}
/*}}}*/

31
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

20
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;
}

15
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

9
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:

24
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

18
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

5
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();

19
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))

Loading…
Cancel
Save