pkgcachegen.cc 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254
  1. // -*- mode: cpp; mode: fold -*-
  2. // Description /*{{{*/
  3. // $Id: pkgcachegen.cc,v 1.3 1998/07/04 22:32:13 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. #include <pkglib/pkgcachegen.h>
  11. #include <pkglib/error.h>
  12. #include <pkglib/version.h>
  13. #include <sys/stat.h>
  14. #include <unistd.h>
  15. /*}}}*/
  16. // CacheGenerator::pkgCacheGenerator - Constructor /*{{{*/
  17. // ---------------------------------------------------------------------
  18. /* We set the diry flag and make sure that is written to the disk */
  19. pkgCacheGenerator::pkgCacheGenerator(DynamicMMap &Map) : Map(Map), Cache(Map)
  20. {
  21. if (_error->PendingError() == true)
  22. return;
  23. if (Map.Size() == 0)
  24. {
  25. Map.RawAllocate(sizeof(pkgCache::Header));
  26. *Cache.HeaderP = pkgCache::Header();
  27. }
  28. Cache.HeaderP->Dirty = true;
  29. Map.Sync(0,sizeof(pkgCache::Header));
  30. Map.UsePools(*Cache.HeaderP->Pools,sizeof(Cache.HeaderP->Pools)/sizeof(Cache.HeaderP->Pools[0]));
  31. }
  32. /*}}}*/
  33. // CacheGenerator::~pkgCacheGenerator - Destructor /*{{{*/
  34. // ---------------------------------------------------------------------
  35. /* We sync the data then unset the dirty flag in two steps so as to
  36. advoid a problem during a crash */
  37. pkgCacheGenerator::~pkgCacheGenerator()
  38. {
  39. if (_error->PendingError() == true)
  40. return;
  41. if (Map.Sync() == false)
  42. return;
  43. Cache.HeaderP->Dirty = false;
  44. Map.Sync(0,sizeof(pkgCache::Header));
  45. }
  46. /*}}}*/
  47. // CacheGenerator::MergeList - Merge the package list /*{{{*/
  48. // ---------------------------------------------------------------------
  49. /* This provides the generation of the entries in the cache. Each loop
  50. goes through a single package record from the underlying parse engine. */
  51. bool pkgCacheGenerator::MergeList(ListParser &List)
  52. {
  53. List.Owner = this;
  54. while (List.Step() == true)
  55. {
  56. // Get a pointer to the package structure
  57. string Package = List.Package();
  58. pkgCache::PkgIterator Pkg = Cache.FindPkg(Package);
  59. if (Pkg.end() == true)
  60. {
  61. if (NewPackage(Pkg,Package) == false)
  62. return false;
  63. if (List.NewPackage(Pkg) == false)
  64. return false;
  65. }
  66. /* Get a pointer to the version structure. We know the list is sorted
  67. so we use that fact in the search. Insertion of new versions is
  68. done with correct sorting */
  69. string Version = List.Version();
  70. if (Version.empty() == true)
  71. {
  72. if (List.UsePackage(Pkg,pkgCache::VerIterator(Cache)) == false)
  73. return false;
  74. continue;
  75. }
  76. pkgCache::VerIterator Ver = Pkg.VersionList();
  77. unsigned long *Last = &Pkg->VersionList;
  78. int Res;
  79. for (; Ver.end() == false; Last = &Ver->NextVer, Ver++)
  80. {
  81. Res = pkgVersionCompare(Version.begin(),Version.end(),Ver.VerStr(),
  82. Ver.VerStr() + strlen(Ver.VerStr()));
  83. if (Res >= 0)
  84. break;
  85. }
  86. /* We already have a version for this item, record that we
  87. saw it */
  88. if (Res == 0)
  89. {
  90. if (List.UsePackage(Pkg,Ver) == false)
  91. return false;
  92. if (NewFileVer(Ver,List) == false)
  93. return false;
  94. continue;
  95. }
  96. // Add a new version
  97. *Last = NewVersion(Ver,Version,*Last);
  98. Ver->ParentPkg = Pkg.Index();
  99. if (List.NewVersion(Ver) == false)
  100. return false;
  101. if (List.UsePackage(Pkg,Ver) == false)
  102. return false;
  103. if (NewFileVer(Ver,List) == false)
  104. return false;
  105. }
  106. return true;
  107. }
  108. /*}}}*/
  109. // CacheGenerator::NewPackage - Add a new package /*{{{*/
  110. // ---------------------------------------------------------------------
  111. /* This creates a new package structure and adds it to the hash table */
  112. bool pkgCacheGenerator::NewPackage(pkgCache::PkgIterator &Pkg,string Name)
  113. {
  114. // Get a structure
  115. unsigned long Package = Map.Allocate(sizeof(pkgCache::Package));
  116. if (Package == 0)
  117. return false;
  118. Pkg = pkgCache::PkgIterator(Cache,Cache.PkgP + Package);
  119. // Insert it into the hash table
  120. unsigned long Hash = Cache.Hash(Name);
  121. Pkg->NextPackage = Cache.HeaderP->HashTable[Hash];
  122. Cache.HeaderP->HashTable[Hash] = Package;
  123. // Set the name and the ID
  124. Pkg->Name = Map.WriteString(Name);
  125. if (Pkg->Name == 0)
  126. return false;
  127. Pkg->ID = Cache.HeaderP->PackageCount++;
  128. return true;
  129. }
  130. /*}}}*/
  131. // CacheGenerator::NewFileVer - Create a new File<->Version association /*{{{*/
  132. // ---------------------------------------------------------------------
  133. /* */
  134. bool pkgCacheGenerator::NewFileVer(pkgCache::VerIterator &Ver,
  135. ListParser &List)
  136. {
  137. return true;
  138. }
  139. /*}}}*/
  140. // CacheGenerator::NewVersion - Create a new Version /*{{{*/
  141. // ---------------------------------------------------------------------
  142. /* This puts a version structure in the linked list */
  143. unsigned long pkgCacheGenerator::NewVersion(pkgCache::VerIterator &Ver,
  144. string VerStr,
  145. unsigned long Next)
  146. {
  147. // Get a structure
  148. unsigned long Version = Map.Allocate(sizeof(pkgCache::Version));
  149. if (Version == 0)
  150. return 0;
  151. // Fill it in
  152. Ver = pkgCache::VerIterator(Cache,Cache.VerP + Version);
  153. Ver->File = CurrentFile - Cache.PkgFileP;
  154. Ver->NextVer = Next;
  155. Ver->ID = Cache.HeaderP->VersionCount++;
  156. Ver->VerStr = Map.WriteString(VerStr);
  157. if (Ver->VerStr == 0)
  158. return 0;
  159. return Version;
  160. }
  161. /*}}}*/
  162. // CacheGenerator::SelectFile - Select the current file being parsed /*{{{*/
  163. // ---------------------------------------------------------------------
  164. /* This is used to select which file is to be associated with all newly
  165. added versions. */
  166. bool pkgCacheGenerator::SelectFile(string File,unsigned long Flags)
  167. {
  168. struct stat Buf;
  169. if (stat(File.c_str(),&Buf) == -1)
  170. return _error->Errno("stat","Couldn't stat ",File.c_str());
  171. // Get some space for the structure
  172. CurrentFile = Cache.PkgFileP + Map.Allocate(sizeof(*CurrentFile));
  173. if (CurrentFile == Cache.PkgFileP)
  174. return false;
  175. // Fill it in
  176. CurrentFile->FileName = Map.WriteString(File);
  177. CurrentFile->Size = Buf.st_size;
  178. CurrentFile->mtime = Buf.st_mtime;
  179. CurrentFile->NextFile = Cache.HeaderP->FileList;
  180. CurrentFile->Flags = Flags;
  181. PkgFileName = File;
  182. if (CurrentFile->FileName == 0)
  183. return false;
  184. }
  185. /*}}}*/
  186. // CacheGenerator::WriteUniqueString - Insert a unique string /*{{{*/
  187. // ---------------------------------------------------------------------
  188. /* This is used to create handles to strings. Given the same text it
  189. always returns the same number */
  190. unsigned long pkgCacheGenerator::WriteUniqString(const char *S,
  191. unsigned int Size)
  192. {
  193. // Search for an insertion point
  194. pkgCache::StringItem *I = Cache.StringItemP + Cache.HeaderP->StringList;
  195. int Res = 1;
  196. unsigned long *Last = &Cache.HeaderP->StringList;
  197. for (; I != Cache.StringItemP; Last = &I->NextItem,
  198. I = Cache.StringItemP + I->NextItem)
  199. {
  200. Res = strncmp(Cache.StrP + I->String,S,Size);
  201. if (Res == 0 && *(Cache.StrP + I->String + Size) != 0)
  202. Res = 1;
  203. if (Res >= 0)
  204. break;
  205. }
  206. // Match
  207. if (Res == 0)
  208. return I->String;
  209. // Get a structure
  210. unsigned long Item = Map.Allocate(sizeof(pkgCache::StringItem));
  211. if (Item == 0)
  212. return 0;
  213. // Fill in the structure
  214. pkgCache::StringItem *ItemP = Cache.StringItemP + Item;
  215. ItemP->NextItem = I - Cache.StringItemP;
  216. *Last = Item;
  217. ItemP->String = Map.WriteString(S,Size);
  218. if (ItemP->String == 0)
  219. return 0;
  220. return ItemP->String;
  221. }
  222. /*}}}*/