diff options
Diffstat (limited to 'apt-pkg/deb')
-rw-r--r-- | apt-pkg/deb/debfile.cc | 250 | ||||
-rw-r--r-- | apt-pkg/deb/debfile.h | 95 | ||||
-rw-r--r-- | apt-pkg/deb/debindexfile.cc | 43 | ||||
-rw-r--r-- | apt-pkg/deb/deblistparser.cc | 40 | ||||
-rw-r--r-- | apt-pkg/deb/deblistparser.h | 57 | ||||
-rw-r--r-- | apt-pkg/deb/debmetaindex.cc | 2 | ||||
-rw-r--r-- | apt-pkg/deb/debsystem.cc | 2 | ||||
-rw-r--r-- | apt-pkg/deb/dpkgpm.cc | 2 |
8 files changed, 382 insertions, 109 deletions
diff --git a/apt-pkg/deb/debfile.cc b/apt-pkg/deb/debfile.cc new file mode 100644 index 000000000..f8d752e7f --- /dev/null +++ b/apt-pkg/deb/debfile.cc @@ -0,0 +1,250 @@ +// -*- mode: cpp; mode: fold -*- +// Description /*{{{*/ +/* ###################################################################### + + Debian Archive File (.deb) + + .DEB archives are AR files containing two tars and an empty marker + member called 'debian-binary'. The two tars contain the meta data and + the actual archive contents. Thus this class is a very simple wrapper + around ar/tar to simply extract the right tar files. + + It also uses the deb package list parser to parse the control file + into the cache. + + ##################################################################### */ + /*}}}*/ +// Include Files /*{{{*/ +#include <config.h> + +#include <apt-pkg/aptconfiguration.h> +#include <apt-pkg/arfile.h> +#include <apt-pkg/debfile.h> +#include <apt-pkg/dirstream.h> +#include <apt-pkg/error.h> +#include <apt-pkg/extracttar.h> +#include <apt-pkg/fileutl.h> +#include <apt-pkg/tagfile.h> + +#include <string> +#include <vector> +#include <string.h> +#include <sys/stat.h> + +#include <apti18n.h> + /*}}}*/ + +// DebFile::debDebFile - Constructor /*{{{*/ +// --------------------------------------------------------------------- +/* Open the AR file and check for consistency */ +debDebFile::debDebFile(FileFd &File) : File(File), AR(File) +{ + if (_error->PendingError() == true) + return; + + if (!CheckMember("debian-binary")) { + _error->Error(_("This is not a valid DEB archive, missing '%s' member"), "debian-binary"); + return; + } + + if (!CheckMember("control.tar") && + !CheckMember("control.tar.gz") && + !CheckMember("control.tar.xz") && + !CheckMember("control.tar.zst")) + { + _error->Error(_("This is not a valid DEB archive, missing '%s' member"), "control.tar"); + return; + } + + if (!CheckMember("data.tar") && + !CheckMember("data.tar.gz") && + !CheckMember("data.tar.bz2") && + !CheckMember("data.tar.lzma") && + !CheckMember("data.tar.xz") && + !CheckMember("data.tar.zst")) + { + _error->Error(_("This is not a valid DEB archive, missing '%s' member"), "data.tar"); + return; + } +} + /*}}}*/ +// DebFile::CheckMember - Check if a named member is in the archive /*{{{*/ +// --------------------------------------------------------------------- +/* This is used to check for a correct deb and to give nicer error messages + for people playing around. */ +bool debDebFile::CheckMember(const char *Name) +{ + if (AR.FindMember(Name) == 0) + return false; + return true; +} + /*}}}*/ +// DebFile::GotoMember - Jump to a Member /*{{{*/ +// --------------------------------------------------------------------- +/* Jump in the file to the start of a named member and return the information + about that member. The caller can then read from the file up to the + returned size. Note, since this relies on the file position this is + a destructive operation, it also changes the last returned Member + structure - so don't nest them! */ +const ARArchive::Member *debDebFile::GotoMember(const char *Name) +{ + // Get the archive member and positition the file + const ARArchive::Member *Member = AR.FindMember(Name); + if (Member == 0) + { + return 0; + } + if (File.Seek(Member->Start) == false) + return 0; + + return Member; +} + /*}}}*/ +// DebFile::ExtractTarMember - Extract the contents of a tar member /*{{{*/ +// --------------------------------------------------------------------- +/* Simple wrapper around tar.. */ +bool debDebFile::ExtractTarMember(pkgDirStream &Stream,const char *Name) +{ + // Get the archive member + const ARArchive::Member *Member = NULL; + std::string Compressor; + + std::vector<APT::Configuration::Compressor> compressor = APT::Configuration::getCompressors(); + for (std::vector<APT::Configuration::Compressor>::const_iterator c = compressor.begin(); + c != compressor.end(); ++c) + { + Member = AR.FindMember(std::string(Name).append(c->Extension).c_str()); + if (Member == NULL) + continue; + Compressor = c->Name; + break; + } + + if (Member == NULL) + Member = AR.FindMember(std::string(Name).c_str()); + + if (Member == NULL) + { + std::string ext = std::string(Name) + ".{"; + for (std::vector<APT::Configuration::Compressor>::const_iterator c = compressor.begin(); + c != compressor.end(); ++c) { + if (!c->Extension.empty()) + ext.append(c->Extension.substr(1)); + } + ext.append("}"); + return _error->Error(_("Internal error, could not locate member %s"), ext.c_str()); + } + + if (File.Seek(Member->Start) == false) + return false; + + // Prepare Tar + ExtractTar Tar(File,Member->Size,Compressor); + if (_error->PendingError() == true) + return false; + return Tar.Go(Stream); +} + /*}}}*/ +// DebFile::ExtractArchive - Extract the archive data itself /*{{{*/ +// --------------------------------------------------------------------- +/* Simple wrapper around DebFile::ExtractTarMember. */ +bool debDebFile::ExtractArchive(pkgDirStream &Stream) +{ + return ExtractTarMember(Stream, "data.tar"); +} + /*}}}*/ + +// DebFile::ControlExtract::DoItem - Control Tar Extraction /*{{{*/ +// --------------------------------------------------------------------- +/* This directory stream handler for the control tar handles extracting + it into the temporary meta directory. It only extracts files, it does + not create directories, links or anything else. */ +bool debDebFile::ControlExtract::DoItem(Item &Itm,int &Fd) +{ + if (Itm.Type != Item::File) + return true; + + /* Cleanse the file name, prevent people from trying to unpack into + absolute paths, .., etc */ + for (char *I = Itm.Name; *I != 0; I++) + if (*I == '/') + *I = '_'; + + /* Force the ownership to be root and ensure correct permissions, + go-w, the rest are left untouched */ + Itm.UID = 0; + Itm.GID = 0; + Itm.Mode &= ~(S_IWGRP | S_IWOTH); + + return pkgDirStream::DoItem(Itm,Fd); +} + /*}}}*/ + +// MemControlExtract::DoItem - Check if it is the control file /*{{{*/ +// --------------------------------------------------------------------- +/* This sets up to extract the control block member file into a memory + block of just the right size. All other files go into the bit bucket. */ +bool debDebFile::MemControlExtract::DoItem(Item &Itm,int &Fd) +{ + // At the control file, allocate buffer memory. + if (Member == Itm.Name) + { + delete [] Control; + Control = new char[Itm.Size+2]; + IsControl = true; + Fd = -2; // Signal to pass to Process + Length = Itm.Size; + } + else + IsControl = false; + + return true; +} + /*}}}*/ +// MemControlExtract::Process - Process extracting the control file /*{{{*/ +// --------------------------------------------------------------------- +/* Just memcopy the block from the tar extractor and put it in the right + place in the pre-allocated memory block. */ +bool debDebFile::MemControlExtract::Process(Item &/*Itm*/,const unsigned char *Data, + unsigned long long Size,unsigned long long Pos) +{ + memcpy(Control + Pos, Data,Size); + return true; +} + /*}}}*/ +// MemControlExtract::Read - Read the control information from the deb /*{{{*/ +// --------------------------------------------------------------------- +/* This uses the internal tar extractor to fetch the control file, and then + it parses it into a tag section parser. */ +bool debDebFile::MemControlExtract::Read(debDebFile &Deb) +{ + if (Deb.ExtractTarMember(*this, "control.tar") == false) + return false; + + if (Control == 0) + return true; + + Control[Length] = '\n'; + Control[Length+1] = '\n'; + if (Section.Scan(Control,Length+2) == false) + return _error->Error(_("Unparsable control file")); + return true; +} + /*}}}*/ +// MemControlExtract::TakeControl - Parse a memory block /*{{{*/ +// --------------------------------------------------------------------- +/* The given memory block is loaded into the parser and parsed as a control + record. */ +bool debDebFile::MemControlExtract::TakeControl(const void *Data,unsigned long long Size) +{ + delete [] Control; + Control = new char[Size+2]; + Length = Size; + memcpy(Control,Data,Size); + + Control[Length] = '\n'; + Control[Length+1] = '\n'; + return Section.Scan(Control,Length+2); +} + /*}}}*/ + diff --git a/apt-pkg/deb/debfile.h b/apt-pkg/deb/debfile.h new file mode 100644 index 000000000..21c59a567 --- /dev/null +++ b/apt-pkg/deb/debfile.h @@ -0,0 +1,95 @@ +// -*- mode: cpp; mode: fold -*- +// Description /*{{{*/ +/* ###################################################################### + + Debian Archive File (.deb) + + This Class handles all the operations performed directly on .deb + files. It makes use of the AR and TAR classes to give the necessary + external interface. + + There are only two things that can be done with a raw package, + extract it's control information and extract the contents itself. + + This should probably subclass an as-yet unwritten super class to + produce a generic archive mechanism. + + The memory control file extractor is useful to extract a single file + into memory from the control.tar.gz + + ##################################################################### */ + /*}}}*/ +#ifndef PKGLIB_DEBFILE_H +#define PKGLIB_DEBFILE_H + +#include <apt-pkg/arfile.h> +#include <apt-pkg/dirstream.h> +#include <apt-pkg/macros.h> +#include <apt-pkg/tagfile.h> + +#include <string> + +#ifndef APT_8_CLEANER_HEADERS +#include <apt-pkg/md5.h> +#endif +#ifndef APT_10_CLEANER_HEADERS +#include <apt-pkg/pkgcache.h> +#endif + +class FileFd; + +class debDebFile +{ + protected: + + FileFd &File; + ARArchive AR; + + bool CheckMember(const char *Name); + + public: + class ControlExtract; + class MemControlExtract; + + bool ExtractTarMember(pkgDirStream &Stream, const char *Name); + bool ExtractArchive(pkgDirStream &Stream); + const ARArchive::Member *GotoMember(const char *Name); + inline FileFd &GetFile() {return File;}; + + explicit debDebFile(FileFd &File); +}; + +class debDebFile::ControlExtract : public pkgDirStream +{ + public: + + virtual bool DoItem(Item &Itm,int &Fd) APT_OVERRIDE; +}; + +class debDebFile::MemControlExtract : public pkgDirStream +{ + bool IsControl; + + public: + + char *Control; + pkgTagSection Section; + unsigned long Length; + std::string Member; + + // Members from DirStream + virtual bool DoItem(Item &Itm,int &Fd) APT_OVERRIDE; + virtual bool Process(Item &Itm,const unsigned char *Data, + unsigned long long Size,unsigned long long Pos) APT_OVERRIDE; + + // Helpers + bool Read(debDebFile &Deb); + bool TakeControl(const void *Data,unsigned long long Size); + + MemControlExtract() : IsControl(false), Control(0), Length(0), Member("control") {}; + explicit MemControlExtract(std::string Member) : IsControl(false), Control(0), Length(0), Member(Member) {}; + ~MemControlExtract() {delete [] Control;}; +}; + /*}}}*/ + +#endif diff --git a/apt-pkg/deb/debindexfile.cc b/apt-pkg/deb/debindexfile.cc index 25e0a3312..279f35a38 100644 --- a/apt-pkg/deb/debindexfile.cc +++ b/apt-pkg/deb/debindexfile.cc @@ -10,7 +10,9 @@ // Include Files /*{{{*/ #include <config.h> +#include <apti18n.h> #include <apt-pkg/configuration.h> +#include <apt-pkg/debfile.h> #include <apt-pkg/debindexfile.h> #include <apt-pkg/deblistparser.h> #include <apt-pkg/debrecords.h> @@ -172,36 +174,23 @@ bool debDebPkgFileIndex::GetContent(std::ostream &content, std::string const &de if (stat(debfile.c_str(), &Buf) != 0) return false; - // get the control data out of the deb file via dpkg-deb -I - std::string dpkg = _config->Find("Dir::Bin::dpkg","dpkg-deb"); - std::vector<const char *> Args; - Args.push_back(dpkg.c_str()); - Args.push_back("-I"); - Args.push_back(debfile.c_str()); - Args.push_back("control"); - Args.push_back(NULL); - FileFd PipeFd; - pid_t Child; - if(Popen((const char**)&Args[0], PipeFd, Child, FileFd::ReadOnly) == false) - return _error->Error("Popen failed"); + FileFd debFd(debfile, FileFd::ReadOnly); + debDebFile deb(debFd); + debDebFile::MemControlExtract extractor("control"); - std::string line; - bool first_line_seen = false; - while (PipeFd.ReadLine(line)) - { - if (first_line_seen == false) - { - if (line.empty()) - continue; - first_line_seen = true; - } - else if (line.empty()) - break; - content << line << "\n"; - } + if (not extractor.Read(deb)) + return _error->Error(_("Could not read meta data from %s"), debfile.c_str()); + + // trim off newlines + while (extractor.Control[extractor.Length] == '\n') + extractor.Control[extractor.Length--] = '\0'; + const char *Control = extractor.Control; + while (isspace_ascii(Control[0])) + Control++; + + content << Control; content << "Filename: " << debfile << "\n"; content << "Size: " << std::to_string(Buf.st_size) << "\n"; - ExecWait(Child, "Popen"); return true; } diff --git a/apt-pkg/deb/deblistparser.cc b/apt-pkg/deb/deblistparser.cc index 80ca10e37..832e3948d 100644 --- a/apt-pkg/deb/deblistparser.cc +++ b/apt-pkg/deb/deblistparser.cc @@ -546,28 +546,6 @@ const char *debListParser::ConvertRelation(const char *I,unsigned int &Op) /* This parses the dependency elements out of a standard string in place, bit by bit. */ const char *debListParser::ParseDepends(const char *Start,const char *Stop, - std::string &Package,std::string &Ver,unsigned int &Op) - { return ParseDepends(Start, Stop, Package, Ver, Op, false, true, false); } -const char *debListParser::ParseDepends(const char *Start,const char *Stop, - std::string &Package,std::string &Ver,unsigned int &Op, - bool const &ParseArchFlags) - { return ParseDepends(Start, Stop, Package, Ver, Op, ParseArchFlags, true, false); } -const char *debListParser::ParseDepends(const char *Start,const char *Stop, - std::string &Package,std::string &Ver,unsigned int &Op, - bool const &ParseArchFlags, bool const &StripMultiArch) - { return ParseDepends(Start, Stop, Package, Ver, Op, ParseArchFlags, StripMultiArch, false); } -const char *debListParser::ParseDepends(const char *Start,const char *Stop, - string &Package,string &Ver, - unsigned int &Op, bool const &ParseArchFlags, - bool const &StripMultiArch, - bool const &ParseRestrictionsList) -{ - return debListParser::ParseDepends(Start, Stop, Package, Ver, Op, ParseArchFlags, - StripMultiArch, ParseRestrictionsList, - _config->Find("APT::Architecture")); -} - -const char *debListParser::ParseDepends(const char *Start,const char *Stop, string &Package,string &Ver, unsigned int &Op, bool const &ParseArchFlags, bool const &StripMultiArch, @@ -584,23 +562,15 @@ const char *debListParser::ParseDepends(const char *Start,const char *Stop, return res; } -const char *debListParser::ParseDepends(const char *Start,const char *Stop, - StringView &Package,StringView &Ver, - unsigned int &Op, bool ParseArchFlags, - bool StripMultiArch, - bool ParseRestrictionsList) -{ - return debListParser::ParseDepends(Start, Stop, Package, Ver, Op, ParseArchFlags, - StripMultiArch, ParseRestrictionsList, - _config->Find("APT::Architecture")); -} -const char *debListParser::ParseDepends(const char *Start,const char *Stop, - StringView &Package,StringView &Ver, +const char *debListParser::ParseDepends(const char *Start, const char *Stop, + StringView &Package, StringView &Ver, unsigned int &Op, bool ParseArchFlags, bool StripMultiArch, - bool ParseRestrictionsList, string const &Arch) + bool ParseRestrictionsList, string Arch) { + if (Arch.empty()) + Arch = _config->Find("APT::Architecture"); // Strip off leading space for (;Start != Stop && isspace_ascii(*Start) != 0; ++Start); diff --git a/apt-pkg/deb/deblistparser.h b/apt-pkg/deb/deblistparser.h index ad2b947fe..807968452 100644 --- a/apt-pkg/deb/deblistparser.h +++ b/apt-pkg/deb/deblistparser.h @@ -18,9 +18,7 @@ #include <string> #include <vector> -#ifdef APT_PKG_EXPOSE_STRING_VIEW #include <apt-pkg/string_view.h> -#endif #ifndef APT_8_CLEANER_HEADERS #include <apt-pkg/indexfile.h> @@ -32,14 +30,12 @@ class APT_HIDDEN debListParser : public pkgCacheListParser { public: -#ifdef APT_PKG_EXPOSE_STRING_VIEW // Parser Helper struct WordList { APT::StringView Str; unsigned char Val; }; -#endif private: std::vector<std::string> forceEssential; @@ -57,9 +53,7 @@ class APT_HIDDEN debListParser : public pkgCacheListParser unsigned int Type); bool ParseProvides(pkgCache::VerIterator &Ver); -#ifdef APT_PKG_EXPOSE_STRING_VIEW APT_HIDDEN static bool GrabWord(APT::StringView Word,const WordList *List,unsigned char &Out); -#endif APT_HIDDEN unsigned char ParseMultiArch(bool const showErrors); public: @@ -69,15 +63,11 @@ class APT_HIDDEN debListParser : public pkgCacheListParser // These all operate against the current section virtual std::string Package() APT_OVERRIDE; virtual bool ArchitectureAll() APT_OVERRIDE; -#ifdef APT_PKG_EXPOSE_STRING_VIEW virtual APT::StringView Architecture() APT_OVERRIDE; virtual APT::StringView Version() APT_OVERRIDE; -#endif virtual bool NewVersion(pkgCache::VerIterator &Ver) APT_OVERRIDE; virtual std::vector<std::string> AvailableDescriptionLanguages() APT_OVERRIDE; -#ifdef APT_PKG_EXPOSE_STRING_VIEW virtual APT::StringView Description_md5() APT_OVERRIDE; -#endif virtual unsigned short VersionHash() APT_OVERRIDE; virtual bool SameVersion(unsigned short const Hash, pkgCache::VerIterator const &Ver) APT_OVERRIDE; virtual bool UsePackage(pkgCache::PkgIterator &Pkg, @@ -87,37 +77,18 @@ class APT_HIDDEN debListParser : public pkgCacheListParser virtual bool Step() APT_OVERRIDE; - APT_PUBLIC static const char *ParseDepends(const char *Start,const char *Stop, - std::string &Package,std::string &Ver,unsigned int &Op); - APT_PUBLIC static const char *ParseDepends(const char *Start,const char *Stop, - std::string &Package,std::string &Ver,unsigned int &Op, - bool const &ParseArchFlags); - APT_PUBLIC static const char *ParseDepends(const char *Start,const char *Stop, - std::string &Package,std::string &Ver,unsigned int &Op, - bool const &ParseArchFlags, bool const &StripMultiArch); - APT_PUBLIC static const char *ParseDepends(const char *Start,const char *Stop, - std::string &Package,std::string &Ver,unsigned int &Op, - bool const &ParseArchFlags, bool const &StripMultiArch, - bool const &ParseRestrictionsList); - APT_PUBLIC static const char *ParseDepends(const char *Start,const char *Stop, - std::string &Package,std::string &Ver,unsigned int &Op, - bool const &ParseArchFlags, bool const &StripMultiArch, - bool const &ParseRestrictionsList, - std::string const &Arch); - -#ifdef APT_PKG_EXPOSE_STRING_VIEW - APT_HIDDEN static const char *ParseDepends(const char *Start,const char *Stop, - APT::StringView &Package, - APT::StringView &Ver,unsigned int &Op, - bool const ParseArchFlags = false, bool StripMultiArch = true, - bool const ParseRestrictionsList = false); - APT_HIDDEN static const char *ParseDepends(const char *Start,const char *Stop, - APT::StringView &Package, - APT::StringView &Ver,unsigned int &Op, - bool const ParseArchFlags, bool StripMultiArch, - bool const ParseRestrictionsList, - std::string const &Arch); -#endif + APT_PUBLIC static const char *ParseDepends(const char *Start, const char *Stop, + std::string &Package, std::string &Ver, unsigned int &Op, + bool const &ParseArchFlags = false, bool const &StripMultiArch = true, + bool const &ParseRestrictionsList = false, + std::string const &Arch = ""); + + APT_PUBLIC static const char *ParseDepends(const char *Start, const char *Stop, + APT::StringView &Package, + APT::StringView &Ver, unsigned int &Op, + bool const ParseArchFlags = false, bool StripMultiArch = true, + bool const ParseRestrictionsList = false, + std::string Arch = ""); APT_PUBLIC static const char *ConvertRelation(const char *I,unsigned int &Op); @@ -139,11 +110,9 @@ class APT_HIDDEN debDebFileParser : public debListParser class APT_HIDDEN debTranslationsParser : public debListParser { public: -#ifdef APT_PKG_EXPOSE_STRING_VIEW // a translation can never be a real package virtual APT::StringView Architecture() APT_OVERRIDE { return ""; } virtual APT::StringView Version() APT_OVERRIDE { return ""; } -#endif explicit debTranslationsParser(FileFd *File) : debListParser(File) {}; @@ -152,7 +121,7 @@ class APT_HIDDEN debTranslationsParser : public debListParser class APT_HIDDEN debStatusListParser : public debListParser { public: - virtual bool ParseStatus(pkgCache::PkgIterator &Pkg,pkgCache::VerIterator &Ver); + virtual bool ParseStatus(pkgCache::PkgIterator &Pkg,pkgCache::VerIterator &Ver) APT_OVERRIDE; explicit debStatusListParser(FileFd *File) : debListParser(File) {}; }; diff --git a/apt-pkg/deb/debmetaindex.cc b/apt-pkg/deb/debmetaindex.cc index 13575e10b..fef58f543 100644 --- a/apt-pkg/deb/debmetaindex.cc +++ b/apt-pkg/deb/debmetaindex.cc @@ -59,7 +59,7 @@ static std::string NormalizeSignedBy(std::string SignedBy, bool const SupportFil // but fingerprints are harder to fake than the others and this option is set once, // not interactively all the time so easy to type is not really a concern. std::transform(SignedBy.begin(), SignedBy.end(), SignedBy.begin(), [](char const c) { - return (isspace(c) == 0) ? c : ','; + return (isspace_ascii(c) == 0) ? c : ','; }); auto fingers = VectorizeString(SignedBy, ','); auto const isAnEmptyString = [](std::string const &s) { return s.empty(); }; diff --git a/apt-pkg/deb/debsystem.cc b/apt-pkg/deb/debsystem.cc index 5df6c58a1..0c7e9ff39 100644 --- a/apt-pkg/deb/debsystem.cc +++ b/apt-pkg/deb/debsystem.cc @@ -153,8 +153,8 @@ bool debSystem::UnLock(bool NoErrors) return _error->Error(_("Not locked")); if (--d->LockCount == 0) { - close(d->FrontendLockFD); close(d->LockFD); + close(d->FrontendLockFD); d->LockCount = 0; } diff --git a/apt-pkg/deb/dpkgpm.cc b/apt-pkg/deb/dpkgpm.cc index ad5a9007e..4de36d528 100644 --- a/apt-pkg/deb/dpkgpm.cc +++ b/apt-pkg/deb/dpkgpm.cc @@ -2460,7 +2460,7 @@ void pkgDPkgPM::WriteApportReport(const char *pkgpath, const char *errormsg) { fprintf(report, "Df:\n"); - FILE *log = popen("/bin/df -l","r"); + FILE *log = popen("/bin/df -l -x squashfs","r"); if(log != NULL) { char buf[1024]; |