sourcelist.cc 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335
  1. // -*- mode: cpp; mode: fold -*-
  2. // Description /*{{{*/
  3. // $Id: sourcelist.cc,v 1.25 2004/06/07 23:08:00 mdz Exp $
  4. /* ######################################################################
  5. List of Sources
  6. ##################################################################### */
  7. /*}}}*/
  8. // Include Files /*{{{*/
  9. #ifdef __GNUG__
  10. #pragma implementation "apt-pkg/sourcelist.h"
  11. #endif
  12. #include <apt-pkg/sourcelist.h>
  13. #include <apt-pkg/error.h>
  14. #include <apt-pkg/fileutl.h>
  15. #include <apt-pkg/configuration.h>
  16. #include <apt-pkg/strutl.h>
  17. #include <apti18n.h>
  18. #include <fstream>
  19. /*}}}*/
  20. using namespace std;
  21. // Global list of Items supported
  22. static pkgSourceList::Type *ItmList[10];
  23. pkgSourceList::Type **pkgSourceList::Type::GlobalList = ItmList;
  24. unsigned long pkgSourceList::Type::GlobalListLen = 0;
  25. // Type::Type - Constructor /*{{{*/
  26. // ---------------------------------------------------------------------
  27. /* Link this to the global list of items*/
  28. pkgSourceList::Type::Type()
  29. {
  30. ItmList[GlobalListLen] = this;
  31. GlobalListLen++;
  32. }
  33. /*}}}*/
  34. // Type::GetType - Get a specific meta for a given type /*{{{*/
  35. // ---------------------------------------------------------------------
  36. /* */
  37. pkgSourceList::Type *pkgSourceList::Type::GetType(const char *Type)
  38. {
  39. for (unsigned I = 0; I != GlobalListLen; I++)
  40. if (strcmp(GlobalList[I]->Name,Type) == 0)
  41. return GlobalList[I];
  42. return 0;
  43. }
  44. /*}}}*/
  45. // Type::FixupURI - Normalize the URI and check it.. /*{{{*/
  46. // ---------------------------------------------------------------------
  47. /* */
  48. bool pkgSourceList::Type::FixupURI(string &URI) const
  49. {
  50. if (URI.empty() == true)
  51. return false;
  52. if (URI.find(':') == string::npos)
  53. return false;
  54. URI = SubstVar(URI,"$(ARCH)",_config->Find("APT::Architecture"));
  55. // Make sure that the URI is / postfixed
  56. if (URI[URI.size() - 1] != '/')
  57. URI += '/';
  58. return true;
  59. }
  60. /*}}}*/
  61. // Type::ParseLine - Parse a single line /*{{{*/
  62. // ---------------------------------------------------------------------
  63. /* This is a generic one that is the 'usual' format for sources.list
  64. Weird types may override this. */
  65. bool pkgSourceList::Type::ParseLine(vector<pkgIndexFile *> &List,
  66. Vendor const *Vendor,
  67. const char *Buffer,
  68. unsigned long CurLine,
  69. string File) const
  70. {
  71. string URI;
  72. string Dist;
  73. string Section;
  74. if (ParseQuoteWord(Buffer,URI) == false)
  75. return _error->Error(_("Malformed line %lu in source list %s (URI)"),CurLine,File.c_str());
  76. if (ParseQuoteWord(Buffer,Dist) == false)
  77. return _error->Error(_("Malformed line %lu in source list %s (dist)"),CurLine,File.c_str());
  78. if (FixupURI(URI) == false)
  79. return _error->Error(_("Malformed line %lu in source list %s (URI parse)"),CurLine,File.c_str());
  80. // Check for an absolute dists specification.
  81. if (Dist.empty() == false && Dist[Dist.size() - 1] == '/')
  82. {
  83. if (ParseQuoteWord(Buffer,Section) == true)
  84. return _error->Error(_("Malformed line %lu in source list %s (Absolute dist)"),CurLine,File.c_str());
  85. Dist = SubstVar(Dist,"$(ARCH)",_config->Find("APT::Architecture"));
  86. return CreateItem(List,URI,Dist,Section,Vendor);
  87. }
  88. // Grab the rest of the dists
  89. if (ParseQuoteWord(Buffer,Section) == false)
  90. return _error->Error(_("Malformed line %lu in source list %s (dist parse)"),CurLine,File.c_str());
  91. do
  92. {
  93. if (CreateItem(List,URI,Dist,Section,Vendor) == false)
  94. return false;
  95. }
  96. while (ParseQuoteWord(Buffer,Section) == true);
  97. return true;
  98. }
  99. /*}}}*/
  100. // SourceList::pkgSourceList - Constructors /*{{{*/
  101. // ---------------------------------------------------------------------
  102. /* */
  103. pkgSourceList::pkgSourceList()
  104. {
  105. }
  106. pkgSourceList::pkgSourceList(string File)
  107. {
  108. Read(File);
  109. }
  110. /*}}}*/
  111. // SourceList::~pkgSourceList - Destructor /*{{{*/
  112. // ---------------------------------------------------------------------
  113. /* */
  114. pkgSourceList::~pkgSourceList()
  115. {
  116. for (const_iterator I = SrcList.begin(); I != SrcList.end(); I++)
  117. delete *I;
  118. for (vector<Vendor const *>::const_iterator I = VendorList.begin();
  119. I != VendorList.end(); I++)
  120. delete *I;
  121. }
  122. /*}}}*/
  123. // SourceList::ReadVendors - Read list of known package vendors /*{{{*/
  124. // ---------------------------------------------------------------------
  125. /* This also scans a directory of vendor files similar to apt.conf.d
  126. which can contain the usual suspects of distribution provided data.
  127. The APT config mechanism allows the user to override these in their
  128. configuration file. */
  129. bool pkgSourceList::ReadVendors()
  130. {
  131. Configuration Cnf;
  132. string CnfFile = _config->FindDir("Dir::Etc::vendorparts");
  133. if (FileExists(CnfFile) == true)
  134. if (ReadConfigDir(Cnf,CnfFile,true) == false)
  135. return false;
  136. CnfFile = _config->FindFile("Dir::Etc::vendorlist");
  137. if (FileExists(CnfFile) == true)
  138. if (ReadConfigFile(Cnf,CnfFile,true) == false)
  139. return false;
  140. for (vector<Vendor const *>::const_iterator I = VendorList.begin();
  141. I != VendorList.end(); I++)
  142. delete *I;
  143. VendorList.erase(VendorList.begin(),VendorList.end());
  144. // Process 'simple-key' type sections
  145. const Configuration::Item *Top = Cnf.Tree("simple-key");
  146. for (Top = (Top == 0?0:Top->Child); Top != 0; Top = Top->Next)
  147. {
  148. Configuration Block(Top);
  149. Vendor *Vendor;
  150. Vendor = new pkgSourceList::Vendor;
  151. Vendor->VendorID = Top->Tag;
  152. Vendor->FingerPrint = Block.Find("Fingerprint");
  153. Vendor->Description = Block.Find("Name");
  154. if (Vendor->FingerPrint.empty() == true ||
  155. Vendor->Description.empty() == true)
  156. {
  157. _error->Error(_("Vendor block %s is invalid"), Vendor->VendorID.c_str());
  158. delete Vendor;
  159. continue;
  160. }
  161. VendorList.push_back(Vendor);
  162. }
  163. /* XXX Process 'group-key' type sections
  164. This is currently faked out so that the vendors file format is
  165. parsed but nothing is done with it except check for validity */
  166. Top = Cnf.Tree("group-key");
  167. for (Top = (Top == 0?0:Top->Child); Top != 0; Top = Top->Next)
  168. {
  169. Configuration Block(Top);
  170. Vendor *Vendor;
  171. Vendor = new pkgSourceList::Vendor;
  172. Vendor->VendorID = Top->Tag;
  173. Vendor->Description = Block.Find("Name");
  174. if (Vendor->Description.empty() == true)
  175. {
  176. _error->Error(_("Vendor block %s is invalid"),
  177. Vendor->VendorID.c_str());
  178. delete Vendor;
  179. continue;
  180. }
  181. VendorList.push_back(Vendor);
  182. }
  183. return !_error->PendingError();
  184. }
  185. /*}}}*/
  186. // SourceList::ReadMainList - Read the main source list from etc /*{{{*/
  187. // ---------------------------------------------------------------------
  188. /* */
  189. bool pkgSourceList::ReadMainList()
  190. {
  191. return ReadVendors() && Read(_config->FindFile("Dir::Etc::sourcelist"));
  192. }
  193. /*}}}*/
  194. // SourceList::Read - Parse the sourcelist file /*{{{*/
  195. // ---------------------------------------------------------------------
  196. /* */
  197. bool pkgSourceList::Read(string File)
  198. {
  199. // Open the stream for reading
  200. ifstream F(File.c_str(),ios::in /*| ios::nocreate*/);
  201. if (!F != 0)
  202. return _error->Errno("ifstream::ifstream",_("Opening %s"),File.c_str());
  203. for (const_iterator I = SrcList.begin(); I != SrcList.end(); I++)
  204. delete *I;
  205. SrcList.erase(SrcList.begin(),SrcList.end());
  206. char Buffer[300];
  207. int CurLine = 0;
  208. while (F.eof() == false)
  209. {
  210. F.getline(Buffer,sizeof(Buffer));
  211. CurLine++;
  212. _strtabexpand(Buffer,sizeof(Buffer));
  213. if (F.fail() && !F.eof())
  214. return _error->Error(_("Line %u too long in source list %s."),
  215. CurLine,File.c_str());
  216. char *I;
  217. for (I = Buffer; *I != 0 && *I != '#'; I++);
  218. *I = 0;
  219. const char *C = _strstrip(Buffer);
  220. // Comment or blank
  221. if (C[0] == '#' || C[0] == 0)
  222. continue;
  223. // Grok it
  224. string LineType;
  225. if (ParseQuoteWord(C,LineType) == false)
  226. return _error->Error(_("Malformed line %u in source list %s (type)"),CurLine,File.c_str());
  227. Type *Parse = Type::GetType(LineType.c_str());
  228. if (Parse == 0)
  229. return _error->Error(_("Type '%s' is not known on line %u in source list %s"),LineType.c_str(),CurLine,File.c_str());
  230. // Authenticated repository
  231. Vendor const *Vndr = 0;
  232. if (C[0] == '[')
  233. {
  234. string VendorID;
  235. if (ParseQuoteWord(C,VendorID) == false)
  236. return _error->Error(_("Malformed line %u in source list %s (vendor id)"),CurLine,File.c_str());
  237. if (VendorID.length() < 2 || VendorID.end()[-1] != ']')
  238. return _error->Error(_("Malformed line %u in source list %s (vendor id)"),CurLine,File.c_str());
  239. VendorID = string(VendorID,1,VendorID.size()-2);
  240. for (vector<Vendor const *>::const_iterator iter = VendorList.begin();
  241. iter != VendorList.end(); iter++)
  242. {
  243. if ((*iter)->VendorID == VendorID)
  244. {
  245. Vndr = *iter;
  246. break;
  247. }
  248. }
  249. if (Vndr == 0)
  250. return _error->Error(_("Unknown vendor ID '%s' in line %u of source list %s"),
  251. VendorID.c_str(),CurLine,File.c_str());
  252. }
  253. if (Parse->ParseLine(SrcList,Vndr,C,CurLine,File) == false)
  254. return false;
  255. }
  256. return true;
  257. }
  258. /*}}}*/
  259. // SourceList::FindIndex - Get the index associated with a file /*{{{*/
  260. // ---------------------------------------------------------------------
  261. /* */
  262. bool pkgSourceList::FindIndex(pkgCache::PkgFileIterator File,
  263. pkgIndexFile *&Found) const
  264. {
  265. for (const_iterator I = SrcList.begin(); I != SrcList.end(); I++)
  266. {
  267. if ((*I)->FindInCache(*File.Cache()) == File)
  268. {
  269. Found = *I;
  270. return true;
  271. }
  272. }
  273. return false;
  274. }
  275. /*}}}*/
  276. // SourceList::GetIndexes - Load the index files into the downloader /*{{{*/
  277. // ---------------------------------------------------------------------
  278. /* */
  279. bool pkgSourceList::GetIndexes(pkgAcquire *Owner) const
  280. {
  281. for (const_iterator I = SrcList.begin(); I != SrcList.end(); I++)
  282. if ((*I)->GetIndexes(Owner) == false)
  283. return false;
  284. return true;
  285. }
  286. /*}}}*/