From 0d29b9d4368284782862c7b507c47002b79ddb27 Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Sat, 26 Apr 2014 00:00:51 +0200 Subject: WIP local deb install --- apt-pkg/deb/debindexfile.cc | 105 ++++++++++++++++++++++++++++++++++++++++++- apt-pkg/deb/debindexfile.h | 31 +++++++++++++ apt-pkg/deb/deblistparser.cc | 20 +++++++++ apt-pkg/deb/deblistparser.h | 15 +++++-- apt-pkg/deb/debmetaindex.cc | 9 ++++ apt-pkg/deb/debmetaindex.h | 24 ++++++++++ apt-pkg/deb/debrecords.h | 18 ++++++-- 7 files changed, 214 insertions(+), 8 deletions(-) (limited to 'apt-pkg/deb') 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 #include #include +#include #include #include @@ -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 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(); + 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 *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 -- cgit v1.2.3 From eafc5435878d4013262131e5506c52d77b8a4bd4 Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Mon, 28 Apr 2014 14:50:11 +0200 Subject: avoid deb specific code in private-install --- apt-pkg/deb/debmetaindex.cc | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) (limited to 'apt-pkg/deb') diff --git a/apt-pkg/deb/debmetaindex.cc b/apt-pkg/deb/debmetaindex.cc index 67da592d6..56eecdca1 100644 --- a/apt-pkg/deb/debmetaindex.cc +++ b/apt-pkg/deb/debmetaindex.cc @@ -516,5 +516,25 @@ class debSLTypeDebSrc : public debSLTypeDebian } }; +class debSLTypeDebFile : public pkgSourceList::Type +{ + public: + + bool CreateItem(vector &List, string const &URI, + string const &Dist, string const &Section, + std::map const &Options) const + { + metaIndex *mi = new debDebFileMetaIndex(URI); + List.push_back(mi); + return true; + } + + debSLTypeDebFile() + { + Name = "deb-file"; + Label = "Debian Deb File"; + } +}; debSLTypeDeb _apt_DebType; debSLTypeDebSrc _apt_DebSrcType; +debSLTypeDebFile _apt_DebFileType; -- cgit v1.2.3 From a9d990a2602fca4f217705e356b449b0f42a7760 Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Mon, 28 Apr 2014 17:09:29 +0200 Subject: use new Popen() --- apt-pkg/deb/debindexfile.cc | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) (limited to 'apt-pkg/deb') diff --git a/apt-pkg/deb/debindexfile.cc b/apt-pkg/deb/debindexfile.cc index f9864c67b..1cecb42cf 100644 --- a/apt-pkg/deb/debindexfile.cc +++ b/apt-pkg/deb/debindexfile.cc @@ -693,18 +693,21 @@ bool debDebPkgFileIndex::Merge(pkgCacheGenerator& Gen, OpProgress* Prog) const // 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"); + const char *Args[5] = {"/usr/bin/dpkg", + "-I", + DebFile.c_str(), + "control", + NULL}; + FileFd PipeFd; + pid_t Child; + if(Popen(Args, PipeFd, Child, FileFd::ReadOnly) == false) + 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); + unsigned long long n = 0; + if(PipeFd.Read(buf, sizeof(buf)-1, &n) == false) + return _error->Errno("read", "Failed to read dpkg pipe"); + ExecWait(Child, "Popen"); // now write the control data to a tempfile SPtr DebControl = GetTempFile("deb-file-" + DebFile); -- cgit v1.2.3 From fb11075f497e5a7afe5837ae84a350fff9f93dc5 Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Mon, 28 Apr 2014 17:40:50 +0200 Subject: use flAbsPath() --- apt-pkg/deb/debindexfile.cc | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'apt-pkg/deb') diff --git a/apt-pkg/deb/debindexfile.cc b/apt-pkg/deb/debindexfile.cc index 1cecb42cf..86ef92bfb 100644 --- a/apt-pkg/deb/debindexfile.cc +++ b/apt-pkg/deb/debindexfile.cc @@ -673,8 +673,7 @@ APT_CONST bool debStatusIndex::Exists() const 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; + DebFileFullPath = flAbsPath(DebFile); } std::string debDebPkgFileIndex::ArchiveURI(std::string /*File*/) const -- cgit v1.2.3