debindexfile.cc 13 KB

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