/* * DREADOVER group:article * * Read the overview record related to an article in a specific group. * This command is typically used for debugging purposes only. * * (c)Copyright 1998, Matthew Dillon, All Rights Reserved. Refer to * the COPYRIGHT file in the base directory of this distribution * for specific rights granted. */ #include char * allocTmpCopy(const char *buf, int bufLen); void DReadOver(char *data); void Usage(void); void OverDump(void); int ForceOpt = 0; int ViewData = 0; int VerboseMode = 0; char * allocTmpCopy(const char *buf, int bufLen) { static char *SaveAry[8]; static int SaveCnt; char **pptr; SaveCnt = (SaveCnt + 1) % arysize(SaveAry); pptr = &SaveAry[SaveCnt]; if (*pptr) free(*pptr); *pptr = malloc(bufLen + 1); memcpy(*pptr, buf, bufLen); (*pptr)[bufLen] = 0; return(*pptr); } int main(int ac, char **av) { int i; int Doneone = 0; LoadDiabloConfig(ac, av); if (ac < 2) Usage(); for (i = 1; i < ac; ++i) { char *ptr = av[i]; if (*ptr != '-' || strcmp(ptr, "-") == 0) { if (*ptr != '-') { DReadOver(ptr); } else { char buf[512]; while (fgets(buf, sizeof(buf), stdin) != NULL) DReadOver(buf); } Doneone = 1; continue; } ptr += 2; switch(ptr[-1]) { case 'a': OverDump(); Doneone = 1; break; case 'C': /* diablo.config path */ break; case 'd': VerboseMode = 1; break; case 'f': ForceOpt = 1; break; case 'V': PrintVersion(); break; case 'v': ViewData = 1; break; default: Usage(); } } if (!Doneone) Usage(); return(0); } void Usage(void) { fprintf(stderr, "Prints out overview info from the overview cache\n"); fprintf(stderr, " Usage: dreadover [-f] [-v] [-a] [group:artno[-artnoend]]\n"); fprintf(stderr, " -f : Force retrieval if art no mismatch\n"); fprintf(stderr, " -v : Also view the overview data\n"); fprintf(stderr, " -a : List maxarts for all newsgroups\n"); fprintf(stderr, " group : The newsgroup group name\n"); fprintf(stderr, " artno : The starting article number\n"); fprintf(stderr, " artnoend : The ending article number\n"); exit(1); } void DReadOver(char *data) { const char *gfname; const char *slash; char *ptr, *p; int artNo = 0; int artNoStart = 0; int artNoEnd = 0; int fd1; int fd2; OverHead oh; struct stat st; int maxarts; char path[1024]; if ((ptr = strrchr(data, ':')) != NULL) { *ptr++ = 0; artNo = strtol(ptr, NULL, 10); artNoStart = artNo; artNoEnd = artNoStart; if ((p = strrchr(ptr, '-')) != NULL) artNoEnd = strtol(p + 1, NULL, 10); } /* * Cycle through the overview entries */ for (artNo = artNoStart; artNo <= artNoEnd; artNo++) { int pos; OverArt oa; /* Open the overview info file */ gfname = GFName(data, GRPFTYPE_OVER, 0, 1, 0, &DOpts.ReaderGroupHashMethod); slash = strchr(gfname, '/'); snprintf(path, sizeof(path), "%s/%s", PatExpand(GroupHomePat), gfname); printf("GROUPINFO:%s:%d\t%s", data, artNo, gfname); if ((fd1 = open(path, O_RDONLY)) < 0) { printf("\t(array open fail)\n"); return; } if (read(fd1, &oh, sizeof(oh)) != sizeof(oh)) { printf("\t(read header fail)\n"); close(fd1); return; } if (oh.oh_Version != OH_VERSION || oh.oh_ByteOrder != OH_BYTEORDER) { printf("\t(wrong version or byte order)\n"); close(fd1); return; } fstat(fd1, &st); maxarts = (st.st_size - oh.oh_HeadSize) / sizeof(OverArt); printf("\tmaxarts=%d", maxarts); pos = oh.oh_HeadSize + ((artNo & 0x7FFFFFFF) % maxarts) * sizeof(OverArt); printf("\tpos=%d", pos); lseek(fd1, pos, 0); if (read(fd1, &oa, sizeof(oa)) != sizeof(oa)) { printf("\t(unable to read OverArt)"); close(fd1); return; } if (oa.oa_ArtNo <= 0) { if (oa.oa_ArtNo == -1) printf("\t(Article cancelled)(%d)\n", oa.oa_ArtNo); else if (oa.oa_ArtNo == -2) printf("\t(Article expired)(%d)\n", oa.oa_ArtNo); else printf("\t(Article not found)(%d)\n", oa.oa_ArtNo); close(fd1); continue; } if (oa.oa_ArtNo != artNo) { printf("\tartNoMismatch(got=%d wanted=%d)\n", oa.oa_ArtNo, artNo); if (!ForceOpt) { close(fd1); continue; } } /* * Open the overview data file */ gfname = GFName(data, GRPFTYPE_DATA, artNo & ~OD_HMASK, 1, 0, &DOpts.ReaderGroupHashMethod); snprintf(path, sizeof(path), "%s/%s", PatExpand(GroupHomePat), gfname); printf("\t%s", gfname); if ((fd2 = open(path, O_RDONLY)) < 0) { printf("\t(data open fail)\n"); close(fd1); return; } printf("\tdataFilePos=%d\tsize=%d\treceived=%d\tbytes=%d\thash=%x.%x\n", oa.oa_SeekPos, oa.oa_Bytes, oa.oa_TimeRcvd, oa.oa_ArtSize, oa.oa_MsgHash.h1, oa.oa_MsgHash.h2); if (ViewData) { static char *buf = NULL; int buflen = 0; int n = oa.oa_Bytes + 1; int r; if (n > buflen) buflen = n; buf = (char *)realloc(buf, buflen); lseek(fd2, oa.oa_SeekPos, 0); while ((r = read(fd2, buf, n)) > 0) { printf("%s", buf); n -= r; } close(fd2); } close(fd1); if (artNo <= artNoEnd) printf("--------------------------------------------------------------------\n"); } printf("\n"); } /* * Dump the contents of the overview info files for all newsgroups in * active file. */ void OverDump(void) { char path[PATH_MAX]; const char *gfname; char *slash; char *groupname; int recLen; int recOff; int fd1; OverHead oh; struct stat st; int maxarts; KPDB *KDBActive = KPDBOpen(PatDbExpand(ReaderDActivePat), O_RDWR); if (KDBActive == NULL) { printf("Unable to open active file\n"); exit(1); } for (recOff = KPDBScanFirst(KDBActive, 0, &recLen); recOff; recOff = KPDBScanNext(KDBActive, recOff, 0, &recLen) ) { int groupLen; const char *rec; const char *group; int begno; rec = KPDBReadRecordAt(KDBActive, recOff, 0, NULL); group = KPDBGetField(rec, recLen, NULL, &groupLen, NULL); if (!group) continue; groupname = allocTmpCopy(group, groupLen); begno = strtol(KPDBGetField(rec, recLen, "NB", NULL, "0"), NULL, 10); gfname = GFName(groupname, GRPFTYPE_OVER, 0, 1, 0, &DOpts.ReaderGroupHashMethod); slash = strchr(gfname, '/'); snprintf(path, sizeof(path), "%s/%s", PatExpand(GroupHomePat), gfname); if ((fd1 = open(path, O_RDONLY)) < 0) { if (VerboseMode) printf("%s (array open fail)\n", groupname); continue;; } if (read(fd1, &oh, sizeof(oh)) != sizeof(oh)) { if (VerboseMode) printf("%s (read header fail)\n", groupname); close(fd1); continue;; } if (oh.oh_Version != OH_VERSION || oh.oh_ByteOrder != OH_BYTEORDER) { if (VerboseMode) printf("%s (wrong version or byte order)\n", groupname); close(fd1); continue;; } fstat(fd1, &st); maxarts = (st.st_size - oh.oh_HeadSize) / sizeof(OverArt); printf("%s:%d\n", groupname, maxarts); close(fd1); } }