1 /* $Id: makedbz.c 6135 2003-01-19 01:15:40Z rra $
3 ** Rebuild dbz file for history db.
13 #include "inn/innconf.h"
14 #include "inn/messages.h"
20 /* FIXME: once we figure out how to integrate this stuff with the
21 * history API this external visibility of internal voodoo should
23 #define HIS_FIELDSEP '\t'
25 char *TextFile = NULL;
26 char *HistoryDir = NULL;
30 ** Remove the DBZ files for the specified base text file.
33 RemoveDBZFiles(char *p)
37 snprintf(buff, sizeof(buff), "%s.dir", p);
38 if (unlink(buff) && errno != ENOENT)
39 syswarn("cannot unlink %s", buff);
41 snprintf(buff, sizeof(buff), "%s.pag", p);
42 if (unlink(buff) && errno != ENOENT)
43 syswarn("cannot unlink %s", buff);
45 snprintf(buff, sizeof(buff), "%s.index", p);
46 if (unlink(buff) && errno != ENOENT)
47 syswarn("cannot unlink %s", buff);
48 snprintf(buff, sizeof(buff), "%s.hash", p);
49 if (unlink(buff) && errno != ENOENT)
50 syswarn("cannot unlink %s", buff);
56 ** Count lines in the history text. A long-winded way of saying "wc -l"
64 /* Open the text file. */
65 qp = QIOopen(TextFile);
67 sysdie("cannot open %s", TextFile);
69 /* Loop through all lines in the text file. */
71 for (; QIOread(qp) != NULL;)
74 sysdie("cannot read %s near line %lu", TextFile,
75 (unsigned long) count);
77 sysdie("line %lu of %s is too long", (unsigned long) count,
86 ** Rebuild the DBZ file from the text file.
89 Rebuild(off_t size, bool IgnoreOld, bool Overwrite)
100 if (chdir(HistoryDir) < 0)
101 sysdie("cannot chdir to %s", HistoryDir);
103 /* If we are ignoring the old database and the user didn't specify a table
104 size, determine one ourselves from the size of the text history file.
105 Note that this will still use the defaults in dbz if the text file is
106 empty, since size will still be left set to 0. */
107 if (IgnoreOld == true && size == 0) {
111 warn("no size specified, using %ld", (unsigned long) size);
114 /* Open the text file. */
115 qp = QIOopen(TextFile);
117 sysdie("cannot open %s", TextFile);
119 /* If using the standard history file, force DBZ to use history.n. */
120 if (strcmp(TextFile, HISTORY) == 0 && !Overwrite) {
121 snprintf(temp, sizeof(temp), "%s.n", HISTORY);
122 if (link(HISTORY, temp) < 0)
123 sysdie("cannot create temporary link to %s", temp);
124 RemoveDBZFiles(temp);
130 ** only do removedbz files if a. we're using something besides
131 ** $pathdb/history, or b. we're ignoring the old db.
133 if (strcmp(TextFile, HISTORY) != 0 || IgnoreOld)
134 RemoveDBZFiles(TextFile);
138 /* Open the new database, using the old file if desired and possible. */
140 opt.pag_incore = INCORE_MEM;
141 #ifndef DO_TAGGED_HASH
142 opt.exists_incore = INCORE_MEM;
146 if (!dbzfresh(p, dbzsize(size))) {
147 syswarn("cannot do dbzfresh");
154 if (!dbzagain(p, HISTORY)) {
155 syswarn("cannot do dbzagain");
162 /* Loop through all lines in the text file. */
164 for (where = QIOtell(qp); (p = QIOread(qp)) != NULL; where = QIOtell(qp)) {
166 if ((save = strchr(p, HIS_FIELDSEP)) == NULL) {
167 warn("bad line #%lu: %.40s", (unsigned long) count, p);
175 if (strlen(p) != ((sizeof(HASH) * 2) + 2)) {
176 warn("invalid length for hash %s, skipping", p);
179 key = TextToHash(p+1);
182 warn("invalid message ID %s in history text", p);
185 switch (dbzstore(key, where)) {
186 case DBZSTORE_EXISTS:
187 warn("duplicate message ID %s in history text", p);
190 syswarn("cannot store %s", p);
199 syswarn("cannot read %s near line %lu", TextFile,
200 (unsigned long) count);
205 if (QIOtoolong(qp)) {
206 warn("line %lu is too long", (unsigned long) count);
215 syswarn("cannot close history");
228 fprintf(stderr, "Usage: makedbz [-f histfile] [-s numlines] [-i] [-o]\n");
234 ** Change to the news user if possible, and if not, die. Used for operations
235 ** that may create new database files, so as not to mess up the ownership.
242 pwd = getpwnam(NEWSUSER);
244 die("can't resolve %s to a UID (account doesn't exist?)", NEWSUSER);
247 if (getuid() != pwd->pw_uid)
248 die("must be run as %s", NEWSUSER);
253 main(int argc, char **argv)
261 /* First thing, set up logging and our identity. */
262 openlog("makedbz", L_OPENLOG_FLAGS | LOG_PID, LOG_INN_PROG);
263 message_program_name = "makedbz";
266 if (!innconf_read(NULL))
268 TextFile = concatpath(innconf->pathdb, _PATH_HISTORY);
269 HISTORY = concatpath(innconf->pathdb, _PATH_HISTORY);
270 HistoryDir = innconf->pathdb;
274 while ((i = getopt(argc, argv, "s:iof:")) != EOF) {
300 if ((p = strrchr(TextFile, '/')) == NULL) {
301 /* find the default history file directory */
302 HistoryDir = innconf->pathdb;
305 HistoryDir = xstrdup(TextFile);
309 if (chdir(HistoryDir) < 0)
310 sysdie("cannot chdir to %s", HistoryDir);
312 /* Change users if necessary. */
315 Rebuild(size, IgnoreOld, Overwrite);