You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

601 lines
19 KiB

  1. // -*- mode: cpp; mode: fold -*-
  2. // Description /*{{{*/
  3. // $Id: debindexfile.cc,v 1.5.2.3 2004/01/04 19:11:00 mdz Exp $
  4. /* ######################################################################
  5. Debian Specific sources.list types and the three sorts of Debian
  6. index files.
  7. ##################################################################### */
  8. /*}}}*/
  9. // Include Files /*{{{*/
  10. #include <config.h>
  11. #include <apt-pkg/debindexfile.h>
  12. #include <apt-pkg/debsrcrecords.h>
  13. #include <apt-pkg/deblistparser.h>
  14. #include <apt-pkg/debrecords.h>
  15. #include <apt-pkg/configuration.h>
  16. #include <apt-pkg/progress.h>
  17. #include <apt-pkg/error.h>
  18. #include <apt-pkg/strutl.h>
  19. #include <apt-pkg/acquire-item.h>
  20. #include <apt-pkg/debmetaindex.h>
  21. #include <apt-pkg/gpgv.h>
  22. #include <apt-pkg/fileutl.h>
  23. #include <apt-pkg/indexfile.h>
  24. #include <apt-pkg/mmap.h>
  25. #include <apt-pkg/pkgcache.h>
  26. #include <apt-pkg/cacheiterators.h>
  27. #include <apt-pkg/pkgcachegen.h>
  28. #include <apt-pkg/pkgrecords.h>
  29. #include <apt-pkg/srcrecords.h>
  30. #include <apt-pkg/sptr.h>
  31. #include <stdio.h>
  32. #include <iostream>
  33. #include <sstream>
  34. #include <string>
  35. #include <sys/stat.h>
  36. /*}}}*/
  37. using std::string;
  38. // SourcesIndex::debSourcesIndex - Constructor /*{{{*/
  39. // ---------------------------------------------------------------------
  40. /* */
  41. debSourcesIndex::debSourcesIndex(IndexTarget const &Target,bool const Trusted) :
  42. pkgIndexTargetFile(Target, Trusted)
  43. {
  44. }
  45. /*}}}*/
  46. // SourcesIndex::SourceInfo - Short 1 liner describing a source /*{{{*/
  47. // ---------------------------------------------------------------------
  48. /* The result looks like:
  49. http://foo/debian/ stable/main src 1.1.1 (dsc) */
  50. string debSourcesIndex::SourceInfo(pkgSrcRecords::Parser const &Record,
  51. pkgSrcRecords::File const &File) const
  52. {
  53. string Res = Target.Description;
  54. Res.erase(Target.Description.rfind(' '));
  55. Res += " ";
  56. Res += Record.Package();
  57. Res += " ";
  58. Res += Record.Version();
  59. if (File.Type.empty() == false)
  60. Res += " (" + File.Type + ")";
  61. return Res;
  62. }
  63. /*}}}*/
  64. // SourcesIndex::CreateSrcParser - Get a parser for the source files /*{{{*/
  65. // ---------------------------------------------------------------------
  66. /* */
  67. pkgSrcRecords::Parser *debSourcesIndex::CreateSrcParser() const
  68. {
  69. string const SourcesURI = IndexFileName();
  70. if (FileExists(SourcesURI))
  71. return new debSrcRecordParser(SourcesURI, this);
  72. return NULL;
  73. }
  74. /*}}}*/
  75. // PackagesIndex::debPackagesIndex - Contructor /*{{{*/
  76. // ---------------------------------------------------------------------
  77. /* */
  78. debPackagesIndex::debPackagesIndex(IndexTarget const &Target, bool const Trusted) :
  79. pkgIndexTargetFile(Target, Trusted)
  80. {
  81. }
  82. /*}}}*/
  83. // PackagesIndex::ArchiveInfo - Short version of the archive url /*{{{*/
  84. // ---------------------------------------------------------------------
  85. /* This is a shorter version that is designed to be < 60 chars or so */
  86. string debPackagesIndex::ArchiveInfo(pkgCache::VerIterator Ver) const
  87. {
  88. std::string const Dist = Target.Option(IndexTarget::RELEASE);
  89. string Res = Target.Option(IndexTarget::SITE) + " " + Dist;
  90. std::string const Component = Target.Option(IndexTarget::COMPONENT);
  91. if (Component.empty() == false)
  92. Res += "/" + Component;
  93. Res += " ";
  94. Res += Ver.ParentPkg().Name();
  95. Res += " ";
  96. if (Dist.empty() == false && Dist[Dist.size() - 1] != '/')
  97. Res.append(Ver.Arch()).append(" ");
  98. Res += Ver.VerStr();
  99. return Res;
  100. }
  101. /*}}}*/
  102. // PackagesIndex::Merge - Load the index file into a cache /*{{{*/
  103. // ---------------------------------------------------------------------
  104. /* */
  105. bool debPackagesIndex::Merge(pkgCacheGenerator &Gen,OpProgress *Prog) const
  106. {
  107. string const PackageFile = IndexFileName();
  108. FileFd Pkg(PackageFile,FileFd::ReadOnly, FileFd::Extension);
  109. debListParser Parser(&Pkg, Target.Option(IndexTarget::ARCHITECTURE));
  110. if (_error->PendingError() == true)
  111. return _error->Error("Problem opening %s",PackageFile.c_str());
  112. if (Prog != NULL)
  113. Prog->SubProgress(0, Target.Description);
  114. std::string const URI = Target.Option(IndexTarget::REPO_URI);
  115. std::string Dist = Target.Option(IndexTarget::RELEASE);
  116. if (Dist.empty())
  117. Dist = "/";
  118. ::URI Tmp(URI);
  119. if (Gen.SelectFile(PackageFile,Tmp.Host,*this) == false)
  120. return _error->Error("Problem with SelectFile %s",PackageFile.c_str());
  121. // Store the IMS information
  122. pkgCache::PkgFileIterator File = Gen.GetCurFile();
  123. pkgCacheGenerator::Dynamic<pkgCache::PkgFileIterator> DynFile(File);
  124. File->Size = Pkg.FileSize();
  125. File->mtime = Pkg.ModificationTime();
  126. if (Gen.MergeList(Parser) == false)
  127. return _error->Error("Problem with MergeList %s",PackageFile.c_str());
  128. // Check the release file
  129. string ReleaseFile = debReleaseIndex(URI,Dist).MetaIndexFile("InRelease");
  130. bool releaseExists = false;
  131. if (FileExists(ReleaseFile) == true)
  132. releaseExists = true;
  133. else
  134. ReleaseFile = debReleaseIndex(URI,Dist).MetaIndexFile("Release");
  135. if (releaseExists == true || FileExists(ReleaseFile) == true)
  136. {
  137. FileFd Rel;
  138. // Beware: The 'Release' file might be clearsigned in case the
  139. // signature for an 'InRelease' file couldn't be checked
  140. if (OpenMaybeClearSignedFile(ReleaseFile, Rel) == false)
  141. return false;
  142. if (_error->PendingError() == true)
  143. return false;
  144. Parser.LoadReleaseInfo(File, Rel, Target.Option(IndexTarget::COMPONENT));
  145. }
  146. return true;
  147. }
  148. /*}}}*/
  149. // PackagesIndex::FindInCache - Find this index /*{{{*/
  150. // ---------------------------------------------------------------------
  151. /* */
  152. pkgCache::PkgFileIterator debPackagesIndex::FindInCache(pkgCache &Cache) const
  153. {
  154. string const FileName = IndexFileName();
  155. pkgCache::PkgFileIterator File = Cache.FileBegin();
  156. for (; File.end() == false; ++File)
  157. {
  158. if (File.FileName() == NULL || FileName != File.FileName())
  159. continue;
  160. struct stat St;
  161. if (stat(File.FileName(),&St) != 0)
  162. {
  163. if (_config->FindB("Debug::pkgCacheGen", false))
  164. std::clog << "PackagesIndex::FindInCache - stat failed on " << File.FileName() << std::endl;
  165. return pkgCache::PkgFileIterator(Cache);
  166. }
  167. if ((unsigned)St.st_size != File->Size || St.st_mtime != File->mtime)
  168. {
  169. if (_config->FindB("Debug::pkgCacheGen", false))
  170. std::clog << "PackagesIndex::FindInCache - size (" << St.st_size << " <> " << File->Size
  171. << ") or mtime (" << St.st_mtime << " <> " << File->mtime
  172. << ") doesn't match for " << File.FileName() << std::endl;
  173. return pkgCache::PkgFileIterator(Cache);
  174. }
  175. return File;
  176. }
  177. return File;
  178. }
  179. /*}}}*/
  180. // TranslationsIndex::debTranslationsIndex - Contructor /*{{{*/
  181. debTranslationsIndex::debTranslationsIndex(IndexTarget const &Target) :
  182. pkgIndexTargetFile(Target, true)
  183. {}
  184. /*}}}*/
  185. bool debTranslationsIndex::HasPackages() const /*{{{*/
  186. {
  187. return Exists();
  188. }
  189. /*}}}*/
  190. // TranslationsIndex::Merge - Load the index file into a cache /*{{{*/
  191. // ---------------------------------------------------------------------
  192. /* */
  193. bool debTranslationsIndex::Merge(pkgCacheGenerator &Gen,OpProgress *Prog) const
  194. {
  195. // Check the translation file, if in use
  196. string const TranslationFile = IndexFileName();
  197. if (FileExists(TranslationFile))
  198. {
  199. FileFd Trans(TranslationFile,FileFd::ReadOnly, FileFd::Extension);
  200. debTranslationsParser TransParser(&Trans);
  201. if (_error->PendingError() == true)
  202. return false;
  203. if (Prog != NULL)
  204. Prog->SubProgress(0, Target.Description);
  205. if (Gen.SelectFile(TranslationFile,string(),*this) == false)
  206. return _error->Error("Problem with SelectFile %s",TranslationFile.c_str());
  207. // Store the IMS information
  208. pkgCache::PkgFileIterator TransFile = Gen.GetCurFile();
  209. TransFile->Size = Trans.FileSize();
  210. TransFile->mtime = Trans.ModificationTime();
  211. if (Gen.MergeList(TransParser) == false)
  212. return _error->Error("Problem with MergeList %s",TranslationFile.c_str());
  213. }
  214. return true;
  215. }
  216. /*}}}*/
  217. // TranslationsIndex::FindInCache - Find this index /*{{{*/
  218. // ---------------------------------------------------------------------
  219. /* */
  220. pkgCache::PkgFileIterator debTranslationsIndex::FindInCache(pkgCache &Cache) const
  221. {
  222. string FileName = IndexFileName();
  223. pkgCache::PkgFileIterator File = Cache.FileBegin();
  224. for (; File.end() == false; ++File)
  225. {
  226. if (FileName != File.FileName())
  227. continue;
  228. struct stat St;
  229. if (stat(File.FileName(),&St) != 0)
  230. {
  231. if (_config->FindB("Debug::pkgCacheGen", false))
  232. std::clog << "TranslationIndex::FindInCache - stat failed on " << File.FileName() << std::endl;
  233. return pkgCache::PkgFileIterator(Cache);
  234. }
  235. if ((unsigned)St.st_size != File->Size || St.st_mtime != File->mtime)
  236. {
  237. if (_config->FindB("Debug::pkgCacheGen", false))
  238. std::clog << "TranslationIndex::FindInCache - size (" << St.st_size << " <> " << File->Size
  239. << ") or mtime (" << St.st_mtime << " <> " << File->mtime
  240. << ") doesn't match for " << File.FileName() << std::endl;
  241. return pkgCache::PkgFileIterator(Cache);
  242. }
  243. return File;
  244. }
  245. return File;
  246. }
  247. /*}}}*/
  248. // StatusIndex::debStatusIndex - Constructor /*{{{*/
  249. // ---------------------------------------------------------------------
  250. /* */
  251. debStatusIndex::debStatusIndex(string File) : pkgIndexFile(true), File(File)
  252. {
  253. }
  254. /*}}}*/
  255. // StatusIndex::Size - Return the size of the index /*{{{*/
  256. // ---------------------------------------------------------------------
  257. /* */
  258. unsigned long debStatusIndex::Size() const
  259. {
  260. struct stat S;
  261. if (stat(File.c_str(),&S) != 0)
  262. return 0;
  263. return S.st_size;
  264. }
  265. /*}}}*/
  266. // StatusIndex::Merge - Load the index file into a cache /*{{{*/
  267. // ---------------------------------------------------------------------
  268. /* */
  269. bool debStatusIndex::Merge(pkgCacheGenerator &Gen,OpProgress *Prog) const
  270. {
  271. FileFd Pkg(File,FileFd::ReadOnly, FileFd::Extension);
  272. if (_error->PendingError() == true)
  273. return false;
  274. debListParser Parser(&Pkg);
  275. if (_error->PendingError() == true)
  276. return false;
  277. if (Prog != NULL)
  278. Prog->SubProgress(0,File);
  279. if (Gen.SelectFile(File,string(),*this,pkgCache::Flag::NotSource) == false)
  280. return _error->Error("Problem with SelectFile %s",File.c_str());
  281. // Store the IMS information
  282. pkgCache::PkgFileIterator CFile = Gen.GetCurFile();
  283. CFile->Size = Pkg.FileSize();
  284. CFile->mtime = Pkg.ModificationTime();
  285. map_stringitem_t const storage = Gen.StoreString(pkgCacheGenerator::MIXED, "now");
  286. CFile->Archive = storage;
  287. if (Gen.MergeList(Parser) == false)
  288. return _error->Error("Problem with MergeList %s",File.c_str());
  289. return true;
  290. }
  291. /*}}}*/
  292. // StatusIndex::FindInCache - Find this index /*{{{*/
  293. // ---------------------------------------------------------------------
  294. /* */
  295. pkgCache::PkgFileIterator debStatusIndex::FindInCache(pkgCache &Cache) const
  296. {
  297. pkgCache::PkgFileIterator File = Cache.FileBegin();
  298. for (; File.end() == false; ++File)
  299. {
  300. if (this->File != File.FileName())
  301. continue;
  302. struct stat St;
  303. if (stat(File.FileName(),&St) != 0)
  304. {
  305. if (_config->FindB("Debug::pkgCacheGen", false))
  306. std::clog << "StatusIndex::FindInCache - stat failed on " << File.FileName() << std::endl;
  307. return pkgCache::PkgFileIterator(Cache);
  308. }
  309. if ((unsigned)St.st_size != File->Size || St.st_mtime != File->mtime)
  310. {
  311. if (_config->FindB("Debug::pkgCacheGen", false))
  312. std::clog << "StatusIndex::FindInCache - size (" << St.st_size << " <> " << File->Size
  313. << ") or mtime (" << St.st_mtime << " <> " << File->mtime
  314. << ") doesn't match for " << File.FileName() << std::endl;
  315. return pkgCache::PkgFileIterator(Cache);
  316. }
  317. return File;
  318. }
  319. return File;
  320. }
  321. /*}}}*/
  322. // StatusIndex::Exists - Check if the index is available /*{{{*/
  323. // ---------------------------------------------------------------------
  324. /* */
  325. APT_CONST bool debStatusIndex::Exists() const
  326. {
  327. // Abort if the file does not exist.
  328. return true;
  329. }
  330. /*}}}*/
  331. // debDebPkgFile - Single .deb file /*{{{*/
  332. debDebPkgFileIndex::debDebPkgFileIndex(std::string DebFile)
  333. : pkgIndexFile(true), DebFile(DebFile)
  334. {
  335. DebFileFullPath = flAbsPath(DebFile);
  336. }
  337. std::string debDebPkgFileIndex::ArchiveURI(std::string /*File*/) const
  338. {
  339. return "file:" + DebFileFullPath;
  340. }
  341. bool debDebPkgFileIndex::Exists() const
  342. {
  343. return FileExists(DebFile);
  344. }
  345. bool debDebPkgFileIndex::GetContent(std::ostream &content, std::string const &debfile)
  346. {
  347. // get the control data out of the deb file via dpkg-deb -I
  348. std::string dpkg = _config->Find("Dir::Bin::dpkg","dpkg-deb");
  349. std::vector<const char *> Args;
  350. Args.push_back(dpkg.c_str());
  351. Args.push_back("-I");
  352. Args.push_back(debfile.c_str());
  353. Args.push_back("control");
  354. Args.push_back(NULL);
  355. FileFd PipeFd;
  356. pid_t Child;
  357. if(Popen((const char**)&Args[0], PipeFd, Child, FileFd::ReadOnly) == false)
  358. return _error->Error("Popen failed");
  359. char buffer[1024];
  360. do {
  361. unsigned long long actual = 0;
  362. if (PipeFd.Read(buffer, sizeof(buffer)-1, &actual) == false)
  363. return _error->Errno("read", "Failed to read dpkg pipe");
  364. if (actual == 0)
  365. break;
  366. buffer[actual] = '\0';
  367. content << buffer;
  368. } while(true);
  369. ExecWait(Child, "Popen");
  370. content << "Filename: " << debfile << "\n";
  371. struct stat Buf;
  372. if (stat(debfile.c_str(), &Buf) != 0)
  373. return false;
  374. content << "Size: " << Buf.st_size << "\n";
  375. return true;
  376. }
  377. bool debDebPkgFileIndex::Merge(pkgCacheGenerator& Gen, OpProgress* Prog) const
  378. {
  379. if(Prog)
  380. Prog->SubProgress(0, "Reading deb file");
  381. // write the control data to a tempfile
  382. SPtr<FileFd> DebControl = GetTempFile("deb-file-" + flNotDir(DebFile));
  383. if(DebControl == NULL)
  384. return false;
  385. std::ostringstream content;
  386. if (GetContent(content, DebFile) == false)
  387. return false;
  388. std::string const contentstr = content.str();
  389. DebControl->Write(contentstr.c_str(), contentstr.length());
  390. // rewind for the listparser
  391. DebControl->Seek(0);
  392. // and give it to the list parser
  393. debDebFileParser Parser(DebControl, DebFile);
  394. if(Gen.SelectFile(DebFile, "local", *this, pkgCache::Flag::LocalSource) == false)
  395. return _error->Error("Problem with SelectFile %s", DebFile.c_str());
  396. pkgCache::PkgFileIterator File = Gen.GetCurFile();
  397. File->Size = DebControl->Size();
  398. File->mtime = DebControl->ModificationTime();
  399. if (Gen.MergeList(Parser) == false)
  400. return _error->Error("Problem with MergeLister for %s", DebFile.c_str());
  401. return true;
  402. }
  403. pkgCache::PkgFileIterator debDebPkgFileIndex::FindInCache(pkgCache &Cache) const
  404. {
  405. pkgCache::PkgFileIterator File = Cache.FileBegin();
  406. for (; File.end() == false; ++File)
  407. {
  408. if (File.FileName() == NULL || DebFile != File.FileName())
  409. continue;
  410. return File;
  411. }
  412. return File;
  413. }
  414. unsigned long debDebPkgFileIndex::Size() const
  415. {
  416. struct stat buf;
  417. if(stat(DebFile.c_str(), &buf) != 0)
  418. return 0;
  419. return buf.st_size;
  420. }
  421. /*}}}*/
  422. // debDscFileIndex stuff
  423. debDscFileIndex::debDscFileIndex(std::string &DscFile)
  424. : pkgIndexFile(true), DscFile(DscFile)
  425. {
  426. }
  427. bool debDscFileIndex::Exists() const
  428. {
  429. return FileExists(DscFile);
  430. }
  431. unsigned long debDscFileIndex::Size() const
  432. {
  433. struct stat buf;
  434. if(stat(DscFile.c_str(), &buf) == 0)
  435. return buf.st_size;
  436. return 0;
  437. }
  438. // DscFileIndex::CreateSrcParser - Get a parser for the .dsc file /*{{{*/
  439. pkgSrcRecords::Parser *debDscFileIndex::CreateSrcParser() const
  440. {
  441. if (!FileExists(DscFile))
  442. return NULL;
  443. return new debDscRecordParser(DscFile,this);
  444. }
  445. /*}}}*/
  446. // Index File types for Debian /*{{{*/
  447. class APT_HIDDEN debIFTypeSrc : public pkgIndexFile::Type
  448. {
  449. public:
  450. debIFTypeSrc() {Label = "Debian Source Index";};
  451. };
  452. class APT_HIDDEN debIFTypePkg : public pkgIndexFile::Type
  453. {
  454. public:
  455. virtual pkgRecords::Parser *CreatePkgParser(pkgCache::PkgFileIterator File) const
  456. {
  457. return new debRecordParser(File.FileName(),*File.Cache());
  458. };
  459. debIFTypePkg() {Label = "Debian Package Index";};
  460. };
  461. class APT_HIDDEN debIFTypeTrans : public debIFTypePkg
  462. {
  463. public:
  464. debIFTypeTrans() {Label = "Debian Translation Index";};
  465. };
  466. class APT_HIDDEN debIFTypeStatus : public pkgIndexFile::Type
  467. {
  468. public:
  469. virtual pkgRecords::Parser *CreatePkgParser(pkgCache::PkgFileIterator File) const
  470. {
  471. return new debRecordParser(File.FileName(),*File.Cache());
  472. };
  473. debIFTypeStatus() {Label = "Debian dpkg status file";};
  474. };
  475. class APT_HIDDEN debIFTypeDebPkgFile : public pkgIndexFile::Type
  476. {
  477. public:
  478. virtual pkgRecords::Parser *CreatePkgParser(pkgCache::PkgFileIterator File) const
  479. {
  480. return new debDebFileRecordParser(File.FileName());
  481. };
  482. debIFTypeDebPkgFile() {Label = "deb Package file";};
  483. };
  484. class APT_HIDDEN debIFTypeDscFile : public pkgIndexFile::Type
  485. {
  486. public:
  487. virtual pkgSrcRecords::Parser *CreateSrcPkgParser(std::string DscFile) const
  488. {
  489. return new debDscRecordParser(DscFile, NULL);
  490. };
  491. debIFTypeDscFile() {Label = "dsc File Source Index";};
  492. };
  493. class APT_HIDDEN debIFTypeDebianSourceDir : public pkgIndexFile::Type
  494. {
  495. public:
  496. virtual pkgSrcRecords::Parser *CreateSrcPkgParser(std::string SourceDir) const
  497. {
  498. return new debDscRecordParser(SourceDir + string("/debian/control"), NULL);
  499. };
  500. debIFTypeDebianSourceDir() {Label = "debian/control File Source Index";};
  501. };
  502. APT_HIDDEN debIFTypeSrc _apt_Src;
  503. APT_HIDDEN debIFTypePkg _apt_Pkg;
  504. APT_HIDDEN debIFTypeTrans _apt_Trans;
  505. APT_HIDDEN debIFTypeStatus _apt_Status;
  506. APT_HIDDEN debIFTypeDebPkgFile _apt_DebPkgFile;
  507. // file based pseudo indexes
  508. APT_HIDDEN debIFTypeDscFile _apt_DscFile;
  509. APT_HIDDEN debIFTypeDebianSourceDir _apt_DebianSourceDir;
  510. const pkgIndexFile::Type *debSourcesIndex::GetType() const
  511. {
  512. return &_apt_Src;
  513. }
  514. const pkgIndexFile::Type *debPackagesIndex::GetType() const
  515. {
  516. return &_apt_Pkg;
  517. }
  518. const pkgIndexFile::Type *debTranslationsIndex::GetType() const
  519. {
  520. return &_apt_Trans;
  521. }
  522. const pkgIndexFile::Type *debStatusIndex::GetType() const
  523. {
  524. return &_apt_Status;
  525. }
  526. const pkgIndexFile::Type *debDebPkgFileIndex::GetType() const
  527. {
  528. return &_apt_DebPkgFile;
  529. }
  530. const pkgIndexFile::Type *debDscFileIndex::GetType() const
  531. {
  532. return &_apt_DscFile;
  533. }
  534. const pkgIndexFile::Type *debDebianSourceDirIndex::GetType() const
  535. {
  536. return &_apt_DebianSourceDir;
  537. }
  538. /*}}}*/
  539. debStatusIndex::~debStatusIndex() {}
  540. debPackagesIndex::~debPackagesIndex() {}
  541. debTranslationsIndex::~debTranslationsIndex() {}
  542. debSourcesIndex::~debSourcesIndex() {}
  543. debDebPkgFileIndex::~debDebPkgFileIndex() {}