1
0
Fork 0
apt/apt-pkg/deb/debindexfile.cc
Daniel Baumann 6810ba718b
Adding upstream version 3.0.2.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
2025-06-20 21:10:43 +02:00

423 lines
12 KiB
C++

// -*- mode: cpp; mode: fold -*-
// Description /*{{{*/
/* ######################################################################
Debian Specific sources.list types and the three sorts of Debian
index files.
##################################################################### */
/*}}}*/
// 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>
#include <apt-pkg/debsrcrecords.h>
#include <apt-pkg/error.h>
#include <apt-pkg/fileutl.h>
#include <apt-pkg/indexfile.h>
#include <apt-pkg/pkgcache.h>
#include <apt-pkg/pkgrecords.h>
#include <apt-pkg/srcrecords.h>
#include <apt-pkg/strutl.h>
#include <cstdio>
#include <iostream>
#include <memory>
#include <sstream>
#include <string>
#include <sys/stat.h>
#include <unistd.h>
using namespace std::literals;
/*}}}*/
// Sources Index /*{{{*/
debSourcesIndex::debSourcesIndex(IndexTarget const &Target,bool const Trusted) :
pkgDebianIndexTargetFile(Target, Trusted), d(NULL)
{
}
std::string debSourcesIndex::SourceInfo(pkgSrcRecords::Parser const &Record,
pkgSrcRecords::File const &File) const
{
// The result looks like: http://foo/debian/ stable/main src 1.1.1 (dsc)
std::string Res = Target.Description;
Res.erase(Target.Description.rfind(' '));
Res += " ";
Res += Record.Package();
Res += " ";
Res += Record.Version();
if (File.Type.empty() == false)
Res += " (" + File.Type + ")";
return Res;
}
pkgSrcRecords::Parser *debSourcesIndex::CreateSrcParser() const
{
std::string const SourcesURI = IndexFileName();
if (FileExists(SourcesURI))
return new debSrcRecordParser(SourcesURI, this);
return NULL;
}
bool debSourcesIndex::OpenListFile(FileFd &, std::string const &)
{
return true;
}
pkgCacheListParser * debSourcesIndex::CreateListParser(FileFd &)
{
return nullptr;
}
uint8_t debSourcesIndex::GetIndexFlags() const
{
return 0;
}
/*}}}*/
// Packages Index /*{{{*/
debPackagesIndex::debPackagesIndex(IndexTarget const &Target, bool const Trusted) :
pkgDebianIndexTargetFile(Target, Trusted), d(NULL)
{
}
std::string debPackagesIndex::ArchiveInfo(pkgCache::VerIterator const &Ver) const
{
std::string Res = Target.Description;
{
auto const space = Target.Description.rfind(' ');
if (space != std::string::npos)
Res.erase(space);
}
Res += " ";
Res += Ver.ParentPkg().Name();
Res += " ";
std::string const Dist = Target.Option(IndexTarget::RELEASE);
if (Dist.empty() == false && Dist[Dist.size() - 1] != '/')
Res.append(Ver.Arch()).append(" ");
Res += Ver.VerStr();
return Res;
}
uint8_t debPackagesIndex::GetIndexFlags() const
{
return 0;
}
/*}}}*/
// Translation-* Index /*{{{*/
debTranslationsIndex::debTranslationsIndex(IndexTarget const &Target) :
pkgDebianIndexTargetFile(Target, true), d(NULL)
{}
bool debTranslationsIndex::HasPackages() const
{
return Exists();
}
bool debTranslationsIndex::OpenListFile(FileFd &Pkg, std::string const &FileName)
{
if (FileExists(FileName))
return pkgDebianIndexTargetFile::OpenListFile(Pkg, FileName);
return true;
}
uint8_t debTranslationsIndex::GetIndexFlags() const
{
return pkgCache::Flag::NotSource | pkgCache::Flag::NoPackages;
}
std::string debTranslationsIndex::GetArchitecture() const
{
return std::string();
}
pkgCacheListParser * debTranslationsIndex::CreateListParser(FileFd &Pkg)
{
if (Pkg.IsOpen() == false)
return nullptr;
_error->PushToStack();
std::unique_ptr<pkgCacheListParser> Parser(new debTranslationsParser(&Pkg));
bool const newError = _error->PendingError();
_error->MergeWithStack();
return newError ? nullptr : Parser.release();
}
/*}}}*/
// dpkg/status Index /*{{{*/
debStatusIndex::debStatusIndex(std::string const &File) : pkgDebianIndexRealFile(File, true), d(NULL)
{
}
std::string debStatusIndex::GetArchitecture() const
{
return std::string();
}
std::string debStatusIndex::GetComponent() const
{
return "now";
}
uint8_t debStatusIndex::GetIndexFlags() const
{
return pkgCache::Flag::NotSource;
}
pkgCacheListParser * debStatusIndex::CreateListParser(FileFd &Pkg)
{
if (Pkg.IsOpen() == false)
return nullptr;
_error->PushToStack();
std::unique_ptr<pkgCacheListParser> Parser(new debStatusListParser(&Pkg));
bool const newError = _error->PendingError();
_error->MergeWithStack();
return newError ? nullptr : Parser.release();
}
/*}}}*/
// DebPkgFile Index - a single .deb file as an index /*{{{*/
debDebPkgFileIndex::debDebPkgFileIndex(std::string const &DebFile)
: pkgDebianIndexRealFile(DebFile, true), d(NULL), DebFile(DebFile)
{
}
bool debDebPkgFileIndex::GetContent(std::ostream &content, std::string const &debfile)
{
struct stat Buf;
if (stat(debfile.c_str(), &Buf) != 0)
return false;
FileFd debFd(debfile, FileFd::ReadOnly);
debDebFile deb(debFd);
debDebFile::MemControlExtract extractor("control");
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 << '\n';
content << "Filename: " << debfile << "\n";
content << "Size: " << std::to_string(Buf.st_size) << "\n";
return true;
}
bool debDebPkgFileIndex::OpenListFile(FileFd &Pkg, std::string const &FileName)
{
// write the control data to a tempfile
if (GetTempFile("deb-file-"s += flNotDir(FileName), true, &Pkg) == NULL)
return false;
std::ostringstream content;
if (GetContent(content, FileName) == false)
return false;
std::string const contentstr = content.str();
if (contentstr.empty())
return true;
if (Pkg.Write(contentstr.c_str(), contentstr.length()) == false || Pkg.Seek(0) == false)
return false;
return true;
}
pkgCacheListParser * debDebPkgFileIndex::CreateListParser(FileFd &Pkg)
{
if (Pkg.IsOpen() == false)
return nullptr;
_error->PushToStack();
std::unique_ptr<pkgCacheListParser> Parser(new debDebFileParser(&Pkg, DebFile));
bool const newError = _error->PendingError();
_error->MergeWithStack();
return newError ? nullptr : Parser.release();
}
uint8_t debDebPkgFileIndex::GetIndexFlags() const
{
return pkgCache::Flag::LocalSource;
}
std::string debDebPkgFileIndex::GetArchitecture() const
{
return std::string();
}
std::string debDebPkgFileIndex::GetComponent() const
{
return "local-deb";
}
pkgCache::PkgFileIterator debDebPkgFileIndex::FindInCache(pkgCache &Cache) const
{
std::string const FileName = IndexFileName();
pkgCache::PkgFileIterator File = Cache.FileBegin();
for (; File.end() == false; ++File)
{
if (File.FileName() == NULL || FileName != File.FileName())
continue;
// we can't do size checks here as file size != content size
return File;
}
return File;
}
std::string debDebPkgFileIndex::ArchiveInfo(pkgCache::VerIterator const &Ver) const
{
std::string Res = IndexFileName() + " ";
Res.append(Ver.ParentPkg().Name()).append(" ");
Res.append(Ver.Arch()).append(" ");
Res.append(Ver.VerStr());
return Res;
}
/*}}}*/
// DscFile Index - a single .dsc file as an index /*{{{*/
debDscFileIndex::debDscFileIndex(std::string const &DscFile)
: pkgDebianIndexRealFile(DscFile, true), d(NULL)
{
}
pkgSrcRecords::Parser *debDscFileIndex::CreateSrcParser() const
{
if (Exists() == false)
return NULL;
return new debDscRecordParser(File, this);
}
std::string debDscFileIndex::GetComponent() const
{
return "local-dsc";
}
std::string debDscFileIndex::GetArchitecture() const
{
return "source";
}
uint8_t debDscFileIndex::GetIndexFlags() const
{
return pkgCache::Flag::LocalSource;
}
/*}}}*/
// ControlFile Index - a directory with a debian/control file /*{{{*/
std::string debDebianSourceDirIndex::GetComponent() const
{
return "local-control";
}
/*}}}*/
// String Package Index - a string of Packages file content /*{{{*/
std::string debStringPackageIndex::GetArchitecture() const
{
return std::string();
}
std::string debStringPackageIndex::GetComponent() const
{
return "apt-tmp-index";
}
uint8_t debStringPackageIndex::GetIndexFlags() const
{
return pkgCache::Flag::NotSource;
}
const pkgIndexFile::Type *debStringPackageIndex::GetType() const
{
return pkgIndexFile::Type::GetType("Debian Package Index");
}
debStringPackageIndex::debStringPackageIndex(std::string const &content) :
pkgDebianIndexRealFile("", false), d(NULL)
{
FileFd fd;
GetTempFile("apt-tmp-index", false, &fd);
fd.Write(content.data(), content.length());
File = fd.Name();
}
debStringPackageIndex::~debStringPackageIndex()
{
RemoveFile("~debStringPackageIndex", File);
}
/*}}}*/
// Index File types for Debian /*{{{*/
class APT_HIDDEN debIFTypeSrc : public pkgIndexFile::Type
{
public:
debIFTypeSrc() {Label = "Debian Source Index";};
};
class APT_HIDDEN debIFTypePkg : public pkgIndexFile::Type
{
public:
[[nodiscard]] pkgRecords::Parser *CreatePkgParser(pkgCache::PkgFileIterator const &File) const override
{
return new debRecordParser(File.FileName(),*File.Cache());
};
debIFTypePkg() {Label = "Debian Package Index";};
};
class APT_HIDDEN debIFTypeTrans : public debIFTypePkg
{
public:
debIFTypeTrans() {Label = "Debian Translation Index";};
};
class APT_HIDDEN debIFTypeStatus : public pkgIndexFile::Type
{
public:
[[nodiscard]] pkgRecords::Parser *CreatePkgParser(pkgCache::PkgFileIterator const &File) const override
{
return new debRecordParser(File.FileName(),*File.Cache());
};
debIFTypeStatus() {Label = "Debian dpkg status file";};
};
class APT_HIDDEN debIFTypeDebPkgFile : public pkgIndexFile::Type
{
public:
[[nodiscard]] pkgRecords::Parser *CreatePkgParser(pkgCache::PkgFileIterator const &File) const override
{
return new debDebFileRecordParser(File.FileName());
};
debIFTypeDebPkgFile() {Label = "Debian deb file";};
};
class APT_HIDDEN debIFTypeDscFile : public pkgIndexFile::Type
{
public:
[[nodiscard]] pkgSrcRecords::Parser *CreateSrcPkgParser(std::string const &DscFile) const override
{
return new debDscRecordParser(DscFile, NULL);
};
debIFTypeDscFile() {Label = "Debian dsc file";};
};
class APT_HIDDEN debIFTypeDebianSourceDir : public pkgIndexFile::Type
{
public:
[[nodiscard]] pkgSrcRecords::Parser *CreateSrcPkgParser(std::string const &SourceDir) const override
{
return new debDscRecordParser(SourceDir + std::string("/debian/control"), NULL);
};
debIFTypeDebianSourceDir() {Label = "Debian control file";};
};
APT_HIDDEN debIFTypeSrc _apt_Src;
APT_HIDDEN debIFTypePkg _apt_Pkg;
APT_HIDDEN debIFTypeTrans _apt_Trans;
APT_HIDDEN debIFTypeStatus _apt_Status;
APT_HIDDEN debIFTypeDebPkgFile _apt_DebPkgFile;
// file based pseudo indexes
APT_HIDDEN debIFTypeDscFile _apt_DscFile;
APT_HIDDEN debIFTypeDebianSourceDir _apt_DebianSourceDir;
const pkgIndexFile::Type *debSourcesIndex::GetType() const
{
return &_apt_Src;
}
const pkgIndexFile::Type *debPackagesIndex::GetType() const
{
return &_apt_Pkg;
}
const pkgIndexFile::Type *debTranslationsIndex::GetType() const
{
return &_apt_Trans;
}
const pkgIndexFile::Type *debStatusIndex::GetType() const
{
return &_apt_Status;
}
const pkgIndexFile::Type *debDebPkgFileIndex::GetType() const
{
return &_apt_DebPkgFile;
}
const pkgIndexFile::Type *debDscFileIndex::GetType() const
{
return &_apt_DscFile;
}
const pkgIndexFile::Type *debDebianSourceDirIndex::GetType() const
{
return &_apt_DebianSourceDir;
}
/*}}}*/
debStatusIndex::~debStatusIndex() {}
debPackagesIndex::~debPackagesIndex() {}
debTranslationsIndex::~debTranslationsIndex() {}
debSourcesIndex::~debSourcesIndex() {}
debDebPkgFileIndex::~debDebPkgFileIndex() {}
debDscFileIndex::~debDscFileIndex() {}