apt-cache.cc 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370
  1. // -*- mode: cpp; mode: fold -*-
  2. // Description /*{{{*/
  3. // $Id: apt-cache.cc,v 1.3 1998/07/19 04:22:10 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. // DumpPackage - Show a dump of a package record /*{{{*/
  56. // ---------------------------------------------------------------------
  57. /* */
  58. bool DumpPackage(pkgCache &Cache,int argc,char *argv[])
  59. {
  60. for (int I = 0; I != argc; I++)
  61. {
  62. pkgCache::PkgIterator Pkg = Cache.FindPkg(argv[I]);
  63. if (Pkg.end() == true)
  64. {
  65. _error->Warning("Unable to locate package %s",argv[0]);
  66. continue;
  67. }
  68. cout << "Package: " << Pkg.Name() << endl;
  69. cout << "Versions: ";
  70. for (pkgCache::VerIterator Cur = Pkg.VersionList(); Cur.end() != true; Cur++)
  71. cout << Cur.VerStr() << ',';
  72. cout << endl;
  73. cout << "Reverse Depends: " << endl;
  74. for (pkgCache::DepIterator D = Pkg.RevDependsList(); D.end() != true; D++)
  75. cout << " " << D.ParentPkg().Name() << ',' << D.TargetPkg().Name() << endl;
  76. cout << "Dependencies: " << endl;
  77. for (pkgCache::VerIterator Cur = Pkg.VersionList(); Cur.end() != true; Cur++)
  78. {
  79. cout << Cur.VerStr() << " - ";
  80. for (pkgCache::DepIterator Dep = Cur.DependsList(); Dep.end() != true; Dep++)
  81. cout << Dep.TargetPkg().Name() << " (" << (int)Dep->CompareOp << " " << Dep.TargetVer() << ") ";
  82. cout << endl;
  83. }
  84. cout << "Provides: " << endl;
  85. for (pkgCache::VerIterator Cur = Pkg.VersionList(); Cur.end() != true; Cur++)
  86. {
  87. cout << Cur.VerStr() << " - ";
  88. for (pkgCache::PrvIterator Prv = Cur.ProvidesList(); Prv.end() != true; Prv++)
  89. cout << Prv.ParentPkg().Name() << " ";
  90. cout << endl;
  91. }
  92. cout << "Reverse Provides: " << endl;
  93. for (pkgCache::PrvIterator Prv = Pkg.ProvidesList(); Prv.end() != true; Prv++)
  94. cout << Prv.OwnerPkg().Name() << " " << Prv.OwnerVer().VerStr();
  95. cout << endl;
  96. }
  97. return true;
  98. }
  99. /*}}}*/
  100. // Stats - Dump some nice statistics /*{{{*/
  101. // ---------------------------------------------------------------------
  102. /* */
  103. bool Stats(pkgCache &Cache)
  104. {
  105. cout << "Total Package Names : " << Cache.Head().PackageCount << endl;
  106. pkgCache::PkgIterator I = Cache.PkgBegin();
  107. int Normal = 0;
  108. int Virtual = 0;
  109. int NVirt = 0;
  110. int DVirt = 0;
  111. int Missing = 0;
  112. for (;I.end() != true; I++)
  113. {
  114. if (I->VersionList != 0 && I->ProvidesList == 0)
  115. {
  116. Normal++;
  117. continue;
  118. }
  119. if (I->VersionList != 0 && I->ProvidesList != 0)
  120. {
  121. NVirt++;
  122. continue;
  123. }
  124. if (I->VersionList == 0 && I->ProvidesList != 0)
  125. {
  126. // Only 1 provides
  127. if (I.ProvidesList()->NextProvides == 0)
  128. {
  129. DVirt++;
  130. }
  131. else
  132. Virtual++;
  133. continue;
  134. }
  135. if (I->VersionList == 0 && I->ProvidesList == 0)
  136. {
  137. Missing++;
  138. continue;
  139. }
  140. }
  141. cout << " Normal Packages: " << Normal << endl;
  142. cout << " Pure Virtual Packages: " << Virtual << endl;
  143. cout << " Single Virtual Packages: " << DVirt << endl;
  144. cout << " Mixed Virtual Packages: " << NVirt << endl;
  145. cout << " Missing: " << Missing << endl;
  146. cout << "Total Distinct Versions: " << Cache.Head().VersionCount << endl;
  147. cout << "Total Dependencies: " << Cache.Head().DependsCount << endl;
  148. return true;
  149. }
  150. /*}}}*/
  151. // Dump - show everything /*{{{*/
  152. // ---------------------------------------------------------------------
  153. /* */
  154. bool Dump(pkgCache &Cache)
  155. {
  156. for (pkgCache::PkgIterator P = Cache.PkgBegin(); P.end() == false; P++)
  157. {
  158. cout << "Package: " << P.Name() << endl;
  159. for (pkgCache::VerIterator V = P.VersionList(); V.end() == false; V++)
  160. {
  161. cout << " Version: " << V.VerStr() << endl;
  162. cout << " File: " << V.FileList().File().FileName() << endl;
  163. for (pkgCache::DepIterator D = V.DependsList(); D.end() == false; D++)
  164. cout << " Depends: " << D.TargetPkg().Name() << ' ' << D.TargetVer() << endl;
  165. }
  166. }
  167. for (pkgCache::PkgFileIterator F(Cache); F.end() == false; F++)
  168. {
  169. cout << "File: " << F.FileName() << endl;
  170. cout << " Size: " << F->Size << endl;
  171. cout << " ID: " << F->ID << endl;
  172. cout << " Flags: " << F->Flags << endl;
  173. cout << " Time: " << ctime(&F->mtime) << endl;
  174. }
  175. return true;
  176. }
  177. /*}}}*/
  178. // DumpAvail - Print out the available list /*{{{*/
  179. // ---------------------------------------------------------------------
  180. /* This is needed to make dpkg --merge happy */
  181. bool DumpAvail(pkgCache &Cache)
  182. {
  183. unsigned char *Buffer = new unsigned char[Cache.HeaderP->MaxVerFileSize];
  184. for (pkgCache::PkgFileIterator I = Cache.FileBegin(); I.end() == false; I++)
  185. {
  186. if ((I->Flags & pkgCache::Flag::NotSource) != 0)
  187. continue;
  188. if (I.IsOk() == false)
  189. {
  190. delete [] Buffer;
  191. return _error->Error("Package file %s is out of sync.",I.FileName());
  192. }
  193. File PkgF(I.FileName(),File::ReadOnly);
  194. if (_error->PendingError() == true)
  195. {
  196. delete [] Buffer;
  197. return false;
  198. }
  199. /* Write all of the records from this package file, we search the entire
  200. structure to find them */
  201. for (pkgCache::PkgIterator P = Cache.PkgBegin(); P.end() == false; P++)
  202. {
  203. for (pkgCache::VerIterator V = P.VersionList(); V.end() == false; V++)
  204. {
  205. if (V->FileList == 0)
  206. continue;
  207. if (V.FileList().File() != I)
  208. continue;
  209. // Read the record and then write it out again.
  210. if (PkgF.Seek(V.FileList()->Offset) == false ||
  211. PkgF.Read(Buffer,V.FileList()->Size) == false ||
  212. write(STDOUT_FILENO,Buffer,V.FileList()->Size) != V.FileList()->Size)
  213. {
  214. delete [] Buffer;
  215. return false;
  216. }
  217. }
  218. }
  219. }
  220. return true;
  221. }
  222. /*}}}*/
  223. // DoAdd - Perform an adding operation /*{{{*/
  224. // ---------------------------------------------------------------------
  225. /* */
  226. bool DoAdd(int argc,char *argv[])
  227. {
  228. string FileName;
  229. string Dist;
  230. string Ver;
  231. // Open the cache
  232. File CacheF(CacheFile,File::WriteEmpty);
  233. if (_error->PendingError() == true)
  234. return false;
  235. DynamicMMap Map(CacheF,MMap::Public);
  236. if (_error->PendingError() == true)
  237. return false;
  238. pkgCacheGenerator Gen(Map);
  239. if (_error->PendingError() == true)
  240. return false;
  241. for (int I = 0; I != argc; I++)
  242. {
  243. if (SplitArg(argv[I],FileName,Dist,Ver) == false)
  244. return false;
  245. cout << FileName << endl;
  246. // Do the merge
  247. File TagF(FileName.c_str(),File::ReadOnly);
  248. debListParser Parser(TagF);
  249. if (_error->PendingError() == true)
  250. return _error->Error("Problem opening %s",FileName.c_str());
  251. if (Gen.SelectFile(FileName) == false)
  252. return _error->Error("Problem with SelectFile");
  253. if (Gen.MergeList(Parser) == false)
  254. return _error->Error("Problem with MergeList");
  255. }
  256. Stats(Gen.GetCache());
  257. return true;
  258. }
  259. /*}}}*/
  260. int main(int argc, char *argv[])
  261. {
  262. // Check arguments.
  263. if (argc < 3)
  264. {
  265. cerr << "Usage is apt-cache add cache file1:dist:ver file2:dist:ver ..." << endl;
  266. return 100;
  267. }
  268. pkgInitialize(*_config);
  269. while (1)
  270. {
  271. CacheFile = argv[2];
  272. if (strcmp(argv[1],"add") == 0)
  273. {
  274. DoAdd(argc - 3,argv + 3);
  275. break;
  276. }
  277. // Open the cache file
  278. File CacheF(CacheFile,File::ReadOnly);
  279. if (_error->PendingError() == true)
  280. break;
  281. MMap Map(CacheF,MMap::Public | MMap::ReadOnly);
  282. if (_error->PendingError() == true)
  283. break;
  284. pkgCache Cache(Map);
  285. if (_error->PendingError() == true)
  286. break;
  287. if (strcmp(argv[1],"showpkg") == 0)
  288. {
  289. CacheFile = argv[2];
  290. DumpPackage(Cache,argc - 3,argv + 3);
  291. break;
  292. }
  293. if (strcmp(argv[1],"stats") == 0)
  294. {
  295. Stats(Cache);
  296. break;
  297. }
  298. if (strcmp(argv[1],"dump") == 0)
  299. {
  300. Dump(Cache);
  301. break;
  302. }
  303. if (strcmp(argv[1],"dumpavail") == 0)
  304. {
  305. DumpAvail(Cache);
  306. break;
  307. }
  308. _error->Error("Invalid operation %s", argv[1]);
  309. break;
  310. }
  311. // Print any errors or warnings found during parsing
  312. if (_error->empty() == false)
  313. {
  314. _error->DumpErrors();
  315. return 100;
  316. }
  317. return 0;
  318. }