pkgcachegen.cc 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367
  1. // -*- mode: cpp; mode: fold -*-
  2. // Description /*{{{*/
  3. // $Id: pkgcachegen.cc,v 1.12 1998/07/21 05:33:19 jgg Exp $
  4. /* ######################################################################
  5. Package Cache Generator - Generator for the cache structure.
  6. This builds the cache structure from the abstract package list parser.
  7. ##################################################################### */
  8. /*}}}*/
  9. // Include Files /*{{{*/
  10. #ifdef __GNUG__
  11. #pragma implementation "apt-pkg/pkgcachegen.h"
  12. #endif
  13. #include <apt-pkg/pkgcachegen.h>
  14. #include <apt-pkg/error.h>
  15. #include <apt-pkg/version.h>
  16. #include <strutl.h>
  17. #include <sys/stat.h>
  18. #include <unistd.h>
  19. /*}}}*/
  20. // CacheGenerator::pkgCacheGenerator - Constructor /*{{{*/
  21. // ---------------------------------------------------------------------
  22. /* We set the diry flag and make sure that is written to the disk */
  23. pkgCacheGenerator::pkgCacheGenerator(DynamicMMap &Map,OpProgress &Prog) :
  24. Map(Map), Cache(Map), Progress(Prog)
  25. {
  26. if (_error->PendingError() == true)
  27. return;
  28. if (Map.Size() == 0)
  29. {
  30. Map.RawAllocate(sizeof(pkgCache::Header));
  31. *Cache.HeaderP = pkgCache::Header();
  32. }
  33. Cache.HeaderP->Dirty = true;
  34. Map.Sync(0,sizeof(pkgCache::Header));
  35. Map.UsePools(*Cache.HeaderP->Pools,sizeof(Cache.HeaderP->Pools)/sizeof(Cache.HeaderP->Pools[0]));
  36. }
  37. /*}}}*/
  38. // CacheGenerator::~pkgCacheGenerator - Destructor /*{{{*/
  39. // ---------------------------------------------------------------------
  40. /* We sync the data then unset the dirty flag in two steps so as to
  41. advoid a problem during a crash */
  42. pkgCacheGenerator::~pkgCacheGenerator()
  43. {
  44. if (_error->PendingError() == true)
  45. return;
  46. if (Map.Sync() == false)
  47. return;
  48. Cache.HeaderP->Dirty = false;
  49. Map.Sync(0,sizeof(pkgCache::Header));
  50. }
  51. /*}}}*/
  52. // CacheGenerator::MergeList - Merge the package list /*{{{*/
  53. // ---------------------------------------------------------------------
  54. /* This provides the generation of the entries in the cache. Each loop
  55. goes through a single package record from the underlying parse engine. */
  56. bool pkgCacheGenerator::MergeList(ListParser &List)
  57. {
  58. List.Owner = this;
  59. while (List.Step() == true)
  60. {
  61. // Get a pointer to the package structure
  62. string PackageName = List.Package();
  63. pkgCache::PkgIterator Pkg;
  64. if (NewPackage(Pkg,PackageName) == false)
  65. return false;
  66. Progress.Progress(List.Offset());
  67. /* Get a pointer to the version structure. We know the list is sorted
  68. so we use that fact in the search. Insertion of new versions is
  69. done with correct sorting */
  70. string Version = List.Version();
  71. if (Version.empty() == true)
  72. {
  73. if (List.UsePackage(Pkg,pkgCache::VerIterator(Cache)) == false)
  74. return false;
  75. continue;
  76. }
  77. pkgCache::VerIterator Ver = Pkg.VersionList();
  78. unsigned long *Last = &Pkg->VersionList;
  79. int Res = 1;
  80. for (; Ver.end() == false; Last = &Ver->NextVer, Ver++)
  81. {
  82. Res = pkgVersionCompare(Version.begin(),Version.end(),Ver.VerStr(),
  83. Ver.VerStr() + strlen(Ver.VerStr()));
  84. if (Res >= 0)
  85. break;
  86. }
  87. /* We already have a version for this item, record that we
  88. saw it */
  89. if (Res == 0)
  90. {
  91. if (List.UsePackage(Pkg,Ver) == false)
  92. return false;
  93. if (NewFileVer(Ver,List) == false)
  94. return false;
  95. continue;
  96. }
  97. // Add a new version
  98. *Last = NewVersion(Ver,Version,*Last);
  99. Ver->ParentPkg = Pkg.Index();
  100. if (List.NewVersion(Ver) == false)
  101. return false;
  102. if (List.UsePackage(Pkg,Ver) == false)
  103. return false;
  104. if (NewFileVer(Ver,List) == false)
  105. return false;
  106. }
  107. return true;
  108. }
  109. /*}}}*/
  110. // CacheGenerator::NewPackage - Add a new package /*{{{*/
  111. // ---------------------------------------------------------------------
  112. /* This creates a new package structure and adds it to the hash table */
  113. bool pkgCacheGenerator::NewPackage(pkgCache::PkgIterator &Pkg,string Name)
  114. {
  115. Pkg = Cache.FindPkg(Name);
  116. if (Pkg.end() == false)
  117. return true;
  118. // Get a structure
  119. unsigned long Package = Map.Allocate(sizeof(pkgCache::Package));
  120. if (Package == 0)
  121. return false;
  122. Pkg = pkgCache::PkgIterator(Cache,Cache.PkgP + Package);
  123. // Insert it into the hash table
  124. unsigned long Hash = Cache.Hash(Name);
  125. Pkg->NextPackage = Cache.HeaderP->HashTable[Hash];
  126. Cache.HeaderP->HashTable[Hash] = Package;
  127. // Set the name and the ID
  128. Pkg->Name = Map.WriteString(Name);
  129. if (Pkg->Name == 0)
  130. return false;
  131. Pkg->ID = Cache.HeaderP->PackageCount++;
  132. return true;
  133. }
  134. /*}}}*/
  135. // CacheGenerator::NewFileVer - Create a new File<->Version association /*{{{*/
  136. // ---------------------------------------------------------------------
  137. /* */
  138. bool pkgCacheGenerator::NewFileVer(pkgCache::VerIterator &Ver,
  139. ListParser &List)
  140. {
  141. // Get a structure
  142. unsigned long VerFile = Map.Allocate(sizeof(pkgCache::VerFile));
  143. if (VerFile == 0)
  144. return 0;
  145. pkgCache::VerFileIterator VF(Cache,Cache.VerFileP + VerFile);
  146. VF->File = CurrentFile - Cache.PkgFileP;
  147. VF->NextFile = Ver->FileList;
  148. Ver->FileList = VF.Index();
  149. VF->Offset = List.Offset();
  150. VF->Size = List.Size();
  151. if (Cache.HeaderP->MaxVerFileSize < VF->Size)
  152. Cache.HeaderP->MaxVerFileSize = VF->Size;
  153. return true;
  154. }
  155. /*}}}*/
  156. // CacheGenerator::NewVersion - Create a new Version /*{{{*/
  157. // ---------------------------------------------------------------------
  158. /* This puts a version structure in the linked list */
  159. unsigned long pkgCacheGenerator::NewVersion(pkgCache::VerIterator &Ver,
  160. string VerStr,
  161. unsigned long Next)
  162. {
  163. // Get a structure
  164. unsigned long Version = Map.Allocate(sizeof(pkgCache::Version));
  165. if (Version == 0)
  166. return 0;
  167. // Fill it in
  168. Ver = pkgCache::VerIterator(Cache,Cache.VerP + Version);
  169. Ver->NextVer = Next;
  170. Ver->ID = Cache.HeaderP->VersionCount++;
  171. Ver->VerStr = Map.WriteString(VerStr);
  172. if (Ver->VerStr == 0)
  173. return 0;
  174. return Version;
  175. }
  176. /*}}}*/
  177. // ListParser::NewDepends - Create a dependency element /*{{{*/
  178. // ---------------------------------------------------------------------
  179. /* This creates a dependency element in the tree. It is linked to the
  180. version and to the package that it is pointing to. */
  181. bool pkgCacheGenerator::ListParser::NewDepends(pkgCache::VerIterator Ver,
  182. string PackageName,
  183. string Version,
  184. unsigned int Op,
  185. unsigned int Type)
  186. {
  187. pkgCache &Cache = Owner->Cache;
  188. // Get a structure
  189. unsigned long Dependency = Owner->Map.Allocate(sizeof(pkgCache::Dependency));
  190. if (Dependency == 0)
  191. return false;
  192. // Fill it in
  193. pkgCache::DepIterator Dep(Cache,Cache.DepP + Dependency);
  194. Dep->ParentVer = Ver.Index();
  195. Dep->Type = Type;
  196. Dep->CompareOp = Op;
  197. Dep->ID = Cache.HeaderP->DependsCount++;
  198. // Locate the target package
  199. pkgCache::PkgIterator Pkg;
  200. if (Owner->NewPackage(Pkg,PackageName) == false)
  201. return false;
  202. // Probe the reverse dependency list for a version string that matches
  203. if (Version.empty() == false)
  204. {
  205. for (pkgCache::DepIterator I = Pkg.RevDependsList(); I.end() == false; I++)
  206. if (I->Version != 0 && I.TargetVer() == Version)
  207. Dep->Version = I->Version;
  208. if (Dep->Version == 0)
  209. if ((Dep->Version = WriteString(Version)) == 0)
  210. return false;
  211. }
  212. // Link it to the package
  213. Dep->Package = Pkg.Index();
  214. Dep->NextRevDepends = Pkg->RevDepends;
  215. Pkg->RevDepends = Dep.Index();
  216. // Link it to the version (at the end of the list)
  217. unsigned long *Last = &Ver->DependsList;
  218. for (pkgCache::DepIterator D = Ver.DependsList(); D.end() == false; D++)
  219. Last = &D->NextDepends;
  220. Dep->NextDepends = *Last;
  221. *Last = Dep.Index();
  222. return true;
  223. }
  224. /*}}}*/
  225. // ListParser::NewProvides - Create a Provides element /*{{{*/
  226. // ---------------------------------------------------------------------
  227. /* */
  228. bool pkgCacheGenerator::ListParser::NewProvides(pkgCache::VerIterator Ver,
  229. string PackageName,
  230. string Version)
  231. {
  232. pkgCache &Cache = Owner->Cache;
  233. // We do not add self referencing provides
  234. if (Ver.ParentPkg().Name() == PackageName)
  235. return true;
  236. // Get a structure
  237. unsigned long Provides = Owner->Map.Allocate(sizeof(pkgCache::Provides));
  238. if (Provides == 0)
  239. return false;
  240. // Fill it in
  241. pkgCache::PrvIterator Prv(Cache,Cache.ProvideP + Provides,Cache.PkgP);
  242. Prv->Version = Ver.Index();
  243. Prv->NextPkgProv = Ver->ProvidesList;
  244. Ver->ProvidesList = Prv.Index();
  245. if (Version.empty() == false && (Prv->Version = WriteString(Version)) == 0)
  246. return false;
  247. // Locate the target package
  248. pkgCache::PkgIterator Pkg;
  249. if (Owner->NewPackage(Pkg,PackageName) == false)
  250. return false;
  251. // Link it to the package
  252. Prv->ParentPkg = Pkg.Index();
  253. Prv->NextProvides = Pkg->ProvidesList;
  254. Pkg->ProvidesList = Prv.Index();
  255. return true;
  256. }
  257. /*}}}*/
  258. // CacheGenerator::SelectFile - Select the current file being parsed /*{{{*/
  259. // ---------------------------------------------------------------------
  260. /* This is used to select which file is to be associated with all newly
  261. added versions. */
  262. bool pkgCacheGenerator::SelectFile(string File,unsigned long Flags)
  263. {
  264. struct stat Buf;
  265. if (stat(File.c_str(),&Buf) == -1)
  266. return _error->Errno("stat","Couldn't stat ",File.c_str());
  267. // Get some space for the structure
  268. CurrentFile = Cache.PkgFileP + Map.Allocate(sizeof(*CurrentFile));
  269. if (CurrentFile == Cache.PkgFileP)
  270. return false;
  271. // Fill it in
  272. CurrentFile->FileName = Map.WriteString(File);
  273. CurrentFile->Size = Buf.st_size;
  274. CurrentFile->mtime = Buf.st_mtime;
  275. CurrentFile->NextFile = Cache.HeaderP->FileList;
  276. CurrentFile->Flags = Flags;
  277. PkgFileName = File;
  278. Cache.HeaderP->FileList = CurrentFile - Cache.PkgFileP;
  279. if (CurrentFile->FileName == 0)
  280. return false;
  281. Progress.SubProgress(Buf.st_size,File);
  282. return true;
  283. }
  284. /*}}}*/
  285. // CacheGenerator::WriteUniqueString - Insert a unique string /*{{{*/
  286. // ---------------------------------------------------------------------
  287. /* This is used to create handles to strings. Given the same text it
  288. always returns the same number */
  289. unsigned long pkgCacheGenerator::WriteUniqString(const char *S,
  290. unsigned int Size)
  291. {
  292. // Search for an insertion point
  293. pkgCache::StringItem *I = Cache.StringItemP + Cache.HeaderP->StringList;
  294. int Res = 1;
  295. unsigned long *Last = &Cache.HeaderP->StringList;
  296. for (; I != Cache.StringItemP; Last = &I->NextItem,
  297. I = Cache.StringItemP + I->NextItem)
  298. {
  299. Res = stringcmp(S,S+Size,Cache.StrP + I->String);
  300. if (Res >= 0)
  301. break;
  302. }
  303. // Match
  304. if (Res == 0)
  305. return I->String;
  306. // Get a structure
  307. unsigned long Item = Map.Allocate(sizeof(pkgCache::StringItem));
  308. if (Item == 0)
  309. return 0;
  310. // Fill in the structure
  311. pkgCache::StringItem *ItemP = Cache.StringItemP + Item;
  312. ItemP->NextItem = I - Cache.StringItemP;
  313. *Last = Item;
  314. ItemP->String = Map.WriteString(S,Size);
  315. if (ItemP->String == 0)
  316. return 0;
  317. return ItemP->String;
  318. }
  319. /*}}}*/