apt-cache.cc 9.9 KB

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