Пример #1
0
OverInfo * 
FindCanceledMsg(const char *group, const char *msgid, artno_t *partNo, int *pvalidGroups)
{
    const char *rec;
    int recLen;
    OverInfo *ov = NULL;

    /*
     * Make sure group is valid before calling GetOverInfo() or we will
     * create random over. files for illegal groups.  Don't lock the record,
     * meaning that we have to re-read it after calling GetOverInfo (otherwise
     * someone else can update the numeric fields in the record while we are 
     * trying to process them).
     */

    *partNo = -1;

    if ((rec = KPDBReadRecord(KDBActive, group, 0, &recLen)) != NULL) {

	++*pvalidGroups;

	if ((ov = GetOverInfo(group)) != NULL) {
	    hash_t hv = hhash(msgid);

	    if ((rec = KPDBReadRecord(KDBActive, group, KP_LOCK, &recLen)) != NULL) {
		artno_t artBeg;
		artno_t artEnd;

		artBeg = strtoll(KPDBGetField(rec, recLen, "NB", NULL, "-1"), NULL, 10);
		artEnd = strtoll(KPDBGetField(rec, recLen, "NE", NULL, "-1"), NULL, 10);
		if (artEnd - artBeg > ov->ov_MaxArts)
		    artBeg = artEnd - ov->ov_MaxArts;

		while (artEnd >= artBeg) {
		    off_t ovpos = 0;
		    const OverArt *oa = GetOverArt(ov, artEnd, &ovpos);

		    if (OA_ARTNOEQ(artEnd, oa->oa_ArtNo) && 
			bcmp(&oa->oa_MsgHash, &hv, sizeof(hv)) == 0
		    ) {
			*partNo = artEnd;
			break;
		    }
		    --artEnd;
		} /* while */
		KPDBUnlock(KDBActive, rec);
	    }
	    if (*partNo == -1) {
		PutOverInfo(ov);
		ov = NULL;
	    }
	} /* if */
    }
    return(ov);
}
Пример #2
0
int
main(int ac, char **av)
{
    int r = 0;
    int i;
    char *arg = NULL;
    char *file = NULL;

    LogFo = stderr;

    LoadDiabloConfig(ac, av);

    for (i = 1; i < ac; ++i) {
	char *ptr = av[i];

	if (*ptr != '-') {
	    arg = ptr;
	    continue;
	}
	ptr += 2;
	switch(ptr[-1]) {
	case 'C':
	    if (*ptr == 0)
		++i;
	    break;
	case 'd':
	    DebugOpt = atoi(*ptr ? ptr : av[++i]);
	    break;
	case 'F':
	    ForceOpt = 1;
	    break;
	case 'f':
	    file = (*ptr) ? ptr : av[++i];
	    break;
	case 'H':
	    ShowFileHeader = 1;
	    break;
	case 'h':
	    HeadOnly = 1;
	    break;
	case 'q':
	    QuietOpt = 1;
	    break;
	case 's':
	    StripCR = 0;
	    break;
	case 'V':
	    PrintVersion();
	    break;
	case 'v':
	    VerifyOnly = 1;
	    LogFo = stdout;
	    break;
	default:
	    fprintf(stderr, "dreadart: Illegal option: %s\n", ptr - 2);
	    Usage(av[0]);
	}
    }

    if (arg == NULL && file == NULL)
	Usage(av[0]);

    HistoryOpen(NULL, HGF_READONLY);
    LoadSpoolCtl(0, 1);

    if (arg == NULL) {
	char buf[8192];
	char msgid[MAXMSGIDLEN];
	FILE *fi = (strcmp(file, "-") == 0) ? stdin : fopen(file, "r");

	if (fi) {
	    while (fgets(buf, sizeof(buf), fi) != NULL) {
		hash_t hv;
		char *m;

		if (strncmp(buf, "DUMP ", 5) == 0) {
		    History h = { 0 };
		    if (sscanf(buf + 5, "%s gm=%d ex=%hd boff=%d bsize=%d",
					msgid, &h.gmt, &h.exp,
					&h.boffset, &h.bsize) == 5) {
			char *p;

			h.hv.h1 = (int32)strtoul(msgid, &p, 16);
			if (*p == '.')
			    h.hv.h2 = (int32)strtoul(p + 1, &p, 16);
			if (*p == '.')
			    h.iter = (int16)strtoul(p + 1, NULL, 16);
			r = LookupHash(h.hv, NULL, &h);
		    }
		} else if ((m = strchr(buf, '<')) != NULL) {
		    char *p;
		    if ((p = strchr(m, '>')) == NULL)
			continue;
		    *++p = 0;
		    hv = hhash(m);
		    r = LookupHash(hv, m, NULL);
		} else if (sscanf(buf, "%x.%x", &hv.h1, &hv.h2) == 2) {
		    r = LookupHash(hv, NULL, NULL);
		}
	    }
	    if (fi != stdin)
		fclose(fi);
	} else {
	    fprintf(stderr, "Unable to open %s (%s)\n", file, strerror(errno));
	}
    } else {
	hash_t hv;
	char *msgid = NULL;

	if (arg[0] == '<') {
	    msgid = arg;
	    hv = hhash(arg);
	    r = LookupHash(hv, msgid, NULL);
	} else if (arg[0] == 'D' && arg[1] == '.') {
	    int32 dummy;

	    if (sscanf(arg + 2, "%x/%x.%x", &dummy, &hv.h1, &hv.h2) != 3) {
		fprintf(stderr, "argument error\n");
		exit(1);
	    }
	    r = LookupHash(hv, msgid, NULL);
	} else if (sscanf(arg, "%x.%x", &hv.h1, &hv.h2) == 2) {
	    r = LookupHash(hv, msgid, NULL);
	} else {
	    char fname[PATH_MAX];
	    char *p = fname;
	    History h = { 0 };

	    *p = 0;
	    if (*arg != '/') {
		sprintf(p, "%s/", PatExpand(SpoolHomePat));
		p += strlen(p);
	    }
	    if (sscanf(arg, "%[^:]:%d,%d", p, &h.boffset, &h.bsize) == 3) {
		DumpArticle(fname, &h, NULL);
	    } else {
		printf("Unknown argument: %s\n", arg);
	    }
	}
    }
    exit(r);
}
Пример #3
0
void
ScanSpoolFileMapOld(const char *base, int bytes, int gmt, int iter, char *dpath, uint16 spoolobj)
{
    int b = 0;
    int count = 0;

    /*
     * scan file
     */

    printf(" (old format) ");
    while (b < bytes) {
	int i = b;
	int inHeader = 1;
	int linesLeft = -1;
	int numLines = 0;

	msgId[0] = 0;
	newsgroups[0] = 0;

	/*
	 * scan article
	 */

	while (i < bytes && linesLeft && base[i] != 0) {
	    int l;

	    /*
	     * Scan line
	     */

	    for (l = i; l < bytes; l++) {
		if (base[l] == '\n') {
		    l++;
		    if (l == i + 1 || !inHeader)
			break;
		    if (l < bytes && base[l] != ' ' && base[l] != '\t')
			break;
		    l--;
		}
	    }

	    if (inHeader) {
		if (l - i == 1) {
		    inHeader = 0;
		} else if (strncasecmp(base + i, "Lines:", 6) == 0) {
		    linesLeft = strtol(base + i + 6, NULL, 0);
		} else if (strncasecmp(base + i, "Message-ID:", 11) == 0) {
		    diablo_strlcpynl(msgId, base + i + 11, l - i - 11, sizeof(msgId));
		} else if (strncasecmp(base + i, "Newsgroups:", 11) == 0) {
		    diablo_strlcpynl2(newsgroups, ',', base + i + 11, l - i - 11, sizeof(newsgroups));
		}
	    } else {
		--linesLeft;
		++numLines;
	    }
	    i = l;
	}
	if (i < bytes && base[i] == 0) {
	    const char *id = MsgId(msgId, NULL);
	    History h = { 0 };

	    h.hv = hhash(id);
	    h.iter = iter;
	    h.gmt = gmt;
	    h.exp = 100 + spoolobj;
	    h.boffset = b;
	    h.bsize = i - b;
	    if (numLines == 0)
		h.exp |= EXPF_HEADONLY;
	    DoArticle(&h, id, newsgroups, " ", " ", 0, " ", " ");
	    count++;
	    ++i;
	} else {
	    if (!QuietOpt) {
		printf("\tFailed %d,%d %s\n", b, i - b, MsgId(msgId, NULL));
		fflush(stdout);
	    }
	    /*
	    write(1, base + b, i - b);
	    write(1, "*", 1);
	    printf("(%d)\n", base[i]);
	    */

	    while (i < bytes && base[i] != 0)
		++i;
	    if (i < bytes)
		++i;
	}
	b = i;
    }
    if (!QuietOpt)
	printf("%d entries", count);
}
Пример #4
0
void
ScanSpoolFileMap(const char *base, int bytes, int gmt, int iter, char *dpath, uint16 spoolobj, int fd)
{
    int count = 0;
    int b = 0;
    int arthdrlen;
    char *artbase = NULL;
    char *artpos;
    SpoolArtHdr ah;
    char cSize[64];
    int headOnly;

    while (b < bytes) {
	bcopy(base + b, &ah, sizeof(ah));
	if ((uint8)ah.Magic1 != STORE_MAGIC1 ||
					(uint8)ah.Magic2 != STORE_MAGIC2) {
	    printf("\tFailed at offset %d: invalid header magic (%d:%d)\n", b,
						ah.Magic1, ah.Magic2);
	    ScanSpoolFileMapOld(base + b, bytes - b, gmt, iter, dpath, spoolobj);
	    return;
	}
	arthdrlen = ah.ArtHdrLen;
	if (ah.StoreType & STORETYPE_GZIP) {
#ifdef USE_ZLIB
	    gzFile *gzf;
	    long len = ah.ArtLen;

	    artbase = (char *)malloc(ah.ArtLen + 2);
	    bzero(artbase, ah.ArtLen + 2);
	    lseek(fd, b + ah.HeadLen, 0);
	    if ((gzf = gzdopen(dup(fd), "r")) != NULL) {
		if (gzread(gzf, artbase, len) != len)
		    arthdrlen = 0;
		gzclose(gzf);
	    } else {
		arthdrlen = 0;
	    }
#else
	    printf("\tCompressed file detected and compression support not enabled\n");
	    arthdrlen = 0;
#endif
	} else {
	    artbase = (char *)base + b + ah.HeadLen;
	}
	artpos = artbase;
	msgId[0] = 0;
	newsgroups[0] = 0;
	while (arthdrlen > 11) {
	    int l;

	    /*
	     * Scan line
	     */

	    for (l = 0; l < arthdrlen; l++) {
		if (artpos[l] == '\n') {
		    l++;
		    if (l < arthdrlen && artpos[l] != ' ' && artpos[l] != '\t')
			break;
		    l--;
		}
	    }

	    if (strncasecmp(artpos, "Message-ID:", 11) == 0) {
		diablo_strlcpynl(msgId, artpos + 11, l - 11, sizeof(msgId));
	    } else if (strncasecmp(artpos, "Newsgroups:", 11) == 0) {
		diablo_strlcpynl2(newsgroups, ',', artpos + 11, l - 11, sizeof(newsgroups));
	    }
	    arthdrlen -= l;
	    artpos += l;
	}
	if (msgId[0]) {
	    const char *id = MsgId(msgId, NULL);
	    History h = { 0 };

	    h.hv = hhash(id);
	    h.iter = iter;
	    h.gmt = gmt;
	    h.exp = 100 + spoolobj;
	    h.boffset = b;
	    h.bsize = ah.StoreLen - 1;
	    headOnly = 0;
	    if (ah.ArtHdrLen == ah.ArtLen) {
		h.exp |= EXPF_HEADONLY;
		headOnly = 1;
	    }
	    cSize[0] = 0;
	    if (ah.StoreType & STORETYPE_GZIP) {
		h.bsize = ah.ArtLen + ah.HeadLen;
		sprintf(cSize, "%d", ah.StoreLen);
	    }
	    DoArticle(&h, id, newsgroups, " ", " ", headOnly, "0", cSize);
	    count++;
	} else {
	    if (VerboseOpt)
		printf("No Message-ID for %d,%d\n", b, ah.StoreLen - 1);
	}
	b += ah.StoreLen;
	if (ah.StoreType & STORETYPE_GZIP) {
	    free(artbase);
	    b++;
	}
    }
    if (!QuietOpt)
	printf("%d entries", count);
}
Пример #5
0
int
WriteOverview(Connection *conn, ArtNumAss *an, const char *group, const char *xref, const char *art, int artLen, const char *msgid)
{
    artno_t artNo = 0;
    const char *body;
    char *xtmp = NULL;
    int xtmpLen = 16 + strlen(conn->co_Auth.dr_VServerDef->vs_ClusterName);
    char logbuf[1024];
    int err = 0;

    /*
     * Locate article number assignment
     */
    {
	ArtNumAss *scan;

	for (scan = an; scan; scan = scan->an_Next) {
	    if (scan->an_GroupName == group) {
		artNo = scan->an_ArtNo;
	    }
	    xtmpLen += scan->an_GroupLen + 15;
	}
    }

    if (artNo == 0)
	return(0);

    /*
     * XXX We should find some way to aggregate these into one log entry.
     */

    snprintf(logbuf, sizeof(logbuf), "%s %s:%lld", msgid, group, artNo);

    /*
     * Locate start of body (we may have to append our own Xref: line)
     */

    {
	int l;
	int lnl = 1;

	for (l = 0; l < artLen; ++l) {
	    /*
	     * blank line terminates headers
	     */
	    if (art[l] == '\r' && (l + 1 >= artLen || art[l+1] == '\n')) {
		if (lnl)
		    break;
	    }
	    lnl = 0;
	    if (art[l] == '\n')
		lnl = 1;
	}
	body = art + l;
    }

    /*
     * Write overview record.
     */

    {
	off_t pos;
	OverInfo *ov;
	const OverArt *oa;
	hash_t hv = hhash(msgid);
	int actLen = 0;
	int iovLen = 0;
	int prealloc_ov, prealloc_oh;
	struct iovec iov[3];

	if ((ov = GetOverInfo(group)) == NULL) {
	    logit(LOG_ERR, "Error in GetOverInfo(%s) msgid=%s", group, msgid);
	    LogCmd(conn, '-', logbuf);
	    if (DRIncomingLogPat != NULL)
		LogIncoming("%s - %s%s", conn->co_Auth.dr_Host, "", logbuf);
	    MBLogPrintf(conn, &conn->co_TMBuf, "400 Error writing data\r\n");
	    NNTerminate(conn);
	    return(1);
	}
	prealloc_ov = (ov->ov_MaxArts * sizeof(OverArt)) / 8;
	prealloc_oh = (1024 * ov->ov_Head->oh_DataEntries) / 8;

	if (MakeOverHFile(ov, artNo, 1) == NULL) {
	    logit(LOG_ERR, "Error in MakeOverHFile() msgid=%s", msgid);
	    LogCmd(conn, '-', logbuf);
	    if (DRIncomingLogPat != NULL)
		LogIncoming("%s - %s%s", conn->co_Auth.dr_Host, "", logbuf);
	    MBLogPrintf(conn, &conn->co_TMBuf, "400 Error writing data\r\n");
	    NNTerminate(conn);
	    return(1);
	}

	hflock(ov->ov_HCache->od_HFd, 0, XLOCK_EX);
	pos = lseek(ov->ov_HCache->od_HFd, 0L, 2);

	errno = 0;

	if (xref) {
	    iov[0].iov_base = (void *)art;
	    iov[0].iov_len = artLen + 1;
	    iovLen = 1;
	} else {
	    ArtNumAss *scan;
	    int soff;
	    
	    xtmp = zalloc(&conn->co_MemPool, xtmpLen);
	    sprintf(xtmp, "Xref: %s", DOpts.ReaderXRefHost);
	    soff = strlen(xtmp);
		
	    for (scan = an; scan; scan = scan->an_Next) {
		xtmp[soff++] = ' ';
		memcpy(xtmp + soff, scan->an_GroupName, scan->an_GroupLen);
		soff += scan->an_GroupLen;
		sprintf(xtmp + soff, ":%lld", scan->an_ArtNo);
		soff += strlen(xtmp + soff);
	    }
	    sprintf(xtmp + soff, "\r\n");
	    soff += 2;
	    iov[0].iov_base = (void *)art;
	    iov[0].iov_len = body - art;
	    iov[1].iov_base = xtmp;
	    iov[1].iov_len = soff;
	    iov[2].iov_base = (void *)body;
	    iov[2].iov_len = (art + artLen + 1) - body;
	    iovLen = 3;
	}

	if (art[0] == 0)
	    logit(LOG_ERR, "Warning: art[0] is NIL! %s", xtmp);
		
	{
	    int i;
	    for (i = 0; i < iovLen; ++i)
		actLen += iov[i].iov_len;
	}

	if (DOpts.ReaderXRefSlaveHost && 
	    (oa = GetOverArt(ov, artNo, NULL)) != NULL &&
	    oa->oa_MsgHash.h1 == hv.h1 &&
	    oa->oa_MsgHash.h2 == hv.h2 &&
	    OA_ARTNOEQ(artNo, oa->oa_ArtNo)
	) {
	    /*
	     * We can detect duplicate articles in XRef slave mode.  If 
	     * we see one, do not do anything.
	     */
	    LogCmd(conn, 'd', logbuf);
	    if (DRIncomingLogPat != NULL)
		LogIncoming("%s d %s%s", conn->co_Auth.dr_Host, "", logbuf);
	    ; /* EMPTY */
	} else if (DOpts.ReaderXOverMode == 0) {
	    /*
	     * Do not write xover info at all.  This mode is not really
	     * supported by the reader but may eventually be supported
	     * in 100% nntp-cache mode if/when we develop it.
	     */
	    logit(LOG_INFO, "ReaderXOverMode0 (%lld:%s)", artNo, msgid);
	    LogCmd(conn, 'm', logbuf);
	    if (DRIncomingLogPat != NULL)
		LogIncoming("%s m %s%s", conn->co_Auth.dr_Host, "", logbuf);
	    ; /* EMPTY */
	} else if (
	    DOpts.ReaderXOverMode == 2 ||
	    (FilePreAllocSpace(ov->ov_HCache->od_HFd, pos,
	     prealloc_oh, iovLen) == 0 &&
	     writev(ov->ov_HCache->od_HFd, iov, iovLen) == actLen)
	) {
	    /*
	     * Our write of the overview data succeeded or we were asked not
	     * to write out the overview data.  Write out the overview 
	     * article record.
	     */
	    OverArt ovart = { 0 };
	    off_t ovpos = 0;

	    hflock(ov->ov_OFd, 0, XLOCK_EX);

	    (void)GetOverArt(ov, artNo, &ovpos);

	    ovart.oa_ArtNo = OA_ARTNOSET(artNo);
	    if (DOpts.ReaderXOverMode == 2)
		ovart.oa_SeekPos = -1;
	    else
		ovart.oa_SeekPos = pos;
	    ovart.oa_Bytes = actLen - 1;	/* do not include \0 */
	    ovart.oa_MsgHash = hv;
	    ovart.oa_TimeRcvd = (int)time(NULL);
	    ovart.oa_ArtSize = (conn->co_ByteCounter > 0.0 ? conn->co_ByteCounter : conn->co_BytesHeader);

	    lseek(ov->ov_OFd, ovpos, 0);
	    FilePreAllocSpace(ov->ov_OFd, ovpos, prealloc_ov, sizeof(ovart));
	    write(ov->ov_OFd, &ovart, sizeof(ovart));
	    hflock(ov->ov_OFd, 0, XLOCK_UN);
	    LogCmd(conn, '+', logbuf);
	    if (DRIncomingLogPat != NULL)
		LogIncoming("%s + %s%s", conn->co_Auth.dr_Host, "", logbuf);
	} else {
	    ftruncate(ov->ov_HCache->od_HFd, pos);
	    logit(LOG_ERR, "error writing overview data file for %s", group);
	    LogCmd(conn, '-', logbuf);
	    if (DRIncomingLogPat != NULL)
		LogIncoming("%s - %s%s", conn->co_Auth.dr_Host, "", logbuf);
	    MBLogPrintf(conn, &conn->co_TMBuf, "400 Error writing data\r\n");
	    NNTerminate(conn);
	    err = 1;
	}
	hflock(ov->ov_HCache->od_HFd, 0, XLOCK_UN);
	PutOverInfo(ov);
    }
    if (xtmp)
	zfree(&conn->co_MemPool, xtmp, xtmpLen);
    return(err);
}
Пример #6
0
int
DILookup(char *id)
{
    hash_t hv;
    History h;
    int r = 0;
    char *p;

    if (id[0] == '<' && (p = strchr(id, '>')) != NULL) {
	*++p = 0;
	hv = hhash(id);
    } else if (id[0] == 'D' && id[1] == '.') {
	int32 dummy;
	char *p = strchr(id, '/');

	if (p && p[1] == 'B' && p[2] == '.') {
	    /*
	     * dqueue data format
	     */
	    if ((id = strchr(p, '<')) != NULL && strchr(id, '>') != NULL) {
		*(strchr(id, '>') + 1) = 0;
		hv = hhash(id);
	    } else {
		fprintf(stderr, "argument error: %s\n", id);
		exit(1);
	    }
	} else {
	    /*
	     * hash code format 1
	     */
	    if (sscanf(id + 2, "%x/%x.%x", &dummy, &hv.h1, &hv.h2) != 3) {
		fprintf(stderr, "argument error: %s\n", id);
		exit(1);
	    }
	}
    } else if (strncmp(id, "DUMP ", 5) == 0) {
	if (sscanf(id + 5, "%x.%x", &hv.h1, &hv.h2) != 2) {
	    fprintf(stderr, "argument error: %s\n", id);
	    exit(1);
	}
    } else if (sscanf(id, "%x.%x", &hv.h1, &hv.h2) != 2) {
	/*
	 * hash code format 2
	 */
	fprintf(stderr, "argument error: %s\n", id);
	exit(1);
    }

    if (HistoryLookupByHash(hv, &h) == 0) {
	char tbuf1[64];
	char tbuf2[64];
	char buf[1024];

	if (QuietOpt)
	    return(r);

	{
	    struct tm *tp;
	    time_t t;

	    t = h.gmt * 60;
	    tp = localtime(&t);
	    strftime(tbuf1, sizeof(tbuf1), "%d-%b-%Y %H:%M:%S", tp);

	    if (H_EXPIRED(h.exp)) {
		if (h.iter == (unsigned short)-1)
		    sprintf(tbuf2, "rejected");
		else
		    sprintf(tbuf2, "expired");
	    } else {
		sprintf(tbuf2, "valid");
	    }
	}


	if (h.boffset || h.bsize) {
	    ArticleFileName(buf, sizeof(buf), &h, ARTFILE_FILE_REL);
	    printf(" [%s hv=%08x.%08x spool=%02x gm=%d ex=%d off=%d len=%d f=%s]"
		   " GM=(%s) EX=(%s)\n",
		buf,
		h.hv.h1,
		h.hv.h2,
		(int)H_SPOOL(h.exp),
		(int)h.gmt,
		(int)h.exp,
		(int)h.boffset,
		(int)h.bsize,
		((h.exp & EXPF_HEADONLY) ? "H" : ""),
		tbuf1,
		tbuf2
	    );
	} else {
	    ArticleFileName(buf, sizeof(buf), &h, ARTFILE_DIR_REL);
	    printf(" [%s/NOFILE hv=%08x.%08x gm=%d ex=%d f=%s] GM=(%s) EX=(%s) (pre-expired)\n",
		buf,
		h.hv.h1,
		h.hv.h2,
		(int)h.gmt,
		(int)h.exp,
		((h.exp & EXPF_HEADONLY) ? "H" : ""),
		tbuf1,
		tbuf2
	    );
	}
    } else {
	printf("Not Found: %s (%08x.%08x)\n", id, hv.h1, hv.h2);
	r = 1;
    }
    return(r);
}