database.c 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222
  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
  9. * published by the Free Software Foundation; either version 2,
  10. * or (at your option) any later version.
  11. *
  12. * This is distributed in the hope that it will be useful, but
  13. * 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
  18. * License along with dpkg; if not, write to the Free Software
  19. * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  20. */
  21. #include <config.h>
  22. #include <compat.h>
  23. #include <dpkg-i18n.h>
  24. #include <ctype.h>
  25. #include <string.h>
  26. #include <dpkg.h>
  27. #include <dpkg-db.h>
  28. #define BINS 8191
  29. /* This must always be a prime for optimal performance.
  30. * With 4093 buckets, we glean a 20% speedup, for 8191 buckets
  31. * we get 23%. The nominal increase in memory usage is a mere
  32. * sizeof(void*)*8063 (I.E. less than 32KB on 32bit systems)
  33. */
  34. static struct pkginfo *bins[BINS];
  35. static int npackages;
  36. #define FNV_offset_basis 2166136261ul
  37. #define FNV_mixing_prime 16777619ul
  38. /* Fowler/Noll/Vo -- simple string hash.
  39. * For more info, see http://www.isthe.com/chongo/tech/comp/fnv/index.html
  40. * */
  41. static unsigned int hash(const char *name) {
  42. register unsigned int h = FNV_offset_basis;
  43. register unsigned int p = FNV_mixing_prime;
  44. while( *name ) {
  45. h *= p;
  46. h ^= *name++;
  47. }
  48. return h;
  49. }
  50. void blankversion(struct versionrevision *version) {
  51. version->epoch= 0;
  52. version->version= version->revision= NULL;
  53. }
  54. void blankpackage(struct pkginfo *pigp) {
  55. pigp->name= NULL;
  56. pigp->status= stat_notinstalled;
  57. pigp->eflag= eflagv_ok;
  58. pigp->want= want_unknown;
  59. pigp->priority= pri_unknown;
  60. pigp->otherpriority = NULL;
  61. pigp->section= NULL;
  62. blankversion(&pigp->configversion);
  63. pigp->files= NULL;
  64. pigp->installed.valid= 0;
  65. pigp->available.valid= 0;
  66. pigp->clientdata= NULL;
  67. pigp->color= white;
  68. pigp->trigaw.head = pigp->trigaw.tail = NULL;
  69. pigp->othertrigaw_head = NULL;
  70. pigp->trigpend_head = NULL;
  71. blankpackageperfile(&pigp->installed);
  72. blankpackageperfile(&pigp->available);
  73. }
  74. void blankpackageperfile(struct pkginfoperfile *pifp) {
  75. pifp->essential= 0;
  76. pifp->depends= NULL;
  77. pifp->depended= NULL;
  78. pifp->description= pifp->maintainer= pifp->source= pifp->installedsize= pifp->bugs= pifp->origin= NULL;
  79. pifp->architecture= NULL;
  80. blankversion(&pifp->version);
  81. pifp->conffiles= NULL;
  82. pifp->arbs= NULL;
  83. pifp->valid= 1;
  84. }
  85. static int nes(const char *s) { return s && *s; }
  86. int informative(struct pkginfo *pkg, struct pkginfoperfile *info) {
  87. /* Used by dselect and dpkg query options as an aid to decide
  88. * whether to display things, and by dump to decide whether to write them
  89. * out.
  90. */
  91. if (info == &pkg->installed &&
  92. (pkg->want != want_unknown ||
  93. pkg->eflag != eflagv_ok ||
  94. pkg->status != stat_notinstalled ||
  95. informativeversion(&pkg->configversion)))
  96. /* We ignore Section and Priority, as these tend to hang around. */
  97. return 1;
  98. if (!info->valid) return 0;
  99. if (info->depends ||
  100. nes(info->description) ||
  101. nes(info->maintainer) ||
  102. nes(info->origin) ||
  103. nes(info->bugs) ||
  104. nes(info->installedsize) ||
  105. nes(info->source) ||
  106. informativeversion(&info->version) ||
  107. info->conffiles ||
  108. info->arbs) return 1;
  109. return 0;
  110. }
  111. struct pkginfo *findpackage(const char *inname) {
  112. struct pkginfo **pointerp, *newpkg;
  113. char *name = m_strdup(inname), *p;
  114. p= name;
  115. while(*p) { *p= tolower(*p); p++; }
  116. pointerp= bins + (hash(name) % (BINS));
  117. while (*pointerp && strcasecmp((*pointerp)->name,name))
  118. pointerp= &(*pointerp)->next;
  119. if (*pointerp) { free(name); return *pointerp; }
  120. newpkg= nfmalloc(sizeof(struct pkginfo));
  121. blankpackage(newpkg);
  122. newpkg->name= nfstrsave(name);
  123. newpkg->next= NULL;
  124. *pointerp= newpkg;
  125. npackages++;
  126. free(name);
  127. return newpkg;
  128. }
  129. int countpackages(void) {
  130. return npackages;
  131. }
  132. struct pkgiterator {
  133. struct pkginfo *pigp;
  134. int nbinn;
  135. };
  136. struct pkgiterator *iterpkgstart(void) {
  137. struct pkgiterator *i;
  138. i= m_malloc(sizeof(struct pkgiterator));
  139. i->pigp= NULL;
  140. i->nbinn= 0;
  141. return i;
  142. }
  143. struct pkginfo *iterpkgnext(struct pkgiterator *i) {
  144. struct pkginfo *r;
  145. while (!i->pigp) {
  146. if (i->nbinn >= BINS) return NULL;
  147. i->pigp= bins[i->nbinn++];
  148. }
  149. r= i->pigp; i->pigp= r->next; return r;
  150. }
  151. void iterpkgend(struct pkgiterator *i) {
  152. free(i);
  153. }
  154. void resetpackages(void) {
  155. int i;
  156. nffreeall();
  157. npackages= 0;
  158. for (i=0; i<BINS; i++) bins[i]= NULL;
  159. }
  160. void hashreport(FILE *file) {
  161. int i, c;
  162. struct pkginfo *pkg;
  163. int *freq;
  164. freq= m_malloc(sizeof(int)*npackages+1);
  165. for (i=0; i<=npackages; i++) freq[i]= 0;
  166. for (i=0; i<BINS; i++) {
  167. for (c=0, pkg= bins[i]; pkg; c++, pkg= pkg->next);
  168. fprintf(file,"bin %5d has %7d\n",i,c);
  169. freq[c]++;
  170. }
  171. for (i=npackages; i>0 && freq[i]==0; i--);
  172. while (i>=0) { fprintf(file,_("size %7d occurs %5d times\n"),i,freq[i]); i--; }
  173. if (ferror(file)) ohshite(_("failed write during hashreport"));
  174. free(freq);
  175. }
  176. /*
  177. * Test dataset package names were:
  178. *
  179. * agetty bash bc bdflush biff bin86 binutil binutils bison bsdutils
  180. * byacc chfn cron dc dictionaries diff dlltools dpkg e2fsprogs ed
  181. * elisp19 elm emacs emacs-nox emacs-x emacs19 file fileutils find
  182. * flex fsprogs gas gawk gcc gcc1 gcc2 gdb ghostview ghstview glibcdoc
  183. * gnuplot grep groff gs gs_both gs_svga gs_x gsfonts gxditviw gzip
  184. * hello hostname idanish ifrench igerman indent inewsinn info inn
  185. * ispell kbd kern1148 language ldso less libc libgr libgrdev librl
  186. * lilo linuxsrc login lout lpr m4 mailx make man manpages more mount
  187. * mtools ncurses netbase netpbm netstd patch perl4 perl5 procps
  188. * psutils rcs rdev sed sendmail seyon shar shellutils smail svgalib
  189. * syslogd sysvinit tar tcpdump tcsh tex texidoc texinfo textutils
  190. * time timezone trn unzip uuencode wenglish wu-ftpd x8514 xaxe xbase
  191. * xbdm2 xcomp xcoral xdevel xfig xfnt100 xfnt75 xfntbig xfntscl
  192. * xgames xherc xmach32 xmach8 xmono xnet xs3 xsvga xtexstuff xv
  193. * xvga16 xxgdb zip
  194. */