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.
 
 
 
 
 
 

575 lines
18 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), d(NULL)
  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), d(NULL)
  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, *this, Target.Option(IndexTarget::ARCHITECTURE), Target.Option(IndexTarget::COMPONENT)) == 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. return true;
  129. }
  130. /*}}}*/
  131. // PackagesIndex::FindInCache - Find this index /*{{{*/
  132. // ---------------------------------------------------------------------
  133. /* */
  134. pkgCache::PkgFileIterator debPackagesIndex::FindInCache(pkgCache &Cache) const
  135. {
  136. string const FileName = IndexFileName();
  137. pkgCache::PkgFileIterator File = Cache.FileBegin();
  138. for (; File.end() == false; ++File)
  139. {
  140. if (File.FileName() == NULL || FileName != File.FileName())
  141. continue;
  142. struct stat St;
  143. if (stat(File.FileName(),&St) != 0)
  144. {
  145. if (_config->FindB("Debug::pkgCacheGen", false))
  146. std::clog << "PackagesIndex::FindInCache - stat failed on " << File.FileName() << std::endl;
  147. return pkgCache::PkgFileIterator(Cache);
  148. }
  149. if ((unsigned)St.st_size != File->Size || St.st_mtime != File->mtime)
  150. {
  151. if (_config->FindB("Debug::pkgCacheGen", false))
  152. std::clog << "PackagesIndex::FindInCache - size (" << St.st_size << " <> " << File->Size
  153. << ") or mtime (" << St.st_mtime << " <> " << File->mtime
  154. << ") doesn't match for " << File.FileName() << std::endl;
  155. return pkgCache::PkgFileIterator(Cache);
  156. }
  157. return File;
  158. }
  159. return File;
  160. }
  161. /*}}}*/
  162. // TranslationsIndex::debTranslationsIndex - Contructor /*{{{*/
  163. debTranslationsIndex::debTranslationsIndex(IndexTarget const &Target) :
  164. pkgIndexTargetFile(Target, true), d(NULL)
  165. {}
  166. /*}}}*/
  167. bool debTranslationsIndex::HasPackages() const /*{{{*/
  168. {
  169. return Exists();
  170. }
  171. /*}}}*/
  172. // TranslationsIndex::Merge - Load the index file into a cache /*{{{*/
  173. // ---------------------------------------------------------------------
  174. /* */
  175. bool debTranslationsIndex::Merge(pkgCacheGenerator &Gen,OpProgress *Prog) const
  176. {
  177. // Check the translation file, if in use
  178. string const TranslationFile = IndexFileName();
  179. if (FileExists(TranslationFile))
  180. {
  181. FileFd Trans(TranslationFile,FileFd::ReadOnly, FileFd::Extension);
  182. debTranslationsParser TransParser(&Trans);
  183. if (_error->PendingError() == true)
  184. return false;
  185. if (Prog != NULL)
  186. Prog->SubProgress(0, Target.Description);
  187. if (Gen.SelectFile(TranslationFile, *this, "", Target.Option(IndexTarget::COMPONENT), pkgCache::Flag::NotSource | pkgCache::Flag::NoPackages) == false)
  188. return _error->Error("Problem with SelectFile %s",TranslationFile.c_str());
  189. // Store the IMS information
  190. pkgCache::PkgFileIterator TransFile = Gen.GetCurFile();
  191. TransFile->Size = Trans.FileSize();
  192. TransFile->mtime = Trans.ModificationTime();
  193. if (Gen.MergeList(TransParser) == false)
  194. return _error->Error("Problem with MergeList %s",TranslationFile.c_str());
  195. }
  196. return true;
  197. }
  198. /*}}}*/
  199. // TranslationsIndex::FindInCache - Find this index /*{{{*/
  200. // ---------------------------------------------------------------------
  201. /* */
  202. pkgCache::PkgFileIterator debTranslationsIndex::FindInCache(pkgCache &Cache) const
  203. {
  204. string FileName = IndexFileName();
  205. pkgCache::PkgFileIterator File = Cache.FileBegin();
  206. for (; File.end() == false; ++File)
  207. {
  208. if (FileName != File.FileName())
  209. continue;
  210. struct stat St;
  211. if (stat(File.FileName(),&St) != 0)
  212. {
  213. if (_config->FindB("Debug::pkgCacheGen", false))
  214. std::clog << "TranslationIndex::FindInCache - stat failed on " << File.FileName() << std::endl;
  215. return pkgCache::PkgFileIterator(Cache);
  216. }
  217. if ((unsigned)St.st_size != File->Size || St.st_mtime != File->mtime)
  218. {
  219. if (_config->FindB("Debug::pkgCacheGen", false))
  220. std::clog << "TranslationIndex::FindInCache - size (" << St.st_size << " <> " << File->Size
  221. << ") or mtime (" << St.st_mtime << " <> " << File->mtime
  222. << ") doesn't match for " << File.FileName() << std::endl;
  223. return pkgCache::PkgFileIterator(Cache);
  224. }
  225. return File;
  226. }
  227. return File;
  228. }
  229. /*}}}*/
  230. // StatusIndex::debStatusIndex - Constructor /*{{{*/
  231. // ---------------------------------------------------------------------
  232. /* */
  233. debStatusIndex::debStatusIndex(string File) : pkgIndexFile(true), d(NULL), File(File)
  234. {
  235. }
  236. /*}}}*/
  237. // StatusIndex::Size - Return the size of the index /*{{{*/
  238. // ---------------------------------------------------------------------
  239. /* */
  240. unsigned long debStatusIndex::Size() const
  241. {
  242. struct stat S;
  243. if (stat(File.c_str(),&S) != 0)
  244. return 0;
  245. return S.st_size;
  246. }
  247. /*}}}*/
  248. // StatusIndex::Merge - Load the index file into a cache /*{{{*/
  249. // ---------------------------------------------------------------------
  250. /* */
  251. bool debStatusIndex::Merge(pkgCacheGenerator &Gen,OpProgress *Prog) const
  252. {
  253. FileFd Pkg(File,FileFd::ReadOnly, FileFd::Extension);
  254. if (_error->PendingError() == true)
  255. return false;
  256. debListParser Parser(&Pkg);
  257. if (_error->PendingError() == true)
  258. return false;
  259. if (Prog != NULL)
  260. Prog->SubProgress(0,File);
  261. if (Gen.SelectFile(File, *this, "", "now", pkgCache::Flag::NotSource) == false)
  262. return _error->Error("Problem with SelectFile %s",File.c_str());
  263. // Store the IMS information
  264. pkgCache::PkgFileIterator CFile = Gen.GetCurFile();
  265. pkgCacheGenerator::Dynamic<pkgCache::PkgFileIterator> DynFile(CFile);
  266. CFile->Size = Pkg.FileSize();
  267. CFile->mtime = Pkg.ModificationTime();
  268. if (Gen.MergeList(Parser) == false)
  269. return _error->Error("Problem with MergeList %s",File.c_str());
  270. return true;
  271. }
  272. /*}}}*/
  273. // StatusIndex::FindInCache - Find this index /*{{{*/
  274. // ---------------------------------------------------------------------
  275. /* */
  276. pkgCache::PkgFileIterator debStatusIndex::FindInCache(pkgCache &Cache) const
  277. {
  278. pkgCache::PkgFileIterator File = Cache.FileBegin();
  279. for (; File.end() == false; ++File)
  280. {
  281. if (this->File != File.FileName())
  282. continue;
  283. struct stat St;
  284. if (stat(File.FileName(),&St) != 0)
  285. {
  286. if (_config->FindB("Debug::pkgCacheGen", false))
  287. std::clog << "StatusIndex::FindInCache - stat failed on " << File.FileName() << std::endl;
  288. return pkgCache::PkgFileIterator(Cache);
  289. }
  290. if ((unsigned)St.st_size != File->Size || St.st_mtime != File->mtime)
  291. {
  292. if (_config->FindB("Debug::pkgCacheGen", false))
  293. std::clog << "StatusIndex::FindInCache - size (" << St.st_size << " <> " << File->Size
  294. << ") or mtime (" << St.st_mtime << " <> " << File->mtime
  295. << ") doesn't match for " << File.FileName() << std::endl;
  296. return pkgCache::PkgFileIterator(Cache);
  297. }
  298. return File;
  299. }
  300. return File;
  301. }
  302. /*}}}*/
  303. // StatusIndex::Exists - Check if the index is available /*{{{*/
  304. // ---------------------------------------------------------------------
  305. /* */
  306. APT_CONST bool debStatusIndex::Exists() const
  307. {
  308. // Abort if the file does not exist.
  309. return true;
  310. }
  311. /*}}}*/
  312. // debDebPkgFileIndex - Single .deb file /*{{{*/
  313. debDebPkgFileIndex::debDebPkgFileIndex(std::string const &DebFile)
  314. : pkgIndexFile(true), d(NULL), DebFile(DebFile)
  315. {
  316. DebFileFullPath = flAbsPath(DebFile);
  317. }
  318. std::string debDebPkgFileIndex::ArchiveURI(std::string /*File*/) const
  319. {
  320. return "file:" + DebFileFullPath;
  321. }
  322. bool debDebPkgFileIndex::Exists() const
  323. {
  324. return FileExists(DebFile);
  325. }
  326. bool debDebPkgFileIndex::GetContent(std::ostream &content, std::string const &debfile)
  327. {
  328. // get the control data out of the deb file via dpkg-deb -I
  329. std::string dpkg = _config->Find("Dir::Bin::dpkg","dpkg-deb");
  330. std::vector<const char *> Args;
  331. Args.push_back(dpkg.c_str());
  332. Args.push_back("-I");
  333. Args.push_back(debfile.c_str());
  334. Args.push_back("control");
  335. Args.push_back(NULL);
  336. FileFd PipeFd;
  337. pid_t Child;
  338. if(Popen((const char**)&Args[0], PipeFd, Child, FileFd::ReadOnly) == false)
  339. return _error->Error("Popen failed");
  340. char buffer[1024];
  341. do {
  342. unsigned long long actual = 0;
  343. if (PipeFd.Read(buffer, sizeof(buffer)-1, &actual) == false)
  344. return _error->Errno("read", "Failed to read dpkg pipe");
  345. if (actual == 0)
  346. break;
  347. buffer[actual] = '\0';
  348. content << buffer;
  349. } while(true);
  350. ExecWait(Child, "Popen");
  351. content << "Filename: " << debfile << "\n";
  352. struct stat Buf;
  353. if (stat(debfile.c_str(), &Buf) != 0)
  354. return false;
  355. content << "Size: " << Buf.st_size << "\n";
  356. return true;
  357. }
  358. bool debDebPkgFileIndex::Merge(pkgCacheGenerator& Gen, OpProgress* Prog) const
  359. {
  360. if(Prog)
  361. Prog->SubProgress(0, "Reading deb file");
  362. // write the control data to a tempfile
  363. SPtr<FileFd> DebControl = GetTempFile("deb-file-" + flNotDir(DebFile));
  364. if(DebControl == NULL)
  365. return false;
  366. std::ostringstream content;
  367. if (GetContent(content, DebFile) == false)
  368. return false;
  369. std::string const contentstr = content.str();
  370. if (contentstr.empty())
  371. return true;
  372. DebControl->Write(contentstr.c_str(), contentstr.length());
  373. // rewind for the listparser
  374. DebControl->Seek(0);
  375. // and give it to the list parser
  376. debDebFileParser Parser(DebControl, DebFile);
  377. if(Gen.SelectFile(DebFile, *this, "", "now", pkgCache::Flag::LocalSource) == false)
  378. return _error->Error("Problem with SelectFile %s", DebFile.c_str());
  379. pkgCache::PkgFileIterator File = Gen.GetCurFile();
  380. File->Size = DebControl->Size();
  381. File->mtime = DebControl->ModificationTime();
  382. if (Gen.MergeList(Parser) == false)
  383. return _error->Error("Problem with MergeLister for %s", DebFile.c_str());
  384. return true;
  385. }
  386. pkgCache::PkgFileIterator debDebPkgFileIndex::FindInCache(pkgCache &Cache) const
  387. {
  388. pkgCache::PkgFileIterator File = Cache.FileBegin();
  389. for (; File.end() == false; ++File)
  390. {
  391. if (File.FileName() == NULL || DebFile != File.FileName())
  392. continue;
  393. return File;
  394. }
  395. return File;
  396. }
  397. unsigned long debDebPkgFileIndex::Size() const
  398. {
  399. struct stat buf;
  400. if(stat(DebFile.c_str(), &buf) != 0)
  401. return 0;
  402. return buf.st_size;
  403. }
  404. /*}}}*/
  405. // debDscFileIndex - a .dsc file /*{{{*/
  406. debDscFileIndex::debDscFileIndex(std::string const &DscFile)
  407. : pkgIndexFile(true), d(NULL), DscFile(DscFile)
  408. {
  409. }
  410. bool debDscFileIndex::Exists() const
  411. {
  412. return FileExists(DscFile);
  413. }
  414. unsigned long debDscFileIndex::Size() const
  415. {
  416. struct stat buf;
  417. if(stat(DscFile.c_str(), &buf) == 0)
  418. return buf.st_size;
  419. return 0;
  420. }
  421. pkgSrcRecords::Parser *debDscFileIndex::CreateSrcParser() const
  422. {
  423. if (!FileExists(DscFile))
  424. return NULL;
  425. return new debDscRecordParser(DscFile,this);
  426. }
  427. /*}}}*/
  428. // Index File types for Debian /*{{{*/
  429. class APT_HIDDEN debIFTypeSrc : public pkgIndexFile::Type
  430. {
  431. public:
  432. debIFTypeSrc() {Label = "Debian Source Index";};
  433. };
  434. class APT_HIDDEN debIFTypePkg : public pkgIndexFile::Type
  435. {
  436. public:
  437. virtual pkgRecords::Parser *CreatePkgParser(pkgCache::PkgFileIterator File) const APT_OVERRIDE
  438. {
  439. return new debRecordParser(File.FileName(),*File.Cache());
  440. };
  441. debIFTypePkg() {Label = "Debian Package Index";};
  442. };
  443. class APT_HIDDEN debIFTypeTrans : public debIFTypePkg
  444. {
  445. public:
  446. debIFTypeTrans() {Label = "Debian Translation Index";};
  447. };
  448. class APT_HIDDEN debIFTypeStatus : public pkgIndexFile::Type
  449. {
  450. public:
  451. virtual pkgRecords::Parser *CreatePkgParser(pkgCache::PkgFileIterator File) const APT_OVERRIDE
  452. {
  453. return new debRecordParser(File.FileName(),*File.Cache());
  454. };
  455. debIFTypeStatus() {Label = "Debian dpkg status file";};
  456. };
  457. class APT_HIDDEN debIFTypeDebPkgFile : public pkgIndexFile::Type
  458. {
  459. public:
  460. virtual pkgRecords::Parser *CreatePkgParser(pkgCache::PkgFileIterator File) const APT_OVERRIDE
  461. {
  462. return new debDebFileRecordParser(File.FileName());
  463. };
  464. debIFTypeDebPkgFile() {Label = "Debian deb file";};
  465. };
  466. class APT_HIDDEN debIFTypeDscFile : public pkgIndexFile::Type
  467. {
  468. public:
  469. virtual pkgSrcRecords::Parser *CreateSrcPkgParser(std::string DscFile) const APT_OVERRIDE
  470. {
  471. return new debDscRecordParser(DscFile, NULL);
  472. };
  473. debIFTypeDscFile() {Label = "Debian dsc file";};
  474. };
  475. class APT_HIDDEN debIFTypeDebianSourceDir : public pkgIndexFile::Type
  476. {
  477. public:
  478. virtual pkgSrcRecords::Parser *CreateSrcPkgParser(std::string SourceDir) const APT_OVERRIDE
  479. {
  480. return new debDscRecordParser(SourceDir + string("/debian/control"), NULL);
  481. };
  482. debIFTypeDebianSourceDir() {Label = "Debian control file";};
  483. };
  484. APT_HIDDEN debIFTypeSrc _apt_Src;
  485. APT_HIDDEN debIFTypePkg _apt_Pkg;
  486. APT_HIDDEN debIFTypeTrans _apt_Trans;
  487. APT_HIDDEN debIFTypeStatus _apt_Status;
  488. APT_HIDDEN debIFTypeDebPkgFile _apt_DebPkgFile;
  489. // file based pseudo indexes
  490. APT_HIDDEN debIFTypeDscFile _apt_DscFile;
  491. APT_HIDDEN debIFTypeDebianSourceDir _apt_DebianSourceDir;
  492. const pkgIndexFile::Type *debSourcesIndex::GetType() const
  493. {
  494. return &_apt_Src;
  495. }
  496. const pkgIndexFile::Type *debPackagesIndex::GetType() const
  497. {
  498. return &_apt_Pkg;
  499. }
  500. const pkgIndexFile::Type *debTranslationsIndex::GetType() const
  501. {
  502. return &_apt_Trans;
  503. }
  504. const pkgIndexFile::Type *debStatusIndex::GetType() const
  505. {
  506. return &_apt_Status;
  507. }
  508. const pkgIndexFile::Type *debDebPkgFileIndex::GetType() const
  509. {
  510. return &_apt_DebPkgFile;
  511. }
  512. const pkgIndexFile::Type *debDscFileIndex::GetType() const
  513. {
  514. return &_apt_DscFile;
  515. }
  516. const pkgIndexFile::Type *debDebianSourceDirIndex::GetType() const
  517. {
  518. return &_apt_DebianSourceDir;
  519. }
  520. /*}}}*/
  521. debStatusIndex::~debStatusIndex() {}
  522. debPackagesIndex::~debPackagesIndex() {}
  523. debTranslationsIndex::~debTranslationsIndex() {}
  524. debSourcesIndex::~debSourcesIndex() {}
  525. debDebPkgFileIndex::~debDebPkgFileIndex() {}
  526. debDscFileIndex::~debDscFileIndex() {}