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 129 130 131 132 133 134 135 136 137
|
#include <sys/types.h>
#include <unistd.h>
#include "strerr.h"
#include "cdb.h"
#include "buffer.h"
#include "seek.h"
#include "fmt.h"
#define USAGE ""
#define FATAL "cdbstats: fatal: "
#define BUFSIZE 1024
const char *progname;
static struct cdb c;
char buf[BUFSIZE];
void usage() { strerr_die4x(100, "usage: ", progname, USAGE, "\n"); }
void getb(char *b, unsigned int len) {
unsigned int l;
while (len) {
switch ((l =buffer_get(buffer_0, b, len))) {
case 0: strerr_die2x(111, FATAL, "unable to read input: truncated file");
case -1: strerr_die2sys(111, FATAL, "unable to read input: ");
}
len -=l; b +=l;
}
}
void put1(char *s, unsigned int l) {
if (buffer_put(buffer_1, s, l) == -1)
strerr_die2sys(111, FATAL, "unable to write output: ");
}
int main(int argc, char **argv) {
uint32 pos;
uint32 eodata;
uint32 keylen;
uint32 datalen;
char num[FMT_ULONG];
unsigned long records;
unsigned long distance[11];
off_t rest;
int i, j;
progname =*argv++;
if (*argv) usage();
pos =0;
records =0;
for (i =0; i < 11; ++i) distance[i] =0;
cdb_init(&c,0);
/* read data size */
getb(buf, 4);
pos +=4;
uint32_unpack(buf, &eodata);
/* data starts after 2048 bytes */
while (pos < 2048) {
getb(buf, (2048 -pos) < BUFSIZE ? (2048 -pos) : BUFSIZE);
pos +=(2048 -pos) < BUFSIZE ? (2048 -pos) : BUFSIZE;
}
while (pos < eodata) {
/* keylen */
getb(buf, 4);
pos +=4;
uint32_unpack(buf, &keylen);
/* datalen */
getb(buf, 4);
pos +=4;
uint32_unpack(buf, &datalen);
/* skip keys with len > BUFSIZE */
if (keylen > BUFSIZE) {
while (keylen) {
getb(buf, keylen < BUFSIZE ? keylen : BUFSIZE);
pos +=keylen < BUFSIZE ? keylen : BUFSIZE;
keylen -=keylen < BUFSIZE ? keylen : BUFSIZE;
}
}
/* lookup records */
else {
/* get keylen */
getb(buf, keylen);
pos +=keylen;
/* save file pos */
rest =lseek(0, (off_t) 0, SEEK_CUR);
/* lookup this record */
cdb_findstart(&c);
do {
switch(cdb_findnext(&c, buf, keylen)) {
case -1: strerr_die2sys(111, FATAL, "unable to read input: ");
case 0: strerr_die2x(111,FATAL,"unable to read input: truncated file");
}
} while (cdb_datapos(&c) != pos);
if (!c.loop)
strerr_die2x(111,FATAL,"unable to read input: truncated file");
/* count records */
++records;
/* count records with specific distance */
if (c.loop > 10) ++distance[10]; else ++distance[c.loop -1];
/* reset file pos */
if (seek_set(0, rest) == -1)
strerr_die2sys(111, FATAL, "unable to read input: ");
}
/* skip data */
while (datalen) {
getb(buf, datalen < BUFSIZE ? datalen : BUFSIZE);
pos +=datalen < BUFSIZE ? datalen : BUFSIZE;
datalen -=datalen < BUFSIZE ? datalen : BUFSIZE;
}
}
/* format output stats */
put1("records ", 8);
for (i =fmt_ulong(0, records); i < 10; ++i)
put1(" ", 1);
put1(num, fmt_ulong(num, records));
put1("\n", 1);
for (j =0; j < 10; ++j) {
put1("d", 1);
put1(num, fmt_ulong(num, j));
put1(" ", 6);
for (i =fmt_ulong(0, distance[j]); i < 10; ++i)
put1(" ", 1);
put1(num, fmt_ulong(num, distance[j]));
put1("\n", 1);
}
put1(">9 ", 8);
for (i =fmt_ulong(0, distance[j]); i < 10; ++i)
put1(" ", 1);
put1(num, fmt_ulong(num, distance[j]));
put1("\n", 1);
if (buffer_flush(buffer_1) == -1)
strerr_die2sys(111, FATAL, "unable to flush output: ");
_exit(0);
}
|