debindexfile.cc 13 KB

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