database.c 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220
  1. /*
  2. * libdpkg - Debian packaging suite library routines
  3. * dpkg-db.h - Low level package database routines (hash tables, etc.)
  4. *
  5. * Copyright © 1995 Ian Jackson <ian@chiark.greenend.org.uk>
  6. *
  7. * This is free software; you can redistribute it and/or modify
  8. * it under the terms of the GNU General Public License as published by
  9. * the Free Software Foundation; either version 2 of the License, or
  10. * (at your option) any later version.
  11. *
  12. * This is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. * GNU General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU General Public License
  18. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  19. */
  20. #include <config.h>
  21. #include <compat.h>
  22. #include <ctype.h>
  23. #include <string.h>
  24. #include <stdlib.h>
  25. #include <dpkg/i18n.h>
  26. #include <dpkg/dpkg.h>
  27. #include <dpkg/dpkg-db.h>
  28. /* This must always be a prime for optimal performance.
  29. * With 4093 buckets, we glean a 20% speedup, for 8191 buckets
  30. * we get 23%. The nominal increase in memory usage is a mere
  31. * sizeof(void *) * 8063 (i.e. less than 32 KiB on 32bit systems). */
  32. #define BINS 8191
  33. static struct pkginfo *bins[BINS];
  34. static int npackages;
  35. #define FNV_offset_basis 2166136261ul
  36. #define FNV_mixing_prime 16777619ul
  37. /**
  38. * Fowler/Noll/Vo -- simple string hash.
  39. *
  40. * For more info, see <http://www.isthe.com/chongo/tech/comp/fnv/index.html>.
  41. */
  42. static unsigned int hash(const char *name) {
  43. register unsigned int h = FNV_offset_basis;
  44. register unsigned int p = FNV_mixing_prime;
  45. while( *name ) {
  46. h *= p;
  47. h ^= *name++;
  48. }
  49. return h;
  50. }
  51. void blankversion(struct versionrevision *version) {
  52. version->epoch= 0;
  53. version->version= version->revision= NULL;
  54. }
  55. void
  56. pkg_blank(struct pkginfo *pigp)
  57. {
  58. pigp->name= NULL;
  59. pigp->status= stat_notinstalled;
  60. pigp->eflag = eflag_ok;
  61. pigp->want= want_unknown;
  62. pigp->priority= pri_unknown;
  63. pigp->otherpriority = NULL;
  64. pigp->section= NULL;
  65. blankversion(&pigp->configversion);
  66. pigp->files= NULL;
  67. pigp->clientdata= NULL;
  68. pigp->trigaw.head = pigp->trigaw.tail = NULL;
  69. pigp->othertrigaw_head = NULL;
  70. pigp->trigpend_head = NULL;
  71. pkg_perfile_blank(&pigp->installed);
  72. pkg_perfile_blank(&pigp->available);
  73. }
  74. void
  75. pkg_perfile_blank(struct pkginfoperfile *pifp)
  76. {
  77. pifp->essential = false;
  78. pifp->depends= NULL;
  79. pifp->depended= NULL;
  80. pifp->description= pifp->maintainer= pifp->source= pifp->installedsize= pifp->bugs= pifp->origin= NULL;
  81. pifp->architecture= NULL;
  82. blankversion(&pifp->version);
  83. pifp->conffiles= NULL;
  84. pifp->arbs= NULL;
  85. }
  86. static int nes(const char *s) { return s && *s; }
  87. /**
  88. * Check if a pkg is informative.
  89. *
  90. * Used by dselect and dpkg query options as an aid to decide whether to
  91. * display things, and by dump to decide whether to write them out.
  92. */
  93. bool
  94. pkg_is_informative(struct pkginfo *pkg, struct pkginfoperfile *info)
  95. {
  96. if (info == &pkg->installed &&
  97. (pkg->want != want_unknown ||
  98. pkg->eflag != eflag_ok ||
  99. pkg->status != stat_notinstalled ||
  100. informativeversion(&pkg->configversion)))
  101. /* We ignore Section and Priority, as these tend to hang around. */
  102. return true;
  103. if (info->depends ||
  104. nes(info->description) ||
  105. nes(info->maintainer) ||
  106. nes(info->origin) ||
  107. nes(info->bugs) ||
  108. nes(info->installedsize) ||
  109. nes(info->source) ||
  110. informativeversion(&info->version) ||
  111. info->conffiles ||
  112. info->arbs)
  113. return true;
  114. return false;
  115. }
  116. struct pkginfo *
  117. pkg_db_find(const char *inname)
  118. {
  119. struct pkginfo **pointerp, *newpkg;
  120. char *name = m_strdup(inname), *p;
  121. p= name;
  122. while(*p) { *p= tolower(*p); p++; }
  123. pointerp= bins + (hash(name) % (BINS));
  124. while (*pointerp && strcasecmp((*pointerp)->name,name))
  125. pointerp= &(*pointerp)->next;
  126. if (*pointerp) { free(name); return *pointerp; }
  127. newpkg= nfmalloc(sizeof(struct pkginfo));
  128. pkg_blank(newpkg);
  129. newpkg->name= nfstrsave(name);
  130. newpkg->next= NULL;
  131. *pointerp= newpkg;
  132. npackages++;
  133. free(name);
  134. return newpkg;
  135. }
  136. int
  137. pkg_db_count(void)
  138. {
  139. return npackages;
  140. }
  141. struct pkgiterator {
  142. struct pkginfo *pigp;
  143. int nbinn;
  144. };
  145. struct pkgiterator *
  146. pkg_db_iter_new(void)
  147. {
  148. struct pkgiterator *i;
  149. i= m_malloc(sizeof(struct pkgiterator));
  150. i->pigp= NULL;
  151. i->nbinn= 0;
  152. return i;
  153. }
  154. struct pkginfo *
  155. pkg_db_iter_next(struct pkgiterator *i)
  156. {
  157. struct pkginfo *r;
  158. while (!i->pigp) {
  159. if (i->nbinn >= BINS) return NULL;
  160. i->pigp= bins[i->nbinn++];
  161. }
  162. r= i->pigp; i->pigp= r->next; return r;
  163. }
  164. void
  165. pkg_db_iter_free(struct pkgiterator *i)
  166. {
  167. free(i);
  168. }
  169. void
  170. pkg_db_reset(void)
  171. {
  172. int i;
  173. nffreeall();
  174. npackages= 0;
  175. for (i=0; i<BINS; i++) bins[i]= NULL;
  176. }
  177. void hashreport(FILE *file) {
  178. int i, c;
  179. struct pkginfo *pkg;
  180. int *freq;
  181. freq= m_malloc(sizeof(int)*npackages+1);
  182. for (i=0; i<=npackages; i++) freq[i]= 0;
  183. for (i=0; i<BINS; i++) {
  184. for (c=0, pkg= bins[i]; pkg; c++, pkg= pkg->next);
  185. fprintf(file,"bin %5d has %7d\n",i,c);
  186. freq[c]++;
  187. }
  188. for (i=npackages; i>0 && freq[i]==0; i--);
  189. while (i>=0) { fprintf(file,_("size %7d occurs %5d times\n"),i,freq[i]); i--; }
  190. m_output(file, "<hash report>");
  191. free(freq);
  192. }