apt-cache.cc 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395
  1. // -*- mode: cpp; mode: fold -*-
  2. // Description /*{{{*/
  3. // $Id: apt-cache.cc,v 1.2 1998/07/16 06:08:43 jgg Exp $
  4. /* ######################################################################
  5. apt-cache - Manages the cache file.
  6. This program should eventually handle both low and high level
  7. manipulation of the cache file. Depending how far things go it
  8. might get quite a sophisticated UI.
  9. Currently the command line is as follows:
  10. apt-cache add cache file1:dist:ver file2:dist:ver ...
  11. ie:
  12. apt-cache add ./cache Pacakges:hamm:1.0
  13. A usefull feature is 'upgradable' ie
  14. apt-cache upgradable ./cache
  15. will list .debs that should be installed to make all packages the latest
  16. version.
  17. Returns 100 on failure, 0 on success.
  18. ##################################################################### */
  19. /*}}}*/
  20. // Include Files /*{{{*/
  21. #include <apt-pkg/error.h>
  22. #include <apt-pkg/pkgcachegen.h>
  23. #include <apt-pkg/deblistparser.h>
  24. #include <apt-pkg/init.h>
  25. #include <iostream.h>
  26. #include <fstream.h>
  27. /*}}}*/
  28. string CacheFile;
  29. // SplitArg - Split the triple /*{{{*/
  30. // ---------------------------------------------------------------------
  31. /* */
  32. bool SplitArg(const char *Arg,string &File,string &Dist,string Ver)
  33. {
  34. const char *Start = Arg;
  35. const char *I = Arg;
  36. for (;*I != 0 && *I != ':'; I++);
  37. if (*I != ':')
  38. return _error->Error("Malformed argument %s, must be in file:dist:rev form",Arg);
  39. File = string(Start,I - Start);
  40. I++;
  41. Start = I;
  42. for (;*I != 0 && *I != ':'; I++);
  43. if (*I != ':')
  44. return _error->Error("Malformed argument %s, must be in file:dist:rev form",Arg);
  45. Dist = string(Start,I - Start);
  46. I++;
  47. Start = I;
  48. for (;*I != 0 && *I != ':'; I++);
  49. if (I == Start)
  50. return _error->Error("Malformed argument %s, must be in file:dist:rev form",Arg);
  51. Ver = string(Start,I - Start);
  52. return true;
  53. }
  54. /*}}}*/
  55. // DoAdd - Perform an adding operation /*{{{*/
  56. // ---------------------------------------------------------------------
  57. /* */
  58. bool DoAdd(int argc,char *argv[])
  59. {
  60. string FileName;
  61. string Dist;
  62. string Ver;
  63. File CacheF(CacheFile,File::WriteEmpty);
  64. if (_error->PendingError() == true)
  65. return false;
  66. DynamicMMap Map(CacheF,MMap::Public);
  67. if (_error->PendingError() == true)
  68. return false;
  69. pkgCacheGenerator Gen(Map);
  70. if (_error->PendingError() == true)
  71. return false;
  72. for (int I = 0; I != argc; I++)
  73. {
  74. if (SplitArg(argv[I],FileName,Dist,Ver) == false)
  75. return false;
  76. cout << FileName << endl;
  77. // Do the merge
  78. File TagF(FileName.c_str(),File::ReadOnly);
  79. debListParser Parser(TagF);
  80. if (_error->PendingError() == true)
  81. return _error->Error("Problem opening %s",FileName.c_str());
  82. if (Gen.SelectFile(FileName) == false)
  83. return _error->Error("Problem with SelectFile");
  84. if (Gen.MergeList(Parser) == false)
  85. return _error->Error("Problem with MergeList");
  86. }
  87. return true;
  88. }
  89. /*}}}*/
  90. // DumpPackage - Show a dump of a package record /*{{{*/
  91. // ---------------------------------------------------------------------
  92. /* */
  93. bool DumpPackage(int argc,char *argv[])
  94. {
  95. File CacheF(CacheFile,File::ReadOnly);
  96. if (_error->PendingError() == true)
  97. return false;
  98. MMap Map(CacheF,MMap::Public | MMap::ReadOnly);
  99. if (_error->PendingError() == true)
  100. return false;
  101. pkgCache Cache(Map);
  102. if (_error->PendingError() == true)
  103. return false;
  104. for (int I = 0; I != argc; I++)
  105. {
  106. pkgCache::PkgIterator Pkg = Cache.FindPkg(argv[I]);
  107. if (Pkg.end() == true)
  108. {
  109. _error->Warning("Unable to locate package %s",argv[0]);
  110. continue;
  111. }
  112. cout << "Package: " << Pkg.Name() << endl;
  113. cout << "Versions: ";
  114. for (pkgCache::VerIterator Cur = Pkg.VersionList(); Cur.end() != true; Cur++)
  115. cout << Cur.VerStr() << ',';
  116. cout << endl;
  117. cout << "Reverse Depends: " << endl;
  118. for (pkgCache::DepIterator D = Pkg.RevDependsList(); D.end() != true; D++)
  119. cout << " " << D.ParentPkg().Name() << ',' << D.TargetPkg().Name() << endl;
  120. cout << "Dependencies: " << endl;
  121. for (pkgCache::VerIterator Cur = Pkg.VersionList(); Cur.end() != true; Cur++)
  122. {
  123. cout << Cur.VerStr() << " - ";
  124. for (pkgCache::DepIterator Dep = Cur.DependsList(); Dep.end() != true; Dep++)
  125. cout << Dep.TargetPkg().Name() << " (" << (int)Dep->CompareOp << " " << Dep.TargetVer() << ") ";
  126. cout << endl;
  127. }
  128. cout << "Provides: " << endl;
  129. for (pkgCache::VerIterator Cur = Pkg.VersionList(); Cur.end() != true; Cur++)
  130. {
  131. cout << Cur.VerStr() << " - ";
  132. for (pkgCache::PrvIterator Prv = Cur.ProvidesList(); Prv.end() != true; Prv++)
  133. cout << Prv.ParentPkg().Name() << " ";
  134. cout << endl;
  135. }
  136. cout << "Reverse Provides: " << endl;
  137. for (pkgCache::PrvIterator Prv = Pkg.ProvidesList(); Prv.end() != true; Prv++)
  138. cout << Prv.OwnerPkg().Name() << " " << Prv.OwnerVer().VerStr();
  139. cout << endl;
  140. }
  141. return true;
  142. }
  143. /*}}}*/
  144. // Stats - Dump some nice statistics /*{{{*/
  145. // ---------------------------------------------------------------------
  146. /* */
  147. bool Stats(const char *FileName)
  148. {
  149. File CacheF(FileName,File::ReadOnly);
  150. if (_error->PendingError() == true)
  151. return false;
  152. MMap Map(CacheF,MMap::Public | MMap::ReadOnly);
  153. if (_error->PendingError() == true)
  154. return false;
  155. pkgCache Cache(Map);
  156. if (_error->PendingError() == true)
  157. return false;
  158. cout << "Total Package Names : " << Cache.Head().PackageCount << endl;
  159. pkgCache::PkgIterator I = Cache.PkgBegin();
  160. int Normal = 0;
  161. int Virtual = 0;
  162. int NVirt = 0;
  163. int DVirt = 0;
  164. int Missing = 0;
  165. for (;I.end() != true; I++)
  166. {
  167. if (I->VersionList != 0 && I->ProvidesList == 0)
  168. {
  169. Normal++;
  170. continue;
  171. }
  172. if (I->VersionList != 0 && I->ProvidesList != 0)
  173. {
  174. NVirt++;
  175. continue;
  176. }
  177. if (I->VersionList == 0 && I->ProvidesList != 0)
  178. {
  179. // Only 1 provides
  180. if (I.ProvidesList()->NextProvides == 0)
  181. {
  182. DVirt++;
  183. }
  184. else
  185. Virtual++;
  186. continue;
  187. }
  188. if (I->VersionList == 0 && I->ProvidesList == 0)
  189. {
  190. Missing++;
  191. continue;
  192. }
  193. }
  194. cout << " Normal Packages: " << Normal << endl;
  195. cout << " Pure Virtual Packages: " << Virtual << endl;
  196. cout << " Single Virtual Packages: " << DVirt << endl;
  197. cout << " Mixed Virtual Packages: " << NVirt << endl;
  198. cout << " Missing: " << Missing << endl;
  199. cout << "Total Distinct Versions: " << Cache.Head().VersionCount << endl;
  200. cout << "Total Dependencies: " << Cache.Head().DependsCount << endl;
  201. return true;
  202. }
  203. /*}}}*/
  204. // Dump - show everything /*{{{*/
  205. // ---------------------------------------------------------------------
  206. /* */
  207. bool Dump()
  208. {
  209. File CacheF(CacheFile,File::ReadOnly);
  210. if (_error->PendingError() == true)
  211. return false;
  212. MMap Map(CacheF,MMap::Public | MMap::ReadOnly);
  213. if (_error->PendingError() == true)
  214. return false;
  215. pkgCache Cache(Map);
  216. if (_error->PendingError() == true)
  217. return false;
  218. for (pkgCache::PkgIterator P = Cache.PkgBegin(); P.end() == false; P++)
  219. {
  220. cout << "Package: " << P.Name() << endl;
  221. for (pkgCache::VerIterator V = P.VersionList(); V.end() == false; V++)
  222. {
  223. cout << " Version: " << V.VerStr() << endl;
  224. cout << " File: " << V.FileList().File().FileName() << endl;
  225. for (pkgCache::DepIterator D = V.DependsList(); D.end() == false; D++)
  226. cout << " Depends: " << D.TargetPkg().Name() << ' ' << D.TargetVer() << endl;
  227. }
  228. }
  229. for (pkgCache::PkgFileIterator F(Cache); F.end() == false; F++)
  230. {
  231. cout << "File: " << F.FileName() << endl;
  232. cout << " Size: " << F->Size << endl;
  233. cout << " ID: " << F->ID << endl;
  234. cout << " Flags: " << F->Flags << endl;
  235. cout << " Time: " << ctime(&F->mtime) << endl;
  236. }
  237. return true;
  238. }
  239. /*}}}*/
  240. // DumpAvail - Print out the available list /*{{{*/
  241. // ---------------------------------------------------------------------
  242. /* This is needed to make dpkg --merge happy */
  243. bool DumpAvail()
  244. {
  245. #if 0
  246. pkgCache Cache(CacheFile,true,true);
  247. if (_error->PendingError() == true)
  248. return false;
  249. pkgControlCache CCache(Cache);
  250. if (_error->PendingError() == true)
  251. return false;
  252. vector<string> Lines;
  253. Lines.reserve(30);
  254. pkgCache::PkgIterator I = Cache.PkgBegin();
  255. for (;I.end() != true; I++)
  256. {
  257. if (I->VersionList == 0)
  258. continue;
  259. pkgSPkgCtrlInfo Inf = CCache[I.VersionList()];
  260. if (Inf.isNull() == true)
  261. return _error->Error("Couldn't locate info record");
  262. // Iterate over each element
  263. pkgPkgCtrlInfo::const_iterator Elm = Inf->begin();
  264. for (; Elm != Inf->end(); Elm++)
  265. {
  266. // Write the tag: value
  267. cout << (*Elm)->Tag() << ": " << (*Elm)->Value() << endl;
  268. // Write the multiline
  269. (*Elm)->GetLines(Lines);
  270. for (vector<string>::iterator j = Lines.begin(); j != Lines.end(); j++)
  271. {
  272. if ((*j).length() == 0)
  273. cout << " ." << endl;
  274. else
  275. cout << " " << *j << endl;
  276. }
  277. Lines.erase(Lines.begin(),Lines.end());
  278. }
  279. cout << endl;
  280. }
  281. #endif
  282. return true;
  283. }
  284. /*}}}*/
  285. int main(int argc, char *argv[])
  286. {
  287. // Check arguments.
  288. if (argc < 3)
  289. {
  290. cerr << "Usage is apt-cache add cache file1:dist:ver file2:dist:ver ..." << endl;
  291. return 100;
  292. }
  293. pkgInitialize(*_config);
  294. while (1)
  295. {
  296. if (strcmp(argv[1],"add") == 0)
  297. {
  298. CacheFile = argv[2];
  299. if (DoAdd(argc - 3,argv + 3) == true)
  300. Stats(argv[2]);
  301. break;
  302. }
  303. if (strcmp(argv[1],"showpkg") == 0)
  304. {
  305. CacheFile = argv[2];
  306. DumpPackage(argc - 3,argv + 3);
  307. break;
  308. }
  309. if (strcmp(argv[1],"stats") == 0)
  310. {
  311. Stats(argv[2]);
  312. break;
  313. }
  314. if (strcmp(argv[1],"dump") == 0)
  315. {
  316. CacheFile = argv[2];
  317. Dump();
  318. break;
  319. }
  320. if (strcmp(argv[1],"dumpavail") == 0)
  321. {
  322. CacheFile = argv[2];
  323. DumpAvail();
  324. break;
  325. }
  326. _error->Error("Invalid operation %s", argv[1]);
  327. break;
  328. }
  329. // Print any errors or warnings found during parsing
  330. if (_error->empty() == false)
  331. {
  332. _error->DumpErrors();
  333. return 100;
  334. }
  335. return 0;
  336. }