debindexfile.cc 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460
  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/error.h>
  17. #include <apt-pkg/fileutl.h>
  18. #include <apt-pkg/indexfile.h>
  19. #include <apt-pkg/pkgcache.h>
  20. #include <apt-pkg/cacheiterators.h>
  21. #include <apt-pkg/pkgrecords.h>
  22. #include <apt-pkg/srcrecords.h>
  23. #include <stdio.h>
  24. #include <iostream>
  25. #include <string>
  26. #include <sstream>
  27. #include <sys/stat.h>
  28. #include <unistd.h>
  29. /*}}}*/
  30. // Sources Index /*{{{*/
  31. debSourcesIndex::debSourcesIndex(IndexTarget const &Target,bool const Trusted) :
  32. pkgDebianIndexTargetFile(Target, Trusted), d(NULL)
  33. {
  34. }
  35. std::string debSourcesIndex::SourceInfo(pkgSrcRecords::Parser const &Record,
  36. pkgSrcRecords::File const &File) const
  37. {
  38. // The result looks like: http://foo/debian/ stable/main src 1.1.1 (dsc)
  39. std::string Res = Target.Description;
  40. Res.erase(Target.Description.rfind(' '));
  41. Res += " ";
  42. Res += Record.Package();
  43. Res += " ";
  44. Res += Record.Version();
  45. if (File.Type.empty() == false)
  46. Res += " (" + File.Type + ")";
  47. return Res;
  48. }
  49. pkgSrcRecords::Parser *debSourcesIndex::CreateSrcParser() const
  50. {
  51. std::string const SourcesURI = IndexFileName();
  52. if (FileExists(SourcesURI))
  53. return new debSrcRecordParser(SourcesURI, this);
  54. return NULL;
  55. }
  56. bool debSourcesIndex::OpenListFile(FileFd &, std::string const &)
  57. {
  58. return true;
  59. }
  60. pkgCacheListParser * debSourcesIndex::CreateListParser(FileFd &)
  61. {
  62. return NULL;
  63. }
  64. uint8_t debSourcesIndex::GetIndexFlags() const
  65. {
  66. return 0;
  67. }
  68. /*}}}*/
  69. // Packages Index /*{{{*/
  70. debPackagesIndex::debPackagesIndex(IndexTarget const &Target, bool const Trusted) :
  71. pkgDebianIndexTargetFile(Target, Trusted), d(NULL)
  72. {
  73. }
  74. std::string debPackagesIndex::ArchiveInfo(pkgCache::VerIterator const &Ver) const
  75. {
  76. std::string Res = Target.Description;
  77. {
  78. auto const space = Target.Description.rfind(' ');
  79. if (space != std::string::npos)
  80. Res.erase(space);
  81. }
  82. Res += " ";
  83. Res += Ver.ParentPkg().Name();
  84. Res += " ";
  85. std::string const Dist = Target.Option(IndexTarget::RELEASE);
  86. if (Dist.empty() == false && Dist[Dist.size() - 1] != '/')
  87. Res.append(Ver.Arch()).append(" ");
  88. Res += Ver.VerStr();
  89. return Res;
  90. }
  91. uint8_t debPackagesIndex::GetIndexFlags() const
  92. {
  93. return 0;
  94. }
  95. /*}}}*/
  96. // Translation-* Index /*{{{*/
  97. debTranslationsIndex::debTranslationsIndex(IndexTarget const &Target) :
  98. pkgDebianIndexTargetFile(Target, true), d(NULL)
  99. {}
  100. bool debTranslationsIndex::HasPackages() const
  101. {
  102. return Exists();
  103. }
  104. bool debTranslationsIndex::OpenListFile(FileFd &Pkg, std::string const &FileName)
  105. {
  106. if (FileExists(FileName))
  107. return pkgDebianIndexTargetFile::OpenListFile(Pkg, FileName);
  108. return true;
  109. }
  110. uint8_t debTranslationsIndex::GetIndexFlags() const
  111. {
  112. return pkgCache::Flag::NotSource | pkgCache::Flag::NoPackages;
  113. }
  114. std::string debTranslationsIndex::GetArchitecture() const
  115. {
  116. return std::string();
  117. }
  118. pkgCacheListParser * debTranslationsIndex::CreateListParser(FileFd &Pkg)
  119. {
  120. if (Pkg.IsOpen() == false)
  121. return nullptr;
  122. _error->PushToStack();
  123. pkgCacheListParser * const Parser = new debTranslationsParser(&Pkg);
  124. bool const newError = _error->PendingError();
  125. _error->MergeWithStack();
  126. if (newError)
  127. {
  128. delete Parser;
  129. return nullptr;
  130. }
  131. else
  132. return Parser;
  133. }
  134. /*}}}*/
  135. // dpkg/status Index /*{{{*/
  136. debStatusIndex::debStatusIndex(std::string const &File) : pkgDebianIndexRealFile(File, true), d(NULL)
  137. {
  138. }
  139. std::string debStatusIndex::GetArchitecture() const
  140. {
  141. return std::string();
  142. }
  143. std::string debStatusIndex::GetComponent() const
  144. {
  145. return "now";
  146. }
  147. uint8_t debStatusIndex::GetIndexFlags() const
  148. {
  149. return pkgCache::Flag::NotSource;
  150. }
  151. pkgCacheListParser * debStatusIndex::CreateListParser(FileFd &Pkg)
  152. {
  153. if (Pkg.IsOpen() == false)
  154. return nullptr;
  155. _error->PushToStack();
  156. pkgCacheListParser * const Parser = new debStatusListParser(&Pkg);
  157. bool const newError = _error->PendingError();
  158. _error->MergeWithStack();
  159. if (newError)
  160. {
  161. delete Parser;
  162. return nullptr;
  163. }
  164. else
  165. return Parser;
  166. }
  167. /*}}}*/
  168. // DebPkgFile Index - a single .deb file as an index /*{{{*/
  169. debDebPkgFileIndex::debDebPkgFileIndex(std::string const &DebFile)
  170. : pkgDebianIndexRealFile(DebFile, true), d(NULL), DebFile(DebFile)
  171. {
  172. }
  173. bool debDebPkgFileIndex::GetContent(std::ostream &content, std::string const &debfile)
  174. {
  175. struct stat Buf;
  176. if (stat(debfile.c_str(), &Buf) != 0)
  177. return false;
  178. // get the control data out of the deb file via dpkg-deb -I
  179. std::string dpkg = _config->Find("Dir::Bin::dpkg","dpkg-deb");
  180. std::vector<const char *> Args;
  181. Args.push_back(dpkg.c_str());
  182. Args.push_back("-I");
  183. Args.push_back(debfile.c_str());
  184. Args.push_back("control");
  185. Args.push_back(NULL);
  186. FileFd PipeFd;
  187. pid_t Child;
  188. if(Popen((const char**)&Args[0], PipeFd, Child, FileFd::ReadOnly) == false)
  189. return _error->Error("Popen failed");
  190. content << "Filename: " << debfile << "\n";
  191. content << "Size: " << std::to_string(Buf.st_size) << "\n";
  192. bool first_line_seen = false;
  193. char buffer[1024];
  194. do {
  195. unsigned long long actual = 0;
  196. if (PipeFd.Read(buffer, sizeof(buffer)-1, &actual) == false)
  197. return _error->Errno("read", "Failed to read dpkg pipe");
  198. if (actual == 0)
  199. break;
  200. buffer[actual] = '\0';
  201. char const * b = buffer;
  202. if (first_line_seen == false)
  203. {
  204. for (; *b != '\0' && (*b == '\n' || *b == '\r'); ++b)
  205. /* skip over leading newlines */;
  206. if (*b == '\0')
  207. continue;
  208. first_line_seen = true;
  209. }
  210. content << b;
  211. } while(true);
  212. ExecWait(Child, "Popen");
  213. return true;
  214. }
  215. bool debDebPkgFileIndex::OpenListFile(FileFd &Pkg, std::string const &FileName)
  216. {
  217. // write the control data to a tempfile
  218. if (GetTempFile("deb-file-" + flNotDir(FileName), true, &Pkg) == NULL)
  219. return false;
  220. std::ostringstream content;
  221. if (GetContent(content, FileName) == false)
  222. return false;
  223. std::string const contentstr = content.str();
  224. if (contentstr.empty())
  225. return true;
  226. if (Pkg.Write(contentstr.c_str(), contentstr.length()) == false || Pkg.Seek(0) == false)
  227. return false;
  228. return true;
  229. }
  230. pkgCacheListParser * debDebPkgFileIndex::CreateListParser(FileFd &Pkg)
  231. {
  232. if (Pkg.IsOpen() == false)
  233. return nullptr;
  234. _error->PushToStack();
  235. pkgCacheListParser * const Parser = new debDebFileParser(&Pkg, DebFile);
  236. bool const newError = _error->PendingError();
  237. _error->MergeWithStack();
  238. if (newError)
  239. {
  240. delete Parser;
  241. return nullptr;
  242. }
  243. else
  244. return Parser;
  245. }
  246. uint8_t debDebPkgFileIndex::GetIndexFlags() const
  247. {
  248. return pkgCache::Flag::LocalSource;
  249. }
  250. std::string debDebPkgFileIndex::GetArchitecture() const
  251. {
  252. return std::string();
  253. }
  254. std::string debDebPkgFileIndex::GetComponent() const
  255. {
  256. return "local-deb";
  257. }
  258. pkgCache::PkgFileIterator debDebPkgFileIndex::FindInCache(pkgCache &Cache) const
  259. {
  260. std::string const FileName = IndexFileName();
  261. pkgCache::PkgFileIterator File = Cache.FileBegin();
  262. for (; File.end() == false; ++File)
  263. {
  264. if (File.FileName() == NULL || FileName != File.FileName())
  265. continue;
  266. // we can't do size checks here as file size != content size
  267. return File;
  268. }
  269. return File;
  270. }
  271. std::string debDebPkgFileIndex::ArchiveInfo_impl(pkgCache::VerIterator const &Ver) const
  272. {
  273. std::string Res = IndexFileName() + " ";
  274. Res.append(Ver.ParentPkg().Name()).append(" ");
  275. Res.append(Ver.Arch()).append(" ");
  276. Res.append(Ver.VerStr());
  277. return Res;
  278. }
  279. /*}}}*/
  280. // DscFile Index - a single .dsc file as an index /*{{{*/
  281. debDscFileIndex::debDscFileIndex(std::string const &DscFile)
  282. : pkgDebianIndexRealFile(DscFile, true), d(NULL)
  283. {
  284. }
  285. pkgSrcRecords::Parser *debDscFileIndex::CreateSrcParser() const
  286. {
  287. if (Exists() == false)
  288. return NULL;
  289. return new debDscRecordParser(File, this);
  290. }
  291. std::string debDscFileIndex::GetComponent() const
  292. {
  293. return "local-dsc";
  294. }
  295. std::string debDscFileIndex::GetArchitecture() const
  296. {
  297. return "source";
  298. }
  299. uint8_t debDscFileIndex::GetIndexFlags() const
  300. {
  301. return pkgCache::Flag::LocalSource;
  302. }
  303. /*}}}*/
  304. // ControlFile Index - a directory with a debian/control file /*{{{*/
  305. std::string debDebianSourceDirIndex::GetComponent() const
  306. {
  307. return "local-control";
  308. }
  309. /*}}}*/
  310. // String Package Index - a string of Packages file content /*{{{*/
  311. std::string debStringPackageIndex::GetArchitecture() const
  312. {
  313. return std::string();
  314. }
  315. std::string debStringPackageIndex::GetComponent() const
  316. {
  317. return "apt-tmp-index";
  318. }
  319. uint8_t debStringPackageIndex::GetIndexFlags() const
  320. {
  321. return pkgCache::Flag::NotSource;
  322. }
  323. const pkgIndexFile::Type *debStringPackageIndex::GetType() const
  324. {
  325. return pkgIndexFile::Type::GetType("Debian Package Index");
  326. }
  327. debStringPackageIndex::debStringPackageIndex(std::string const &content) :
  328. pkgDebianIndexRealFile("", false), d(NULL)
  329. {
  330. char fn[1024];
  331. std::string const tempdir = GetTempDir();
  332. snprintf(fn, sizeof(fn), "%s/%s.XXXXXX", tempdir.c_str(), "apt-tmp-index");
  333. int const fd = mkstemp(fn);
  334. File = fn;
  335. FileFd::Write(fd, content.data(), content.length());
  336. close(fd);
  337. }
  338. debStringPackageIndex::~debStringPackageIndex()
  339. {
  340. RemoveFile("~debStringPackageIndex", File);
  341. }
  342. /*}}}*/
  343. // Index File types for Debian /*{{{*/
  344. class APT_HIDDEN debIFTypeSrc : public pkgIndexFile::Type
  345. {
  346. public:
  347. debIFTypeSrc() {Label = "Debian Source Index";};
  348. };
  349. class APT_HIDDEN debIFTypePkg : public pkgIndexFile::Type
  350. {
  351. public:
  352. virtual pkgRecords::Parser *CreatePkgParser(pkgCache::PkgFileIterator const &File) const APT_OVERRIDE
  353. {
  354. return new debRecordParser(File.FileName(),*File.Cache());
  355. };
  356. debIFTypePkg() {Label = "Debian Package Index";};
  357. };
  358. class APT_HIDDEN debIFTypeTrans : public debIFTypePkg
  359. {
  360. public:
  361. debIFTypeTrans() {Label = "Debian Translation Index";};
  362. };
  363. class APT_HIDDEN debIFTypeStatus : public pkgIndexFile::Type
  364. {
  365. public:
  366. virtual pkgRecords::Parser *CreatePkgParser(pkgCache::PkgFileIterator const &File) const APT_OVERRIDE
  367. {
  368. return new debRecordParser(File.FileName(),*File.Cache());
  369. };
  370. debIFTypeStatus() {Label = "Debian dpkg status file";};
  371. };
  372. class APT_HIDDEN debIFTypeDebPkgFile : public pkgIndexFile::Type
  373. {
  374. public:
  375. virtual pkgRecords::Parser *CreatePkgParser(pkgCache::PkgFileIterator const &File) const APT_OVERRIDE
  376. {
  377. return new debDebFileRecordParser(File.FileName());
  378. };
  379. debIFTypeDebPkgFile() {Label = "Debian deb file";};
  380. };
  381. class APT_HIDDEN debIFTypeDscFile : public pkgIndexFile::Type
  382. {
  383. public:
  384. virtual pkgSrcRecords::Parser *CreateSrcPkgParser(std::string const &DscFile) const APT_OVERRIDE
  385. {
  386. return new debDscRecordParser(DscFile, NULL);
  387. };
  388. debIFTypeDscFile() {Label = "Debian dsc file";};
  389. };
  390. class APT_HIDDEN debIFTypeDebianSourceDir : public pkgIndexFile::Type
  391. {
  392. public:
  393. virtual pkgSrcRecords::Parser *CreateSrcPkgParser(std::string const &SourceDir) const APT_OVERRIDE
  394. {
  395. return new debDscRecordParser(SourceDir + std::string("/debian/control"), NULL);
  396. };
  397. debIFTypeDebianSourceDir() {Label = "Debian control file";};
  398. };
  399. APT_HIDDEN debIFTypeSrc _apt_Src;
  400. APT_HIDDEN debIFTypePkg _apt_Pkg;
  401. APT_HIDDEN debIFTypeTrans _apt_Trans;
  402. APT_HIDDEN debIFTypeStatus _apt_Status;
  403. APT_HIDDEN debIFTypeDebPkgFile _apt_DebPkgFile;
  404. // file based pseudo indexes
  405. APT_HIDDEN debIFTypeDscFile _apt_DscFile;
  406. APT_HIDDEN debIFTypeDebianSourceDir _apt_DebianSourceDir;
  407. const pkgIndexFile::Type *debSourcesIndex::GetType() const
  408. {
  409. return &_apt_Src;
  410. }
  411. const pkgIndexFile::Type *debPackagesIndex::GetType() const
  412. {
  413. return &_apt_Pkg;
  414. }
  415. const pkgIndexFile::Type *debTranslationsIndex::GetType() const
  416. {
  417. return &_apt_Trans;
  418. }
  419. const pkgIndexFile::Type *debStatusIndex::GetType() const
  420. {
  421. return &_apt_Status;
  422. }
  423. const pkgIndexFile::Type *debDebPkgFileIndex::GetType() const
  424. {
  425. return &_apt_DebPkgFile;
  426. }
  427. const pkgIndexFile::Type *debDscFileIndex::GetType() const
  428. {
  429. return &_apt_DscFile;
  430. }
  431. const pkgIndexFile::Type *debDebianSourceDirIndex::GetType() const
  432. {
  433. return &_apt_DebianSourceDir;
  434. }
  435. /*}}}*/
  436. debStatusIndex::~debStatusIndex() {}
  437. debPackagesIndex::~debPackagesIndex() {}
  438. debTranslationsIndex::~debTranslationsIndex() {}
  439. debSourcesIndex::~debSourcesIndex() {}
  440. debDebPkgFileIndex::~debDebPkgFileIndex() {}
  441. debDscFileIndex::~debDscFileIndex() {}