File: cdbmake.c

package info (click to toggle)
freecdb 0.62
  • links: PTS
  • area: main
  • in suites: sarge, woody
  • size: 116 kB
  • ctags: 90
  • sloc: ansic: 614; makefile: 91; sh: 12
file content (128 lines) | stat: -rw-r--r-- 3,001 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
#include <stdio.h>
#include "freecdbmake.h"
#include <unistd.h>

extern char *malloc();

void diesys(why) char *why; { perror(why); exit(111); }

void writeerror() { diesys("cdbmake: fatal: unable to write"); }

void nomem() { fputs("cdbmake: fatal: out of memory\n",stderr); exit(111); }

void overflow() { fputs("cdbmake: fatal: database too large\n",stderr); exit(111); }

void usage() { fputs("cdbmake: usage: cdbmake fn fntemp\n",stderr); exit(1); }

void format() { fputs("cdbmake: fatal: bad input format\n",stderr); exit(1); }

void readerror()
{
  if (ferror(stdin)) diesys("cdbmake: fatal: unable to read");
  format();
}

int get()
{
  int c;
  c = getchar();
  if (c == EOF) readerror();
  return c;
}

uint32_t safeadd(u,v) uint32_t u; uint32_t v;
{
  u += v;
  if (u < v) overflow();
  return u;
}

struct cdbmake cdbm;
uint32_t pos;
char packbuf[8];

int main(argc,argv)
int argc;
char **argv;
{
  char *fntemp;
  char *fn;
  FILE *fi;
  uint32_t len;
  uint32_t u;
  uint32_t h;
  int i;
  int c;
  unsigned long keylen;
  unsigned long datalen;

  fn = argv[1];
  if (!fn) usage();
  fntemp = argv[2];
  if (!fntemp) usage();

  cdbmake_init(&cdbm);

  fi = fopen(fntemp,"w");
  if (!fi) diesys("cdbmake: fatal: unable to open temporary file");

  for (i = 0;i < sizeof(cdbm.final);++i)
    if (putc(' ',fi) == EOF)
      writeerror();

  pos = sizeof(cdbm.final);

  while (get() != '\n') {
    keylen = 0;
    while ((c = get()) != ',') keylen = keylen * 10 + (c - '0');
    datalen = 0;
    while ((c = get()) != ':') datalen = datalen * 10 + (c - '0');
    cdbmake_pack(packbuf,(uint32_t) keylen);
    cdbmake_pack(packbuf + 4,(uint32_t) datalen);

    if (fwrite(packbuf,1,8,fi) < 8) writeerror();

    h = CDBMAKE_HASHSTART;
    for (i = 0;i < keylen;++i) {
      c = get();
      h = cdbmake_hashadd(h,c);
      if (putc(c,fi) == EOF) writeerror();
    }
    if (get() != '-') format();
    if (get() != '>') format();
    for (i = 0;i < datalen;++i) {
      c = get();
      if (putc(c,fi) == EOF) writeerror();
    }
    if (get() != '\n') format();

    if (!cdbmake_add(&cdbm,h,pos,malloc)) nomem();
    pos = safeadd(pos,(uint32_t) 8);
    pos = safeadd(pos,(uint32_t) keylen);
    pos = safeadd(pos,(uint32_t) datalen);
  }

  if (!cdbmake_split(&cdbm,malloc)) nomem();

  for (i = 0;i < 256;++i) {
    len = cdbmake_throw(&cdbm,pos,i);
    for (u = 0;u < len;++u) {
      cdbmake_pack(packbuf,cdbm.hash[u].h);
      cdbmake_pack(packbuf + 4,cdbm.hash[u].p);
      if (fwrite(packbuf,1,8,fi) < 8) writeerror();
      pos = safeadd(pos,(uint32_t) 8);
    }
  }

  if (fflush(fi) == EOF) writeerror();
  rewind(fi);

  if (fwrite(cdbm.final,1,sizeof(cdbm.final),fi) < sizeof(cdbm.final)) writeerror();
  if (fflush(fi) == EOF) writeerror();

  if (fsync(fileno(fi)) == -1) diesys("cdbmake: fatal: unable to fsync");
  if (close(fileno(fi)) == -1) diesys("cdbmake: fatal: unable to close");

  if (rename(fntemp,fn)) diesys("cdbmake: fatal: unable to rename");
  exit(0);
}