X-Git-Url: https://git.saurik.com/apt.git/blobdiff_plain/2830b8436ac8a6f2f3dac4ce2cd030c24eebce04..15e1ed52a741ff82deb0a4cd6150cf10e23b7368:/apt-pkg/deb/debindexfile.cc diff --git a/apt-pkg/deb/debindexfile.cc b/apt-pkg/deb/debindexfile.cc index c1c2b726a..c55847305 100644 --- a/apt-pkg/deb/debindexfile.cc +++ b/apt-pkg/deb/debindexfile.cc @@ -16,55 +16,35 @@ #include #include #include -#include #include -#include -#include -#include -#include #include #include -#include #include #include -#include #include #include -#include #include #include #include +#include + #include +#include /*}}}*/ -using std::string; - -// SourcesIndex::debSourcesIndex - Constructor /*{{{*/ -// --------------------------------------------------------------------- -/* */ -debSourcesIndex::debSourcesIndex(string URI,string Dist,string Section,bool Trusted) : - pkgIndexFile(Trusted), URI(URI), Dist(Dist), Section(Section) +// Sources Index /*{{{*/ +debSourcesIndex::debSourcesIndex(IndexTarget const &Target,bool const Trusted) : + pkgDebianIndexTargetFile(Target, Trusted), d(NULL) { } - /*}}}*/ -// SourcesIndex::SourceInfo - Short 1 liner describing a source /*{{{*/ -// --------------------------------------------------------------------- -/* The result looks like: - http://foo/debian/ stable/main src 1.1.1 (dsc) */ -string debSourcesIndex::SourceInfo(pkgSrcRecords::Parser const &Record, +std::string debSourcesIndex::SourceInfo(pkgSrcRecords::Parser const &Record, pkgSrcRecords::File const &File) const { - string Res; - Res = ::URI::NoUserPassword(URI) + ' '; - if (Dist[Dist.size() - 1] == '/') - { - if (Dist != "/") - Res += Dist; - } - else - Res += Dist + '/' + Section; - + // 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 += " "; @@ -73,796 +53,372 @@ string debSourcesIndex::SourceInfo(pkgSrcRecords::Parser const &Record, Res += " (" + File.Type + ")"; return Res; } - /*}}}*/ -// SourcesIndex::CreateSrcParser - Get a parser for the source files /*{{{*/ -// --------------------------------------------------------------------- -/* */ pkgSrcRecords::Parser *debSourcesIndex::CreateSrcParser() const { - string SourcesURI = _config->FindDir("Dir::State::lists") + - URItoFileName(IndexURI("Sources")); - string SourcesURIgzip = SourcesURI + ".gz"; - - if (!FileExists(SourcesURI) && !FileExists(SourcesURIgzip)) - return NULL; - else if (!FileExists(SourcesURI) && FileExists(SourcesURIgzip)) - SourcesURI = SourcesURIgzip; - - return new debSrcRecordParser(SourcesURI,this); -} - /*}}}*/ -// SourcesIndex::Describe - Give a descriptive path to the index /*{{{*/ -// --------------------------------------------------------------------- -/* */ -string debSourcesIndex::Describe(bool Short) const -{ - char S[300]; - if (Short == true) - snprintf(S,sizeof(S),"%s",Info("Sources").c_str()); - else - snprintf(S,sizeof(S),"%s (%s)",Info("Sources").c_str(), - IndexFile("Sources").c_str()); - - return S; -} - /*}}}*/ -// SourcesIndex::Info - One liner describing the index URI /*{{{*/ -// --------------------------------------------------------------------- -/* */ -string debSourcesIndex::Info(const char *Type) const -{ - string Info = ::URI::NoUserPassword(URI) + ' '; - if (Dist[Dist.size() - 1] == '/') - { - if (Dist != "/") - Info += Dist; - } - else - Info += Dist + '/' + Section; - Info += " "; - Info += Type; - return Info; + std::string const SourcesURI = IndexFileName(); + if (FileExists(SourcesURI)) + return new debSrcRecordParser(SourcesURI, this); + return NULL; } - /*}}}*/ -// SourcesIndex::Index* - Return the URI to the index files /*{{{*/ -// --------------------------------------------------------------------- -/* */ -inline string debSourcesIndex::IndexFile(const char *Type) const -{ - string s = URItoFileName(IndexURI(Type)); - string sgzip = s + ".gz"; - if (!FileExists(s) && FileExists(sgzip)) - return sgzip; - else - return s; -} - -string debSourcesIndex::IndexURI(const char *Type) const +bool debSourcesIndex::OpenListFile(FileFd &, std::string const &) { - string Res; - if (Dist[Dist.size() - 1] == '/') - { - if (Dist != "/") - Res = URI + Dist; - else - Res = URI; - } - else - Res = URI + "dists/" + Dist + '/' + Section + - "/source/"; - - Res += Type; - return Res; + return true; } - /*}}}*/ -// SourcesIndex::Exists - Check if the index is available /*{{{*/ -// --------------------------------------------------------------------- -/* */ -bool debSourcesIndex::Exists() const +pkgCacheListParser * debSourcesIndex::CreateListParser(FileFd &) { - return FileExists(IndexFile("Sources")); + return NULL; } - /*}}}*/ -// SourcesIndex::Size - Return the size of the index /*{{{*/ -// --------------------------------------------------------------------- -/* */ -unsigned long debSourcesIndex::Size() const +uint8_t debSourcesIndex::GetIndexFlags() const { - unsigned long size = 0; - - /* we need to ignore errors here; if the lists are absent, just return 0 */ - _error->PushToStack(); - - FileFd f(IndexFile("Sources"), FileFd::ReadOnly, FileFd::Extension); - if (!f.Failed()) - size = f.Size(); - - if (_error->PendingError() == true) - size = 0; - _error->RevertToStack(); - - return size; + return 0; } /*}}}*/ - -// PackagesIndex::debPackagesIndex - Contructor /*{{{*/ -// --------------------------------------------------------------------- -/* */ -debPackagesIndex::debPackagesIndex(string const &URI, string const &Dist, string const &Section, - bool const &Trusted, string const &Arch) : - pkgIndexFile(Trusted), URI(URI), Dist(Dist), Section(Section), Architecture(Arch) +// Packages Index /*{{{*/ +debPackagesIndex::debPackagesIndex(IndexTarget const &Target, bool const Trusted) : + pkgDebianIndexTargetFile(Target, Trusted), d(NULL) { - if (Architecture == "native") - Architecture = _config->Find("APT::Architecture"); } - /*}}}*/ -// PackagesIndex::ArchiveInfo - Short version of the archive url /*{{{*/ -// --------------------------------------------------------------------- -/* This is a shorter version that is designed to be < 60 chars or so */ -string debPackagesIndex::ArchiveInfo(pkgCache::VerIterator Ver) const +std::string debPackagesIndex::ArchiveInfo(pkgCache::VerIterator const &Ver) const { - string Res = ::URI::NoUserPassword(URI) + ' '; - if (Dist[Dist.size() - 1] == '/') + std::string Res = Target.Description; { - if (Dist != "/") - Res += Dist; + auto const space = Target.Description.rfind(' '); + if (space != std::string::npos) + Res.erase(space); } - else - Res += Dist + '/' + Section; - + Res += " "; Res += Ver.ParentPkg().Name(); Res += " "; - if (Dist[Dist.size() - 1] != '/') + 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; } - /*}}}*/ -// PackagesIndex::Describe - Give a descriptive path to the index /*{{{*/ -// --------------------------------------------------------------------- -/* This should help the user find the index in the sources.list and - in the filesystem for problem solving */ -string debPackagesIndex::Describe(bool Short) const -{ - char S[300]; - if (Short == true) - snprintf(S,sizeof(S),"%s",Info("Packages").c_str()); - else - snprintf(S,sizeof(S),"%s (%s)",Info("Packages").c_str(), - IndexFile("Packages").c_str()); - return S; +uint8_t debPackagesIndex::GetIndexFlags() const +{ + return 0; } /*}}}*/ -// PackagesIndex::Info - One liner describing the index URI /*{{{*/ -// --------------------------------------------------------------------- -/* */ -string debPackagesIndex::Info(const char *Type) const +// Translation-* Index /*{{{*/ +debTranslationsIndex::debTranslationsIndex(IndexTarget const &Target) : + pkgDebianIndexTargetFile(Target, true), d(NULL) +{} +bool debTranslationsIndex::HasPackages() const { - string Info = ::URI::NoUserPassword(URI) + ' '; - if (Dist[Dist.size() - 1] == '/') - { - if (Dist != "/") - Info += Dist; - } - else - Info += Dist + '/' + Section; - Info += " "; - if (Dist[Dist.size() - 1] != '/') - Info += Architecture + " "; - Info += Type; - return Info; + return Exists(); } - /*}}}*/ -// PackagesIndex::Index* - Return the URI to the index files /*{{{*/ -// --------------------------------------------------------------------- -/* */ -inline string debPackagesIndex::IndexFile(const char *Type) const -{ - string s =_config->FindDir("Dir::State::lists") + URItoFileName(IndexURI(Type)); - string sgzip = s + ".gz"; - if (!FileExists(s) && FileExists(sgzip)) - return sgzip; - else - return s; +bool debTranslationsIndex::OpenListFile(FileFd &Pkg, std::string const &FileName) +{ + if (FileExists(FileName)) + return pkgDebianIndexTargetFile::OpenListFile(Pkg, FileName); + return true; } -string debPackagesIndex::IndexURI(const char *Type) const +uint8_t debTranslationsIndex::GetIndexFlags() const { - string Res; - if (Dist[Dist.size() - 1] == '/') - { - if (Dist != "/") - Res = URI + Dist; - else - Res = URI; - } - else - Res = URI + "dists/" + Dist + '/' + Section + - "/binary-" + Architecture + '/'; - - Res += Type; - return Res; + return pkgCache::Flag::NotSource | pkgCache::Flag::NoPackages; } - /*}}}*/ -// PackagesIndex::Exists - Check if the index is available /*{{{*/ -// --------------------------------------------------------------------- -/* */ -bool debPackagesIndex::Exists() const +std::string debTranslationsIndex::GetArchitecture() const { - return FileExists(IndexFile("Packages")); + return std::string(); } - /*}}}*/ -// PackagesIndex::Size - Return the size of the index /*{{{*/ -// --------------------------------------------------------------------- -/* This is really only used for progress reporting. */ -unsigned long debPackagesIndex::Size() const +pkgCacheListParser * debTranslationsIndex::CreateListParser(FileFd &Pkg) { - unsigned long size = 0; - - /* we need to ignore errors here; if the lists are absent, just return 0 */ + if (Pkg.IsOpen() == false) + return nullptr; _error->PushToStack(); - - FileFd f(IndexFile("Packages"), FileFd::ReadOnly, FileFd::Extension); - if (!f.Failed()) - size = f.Size(); - - if (_error->PendingError() == true) - size = 0; - _error->RevertToStack(); - - return size; -} - /*}}}*/ -// PackagesIndex::Merge - Load the index file into a cache /*{{{*/ -// --------------------------------------------------------------------- -/* */ -bool debPackagesIndex::Merge(pkgCacheGenerator &Gen,OpProgress *Prog) const -{ - string PackageFile = IndexFile("Packages"); - FileFd Pkg(PackageFile,FileFd::ReadOnly, FileFd::Extension); - debListParser Parser(&Pkg, Architecture); - - if (_error->PendingError() == true) - return _error->Error("Problem opening %s",PackageFile.c_str()); - if (Prog != NULL) - Prog->SubProgress(0,Info("Packages")); - ::URI Tmp(URI); - if (Gen.SelectFile(PackageFile,Tmp.Host,*this) == false) - return _error->Error("Problem with SelectFile %s",PackageFile.c_str()); - - // Store the IMS information - pkgCache::PkgFileIterator File = Gen.GetCurFile(); - pkgCacheGenerator::Dynamic DynFile(File); - File->Size = Pkg.FileSize(); - File->mtime = Pkg.ModificationTime(); - - if (Gen.MergeList(Parser) == false) - return _error->Error("Problem with MergeList %s",PackageFile.c_str()); - - // Check the release file - string ReleaseFile = debReleaseIndex(URI,Dist).MetaIndexFile("InRelease"); - bool releaseExists = false; - if (FileExists(ReleaseFile) == true) - releaseExists = true; - else - ReleaseFile = debReleaseIndex(URI,Dist).MetaIndexFile("Release"); - - if (releaseExists == true || FileExists(ReleaseFile) == true) + pkgCacheListParser * const Parser = new debTranslationsParser(&Pkg); + bool const newError = _error->PendingError(); + _error->MergeWithStack(); + if (newError) { - FileFd Rel; - // Beware: The 'Release' file might be clearsigned in case the - // signature for an 'InRelease' file couldn't be checked - if (OpenMaybeClearSignedFile(ReleaseFile, Rel) == false) - return false; - - if (_error->PendingError() == true) - return false; - Parser.LoadReleaseInfo(File,Rel,Section); + delete Parser; + return nullptr; } - - return true; + else + return Parser; } /*}}}*/ -// PackagesIndex::FindInCache - Find this index /*{{{*/ -// --------------------------------------------------------------------- -/* */ -pkgCache::PkgFileIterator debPackagesIndex::FindInCache(pkgCache &Cache) const +// dpkg/status Index /*{{{*/ +debStatusIndex::debStatusIndex(std::string const &File) : pkgDebianIndexRealFile(File, true), d(NULL) { - string FileName = IndexFile("Packages"); - pkgCache::PkgFileIterator File = Cache.FileBegin(); - for (; File.end() == false; ++File) - { - if (File.FileName() == NULL || FileName != File.FileName()) - continue; - - struct stat St; - if (stat(File.FileName(),&St) != 0) - { - if (_config->FindB("Debug::pkgCacheGen", false)) - std::clog << "PackagesIndex::FindInCache - stat failed on " << File.FileName() << std::endl; - return pkgCache::PkgFileIterator(Cache); - } - if ((unsigned)St.st_size != File->Size || St.st_mtime != File->mtime) - { - if (_config->FindB("Debug::pkgCacheGen", false)) - std::clog << "PackagesIndex::FindInCache - size (" << St.st_size << " <> " << File->Size - << ") or mtime (" << St.st_mtime << " <> " << File->mtime - << ") doesn't match for " << File.FileName() << std::endl; - return pkgCache::PkgFileIterator(Cache); - } - return File; - } - - return File; } - /*}}}*/ - -// TranslationsIndex::debTranslationsIndex - Contructor /*{{{*/ -// --------------------------------------------------------------------- -/* */ -debTranslationsIndex::debTranslationsIndex(string URI,string Dist,string Section, - char const * const Translation) : - pkgIndexFile(true), URI(URI), Dist(Dist), Section(Section), - Language(Translation) -{} - /*}}}*/ -// TranslationIndex::Trans* - Return the URI to the translation files /*{{{*/ -// --------------------------------------------------------------------- -/* */ -inline string debTranslationsIndex::IndexFile(const char *Type) const -{ - string s =_config->FindDir("Dir::State::lists") + URItoFileName(IndexURI(Type)); - string sgzip = s + ".gz"; - if (!FileExists(s) && FileExists(sgzip)) - return sgzip; - else - return s; -} -string debTranslationsIndex::IndexURI(const char *Type) const +std::string debStatusIndex::GetArchitecture() const { - string Res; - if (Dist[Dist.size() - 1] == '/') - { - if (Dist != "/") - Res = URI + Dist; - else - Res = URI; - } - else - Res = URI + "dists/" + Dist + '/' + Section + - "/i18n/Translation-"; - - Res += Type; - return Res; + return std::string(); } - /*}}}*/ -// TranslationsIndex::GetIndexes - Fetch the index files /*{{{*/ -// --------------------------------------------------------------------- -/* */ -bool debTranslationsIndex::GetIndexes(pkgAcquire *Owner) const -{ - string const TranslationFile = string("Translation-").append(Language); - new pkgAcqIndexTrans(Owner, IndexURI(Language), - Info(TranslationFile.c_str()), - TranslationFile); - - return true; +std::string debStatusIndex::GetComponent() const +{ + return "now"; } - /*}}}*/ -// TranslationsIndex::Describe - Give a descriptive path to the index /*{{{*/ -// --------------------------------------------------------------------- -/* This should help the user find the index in the sources.list and - in the filesystem for problem solving */ -string debTranslationsIndex::Describe(bool Short) const -{ - char S[300]; - if (Short == true) - snprintf(S,sizeof(S),"%s",Info(TranslationFile().c_str()).c_str()); - else - snprintf(S,sizeof(S),"%s (%s)",Info(TranslationFile().c_str()).c_str(), - IndexFile(Language).c_str()); - return S; +uint8_t debStatusIndex::GetIndexFlags() const +{ + return pkgCache::Flag::NotSource; } - /*}}}*/ -// TranslationsIndex::Info - One liner describing the index URI /*{{{*/ -// --------------------------------------------------------------------- -/* */ -string debTranslationsIndex::Info(const char *Type) const + +pkgCacheListParser * debStatusIndex::CreateListParser(FileFd &Pkg) { - string Info = ::URI::NoUserPassword(URI) + ' '; - if (Dist[Dist.size() - 1] == '/') + if (Pkg.IsOpen() == false) + return nullptr; + _error->PushToStack(); + pkgCacheListParser * const Parser = new debStatusListParser(&Pkg); + bool const newError = _error->PendingError(); + _error->MergeWithStack(); + if (newError) { - if (Dist != "/") - Info += Dist; + delete Parser; + return nullptr; } else - Info += Dist + '/' + Section; - Info += " "; - Info += Type; - return Info; + return Parser; } /*}}}*/ -bool debTranslationsIndex::HasPackages() const /*{{{*/ +// DebPkgFile Index - a single .deb file as an index /*{{{*/ +debDebPkgFileIndex::debDebPkgFileIndex(std::string const &DebFile) + : pkgDebianIndexRealFile(DebFile, true), d(NULL), DebFile(DebFile) { - return FileExists(IndexFile(Language)); } - /*}}}*/ -// TranslationsIndex::Exists - Check if the index is available /*{{{*/ -// --------------------------------------------------------------------- -/* */ -bool debTranslationsIndex::Exists() const -{ - return FileExists(IndexFile(Language)); -} - /*}}}*/ -// TranslationsIndex::Size - Return the size of the index /*{{{*/ -// --------------------------------------------------------------------- -/* This is really only used for progress reporting. */ -unsigned long debTranslationsIndex::Size() const +bool debDebPkgFileIndex::GetContent(std::ostream &content, std::string const &debfile) { - unsigned long size = 0; - - /* we need to ignore errors here; if the lists are absent, just return 0 */ - _error->PushToStack(); + struct stat Buf; + if (stat(debfile.c_str(), &Buf) != 0) + return false; - FileFd f(IndexFile(Language), FileFd::ReadOnly, FileFd::Extension); - if (!f.Failed()) - size = f.Size(); + // 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 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"); - if (_error->PendingError() == true) - size = 0; - _error->RevertToStack(); + content << "Filename: " << debfile << "\n"; + content << "Size: " << std::to_string(Buf.st_size) << "\n"; + bool first_line_seen = false; + char buffer[1024]; + do { + unsigned long long actual = 0; + if (PipeFd.Read(buffer, sizeof(buffer)-1, &actual) == false) + return _error->Errno("read", "Failed to read dpkg pipe"); + if (actual == 0) + break; + buffer[actual] = '\0'; + char const * b = buffer; + if (first_line_seen == false) + { + for (; *b != '\0' && (*b == '\n' || *b == '\r'); ++b) + /* skip over leading newlines */; + if (*b == '\0') + continue; + first_line_seen = true; + } + content << b; + } while(true); + ExecWait(Child, "Popen"); - return size; + return true; } - /*}}}*/ -// TranslationsIndex::Merge - Load the index file into a cache /*{{{*/ -// --------------------------------------------------------------------- -/* */ -bool debTranslationsIndex::Merge(pkgCacheGenerator &Gen,OpProgress *Prog) const -{ - // Check the translation file, if in use - string TranslationFile = IndexFile(Language); - if (FileExists(TranslationFile)) - { - FileFd Trans(TranslationFile,FileFd::ReadOnly, FileFd::Extension); - debTranslationsParser TransParser(&Trans); - if (_error->PendingError() == true) - return false; - - if (Prog != NULL) - Prog->SubProgress(0, Info(TranslationFile.c_str())); - if (Gen.SelectFile(TranslationFile,string(),*this) == false) - return _error->Error("Problem with SelectFile %s",TranslationFile.c_str()); - - // Store the IMS information - pkgCache::PkgFileIterator TransFile = Gen.GetCurFile(); - TransFile->Size = Trans.FileSize(); - TransFile->mtime = Trans.ModificationTime(); - - if (Gen.MergeList(TransParser) == false) - return _error->Error("Problem with MergeList %s",TranslationFile.c_str()); - } - +bool debDebPkgFileIndex::OpenListFile(FileFd &Pkg, std::string const &FileName) +{ + // write the control data to a tempfile + if (GetTempFile("deb-file-" + 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; } - /*}}}*/ -// TranslationsIndex::FindInCache - Find this index /*{{{*/ -// --------------------------------------------------------------------- -/* */ -pkgCache::PkgFileIterator debTranslationsIndex::FindInCache(pkgCache &Cache) const +pkgCacheListParser * debDebPkgFileIndex::CreateListParser(FileFd &Pkg) { - string FileName = IndexFile(Language); - - pkgCache::PkgFileIterator File = Cache.FileBegin(); - for (; File.end() == false; ++File) + if (Pkg.IsOpen() == false) + return nullptr; + _error->PushToStack(); + pkgCacheListParser * const Parser = new debDebFileParser(&Pkg, DebFile); + bool const newError = _error->PendingError(); + _error->MergeWithStack(); + if (newError) { - if (FileName != File.FileName()) - continue; - - struct stat St; - if (stat(File.FileName(),&St) != 0) - { - if (_config->FindB("Debug::pkgCacheGen", false)) - std::clog << "TranslationIndex::FindInCache - stat failed on " << File.FileName() << std::endl; - return pkgCache::PkgFileIterator(Cache); - } - if ((unsigned)St.st_size != File->Size || St.st_mtime != File->mtime) - { - if (_config->FindB("Debug::pkgCacheGen", false)) - std::clog << "TranslationIndex::FindInCache - size (" << St.st_size << " <> " << File->Size - << ") or mtime (" << St.st_mtime << " <> " << File->mtime - << ") doesn't match for " << File.FileName() << std::endl; - return pkgCache::PkgFileIterator(Cache); - } - return File; - } - return File; + delete Parser; + return nullptr; + } + else + return Parser; } - /*}}}*/ -// StatusIndex::debStatusIndex - Constructor /*{{{*/ -// --------------------------------------------------------------------- -/* */ -debStatusIndex::debStatusIndex(string File) : pkgIndexFile(true), File(File) +uint8_t debDebPkgFileIndex::GetIndexFlags() const { + return pkgCache::Flag::LocalSource; } - /*}}}*/ -// StatusIndex::Size - Return the size of the index /*{{{*/ -// --------------------------------------------------------------------- -/* */ -unsigned long debStatusIndex::Size() const +std::string debDebPkgFileIndex::GetArchitecture() const { - struct stat S; - if (stat(File.c_str(),&S) != 0) - return 0; - return S.st_size; + return std::string(); } - /*}}}*/ -// StatusIndex::Merge - Load the index file into a cache /*{{{*/ -// --------------------------------------------------------------------- -/* */ -bool debStatusIndex::Merge(pkgCacheGenerator &Gen,OpProgress *Prog) const +std::string debDebPkgFileIndex::GetComponent() const { - FileFd Pkg(File,FileFd::ReadOnly, FileFd::Extension); - if (_error->PendingError() == true) - return false; - debListParser Parser(&Pkg); - if (_error->PendingError() == true) - return false; - - if (Prog != NULL) - Prog->SubProgress(0,File); - if (Gen.SelectFile(File,string(),*this,pkgCache::Flag::NotSource) == false) - return _error->Error("Problem with SelectFile %s",File.c_str()); - - // Store the IMS information - pkgCache::PkgFileIterator CFile = Gen.GetCurFile(); - CFile->Size = Pkg.FileSize(); - CFile->mtime = Pkg.ModificationTime(); - map_stringitem_t const storage = Gen.WriteUniqString("now"); - CFile->Archive = storage; - - if (Gen.MergeList(Parser) == false) - return _error->Error("Problem with MergeList %s",File.c_str()); - return true; + return "local-deb"; } - /*}}}*/ -// StatusIndex::FindInCache - Find this index /*{{{*/ -// --------------------------------------------------------------------- -/* */ -pkgCache::PkgFileIterator debStatusIndex::FindInCache(pkgCache &Cache) const +pkgCache::PkgFileIterator debDebPkgFileIndex::FindInCache(pkgCache &Cache) const { + std::string const FileName = IndexFileName(); pkgCache::PkgFileIterator File = Cache.FileBegin(); for (; File.end() == false; ++File) { - if (this->File != File.FileName()) + if (File.FileName() == NULL || FileName != File.FileName()) continue; - - struct stat St; - if (stat(File.FileName(),&St) != 0) - { - if (_config->FindB("Debug::pkgCacheGen", false)) - std::clog << "StatusIndex::FindInCache - stat failed on " << File.FileName() << std::endl; - return pkgCache::PkgFileIterator(Cache); - } - if ((unsigned)St.st_size != File->Size || St.st_mtime != File->mtime) - { - if (_config->FindB("Debug::pkgCacheGen", false)) - std::clog << "StatusIndex::FindInCache - size (" << St.st_size << " <> " << File->Size - << ") or mtime (" << St.st_mtime << " <> " << File->mtime - << ") doesn't match for " << File.FileName() << std::endl; - return pkgCache::PkgFileIterator(Cache); - } + // we can't do size checks here as file size != content size return File; - } + } + return File; } - /*}}}*/ -// StatusIndex::Exists - Check if the index is available /*{{{*/ -// --------------------------------------------------------------------- -/* */ -APT_CONST bool debStatusIndex::Exists() const +std::string debDebPkgFileIndex::ArchiveInfo_impl(pkgCache::VerIterator const &Ver) const { - // Abort if the file does not exist. - return true; + std::string Res = IndexFileName() + " "; + Res.append(Ver.ParentPkg().Name()).append(" "); + Res.append(Ver.Arch()).append(" "); + Res.append(Ver.VerStr()); + return Res; } /*}}}*/ - -// debDebPkgFile - Single .deb file /*{{{*/ -// --------------------------------------------------------------------- -debDebPkgFileIndex::debDebPkgFileIndex(std::string DebFile) - : pkgIndexFile(true), DebFile(DebFile) +// DscFile Index - a single .dsc file as an index /*{{{*/ +debDscFileIndex::debDscFileIndex(std::string const &DscFile) + : pkgDebianIndexRealFile(DscFile, true), d(NULL) { - DebFileFullPath = flAbsPath(DebFile); } - -std::string debDebPkgFileIndex::ArchiveURI(std::string /*File*/) const +pkgSrcRecords::Parser *debDscFileIndex::CreateSrcParser() const { - return "file:" + DebFileFullPath; + if (Exists() == false) + return NULL; + return new debDscRecordParser(File, this); } - -bool debDebPkgFileIndex::Exists() const +std::string debDscFileIndex::GetComponent() const { - return FileExists(DebFile); + return "local-dsc"; } -bool debDebPkgFileIndex::Merge(pkgCacheGenerator& Gen, OpProgress* Prog) const +std::string debDscFileIndex::GetArchitecture() 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? - std::string dpkg = _config->Find("Dir::Bin::dpkg","dpkg"); - const char *Args[5] = {dpkg.c_str(), - "-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]; - 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); - 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; + return "source"; } -pkgCache::PkgFileIterator debDebPkgFileIndex::FindInCache(pkgCache &Cache) const +uint8_t debDscFileIndex::GetIndexFlags() 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; + return pkgCache::Flag::LocalSource; } -unsigned long debDebPkgFileIndex::Size() const + /*}}}*/ +// ControlFile Index - a directory with a debian/control file /*{{{*/ +std::string debDebianSourceDirIndex::GetComponent() const { - struct stat buf; - if(stat(DebFile.c_str(), &buf) != 0) - return 0; - return buf.st_size; + return "local-control"; } /*}}}*/ - -// debDscFileIndex stuff -debDscFileIndex::debDscFileIndex(std::string &DscFile) - : pkgIndexFile(true), DscFile(DscFile) +// String Package Index - a string of Packages file content /*{{{*/ +std::string debStringPackageIndex::GetArchitecture() const { + return std::string(); } - -bool debDscFileIndex::Exists() const +std::string debStringPackageIndex::GetComponent() const { - return FileExists(DscFile); + return "apt-tmp-index"; } - -unsigned long debDscFileIndex::Size() const +uint8_t debStringPackageIndex::GetIndexFlags() const { - struct stat buf; - if(stat(DscFile.c_str(), &buf) == 0) - return buf.st_size; - return 0; + return pkgCache::Flag::NotSource; } - -// DscFileIndex::CreateSrcParser - Get a parser for the .dsc file /*{{{*/ -// --------------------------------------------------------------------- -/* */ -pkgSrcRecords::Parser *debDscFileIndex::CreateSrcParser() const +const pkgIndexFile::Type *debStringPackageIndex::GetType() const { - if (!FileExists(DscFile)) - return NULL; - - return new debDscRecordParser(DscFile,this); + return pkgIndexFile::Type::GetType("Debian Package Index"); +} +debStringPackageIndex::debStringPackageIndex(std::string const &content) : + pkgDebianIndexRealFile("", false), d(NULL) +{ + char fn[1024]; + std::string const tempdir = GetTempDir(); + snprintf(fn, sizeof(fn), "%s/%s.XXXXXX", tempdir.c_str(), "apt-tmp-index"); + int const fd = mkstemp(fn); + File = fn; + FileFd::Write(fd, content.data(), content.length()); + close(fd); +} +debStringPackageIndex::~debStringPackageIndex() +{ + RemoveFile("~debStringPackageIndex", File); } /*}}}*/ - - - -// --------------------------------------------------------------------- // Index File types for Debian /*{{{*/ -class debIFTypeSrc : public pkgIndexFile::Type +class APT_HIDDEN debIFTypeSrc : public pkgIndexFile::Type { public: - debIFTypeSrc() {Label = "Debian Source Index";}; }; -class debIFTypePkg : public pkgIndexFile::Type +class APT_HIDDEN debIFTypePkg : public pkgIndexFile::Type { public: - - virtual pkgRecords::Parser *CreatePkgParser(pkgCache::PkgFileIterator File) const + virtual pkgRecords::Parser *CreatePkgParser(pkgCache::PkgFileIterator const &File) const APT_OVERRIDE { return new debRecordParser(File.FileName(),*File.Cache()); }; debIFTypePkg() {Label = "Debian Package Index";}; }; -class debIFTypeTrans : public debIFTypePkg +class APT_HIDDEN debIFTypeTrans : public debIFTypePkg { public: debIFTypeTrans() {Label = "Debian Translation Index";}; }; -class debIFTypeStatus : public pkgIndexFile::Type +class APT_HIDDEN debIFTypeStatus : public pkgIndexFile::Type { public: - - virtual pkgRecords::Parser *CreatePkgParser(pkgCache::PkgFileIterator File) const + virtual pkgRecords::Parser *CreatePkgParser(pkgCache::PkgFileIterator const &File) const APT_OVERRIDE { return new debRecordParser(File.FileName(),*File.Cache()); }; debIFTypeStatus() {Label = "Debian dpkg status file";}; }; -class debIFTypeDebPkgFile : public pkgIndexFile::Type +class APT_HIDDEN debIFTypeDebPkgFile : public pkgIndexFile::Type { public: - virtual pkgRecords::Parser *CreatePkgParser(pkgCache::PkgFileIterator File) const + virtual pkgRecords::Parser *CreatePkgParser(pkgCache::PkgFileIterator const &File) const APT_OVERRIDE { - return new debDebFileRecordParser(File.FileName(),*File.Cache()); + return new debDebFileRecordParser(File.FileName()); }; - debIFTypeDebPkgFile() {Label = "deb Package file";}; + debIFTypeDebPkgFile() {Label = "Debian deb file";}; }; -class debIFTypeDscFile : public pkgIndexFile::Type +class APT_HIDDEN debIFTypeDscFile : public pkgIndexFile::Type { public: - virtual pkgSrcRecords::Parser *CreateSrcPkgParser(std::string DscFile) const + virtual pkgSrcRecords::Parser *CreateSrcPkgParser(std::string const &DscFile) const APT_OVERRIDE { return new debDscRecordParser(DscFile, NULL); }; - debIFTypeDscFile() {Label = "dsc File Source Index";}; + debIFTypeDscFile() {Label = "Debian dsc file";}; }; -class debIFTypeDebianSourceDir : public pkgIndexFile::Type +class APT_HIDDEN debIFTypeDebianSourceDir : public pkgIndexFile::Type { public: - virtual pkgSrcRecords::Parser *CreateSrcPkgParser(std::string SourceDir) const + virtual pkgSrcRecords::Parser *CreateSrcPkgParser(std::string const &SourceDir) const APT_OVERRIDE { - return new debDscRecordParser(SourceDir + string("/debian/control"), NULL); + return new debDscRecordParser(SourceDir + std::string("/debian/control"), NULL); }; - debIFTypeDebianSourceDir() {Label = "debian/control File Source Index";}; + debIFTypeDebianSourceDir() {Label = "Debian control file";}; }; -static debIFTypeSrc _apt_Src; -static debIFTypePkg _apt_Pkg; -static debIFTypeTrans _apt_Trans; -static debIFTypeStatus _apt_Status; -static debIFTypeDebPkgFile _apt_DebPkgFile; +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 -static debIFTypeDscFile _apt_DscFile; -static debIFTypeDebianSourceDir _apt_DebianSourceDir; +APT_HIDDEN debIFTypeDscFile _apt_DscFile; +APT_HIDDEN debIFTypeDebianSourceDir _apt_DebianSourceDir; const pkgIndexFile::Type *debSourcesIndex::GetType() const { @@ -893,3 +449,11 @@ const pkgIndexFile::Type *debDebianSourceDirIndex::GetType() const return &_apt_DebianSourceDir; } /*}}}*/ + +debStatusIndex::~debStatusIndex() {} +debPackagesIndex::~debPackagesIndex() {} +debTranslationsIndex::~debTranslationsIndex() {} +debSourcesIndex::~debSourcesIndex() {} + +debDebPkgFileIndex::~debDebPkgFileIndex() {} +debDscFileIndex::~debDscFileIndex() {}