database.c 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267
  1. /*
  2. * libdpkg - Debian packaging suite library routines
  3. * dpkg-db.h - Low level package database routines (hash tables, etc.)
  4. *
  5. * Copyright (C) 1995 Ian Jackson <iwj10@cus.cam.ac.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 <ctype.h>
  22. #include <string.h>
  23. #include <config.h>
  24. #include <dpkg.h>
  25. #include <dpkg-db.h>
  26. #define BINS (1 << 7)
  27. /* This must always be a power of two. If you change it
  28. * consider changing the per-character hashing factor (currently 5) too.
  29. */
  30. static struct pkginfo *bins[BINS];
  31. static int npackages;
  32. static int hash(const char *name) {
  33. int v= 0;
  34. while (*name) { v *= 5; v += tolower(*name); name++; }
  35. return v;
  36. /* These results were achieved with 128 bins, and the list of packages
  37. * shown at the bottom of this file.
  38. */
  39. /* while (*name) { v *= 17; v += tolower(*name); name++; }
  40. * size 5 occurs 1 times
  41. * size 4 occurs 0 times
  42. * size 3 occurs 7 times
  43. * size 2 occurs 32 times
  44. * size 1 occurs 51 times
  45. * size 0 occurs 37 times
  46. */
  47. /* while (*name) { v *= 5; v += tolower(*name); name++; }
  48. * size 4 occurs 1 times
  49. * size 3 occurs 14 times
  50. * size 2 occurs 20 times
  51. * size 1 occurs 55 times
  52. * size 0 occurs 38 times
  53. */
  54. /* while (*name) { v *= 11; v += tolower(*name); name++; }
  55. * size 5 occurs 1 times
  56. * size 4 occurs 4 times
  57. * size 3 occurs 9 times
  58. * size 2 occurs 25 times
  59. * size 1 occurs 43 times
  60. * size 0 occurs 46 times
  61. */
  62. /* while (*name) { v *= 31; v += tolower(*name); name++; }
  63. * size 6 occurs 1 times
  64. * size 5 occurs 0 times
  65. * size 4 occurs 1 times
  66. * size 3 occurs 11 times
  67. * size 2 occurs 27 times
  68. * size 1 occurs 44 times
  69. * size 0 occurs 44 times
  70. */
  71. /* while (*name) { v *= 111; v += tolower(*name); name++; }
  72. * size 5 occurs 1 times
  73. * size 4 occurs 1 times
  74. * size 3 occurs 14 times
  75. * size 2 occurs 23 times
  76. * size 1 occurs 44 times
  77. * size 0 occurs 45 times
  78. */
  79. /* while (*name) { v += (v<<3); v += tolower(*name); name++; }
  80. * size 4 occurs 5 times
  81. * size 3 occurs 12 times
  82. * size 2 occurs 22 times
  83. * size 1 occurs 41 times
  84. * size 0 occurs 48 times
  85. */
  86. /* while (*name) { v *= 29; v += tolower(*name); name++; }
  87. * size 5 occurs 1 times
  88. * size 4 occurs 2 times
  89. * size 3 occurs 10 times
  90. * size 2 occurs 26 times
  91. * size 1 occurs 46 times
  92. * size 0 occurs 43 times
  93. */
  94. /* while (*name) { v *= 13; v += tolower(*name); name++; }
  95. * size 5 occurs 1 times
  96. * size 4 occurs 2 times
  97. * size 3 occurs 5 times
  98. * size 2 occurs 30 times
  99. * size 1 occurs 53 times
  100. * size 0 occurs 37 times
  101. */
  102. }
  103. void blankversion(struct versionrevision *version) {
  104. version->epoch= 0;
  105. version->version= version->revision= 0;
  106. }
  107. void blankpackage(struct pkginfo *pigp) {
  108. pigp->name= 0;
  109. pigp->status= stat_notinstalled;
  110. pigp->eflag= eflagv_ok;
  111. pigp->want= want_unknown;
  112. pigp->priority= pri_unknown;
  113. pigp->section= 0;
  114. blankversion(&pigp->configversion);
  115. pigp->files= 0;
  116. pigp->installed.valid= 0;
  117. pigp->available.valid= 0;
  118. pigp->clientdata= 0;
  119. }
  120. void blankpackageperfile(struct pkginfoperfile *pifp) {
  121. pifp->essential= 0;
  122. pifp->depends= 0;
  123. pifp->depended= 0;
  124. pifp->description= pifp->maintainer= pifp->source= pifp->installedsize= pifp->bugs= pifp->origin= 0;
  125. pifp->architecture= 0;
  126. blankversion(&pifp->version);
  127. pifp->conffiles= 0;
  128. pifp->arbs= 0;
  129. pifp->valid= 1;
  130. }
  131. static int nes(const char *s) { return s && *s; }
  132. int informative(struct pkginfo *pkg, struct pkginfoperfile *info) {
  133. /* Used by dselect and dpkg query options as an aid to decide
  134. * whether to display things, and by dump to decide whether to write them
  135. * out.
  136. */
  137. if (info == &pkg->installed &&
  138. (pkg->want != want_unknown ||
  139. pkg->eflag != eflagv_ok ||
  140. pkg->status != stat_notinstalled ||
  141. informativeversion(&pkg->configversion)))
  142. /* We ignore Section and Priority, as these tend to hang around. */
  143. return 1;
  144. if (!info->valid) return 0;
  145. if (info->depends ||
  146. nes(info->description) ||
  147. nes(info->maintainer) ||
  148. nes(info->origin) ||
  149. nes(info->bugs) ||
  150. nes(info->installedsize) ||
  151. nes(info->source) ||
  152. nes(info->architecture) ||
  153. informativeversion(&info->version) ||
  154. info->conffiles ||
  155. info->arbs) return 1;
  156. return 0;
  157. }
  158. struct pkginfo *findpackage(const char *name) {
  159. struct pkginfo **pointerp, *newpkg;
  160. pointerp= bins + (hash(name) & (BINS-1));
  161. while (*pointerp && strcasecmp((*pointerp)->name,name))
  162. pointerp= &(*pointerp)->next;
  163. if (*pointerp) return *pointerp;
  164. newpkg= nfmalloc(sizeof(struct pkginfo));
  165. blankpackage(newpkg);
  166. newpkg->name= nfstrsave(name);
  167. newpkg->next= 0;
  168. *pointerp= newpkg;
  169. npackages++;
  170. return newpkg;
  171. }
  172. int countpackages(void) {
  173. return npackages;
  174. }
  175. struct pkgiterator {
  176. struct pkginfo *pigp;
  177. int nbinn;
  178. };
  179. struct pkgiterator *iterpkgstart(void) {
  180. struct pkgiterator *i;
  181. i= m_malloc(sizeof(struct pkgiterator));
  182. i->pigp= 0;
  183. i->nbinn= 0;
  184. return i;
  185. }
  186. struct pkginfo *iterpkgnext(struct pkgiterator *i) {
  187. struct pkginfo *r;
  188. while (!i->pigp) {
  189. if (i->nbinn >= BINS) return 0;
  190. i->pigp= bins[i->nbinn++];
  191. }
  192. r= i->pigp; i->pigp= r->next; return r;
  193. }
  194. void iterpkgend(struct pkgiterator *i) {
  195. free(i);
  196. }
  197. void resetpackages(void) {
  198. int i;
  199. nffreeall();
  200. npackages= 0;
  201. for (i=0; i<BINS; i++) bins[i]= 0;
  202. }
  203. void hashreport(FILE *file) {
  204. int i, c;
  205. struct pkginfo *pkg;
  206. int *freq;
  207. freq= m_malloc(sizeof(int)*npackages+1);
  208. for (i=0; i<=npackages; i++) freq[i]= 0;
  209. for (i=0; i<BINS; i++) {
  210. for (c=0, pkg= bins[i]; pkg; c++, pkg= pkg->next);
  211. fprintf(file,"bin %5d has %7d\n",i,c);
  212. freq[c]++;
  213. }
  214. for (i=npackages; i>0 && freq[i]==0; i--);
  215. while (i>=0) { fprintf(file,_("size %7d occurs %5d times\n"),i,freq[i]); i--; }
  216. if (ferror(file)) ohshite(_("failed write during hashreport"));
  217. }
  218. /*
  219. * Test dataset package names were:
  220. *
  221. * agetty bash bc bdflush biff bin86 binutil binutils bison bsdutils
  222. * byacc chfn cron dc dictionaries diff dlltools dpkg e2fsprogs ed
  223. * elisp19 elm emacs emacs-nox emacs-x emacs19 file fileutils find
  224. * flex fsprogs gas gawk gcc gcc1 gcc2 gdb ghostview ghstview glibcdoc
  225. * gnuplot grep groff gs gs_both gs_svga gs_x gsfonts gxditviw gzip
  226. * hello hostname idanish ifrench igerman indent inewsinn info inn
  227. * ispell kbd kern1148 language ldso less libc libgr libgrdev librl
  228. * lilo linuxsrc login lout lpr m4 mailx make man manpages more mount
  229. * mtools ncurses netbase netpbm netstd patch perl4 perl5 procps
  230. * psutils rcs rdev sed sendmail seyon shar shellutils smail svgalib
  231. * syslogd sysvinit tar tcpdump tcsh tex texidoc texinfo textutils
  232. * time timezone trn unzip uuencode wenglish wu-ftpd x8514 xaxe xbase
  233. * xbdm2 xcomp xcoral xdevel xfig xfnt100 xfnt75 xfntbig xfntscl
  234. * xgames xherc xmach32 xmach8 xmono xnet xs3 xsvga xtexstuff xv
  235. * xvga16 xxgdb zip
  236. */