debindexfile.cc 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909
  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 <string>
  34. #include <sys/stat.h>
  35. /*}}}*/
  36. using std::string;
  37. // SourcesIndex::debSourcesIndex - Constructor /*{{{*/
  38. // ---------------------------------------------------------------------
  39. /* */
  40. debSourcesIndex::debSourcesIndex(string URI,string Dist,string Section,bool Trusted) :
  41. pkgIndexFile(Trusted), URI(URI), Dist(Dist), Section(Section)
  42. {
  43. }
  44. /*}}}*/
  45. // SourcesIndex::SourceInfo - Short 1 liner describing a source /*{{{*/
  46. // ---------------------------------------------------------------------
  47. /* The result looks like:
  48. http://foo/debian/ stable/main src 1.1.1 (dsc) */
  49. string debSourcesIndex::SourceInfo(pkgSrcRecords::Parser const &Record,
  50. pkgSrcRecords::File const &File) const
  51. {
  52. string Res;
  53. Res = ::URI::NoUserPassword(URI) + ' ';
  54. if (Dist[Dist.size() - 1] == '/')
  55. {
  56. if (Dist != "/")
  57. Res += Dist;
  58. }
  59. else
  60. Res += Dist + '/' + Section;
  61. Res += " ";
  62. Res += Record.Package();
  63. Res += " ";
  64. Res += Record.Version();
  65. if (File.Type.empty() == false)
  66. Res += " (" + File.Type + ")";
  67. return Res;
  68. }
  69. /*}}}*/
  70. // SourcesIndex::CreateSrcParser - Get a parser for the source files /*{{{*/
  71. // ---------------------------------------------------------------------
  72. /* */
  73. pkgSrcRecords::Parser *debSourcesIndex::CreateSrcParser() const
  74. {
  75. string SourcesURI = _config->FindDir("Dir::State::lists") +
  76. URItoFileName(IndexURI("Sources"));
  77. std::vector<std::string> types = APT::Configuration::getCompressionTypes();
  78. for (std::vector<std::string>::const_iterator t = types.begin(); t != types.end(); ++t)
  79. {
  80. string p;
  81. p = SourcesURI + '.' + *t;
  82. if (FileExists(p))
  83. return new debSrcRecordParser(p, this);
  84. }
  85. if (FileExists(SourcesURI))
  86. return new debSrcRecordParser(SourcesURI, this);
  87. return NULL;
  88. }
  89. /*}}}*/
  90. // SourcesIndex::Describe - Give a descriptive path to the index /*{{{*/
  91. // ---------------------------------------------------------------------
  92. /* */
  93. string debSourcesIndex::Describe(bool Short) const
  94. {
  95. char S[300];
  96. if (Short == true)
  97. snprintf(S,sizeof(S),"%s",Info("Sources").c_str());
  98. else
  99. snprintf(S,sizeof(S),"%s (%s)",Info("Sources").c_str(),
  100. IndexFile("Sources").c_str());
  101. return S;
  102. }
  103. /*}}}*/
  104. // SourcesIndex::Info - One liner describing the index URI /*{{{*/
  105. // ---------------------------------------------------------------------
  106. /* */
  107. string debSourcesIndex::Info(const char *Type) const
  108. {
  109. string Info = ::URI::NoUserPassword(URI) + ' ';
  110. if (Dist[Dist.size() - 1] == '/')
  111. {
  112. if (Dist != "/")
  113. Info += Dist;
  114. }
  115. else
  116. Info += Dist + '/' + Section;
  117. Info += " ";
  118. Info += Type;
  119. return Info;
  120. }
  121. /*}}}*/
  122. // SourcesIndex::Index* - Return the URI to the index files /*{{{*/
  123. // ---------------------------------------------------------------------
  124. /* */
  125. string debSourcesIndex::IndexFile(const char *Type) const
  126. {
  127. string s = URItoFileName(IndexURI(Type));
  128. std::vector<std::string> types = APT::Configuration::getCompressionTypes();
  129. for (std::vector<std::string>::const_iterator t = types.begin(); t != types.end(); ++t)
  130. {
  131. string p = s + '.' + *t;
  132. if (FileExists(p))
  133. return p;
  134. }
  135. return s;
  136. }
  137. string debSourcesIndex::IndexURI(const char *Type) const
  138. {
  139. string Res;
  140. if (Dist[Dist.size() - 1] == '/')
  141. {
  142. if (Dist != "/")
  143. Res = URI + Dist;
  144. else
  145. Res = URI;
  146. }
  147. else
  148. Res = URI + "dists/" + Dist + '/' + Section +
  149. "/source/";
  150. Res += Type;
  151. return Res;
  152. }
  153. /*}}}*/
  154. // SourcesIndex::Exists - Check if the index is available /*{{{*/
  155. // ---------------------------------------------------------------------
  156. /* */
  157. bool debSourcesIndex::Exists() const
  158. {
  159. return FileExists(IndexFile("Sources"));
  160. }
  161. /*}}}*/
  162. // SourcesIndex::Size - Return the size of the index /*{{{*/
  163. // ---------------------------------------------------------------------
  164. /* */
  165. unsigned long debSourcesIndex::Size() const
  166. {
  167. unsigned long size = 0;
  168. /* we need to ignore errors here; if the lists are absent, just return 0 */
  169. _error->PushToStack();
  170. FileFd f(IndexFile("Sources"), FileFd::ReadOnly, FileFd::Extension);
  171. if (!f.Failed())
  172. size = f.Size();
  173. if (_error->PendingError() == true)
  174. size = 0;
  175. _error->RevertToStack();
  176. return size;
  177. }
  178. /*}}}*/
  179. // PackagesIndex::debPackagesIndex - Contructor /*{{{*/
  180. // ---------------------------------------------------------------------
  181. /* */
  182. debPackagesIndex::debPackagesIndex(string const &URI, string const &Dist, string const &Section,
  183. bool const &Trusted, string const &Arch) :
  184. pkgIndexFile(Trusted), URI(URI), Dist(Dist), Section(Section), Architecture(Arch)
  185. {
  186. if (Architecture == "native")
  187. Architecture = _config->Find("APT::Architecture");
  188. }
  189. /*}}}*/
  190. // PackagesIndex::ArchiveInfo - Short version of the archive url /*{{{*/
  191. // ---------------------------------------------------------------------
  192. /* This is a shorter version that is designed to be < 60 chars or so */
  193. string debPackagesIndex::ArchiveInfo(pkgCache::VerIterator Ver) const
  194. {
  195. string Res = ::URI::NoUserPassword(URI) + ' ';
  196. if (Dist[Dist.size() - 1] == '/')
  197. {
  198. if (Dist != "/")
  199. Res += Dist;
  200. }
  201. else
  202. Res += Dist + '/' + Section;
  203. Res += " ";
  204. Res += Ver.ParentPkg().Name();
  205. Res += " ";
  206. if (Dist[Dist.size() - 1] != '/')
  207. Res.append(Ver.Arch()).append(" ");
  208. Res += Ver.VerStr();
  209. return Res;
  210. }
  211. /*}}}*/
  212. // PackagesIndex::Describe - Give a descriptive path to the index /*{{{*/
  213. // ---------------------------------------------------------------------
  214. /* This should help the user find the index in the sources.list and
  215. in the filesystem for problem solving */
  216. string debPackagesIndex::Describe(bool Short) const
  217. {
  218. char S[300];
  219. if (Short == true)
  220. snprintf(S,sizeof(S),"%s",Info("Packages").c_str());
  221. else
  222. snprintf(S,sizeof(S),"%s (%s)",Info("Packages").c_str(),
  223. IndexFile("Packages").c_str());
  224. return S;
  225. }
  226. /*}}}*/
  227. // PackagesIndex::Info - One liner describing the index URI /*{{{*/
  228. // ---------------------------------------------------------------------
  229. /* */
  230. string debPackagesIndex::Info(const char *Type) const
  231. {
  232. string Info = ::URI::NoUserPassword(URI) + ' ';
  233. if (Dist[Dist.size() - 1] == '/')
  234. {
  235. if (Dist != "/")
  236. Info += Dist;
  237. }
  238. else
  239. Info += Dist + '/' + Section;
  240. Info += " ";
  241. if (Dist[Dist.size() - 1] != '/')
  242. Info += Architecture + " ";
  243. Info += Type;
  244. return Info;
  245. }
  246. /*}}}*/
  247. // PackagesIndex::Index* - Return the URI to the index files /*{{{*/
  248. // ---------------------------------------------------------------------
  249. /* */
  250. string debPackagesIndex::IndexFile(const char *Type) const
  251. {
  252. string s =_config->FindDir("Dir::State::lists") + URItoFileName(IndexURI(Type));
  253. std::vector<std::string> types = APT::Configuration::getCompressionTypes();
  254. for (std::vector<std::string>::const_iterator t = types.begin(); t != types.end(); ++t)
  255. {
  256. string p = s + '.' + *t;
  257. if (FileExists(p))
  258. return p;
  259. }
  260. return s;
  261. }
  262. string debPackagesIndex::IndexURI(const char *Type) const
  263. {
  264. string Res;
  265. if (Dist[Dist.size() - 1] == '/')
  266. {
  267. if (Dist != "/")
  268. Res = URI + Dist;
  269. else
  270. Res = URI;
  271. }
  272. else
  273. Res = URI + "dists/" + Dist + '/' + Section +
  274. "/binary-" + Architecture + '/';
  275. Res += Type;
  276. return Res;
  277. }
  278. /*}}}*/
  279. // PackagesIndex::Exists - Check if the index is available /*{{{*/
  280. // ---------------------------------------------------------------------
  281. /* */
  282. bool debPackagesIndex::Exists() const
  283. {
  284. return FileExists(IndexFile("Packages"));
  285. }
  286. /*}}}*/
  287. // PackagesIndex::Size - Return the size of the index /*{{{*/
  288. // ---------------------------------------------------------------------
  289. /* This is really only used for progress reporting. */
  290. unsigned long debPackagesIndex::Size() const
  291. {
  292. unsigned long size = 0;
  293. /* we need to ignore errors here; if the lists are absent, just return 0 */
  294. _error->PushToStack();
  295. FileFd f(IndexFile("Packages"), FileFd::ReadOnly, FileFd::Extension);
  296. if (!f.Failed())
  297. size = f.Size();
  298. if (_error->PendingError() == true)
  299. size = 0;
  300. _error->RevertToStack();
  301. return size;
  302. }
  303. /*}}}*/
  304. // PackagesIndex::Merge - Load the index file into a cache /*{{{*/
  305. // ---------------------------------------------------------------------
  306. /* */
  307. bool debPackagesIndex::Merge(pkgCacheGenerator &Gen,OpProgress *Prog) const
  308. {
  309. string PackageFile = IndexFile("Packages");
  310. FileFd Pkg(PackageFile,FileFd::ReadOnly, FileFd::Extension);
  311. debListParser Parser(&Pkg, Architecture);
  312. if (_error->PendingError() == true)
  313. return _error->Error("Problem opening %s",PackageFile.c_str());
  314. if (Prog != NULL)
  315. Prog->SubProgress(0,Info("Packages"));
  316. ::URI Tmp(URI);
  317. if (Gen.SelectFile(PackageFile,Tmp.Host,*this) == false)
  318. return _error->Error("Problem with SelectFile %s",PackageFile.c_str());
  319. // Store the IMS information
  320. pkgCache::PkgFileIterator File = Gen.GetCurFile();
  321. pkgCacheGenerator::Dynamic<pkgCache::PkgFileIterator> DynFile(File);
  322. File->Size = Pkg.FileSize();
  323. File->mtime = Pkg.ModificationTime();
  324. if (Gen.MergeList(Parser) == false)
  325. return _error->Error("Problem with MergeList %s",PackageFile.c_str());
  326. // Check the release file
  327. string ReleaseFile = debReleaseIndex(URI,Dist).MetaIndexFile("InRelease");
  328. bool releaseExists = false;
  329. if (FileExists(ReleaseFile) == true)
  330. releaseExists = true;
  331. else
  332. ReleaseFile = debReleaseIndex(URI,Dist).MetaIndexFile("Release");
  333. if (releaseExists == true || FileExists(ReleaseFile) == true)
  334. {
  335. FileFd Rel;
  336. // Beware: The 'Release' file might be clearsigned in case the
  337. // signature for an 'InRelease' file couldn't be checked
  338. if (OpenMaybeClearSignedFile(ReleaseFile, Rel) == false)
  339. return false;
  340. if (_error->PendingError() == true)
  341. return false;
  342. Parser.LoadReleaseInfo(File,Rel,Section);
  343. }
  344. return true;
  345. }
  346. /*}}}*/
  347. // PackagesIndex::FindInCache - Find this index /*{{{*/
  348. // ---------------------------------------------------------------------
  349. /* */
  350. pkgCache::PkgFileIterator debPackagesIndex::FindInCache(pkgCache &Cache) const
  351. {
  352. string FileName = IndexFile("Packages");
  353. pkgCache::PkgFileIterator File = Cache.FileBegin();
  354. for (; File.end() == false; ++File)
  355. {
  356. if (File.FileName() == NULL || FileName != File.FileName())
  357. continue;
  358. struct stat St;
  359. if (stat(File.FileName(),&St) != 0)
  360. {
  361. if (_config->FindB("Debug::pkgCacheGen", false))
  362. std::clog << "PackagesIndex::FindInCache - stat failed on " << File.FileName() << std::endl;
  363. return pkgCache::PkgFileIterator(Cache);
  364. }
  365. if ((unsigned)St.st_size != File->Size || St.st_mtime != File->mtime)
  366. {
  367. if (_config->FindB("Debug::pkgCacheGen", false))
  368. std::clog << "PackagesIndex::FindInCache - size (" << St.st_size << " <> " << File->Size
  369. << ") or mtime (" << St.st_mtime << " <> " << File->mtime
  370. << ") doesn't match for " << File.FileName() << std::endl;
  371. return pkgCache::PkgFileIterator(Cache);
  372. }
  373. return File;
  374. }
  375. return File;
  376. }
  377. /*}}}*/
  378. // TranslationsIndex::debTranslationsIndex - Contructor /*{{{*/
  379. // ---------------------------------------------------------------------
  380. /* */
  381. debTranslationsIndex::debTranslationsIndex(string URI,string Dist,string Section,
  382. char const * const Translation) :
  383. pkgIndexFile(true), URI(URI), Dist(Dist), Section(Section),
  384. Language(Translation)
  385. {}
  386. /*}}}*/
  387. // TranslationIndex::Trans* - Return the URI to the translation files /*{{{*/
  388. // ---------------------------------------------------------------------
  389. /* */
  390. string debTranslationsIndex::IndexFile(const char *Type) const
  391. {
  392. string s =_config->FindDir("Dir::State::lists") + URItoFileName(IndexURI(Type));
  393. std::vector<std::string> types = APT::Configuration::getCompressionTypes();
  394. for (std::vector<std::string>::const_iterator t = types.begin(); t != types.end(); ++t)
  395. {
  396. string p = s + '.' + *t;
  397. if (FileExists(p))
  398. return p;
  399. }
  400. return s;
  401. }
  402. string debTranslationsIndex::IndexURI(const char *Type) const
  403. {
  404. string Res;
  405. if (Dist[Dist.size() - 1] == '/')
  406. {
  407. if (Dist != "/")
  408. Res = URI + Dist;
  409. else
  410. Res = URI;
  411. }
  412. else
  413. Res = URI + "dists/" + Dist + '/' + Section +
  414. "/i18n/Translation-";
  415. Res += Type;
  416. return Res;
  417. }
  418. /*}}}*/
  419. // TranslationsIndex::Describe - Give a descriptive path to the index /*{{{*/
  420. // ---------------------------------------------------------------------
  421. /* This should help the user find the index in the sources.list and
  422. in the filesystem for problem solving */
  423. string debTranslationsIndex::Describe(bool Short) const
  424. {
  425. char S[300];
  426. if (Short == true)
  427. snprintf(S,sizeof(S),"%s",Info(TranslationFile().c_str()).c_str());
  428. else
  429. snprintf(S,sizeof(S),"%s (%s)",Info(TranslationFile().c_str()).c_str(),
  430. IndexFile(Language).c_str());
  431. return S;
  432. }
  433. /*}}}*/
  434. // TranslationsIndex::Info - One liner describing the index URI /*{{{*/
  435. // ---------------------------------------------------------------------
  436. /* */
  437. string debTranslationsIndex::Info(const char *Type) const
  438. {
  439. string Info = ::URI::NoUserPassword(URI) + ' ';
  440. if (Dist[Dist.size() - 1] == '/')
  441. {
  442. if (Dist != "/")
  443. Info += Dist;
  444. }
  445. else
  446. Info += Dist + '/' + Section;
  447. Info += " ";
  448. Info += Type;
  449. return Info;
  450. }
  451. /*}}}*/
  452. bool debTranslationsIndex::HasPackages() const /*{{{*/
  453. {
  454. return FileExists(IndexFile(Language));
  455. }
  456. /*}}}*/
  457. // TranslationsIndex::Exists - Check if the index is available /*{{{*/
  458. // ---------------------------------------------------------------------
  459. /* */
  460. bool debTranslationsIndex::Exists() const
  461. {
  462. return FileExists(IndexFile(Language));
  463. }
  464. /*}}}*/
  465. // TranslationsIndex::Size - Return the size of the index /*{{{*/
  466. // ---------------------------------------------------------------------
  467. /* This is really only used for progress reporting. */
  468. unsigned long debTranslationsIndex::Size() const
  469. {
  470. unsigned long size = 0;
  471. /* we need to ignore errors here; if the lists are absent, just return 0 */
  472. _error->PushToStack();
  473. FileFd f(IndexFile(Language), FileFd::ReadOnly, FileFd::Extension);
  474. if (!f.Failed())
  475. size = f.Size();
  476. if (_error->PendingError() == true)
  477. size = 0;
  478. _error->RevertToStack();
  479. return size;
  480. }
  481. /*}}}*/
  482. // TranslationsIndex::Merge - Load the index file into a cache /*{{{*/
  483. // ---------------------------------------------------------------------
  484. /* */
  485. bool debTranslationsIndex::Merge(pkgCacheGenerator &Gen,OpProgress *Prog) const
  486. {
  487. // Check the translation file, if in use
  488. string TranslationFile = IndexFile(Language);
  489. if (FileExists(TranslationFile))
  490. {
  491. FileFd Trans(TranslationFile,FileFd::ReadOnly, FileFd::Extension);
  492. debTranslationsParser TransParser(&Trans);
  493. if (_error->PendingError() == true)
  494. return false;
  495. if (Prog != NULL)
  496. Prog->SubProgress(0, Info(TranslationFile.c_str()));
  497. if (Gen.SelectFile(TranslationFile,string(),*this) == false)
  498. return _error->Error("Problem with SelectFile %s",TranslationFile.c_str());
  499. // Store the IMS information
  500. pkgCache::PkgFileIterator TransFile = Gen.GetCurFile();
  501. TransFile->Size = Trans.FileSize();
  502. TransFile->mtime = Trans.ModificationTime();
  503. if (Gen.MergeList(TransParser) == false)
  504. return _error->Error("Problem with MergeList %s",TranslationFile.c_str());
  505. }
  506. return true;
  507. }
  508. /*}}}*/
  509. // TranslationsIndex::FindInCache - Find this index /*{{{*/
  510. // ---------------------------------------------------------------------
  511. /* */
  512. pkgCache::PkgFileIterator debTranslationsIndex::FindInCache(pkgCache &Cache) const
  513. {
  514. string FileName = IndexFile(Language);
  515. pkgCache::PkgFileIterator File = Cache.FileBegin();
  516. for (; File.end() == false; ++File)
  517. {
  518. if (FileName != File.FileName())
  519. continue;
  520. struct stat St;
  521. if (stat(File.FileName(),&St) != 0)
  522. {
  523. if (_config->FindB("Debug::pkgCacheGen", false))
  524. std::clog << "TranslationIndex::FindInCache - stat failed on " << File.FileName() << std::endl;
  525. return pkgCache::PkgFileIterator(Cache);
  526. }
  527. if ((unsigned)St.st_size != File->Size || St.st_mtime != File->mtime)
  528. {
  529. if (_config->FindB("Debug::pkgCacheGen", false))
  530. std::clog << "TranslationIndex::FindInCache - size (" << St.st_size << " <> " << File->Size
  531. << ") or mtime (" << St.st_mtime << " <> " << File->mtime
  532. << ") doesn't match for " << File.FileName() << std::endl;
  533. return pkgCache::PkgFileIterator(Cache);
  534. }
  535. return File;
  536. }
  537. return File;
  538. }
  539. /*}}}*/
  540. // StatusIndex::debStatusIndex - Constructor /*{{{*/
  541. // ---------------------------------------------------------------------
  542. /* */
  543. debStatusIndex::debStatusIndex(string File) : pkgIndexFile(true), File(File)
  544. {
  545. }
  546. /*}}}*/
  547. // StatusIndex::Size - Return the size of the index /*{{{*/
  548. // ---------------------------------------------------------------------
  549. /* */
  550. unsigned long debStatusIndex::Size() const
  551. {
  552. struct stat S;
  553. if (stat(File.c_str(),&S) != 0)
  554. return 0;
  555. return S.st_size;
  556. }
  557. /*}}}*/
  558. // StatusIndex::Merge - Load the index file into a cache /*{{{*/
  559. // ---------------------------------------------------------------------
  560. /* */
  561. bool debStatusIndex::Merge(pkgCacheGenerator &Gen,OpProgress *Prog) const
  562. {
  563. FileFd Pkg(File,FileFd::ReadOnly, FileFd::Extension);
  564. if (_error->PendingError() == true)
  565. return false;
  566. debListParser Parser(&Pkg);
  567. if (_error->PendingError() == true)
  568. return false;
  569. if (Prog != NULL)
  570. Prog->SubProgress(0,File);
  571. if (Gen.SelectFile(File,string(),*this,pkgCache::Flag::NotSource) == false)
  572. return _error->Error("Problem with SelectFile %s",File.c_str());
  573. // Store the IMS information
  574. pkgCache::PkgFileIterator CFile = Gen.GetCurFile();
  575. CFile->Size = Pkg.FileSize();
  576. CFile->mtime = Pkg.ModificationTime();
  577. map_stringitem_t const storage = Gen.StoreString(pkgCacheGenerator::MIXED, "now");
  578. CFile->Archive = storage;
  579. if (Gen.MergeList(Parser) == false)
  580. return _error->Error("Problem with MergeList %s",File.c_str());
  581. return true;
  582. }
  583. /*}}}*/
  584. // StatusIndex::FindInCache - Find this index /*{{{*/
  585. // ---------------------------------------------------------------------
  586. /* */
  587. pkgCache::PkgFileIterator debStatusIndex::FindInCache(pkgCache &Cache) const
  588. {
  589. pkgCache::PkgFileIterator File = Cache.FileBegin();
  590. for (; File.end() == false; ++File)
  591. {
  592. if (this->File != File.FileName())
  593. continue;
  594. struct stat St;
  595. if (stat(File.FileName(),&St) != 0)
  596. {
  597. if (_config->FindB("Debug::pkgCacheGen", false))
  598. std::clog << "StatusIndex::FindInCache - stat failed on " << File.FileName() << std::endl;
  599. return pkgCache::PkgFileIterator(Cache);
  600. }
  601. if ((unsigned)St.st_size != File->Size || St.st_mtime != File->mtime)
  602. {
  603. if (_config->FindB("Debug::pkgCacheGen", false))
  604. std::clog << "StatusIndex::FindInCache - size (" << St.st_size << " <> " << File->Size
  605. << ") or mtime (" << St.st_mtime << " <> " << File->mtime
  606. << ") doesn't match for " << File.FileName() << std::endl;
  607. return pkgCache::PkgFileIterator(Cache);
  608. }
  609. return File;
  610. }
  611. return File;
  612. }
  613. /*}}}*/
  614. // StatusIndex::Exists - Check if the index is available /*{{{*/
  615. // ---------------------------------------------------------------------
  616. /* */
  617. APT_CONST bool debStatusIndex::Exists() const
  618. {
  619. // Abort if the file does not exist.
  620. return true;
  621. }
  622. /*}}}*/
  623. // debDebPkgFile - Single .deb file /*{{{*/
  624. // ---------------------------------------------------------------------
  625. debDebPkgFileIndex::debDebPkgFileIndex(std::string DebFile)
  626. : pkgIndexFile(true), DebFile(DebFile)
  627. {
  628. DebFileFullPath = flAbsPath(DebFile);
  629. }
  630. std::string debDebPkgFileIndex::ArchiveURI(std::string /*File*/) const
  631. {
  632. return "file:" + DebFileFullPath;
  633. }
  634. bool debDebPkgFileIndex::Exists() const
  635. {
  636. return FileExists(DebFile);
  637. }
  638. bool debDebPkgFileIndex::Merge(pkgCacheGenerator& Gen, OpProgress* Prog) const
  639. {
  640. if(Prog)
  641. Prog->SubProgress(0, "Reading deb file");
  642. // get the control data out of the deb file vid dpkg -I
  643. // ... can I haz libdpkg?
  644. Configuration::Item const *Opts = _config->Tree("DPkg::Options");
  645. std::string dpkg = _config->Find("Dir::Bin::dpkg","dpkg");
  646. std::vector<const char *> Args;
  647. Args.push_back(dpkg.c_str());
  648. if (Opts != 0)
  649. {
  650. Opts = Opts->Child;
  651. for (; Opts != 0; Opts = Opts->Next)
  652. {
  653. if (Opts->Value.empty() == true)
  654. continue;
  655. Args.push_back(Opts->Value.c_str());
  656. }
  657. }
  658. Args.push_back("-I");
  659. Args.push_back(DebFile.c_str());
  660. Args.push_back("control");
  661. Args.push_back(NULL);
  662. FileFd PipeFd;
  663. pid_t Child;
  664. if(Popen((const char**)&Args[0], PipeFd, Child, FileFd::ReadOnly) == false)
  665. return _error->Error("Popen failed");
  666. // FIXME: static buffer
  667. char buf[8*1024];
  668. unsigned long long n = 0;
  669. if(PipeFd.Read(buf, sizeof(buf)-1, &n) == false)
  670. return _error->Errno("read", "Failed to read dpkg pipe");
  671. ExecWait(Child, "Popen");
  672. // now write the control data to a tempfile
  673. SPtr<FileFd> DebControl = GetTempFile("deb-file-" + flNotDir(DebFile));
  674. if(DebControl == NULL)
  675. return false;
  676. DebControl->Write(buf, n);
  677. // append size of the file
  678. FileFd Fd(DebFile, FileFd::ReadOnly);
  679. string Size;
  680. strprintf(Size, "Size: %llu\n", Fd.Size());
  681. DebControl->Write(Size.c_str(), Size.size());
  682. // and rewind for the listparser
  683. DebControl->Seek(0);
  684. // and give it to the list parser
  685. debDebFileParser Parser(DebControl, DebFile);
  686. if(Gen.SelectFile(DebFile, "local", *this) == false)
  687. return _error->Error("Problem with SelectFile %s", DebFile.c_str());
  688. pkgCache::PkgFileIterator File = Gen.GetCurFile();
  689. File->Size = DebControl->Size();
  690. File->mtime = DebControl->ModificationTime();
  691. if (Gen.MergeList(Parser) == false)
  692. return _error->Error("Problem with MergeLister for %s", DebFile.c_str());
  693. return true;
  694. }
  695. pkgCache::PkgFileIterator debDebPkgFileIndex::FindInCache(pkgCache &Cache) const
  696. {
  697. pkgCache::PkgFileIterator File = Cache.FileBegin();
  698. for (; File.end() == false; ++File)
  699. {
  700. if (File.FileName() == NULL || DebFile != File.FileName())
  701. continue;
  702. return File;
  703. }
  704. return File;
  705. }
  706. unsigned long debDebPkgFileIndex::Size() const
  707. {
  708. struct stat buf;
  709. if(stat(DebFile.c_str(), &buf) != 0)
  710. return 0;
  711. return buf.st_size;
  712. }
  713. /*}}}*/
  714. // debDscFileIndex stuff
  715. debDscFileIndex::debDscFileIndex(std::string &DscFile)
  716. : pkgIndexFile(true), DscFile(DscFile)
  717. {
  718. }
  719. bool debDscFileIndex::Exists() const
  720. {
  721. return FileExists(DscFile);
  722. }
  723. unsigned long debDscFileIndex::Size() const
  724. {
  725. struct stat buf;
  726. if(stat(DscFile.c_str(), &buf) == 0)
  727. return buf.st_size;
  728. return 0;
  729. }
  730. // DscFileIndex::CreateSrcParser - Get a parser for the .dsc file /*{{{*/
  731. pkgSrcRecords::Parser *debDscFileIndex::CreateSrcParser() const
  732. {
  733. if (!FileExists(DscFile))
  734. return NULL;
  735. return new debDscRecordParser(DscFile,this);
  736. }
  737. /*}}}*/
  738. // Index File types for Debian /*{{{*/
  739. class APT_HIDDEN debIFTypeSrc : public pkgIndexFile::Type
  740. {
  741. public:
  742. debIFTypeSrc() {Label = "Debian Source Index";};
  743. };
  744. class APT_HIDDEN debIFTypePkg : public pkgIndexFile::Type
  745. {
  746. public:
  747. virtual pkgRecords::Parser *CreatePkgParser(pkgCache::PkgFileIterator File) const
  748. {
  749. return new debRecordParser(File.FileName(),*File.Cache());
  750. };
  751. debIFTypePkg() {Label = "Debian Package Index";};
  752. };
  753. class APT_HIDDEN debIFTypeTrans : public debIFTypePkg
  754. {
  755. public:
  756. debIFTypeTrans() {Label = "Debian Translation Index";};
  757. };
  758. class APT_HIDDEN debIFTypeStatus : public pkgIndexFile::Type
  759. {
  760. public:
  761. virtual pkgRecords::Parser *CreatePkgParser(pkgCache::PkgFileIterator File) const
  762. {
  763. return new debRecordParser(File.FileName(),*File.Cache());
  764. };
  765. debIFTypeStatus() {Label = "Debian dpkg status file";};
  766. };
  767. class APT_HIDDEN debIFTypeDebPkgFile : public pkgIndexFile::Type
  768. {
  769. public:
  770. virtual pkgRecords::Parser *CreatePkgParser(pkgCache::PkgFileIterator File) const
  771. {
  772. return new debDebFileRecordParser(File.FileName(),*File.Cache());
  773. };
  774. debIFTypeDebPkgFile() {Label = "deb Package file";};
  775. };
  776. class APT_HIDDEN debIFTypeDscFile : public pkgIndexFile::Type
  777. {
  778. public:
  779. virtual pkgSrcRecords::Parser *CreateSrcPkgParser(std::string DscFile) const
  780. {
  781. return new debDscRecordParser(DscFile, NULL);
  782. };
  783. debIFTypeDscFile() {Label = "dsc File Source Index";};
  784. };
  785. class APT_HIDDEN debIFTypeDebianSourceDir : public pkgIndexFile::Type
  786. {
  787. public:
  788. virtual pkgSrcRecords::Parser *CreateSrcPkgParser(std::string SourceDir) const
  789. {
  790. return new debDscRecordParser(SourceDir + string("/debian/control"), NULL);
  791. };
  792. debIFTypeDebianSourceDir() {Label = "debian/control File Source Index";};
  793. };
  794. APT_HIDDEN debIFTypeSrc _apt_Src;
  795. APT_HIDDEN debIFTypePkg _apt_Pkg;
  796. APT_HIDDEN debIFTypeTrans _apt_Trans;
  797. APT_HIDDEN debIFTypeStatus _apt_Status;
  798. APT_HIDDEN debIFTypeDebPkgFile _apt_DebPkgFile;
  799. // file based pseudo indexes
  800. APT_HIDDEN debIFTypeDscFile _apt_DscFile;
  801. APT_HIDDEN debIFTypeDebianSourceDir _apt_DebianSourceDir;
  802. const pkgIndexFile::Type *debSourcesIndex::GetType() const
  803. {
  804. return &_apt_Src;
  805. }
  806. const pkgIndexFile::Type *debPackagesIndex::GetType() const
  807. {
  808. return &_apt_Pkg;
  809. }
  810. const pkgIndexFile::Type *debTranslationsIndex::GetType() const
  811. {
  812. return &_apt_Trans;
  813. }
  814. const pkgIndexFile::Type *debStatusIndex::GetType() const
  815. {
  816. return &_apt_Status;
  817. }
  818. const pkgIndexFile::Type *debDebPkgFileIndex::GetType() const
  819. {
  820. return &_apt_DebPkgFile;
  821. }
  822. const pkgIndexFile::Type *debDscFileIndex::GetType() const
  823. {
  824. return &_apt_DscFile;
  825. }
  826. const pkgIndexFile::Type *debDebianSourceDirIndex::GetType() const
  827. {
  828. return &_apt_DebianSourceDir;
  829. }
  830. /*}}}*/
  831. debStatusIndex::~debStatusIndex() {}
  832. debPackagesIndex::~debPackagesIndex() {}
  833. debTranslationsIndex::~debTranslationsIndex() {}
  834. debSourcesIndex::~debSourcesIndex() {}
  835. debDebPkgFileIndex::~debDebPkgFileIndex() {}