apt-cache.cc 10 KB

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