debindexfile.cc 27 KB

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