debindexfile.cc 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621
  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. #ifdef __GNUG__
  11. #pragma implementation "apt-pkg/debindexfile.h"
  12. #endif
  13. #include <apt-pkg/debindexfile.h>
  14. #include <apt-pkg/debsrcrecords.h>
  15. #include <apt-pkg/deblistparser.h>
  16. #include <apt-pkg/debrecords.h>
  17. #include <apt-pkg/sourcelist.h>
  18. #include <apt-pkg/configuration.h>
  19. #include <apt-pkg/progress.h>
  20. #include <apt-pkg/error.h>
  21. #include <apt-pkg/strutl.h>
  22. #include <apt-pkg/acquire-item.h>
  23. #include <apt-pkg/debmetaindex.h>
  24. #include <sys/stat.h>
  25. /*}}}*/
  26. // SourcesIndex::debSourcesIndex - Constructor /*{{{*/
  27. // ---------------------------------------------------------------------
  28. /* */
  29. debSourcesIndex::debSourcesIndex(string URI,string Dist,string Section,bool Trusted) :
  30. pkgIndexFile(Trusted), URI(URI), Dist(Dist), Section(Section)
  31. {
  32. }
  33. /*}}}*/
  34. // SourcesIndex::SourceInfo - Short 1 liner describing a source /*{{{*/
  35. // ---------------------------------------------------------------------
  36. /* The result looks like:
  37. http://foo/ stable/main src 1.1.1 (dsc) */
  38. string debSourcesIndex::SourceInfo(pkgSrcRecords::Parser const &Record,
  39. pkgSrcRecords::File const &File) const
  40. {
  41. string Res;
  42. Res = ::URI::SiteOnly(URI) + ' ';
  43. if (Dist[Dist.size() - 1] == '/')
  44. {
  45. if (Dist != "/")
  46. Res += Dist;
  47. }
  48. else
  49. Res += Dist + '/' + Section;
  50. Res += " ";
  51. Res += Record.Package();
  52. Res += " ";
  53. Res += Record.Version();
  54. if (File.Type.empty() == false)
  55. Res += " (" + File.Type + ")";
  56. return Res;
  57. }
  58. /*}}}*/
  59. // SourcesIndex::CreateSrcParser - Get a parser for the source files /*{{{*/
  60. // ---------------------------------------------------------------------
  61. /* */
  62. pkgSrcRecords::Parser *debSourcesIndex::CreateSrcParser() const
  63. {
  64. string SourcesURI = URItoFileName(IndexURI("Sources"));
  65. return new debSrcRecordParser(_config->FindDir("Dir::State::lists") +
  66. SourcesURI,this);
  67. }
  68. /*}}}*/
  69. // SourcesIndex::Describe - Give a descriptive path to the index /*{{{*/
  70. // ---------------------------------------------------------------------
  71. /* */
  72. string debSourcesIndex::Describe(bool Short) const
  73. {
  74. char S[300];
  75. if (Short == true)
  76. snprintf(S,sizeof(S),"%s",Info("Sources").c_str());
  77. else
  78. snprintf(S,sizeof(S),"%s (%s)",Info("Sources").c_str(),
  79. IndexFile("Sources").c_str());
  80. return S;
  81. }
  82. /*}}}*/
  83. // SourcesIndex::Info - One liner describing the index URI /*{{{*/
  84. // ---------------------------------------------------------------------
  85. /* */
  86. string debSourcesIndex::Info(const char *Type) const
  87. {
  88. string Info = ::URI::SiteOnly(URI) + ' ';
  89. if (Dist[Dist.size() - 1] == '/')
  90. {
  91. if (Dist != "/")
  92. Info += Dist;
  93. }
  94. else
  95. Info += Dist + '/' + Section;
  96. Info += " ";
  97. Info += Type;
  98. return Info;
  99. }
  100. /*}}}*/
  101. // SourcesIndex::Index* - Return the URI to the index files /*{{{*/
  102. // ---------------------------------------------------------------------
  103. /* */
  104. inline string debSourcesIndex::IndexFile(const char *Type) const
  105. {
  106. return URItoFileName(IndexURI(Type));
  107. }
  108. string debSourcesIndex::IndexURI(const char *Type) const
  109. {
  110. string Res;
  111. if (Dist[Dist.size() - 1] == '/')
  112. {
  113. if (Dist != "/")
  114. Res = URI + Dist;
  115. else
  116. Res = URI;
  117. }
  118. else
  119. Res = URI + "dists/" + Dist + '/' + Section +
  120. "/source/";
  121. Res += Type;
  122. return Res;
  123. }
  124. /*}}}*/
  125. // SourcesIndex::Exists - Check if the index is available /*{{{*/
  126. // ---------------------------------------------------------------------
  127. /* */
  128. bool debSourcesIndex::Exists() const
  129. {
  130. return FileExists(IndexFile("Sources"));
  131. }
  132. /*}}}*/
  133. // SourcesIndex::Size - Return the size of the index /*{{{*/
  134. // ---------------------------------------------------------------------
  135. /* */
  136. unsigned long debSourcesIndex::Size() const
  137. {
  138. struct stat S;
  139. if (stat(IndexFile("Sources").c_str(),&S) != 0)
  140. return 0;
  141. return S.st_size;
  142. }
  143. /*}}}*/
  144. // PackagesIndex::debPackagesIndex - Contructor /*{{{*/
  145. // ---------------------------------------------------------------------
  146. /* */
  147. debPackagesIndex::debPackagesIndex(string URI,string Dist,string Section,bool Trusted) :
  148. pkgIndexFile(Trusted), URI(URI), Dist(Dist), Section(Section)
  149. {
  150. }
  151. /*}}}*/
  152. // PackagesIndex::ArchiveInfo - Short version of the archive url /*{{{*/
  153. // ---------------------------------------------------------------------
  154. /* This is a shorter version that is designed to be < 60 chars or so */
  155. string debPackagesIndex::ArchiveInfo(pkgCache::VerIterator Ver) const
  156. {
  157. string Res = ::URI::SiteOnly(URI) + ' ';
  158. if (Dist[Dist.size() - 1] == '/')
  159. {
  160. if (Dist != "/")
  161. Res += Dist;
  162. }
  163. else
  164. Res += Dist + '/' + Section;
  165. Res += " ";
  166. Res += Ver.ParentPkg().Name();
  167. Res += " ";
  168. Res += Ver.VerStr();
  169. return Res;
  170. }
  171. /*}}}*/
  172. // PackagesIndex::Describe - Give a descriptive path to the index /*{{{*/
  173. // ---------------------------------------------------------------------
  174. /* This should help the user find the index in the sources.list and
  175. in the filesystem for problem solving */
  176. string debPackagesIndex::Describe(bool Short) const
  177. {
  178. char S[300];
  179. if (Short == true)
  180. snprintf(S,sizeof(S),"%s",Info("Packages").c_str());
  181. else
  182. snprintf(S,sizeof(S),"%s (%s)",Info("Packages").c_str(),
  183. IndexFile("Packages").c_str());
  184. return S;
  185. }
  186. /*}}}*/
  187. // PackagesIndex::Info - One liner describing the index URI /*{{{*/
  188. // ---------------------------------------------------------------------
  189. /* */
  190. string debPackagesIndex::Info(const char *Type) const
  191. {
  192. string Info = ::URI::SiteOnly(URI) + ' ';
  193. if (Dist[Dist.size() - 1] == '/')
  194. {
  195. if (Dist != "/")
  196. Info += Dist;
  197. }
  198. else
  199. Info += Dist + '/' + Section;
  200. Info += " ";
  201. Info += Type;
  202. return Info;
  203. }
  204. /*}}}*/
  205. // PackagesIndex::Index* - Return the URI to the index files /*{{{*/
  206. // ---------------------------------------------------------------------
  207. /* */
  208. inline string debPackagesIndex::IndexFile(const char *Type) const
  209. {
  210. return _config->FindDir("Dir::State::lists") + URItoFileName(IndexURI(Type));
  211. }
  212. string debPackagesIndex::IndexURI(const char *Type) const
  213. {
  214. string Res;
  215. if (Dist[Dist.size() - 1] == '/')
  216. {
  217. if (Dist != "/")
  218. Res = URI + Dist;
  219. else
  220. Res = URI;
  221. }
  222. else
  223. Res = URI + "dists/" + Dist + '/' + Section +
  224. "/binary-" + _config->Find("APT::Architecture") + '/';
  225. Res += Type;
  226. return Res;
  227. }
  228. /*}}}*/
  229. // PackagesIndex::Exists - Check if the index is available /*{{{*/
  230. // ---------------------------------------------------------------------
  231. /* */
  232. bool debPackagesIndex::Exists() const
  233. {
  234. return FileExists(IndexFile("Packages"));
  235. }
  236. /*}}}*/
  237. // PackagesIndex::Size - Return the size of the index /*{{{*/
  238. // ---------------------------------------------------------------------
  239. /* This is really only used for progress reporting. */
  240. unsigned long debPackagesIndex::Size() const
  241. {
  242. struct stat S;
  243. if (stat(IndexFile("Packages").c_str(),&S) != 0)
  244. return 0;
  245. return S.st_size;
  246. }
  247. /*}}}*/
  248. // PackagesIndex::Merge - Load the index file into a cache /*{{{*/
  249. // ---------------------------------------------------------------------
  250. /* */
  251. bool debPackagesIndex::Merge(pkgCacheGenerator &Gen,OpProgress &Prog) const
  252. {
  253. string PackageFile = IndexFile("Packages");
  254. FileFd Pkg(PackageFile,FileFd::ReadOnly);
  255. debListParser Parser(&Pkg);
  256. if (_error->PendingError() == true)
  257. return _error->Error("Problem opening %s",PackageFile.c_str());
  258. Prog.SubProgress(0,Info("Packages"));
  259. ::URI Tmp(URI);
  260. if (Gen.SelectFile(PackageFile,Tmp.Host,*this) == false)
  261. return _error->Error("Problem with SelectFile %s",PackageFile.c_str());
  262. // Store the IMS information
  263. pkgCache::PkgFileIterator File = Gen.GetCurFile();
  264. struct stat St;
  265. if (fstat(Pkg.Fd(),&St) != 0)
  266. return _error->Errno("fstat","Failed to stat");
  267. File->Size = St.st_size;
  268. File->mtime = St.st_mtime;
  269. if (Gen.MergeList(Parser) == false)
  270. return _error->Error("Problem with MergeList %s",PackageFile.c_str());
  271. // Check the release file
  272. string ReleaseFile = debReleaseIndex(URI,Dist).MetaIndexFile("Release");
  273. if (FileExists(ReleaseFile) == true)
  274. {
  275. FileFd Rel(ReleaseFile,FileFd::ReadOnly);
  276. if (_error->PendingError() == true)
  277. return false;
  278. Parser.LoadReleaseInfo(File,Rel,Section);
  279. }
  280. return true;
  281. }
  282. /*}}}*/
  283. // PackagesIndex::FindInCache - Find this index /*{{{*/
  284. // ---------------------------------------------------------------------
  285. /* */
  286. pkgCache::PkgFileIterator debPackagesIndex::FindInCache(pkgCache &Cache) const
  287. {
  288. string FileName = IndexFile("Packages");
  289. pkgCache::PkgFileIterator File = Cache.FileBegin();
  290. for (; File.end() == false; File++)
  291. {
  292. if (File.FileName() == NULL || FileName != File.FileName())
  293. continue;
  294. struct stat St;
  295. if (stat(File.FileName(),&St) != 0)
  296. return pkgCache::PkgFileIterator(Cache);
  297. if ((unsigned)St.st_size != File->Size || St.st_mtime != File->mtime)
  298. return pkgCache::PkgFileIterator(Cache);
  299. return File;
  300. }
  301. return File;
  302. }
  303. /*}}}*/
  304. // TranslationsIndex::debTranslationsIndex - Contructor /*{{{*/
  305. // ---------------------------------------------------------------------
  306. /* */
  307. debTranslationsIndex::debTranslationsIndex(string URI,string Dist,string Section) :
  308. pkgIndexFile(true), URI(URI), Dist(Dist), Section(Section)
  309. {
  310. }
  311. /*}}}*/
  312. // TranslationIndex::Trans* - Return the URI to the translation files /*{{{*/
  313. // ---------------------------------------------------------------------
  314. /* */
  315. inline string debTranslationsIndex::IndexFile(const char *Type) const
  316. {
  317. return _config->FindDir("Dir::State::lists") + URItoFileName(IndexURI(Type));
  318. }
  319. string debTranslationsIndex::IndexURI(const char *Type) const
  320. {
  321. string Res;
  322. if (Dist[Dist.size() - 1] == '/')
  323. {
  324. if (Dist != "/")
  325. Res = URI + Dist;
  326. else
  327. Res = URI;
  328. }
  329. else
  330. Res = URI + "dists/" + Dist + '/' + Section +
  331. "/i18n/Translation-";
  332. Res += Type;
  333. return Res;
  334. }
  335. /*}}}*/
  336. // TranslationsIndex::GetIndexes - Fetch the index files /*{{{*/
  337. // ---------------------------------------------------------------------
  338. /* */
  339. bool debTranslationsIndex::GetIndexes(pkgAcquire *Owner) const
  340. {
  341. if (TranslationsAvailable()) {
  342. string TranslationFile = "Translation-" + LanguageCode();
  343. new pkgAcqIndexTrans(Owner, IndexURI(LanguageCode().c_str()),
  344. Info(TranslationFile.c_str()),
  345. TranslationFile);
  346. }
  347. return true;
  348. }
  349. /*}}}*/
  350. // TranslationsIndex::Describe - Give a descriptive path to the index /*{{{*/
  351. // ---------------------------------------------------------------------
  352. /* This should help the user find the index in the sources.list and
  353. in the filesystem for problem solving */
  354. string debTranslationsIndex::Describe(bool Short) const
  355. {
  356. char S[300];
  357. if (Short == true)
  358. snprintf(S,sizeof(S),"%s",Info(TranslationFile().c_str()).c_str());
  359. else
  360. snprintf(S,sizeof(S),"%s (%s)",Info(TranslationFile().c_str()).c_str(),
  361. IndexFile(LanguageCode().c_str()).c_str());
  362. return S;
  363. }
  364. /*}}}*/
  365. // TranslationsIndex::Info - One liner describing the index URI /*{{{*/
  366. // ---------------------------------------------------------------------
  367. /* */
  368. string debTranslationsIndex::Info(const char *Type) const
  369. {
  370. string Info = ::URI::SiteOnly(URI) + ' ';
  371. if (Dist[Dist.size() - 1] == '/')
  372. {
  373. if (Dist != "/")
  374. Info += Dist;
  375. }
  376. else
  377. Info += Dist + '/' + Section;
  378. Info += " ";
  379. Info += Type;
  380. return Info;
  381. }
  382. /*}}}*/
  383. bool debTranslationsIndex::HasPackages() const
  384. {
  385. if(!TranslationsAvailable())
  386. return false;
  387. return FileExists(IndexFile(LanguageCode().c_str()));
  388. }
  389. // TranslationsIndex::Exists - Check if the index is available /*{{{*/
  390. // ---------------------------------------------------------------------
  391. /* */
  392. bool debTranslationsIndex::Exists() const
  393. {
  394. return FileExists(IndexFile(LanguageCode().c_str()));
  395. }
  396. /*}}}*/
  397. // TranslationsIndex::Size - Return the size of the index /*{{{*/
  398. // ---------------------------------------------------------------------
  399. /* This is really only used for progress reporting. */
  400. unsigned long debTranslationsIndex::Size() const
  401. {
  402. struct stat S;
  403. if (stat(IndexFile(LanguageCode().c_str()).c_str(),&S) != 0)
  404. return 0;
  405. return S.st_size;
  406. }
  407. /*}}}*/
  408. // TranslationsIndex::Merge - Load the index file into a cache /*{{{*/
  409. // ---------------------------------------------------------------------
  410. /* */
  411. bool debTranslationsIndex::Merge(pkgCacheGenerator &Gen,OpProgress &Prog) const
  412. {
  413. // Check the translation file, if in use
  414. string TranslationFile = IndexFile(LanguageCode().c_str());
  415. if (TranslationsAvailable() && FileExists(TranslationFile))
  416. {
  417. FileFd Trans(TranslationFile,FileFd::ReadOnly);
  418. debListParser TransParser(&Trans);
  419. if (_error->PendingError() == true)
  420. return false;
  421. Prog.SubProgress(0, Info(TranslationFile.c_str()));
  422. if (Gen.SelectFile(TranslationFile,string(),*this) == false)
  423. return _error->Error("Problem with SelectFile %s",TranslationFile.c_str());
  424. // Store the IMS information
  425. pkgCache::PkgFileIterator TransFile = Gen.GetCurFile();
  426. struct stat TransSt;
  427. if (fstat(Trans.Fd(),&TransSt) != 0)
  428. return _error->Errno("fstat","Failed to stat");
  429. TransFile->Size = TransSt.st_size;
  430. TransFile->mtime = TransSt.st_mtime;
  431. if (Gen.MergeList(TransParser) == false)
  432. return _error->Error("Problem with MergeList %s",TranslationFile.c_str());
  433. }
  434. return true;
  435. }
  436. /*}}}*/
  437. // TranslationsIndex::FindInCache - Find this index /*{{{*/
  438. // ---------------------------------------------------------------------
  439. /* */
  440. pkgCache::PkgFileIterator debTranslationsIndex::FindInCache(pkgCache &Cache) const
  441. {
  442. string FileName = IndexFile(LanguageCode().c_str());
  443. pkgCache::PkgFileIterator File = Cache.FileBegin();
  444. for (; File.end() == false; File++)
  445. {
  446. if (FileName != File.FileName())
  447. continue;
  448. struct stat St;
  449. if (stat(File.FileName(),&St) != 0)
  450. return pkgCache::PkgFileIterator(Cache);
  451. if ((unsigned)St.st_size != File->Size || St.st_mtime != File->mtime)
  452. return pkgCache::PkgFileIterator(Cache);
  453. return File;
  454. }
  455. return File;
  456. }
  457. /*}}}*/
  458. // StatusIndex::debStatusIndex - Constructor /*{{{*/
  459. // ---------------------------------------------------------------------
  460. /* */
  461. debStatusIndex::debStatusIndex(string File) : pkgIndexFile(true), File(File)
  462. {
  463. }
  464. /*}}}*/
  465. // StatusIndex::Size - Return the size of the index /*{{{*/
  466. // ---------------------------------------------------------------------
  467. /* */
  468. unsigned long debStatusIndex::Size() const
  469. {
  470. struct stat S;
  471. if (stat(File.c_str(),&S) != 0)
  472. return 0;
  473. return S.st_size;
  474. }
  475. /*}}}*/
  476. // StatusIndex::Merge - Load the index file into a cache /*{{{*/
  477. // ---------------------------------------------------------------------
  478. /* */
  479. bool debStatusIndex::Merge(pkgCacheGenerator &Gen,OpProgress &Prog) const
  480. {
  481. FileFd Pkg(File,FileFd::ReadOnly);
  482. if (_error->PendingError() == true)
  483. return false;
  484. debListParser Parser(&Pkg);
  485. if (_error->PendingError() == true)
  486. return false;
  487. Prog.SubProgress(0,File);
  488. if (Gen.SelectFile(File,string(),*this,pkgCache::Flag::NotSource) == false)
  489. return _error->Error("Problem with SelectFile %s",File.c_str());
  490. // Store the IMS information
  491. pkgCache::PkgFileIterator CFile = Gen.GetCurFile();
  492. struct stat St;
  493. if (fstat(Pkg.Fd(),&St) != 0)
  494. return _error->Errno("fstat","Failed to stat");
  495. CFile->Size = St.st_size;
  496. CFile->mtime = St.st_mtime;
  497. CFile->Archive = Gen.WriteUniqString("now");
  498. if (Gen.MergeList(Parser) == false)
  499. return _error->Error("Problem with MergeList %s",File.c_str());
  500. return true;
  501. }
  502. /*}}}*/
  503. // StatusIndex::FindInCache - Find this index /*{{{*/
  504. // ---------------------------------------------------------------------
  505. /* */
  506. pkgCache::PkgFileIterator debStatusIndex::FindInCache(pkgCache &Cache) const
  507. {
  508. pkgCache::PkgFileIterator File = Cache.FileBegin();
  509. for (; File.end() == false; File++)
  510. {
  511. if (this->File != File.FileName())
  512. continue;
  513. struct stat St;
  514. if (stat(File.FileName(),&St) != 0)
  515. return pkgCache::PkgFileIterator(Cache);
  516. if ((unsigned)St.st_size != File->Size || St.st_mtime != File->mtime)
  517. return pkgCache::PkgFileIterator(Cache);
  518. return File;
  519. }
  520. return File;
  521. }
  522. /*}}}*/
  523. // StatusIndex::Exists - Check if the index is available /*{{{*/
  524. // ---------------------------------------------------------------------
  525. /* */
  526. bool debStatusIndex::Exists() const
  527. {
  528. // Abort if the file does not exist.
  529. return true;
  530. }
  531. /*}}}*/
  532. // Index File types for Debian /*{{{*/
  533. class debIFTypeSrc : public pkgIndexFile::Type
  534. {
  535. public:
  536. debIFTypeSrc() {Label = "Debian Source Index";};
  537. };
  538. class debIFTypePkg : public pkgIndexFile::Type
  539. {
  540. public:
  541. virtual pkgRecords::Parser *CreatePkgParser(pkgCache::PkgFileIterator File) const
  542. {
  543. return new debRecordParser(File.FileName(),*File.Cache());
  544. };
  545. debIFTypePkg() {Label = "Debian Package Index";};
  546. };
  547. class debIFTypeTrans : public debIFTypePkg
  548. {
  549. public:
  550. debIFTypeTrans() {Label = "Debian Translation Index";};
  551. };
  552. class debIFTypeStatus : public pkgIndexFile::Type
  553. {
  554. public:
  555. virtual pkgRecords::Parser *CreatePkgParser(pkgCache::PkgFileIterator File) const
  556. {
  557. return new debRecordParser(File.FileName(),*File.Cache());
  558. };
  559. debIFTypeStatus() {Label = "Debian dpkg status file";};
  560. };
  561. static debIFTypeSrc _apt_Src;
  562. static debIFTypePkg _apt_Pkg;
  563. static debIFTypeTrans _apt_Trans;
  564. static debIFTypeStatus _apt_Status;
  565. const pkgIndexFile::Type *debSourcesIndex::GetType() const
  566. {
  567. return &_apt_Src;
  568. }
  569. const pkgIndexFile::Type *debPackagesIndex::GetType() const
  570. {
  571. return &_apt_Pkg;
  572. }
  573. const pkgIndexFile::Type *debTranslationsIndex::GetType() const
  574. {
  575. return &_apt_Trans;
  576. }
  577. const pkgIndexFile::Type *debStatusIndex::GetType() const
  578. {
  579. return &_apt_Status;
  580. }
  581. /*}}}*/