sourcelist.cc 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291
  1. // -*- mode: cpp; mode: fold -*-
  2. // Description /*{{{*/
  3. // $Id: sourcelist.cc,v 1.3 1998/07/12 23:58:36 jgg 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 <strutl.h>
  17. #include <fstream.h>
  18. #include <stdio.h>
  19. #include <unistd.h>
  20. #include <sys/stat.h>
  21. /*}}}*/
  22. // SourceList::pkgSourceList - Constructors /*{{{*/
  23. // ---------------------------------------------------------------------
  24. /* */
  25. pkgSourceList::pkgSourceList()
  26. {
  27. }
  28. pkgSourceList::pkgSourceList(string File)
  29. {
  30. Read(File);
  31. }
  32. /*}}}*/
  33. // SourceList::ReadMainList - Read the main source list from etc /*{{{*/
  34. // ---------------------------------------------------------------------
  35. /* */
  36. bool pkgSourceList::ReadMainList()
  37. {
  38. return Read(_config->Find("APT::Etc:sourcelist"));
  39. }
  40. /*}}}*/
  41. // SourceList::Read - Parse the sourcelist file /*{{{*/
  42. // ---------------------------------------------------------------------
  43. /* */
  44. bool pkgSourceList::Read(string File)
  45. {
  46. // Open the stream for reading
  47. ifstream F(File.c_str(),ios::in | ios::nocreate);
  48. if (!F != 0)
  49. return _error->Errno("ifstream::ifstream","Opening %s",File.c_str());
  50. List.erase(List.begin(),List.end());
  51. char Buffer[300];
  52. int CurLine = 0;
  53. while (F.eof() == false)
  54. {
  55. F.getline(Buffer,sizeof(Buffer));
  56. CurLine++;
  57. _strtabexpand(Buffer,sizeof(Buffer));
  58. _strstrip(Buffer);
  59. // Comment or blank
  60. if (Buffer[0] == '#' || Buffer[0] == 0)
  61. continue;
  62. // Grok it
  63. string Type;
  64. string URI;
  65. Item Itm;
  66. char *C = Buffer;
  67. if (ParseQuoteWord(C,Type) == false)
  68. return _error->Error("Malformed line %u in source list %s (type)",CurLine,File.c_str());
  69. if (ParseQuoteWord(C,URI) == false)
  70. return _error->Error("Malformed line %u in source list %s (URI)",CurLine,File.c_str());
  71. if (ParseQuoteWord(C,Itm.Dist) == false)
  72. return _error->Error("Malformed line %u in source list %s (dist)",CurLine,File.c_str());
  73. if (Itm.SetType(Type) == false)
  74. return _error->Error("Malformed line %u in source list %s (type parse)",CurLine,File.c_str());
  75. if (Itm.SetURI(URI) == false)
  76. return _error->Error("Malformed line %u in source list %s (URI parse)",CurLine,File.c_str());
  77. // Check for an absolute dists specification.
  78. if (Itm.Dist.empty() == false && Itm.Dist[Itm.Dist.size() - 1] == '/')
  79. {
  80. if (ParseQuoteWord(C,Itm.Section) == true)
  81. return _error->Error("Malformed line %u in source list %s (Absolute dist)",CurLine,File.c_str());
  82. Itm.Dist = SubstVar(Itm.Dist,"$(ARCH)",_config->Find("APT::Architecture"));
  83. List.push_back(Itm);
  84. continue;
  85. }
  86. // Grab the rest of the dists
  87. if (ParseQuoteWord(C,Itm.Section) == false)
  88. return _error->Error("Malformed line %u in source list %s (dist parse)",CurLine,File.c_str());
  89. do
  90. {
  91. List.push_back(Itm);
  92. }
  93. while (ParseQuoteWord(C,Itm.Section) == true);
  94. }
  95. return true;
  96. }
  97. /*}}}*/
  98. // SourceList::SanitizeURI - Hash the uri /*{{{*/
  99. // ---------------------------------------------------------------------
  100. /* This converts a URI into a safe filename. It quotes all unsafe characters
  101. and converts / to _ and removes the scheme identifier. */
  102. string pkgSourceList::SanitizeURI(string URI)
  103. {
  104. string::const_iterator I = URI.begin() + URI.find(':') + 1;
  105. for (; I < URI.end() && *I == '/'; I++);
  106. // "\x00-\x20{}|\\\\^\\[\\]<>\"\x7F-\xFF";
  107. URI = QuoteString(string(I,URI.end() - I),"\\|{}[]<>\"^~_=!@#$%^&*");
  108. string::iterator J = URI.begin();
  109. for (; J != URI.end(); J++)
  110. if (*J == '/')
  111. *J = '_';
  112. return URI;
  113. }
  114. /*}}}*/
  115. // SourceList::MatchPkgFile - Find the package file that has the ver /*{{{*/
  116. // ---------------------------------------------------------------------
  117. /* This will return List.end() if it could not find the matching
  118. file */
  119. pkgSourceList::const_iterator pkgSourceList::MatchPkgFile(pkgCache::VerIterator Ver)
  120. {
  121. string Base = _config->Find("APT::Architecture");
  122. for (const_iterator I = List.begin(); I != List.end(); I++)
  123. {
  124. string URI = I->PackagesURI();
  125. switch (I->Type)
  126. {
  127. case Item::Deb:
  128. /* if (Base + SanitizeURI(URI) == Ver.File().FileName())
  129. return I;*/
  130. break;
  131. };
  132. }
  133. return List.end();
  134. }
  135. /*}}}*/
  136. // SourceList::Item << - Writes the item to a stream /*{{{*/
  137. // ---------------------------------------------------------------------
  138. /* This is not suitable for rebuilding the sourcelist file but it good for
  139. debugging. */
  140. ostream &operator <<(ostream &O,pkgSourceList::Item &Itm)
  141. {
  142. O << Itm.Type << ' ' << Itm.URI << ' ' << Itm.Dist << ' ' << Itm.Section;
  143. return O;
  144. }
  145. /*}}}*/
  146. // SourceList::Item::SetType - Sets the distribution type /*{{{*/
  147. // ---------------------------------------------------------------------
  148. /* */
  149. bool pkgSourceList::Item::SetType(string S)
  150. {
  151. if (S == "deb")
  152. {
  153. Type = Deb;
  154. return true;
  155. }
  156. return true;
  157. }
  158. /*}}}*/
  159. // SourceList::Item::SetURI - Set the URI /*{{{*/
  160. // ---------------------------------------------------------------------
  161. /* For simplicity we strip the scheme off the uri */
  162. bool pkgSourceList::Item::SetURI(string S)
  163. {
  164. if (S.empty() == true)
  165. return false;
  166. if (S.find(':') == string::npos)
  167. return false;
  168. S = SubstVar(S,"$(ARCH)",_config->Find("APT::Architecture"));
  169. // Make sure that the URN is / postfixed
  170. URI = S;
  171. if (URI[URI.size() - 1] != '/')
  172. URI += '/';
  173. return true;
  174. }
  175. /*}}}*/
  176. // SourceList::Item::PackagesURI - Returns a URI to the packages file /*{{{*/
  177. // ---------------------------------------------------------------------
  178. /* */
  179. string pkgSourceList::Item::PackagesURI() const
  180. {
  181. string Res;
  182. switch (Type)
  183. {
  184. case Deb:
  185. if (Dist[Dist.size() - 1] == '/')
  186. Res = URI + Dist;
  187. else
  188. Res = URI + "dists/" + Dist + '/' + Section +
  189. "/binary-" + _config->Find("APT::Architecture") + '/';
  190. Res += "Packages";
  191. break;
  192. };
  193. return Res;
  194. }
  195. /*}}}*/
  196. // SourceList::Item::PackagesInfo - Shorter version of the URI /*{{{*/
  197. // ---------------------------------------------------------------------
  198. /* This is a shorter version that is designed to be < 60 chars or so */
  199. string pkgSourceList::Item::PackagesInfo() const
  200. {
  201. string Res;
  202. switch (Type)
  203. {
  204. case Deb:
  205. Res += SiteOnly(URI) + ' ';
  206. if (Dist[Dist.size() - 1] == '/')
  207. Res += Dist;
  208. else
  209. Res += Dist + '/' + Section;
  210. Res += " Packages";
  211. break;
  212. };
  213. return Res;
  214. }
  215. /*}}}*/
  216. // SourceList::Item::ArchiveInfo - Shorter version of the archive spec /*{{{*/
  217. // ---------------------------------------------------------------------
  218. /* This is a shorter version that is designed to be < 60 chars or so */
  219. string pkgSourceList::Item::ArchiveInfo(pkgCache::VerIterator Ver) const
  220. {
  221. string Res;
  222. switch (Type)
  223. {
  224. case Deb:
  225. Res += SiteOnly(URI) + ' ';
  226. if (Dist[Dist.size() - 1] == '/')
  227. Res += Dist;
  228. else
  229. Res += Dist + '/' + Section;
  230. Res += " ";
  231. Res += Ver.ParentPkg().Name();
  232. break;
  233. };
  234. return Res;
  235. }
  236. /*}}}*/
  237. // SourceList::Item::ArchiveURI - Returns a URI to the given archive /*{{{*/
  238. // ---------------------------------------------------------------------
  239. /* */
  240. string pkgSourceList::Item::ArchiveURI(string File) const
  241. {
  242. string Res;
  243. switch (Type)
  244. {
  245. case Deb:
  246. Res = URI + File;
  247. break;
  248. };
  249. return Res;
  250. }
  251. /*}}}*/
  252. // SourceList::Item::SiteOnly - Strip off the path part of a URI /*{{{*/
  253. // ---------------------------------------------------------------------
  254. /* */
  255. string pkgSourceList::Item::SiteOnly(string URI) const
  256. {
  257. unsigned int Pos = URI.find(':');
  258. if (Pos == string::npos || Pos + 3 > URI.length())
  259. return URI;
  260. if (URI[Pos + 1] != '/' || URI[Pos + 2] != '/')
  261. return URI;
  262. Pos = URI.find('/',Pos + 3);
  263. if (Pos == string::npos)
  264. return URI;
  265. return string(URI,0,Pos);
  266. }
  267. /*}}}*/