/
githubmirror
/
rsyslog
Обзор
Документация
Войти
/
githubmirror
/
rsyslog
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
tests/chkseq.c
266 строк
9 KB
Rainer Gerhards
Fix chkseq EOF handling
08 май 2026, 10:47
Не верифицирован
08 май 2026, 10:47
29bb6aa
Код
Авторство
О чём код?
/* Checks if a file consists of line of strictly monotonically * increasing numbers. An expected start and end number may * be set. * * Params * -f<filename> file to process, if not given stdin is processed. * -s<starting number> -e<ending number> * default for s is 0. -e should be given (else it is also 0) * -d may be specified, in which case duplicate messages are permitted. * -m number of messages permitted to be missing without triggering a * failure. This is necessary for some failover tests, where it is * impossible to totally guard against message loss. By default, NO * message is permitted to be lost. * -T anticipate truncation (which means specified payload length may be * more than actual payload (which may have been truncated) * -i increment between messages (default: 1). Can be used for tests which * intentionally leave consistent gaps in the message numbering. * * Part of the testbench for rsyslog. * * Copyright 2009-2018 Rainer Gerhards and Adiscon GmbH. * * This file is part of rsyslog. * * Rsyslog is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Rsyslog is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Rsyslog. If not, see <http://www.gnu.org/licenses/>. * * A copy of the GPL can be found in the file "COPYING" in this distribution. */ #include "config.h" #include <stdio.h> #include <stdlib.h> #include <string.h> #if defined(_AIX) #include <unistd.h> #else #include <getopt.h> #endif #define EDBUF_SIZE (500 * 1024) int main(int argc, char *argv[]) { FILE *fp; int val = -1; int i; int ret = 0; int scanfOK; int verbose = 0; int bHaveExtraData = 0; int bAnticipateTruncation = 0; int dupsPermitted = 0; int start = 0, end = 0; int opt; int lostok = 0; /* how many messages are OK to be lost? */ int nDups = 0; int increment = 1; int reachedEOF = 0; int edLen; /* length of extra data */ static char edBuf[EDBUF_SIZE]; /* buffer for extra data (pretty large to be on the safe side...) */ static char ioBuf[sizeof(edBuf) + 1024]; char extraFmt[64]; char *file = NULL; snprintf(extraFmt, sizeof(extraFmt), "%%d,%%d,%%%zus\n", sizeof(edBuf) - 1); while ((opt = getopt(argc, argv, "i:e:f:ds:vm:ET")) != EOF) { switch ((char)opt) { case 'f': file = optarg; break; case 'd': dupsPermitted = 1; break; case 'i': increment = atoi(optarg); break; case 'e': end = atoi(optarg); break; case 's': start = atoi(optarg); break; case 'v': ++verbose; break; case 'm': lostok = atoi(optarg); break; case 'E': bHaveExtraData = 1; break; case 'T': bAnticipateTruncation = 1; break; default: printf("Invalid call of chkseq, optchar='%c'\n", opt); printf("Usage: chkseq -f<file> -s<start> -e<end> [-d] [-E] [-T] [-v] [-m<lostok>] [-i<increment>]\n"); exit(1); } } if (start > end) { printf("start must be less than or equal end!\n"); exit(1); } if (verbose) { printf("chkseq: start %d, end %d\n", start, end); } /* read file */ if (file == NULL) { fp = stdin; } else { fp = fopen(file, "r"); } if (fp == NULL) { printf("error opening file '%s'\n", file); perror(file); exit(1); } for (i = start; i <= end; i += increment) { if (bHaveExtraData) { edLen = 0; edBuf[0] = '\0'; if (fgets(ioBuf, sizeof(ioBuf), fp) == NULL) { scanfOK = 0; } else { scanfOK = sscanf(ioBuf, extraFmt, &val, &edLen, edBuf) == 3; } if (scanfOK && edLen != (int)strlen(edBuf)) { if (bAnticipateTruncation == 1) { if (edLen < (int)strlen(edBuf)) { printf( "extra data length specified %d, but actually is %ld in" " record %d (truncation was anticipated, but payload should" " have been smaller than data-length, not larger)\n", edLen, (long)strlen(edBuf), i); exit(1); } } else { printf("extra data length specified %d, but actually is %ld in record %d\n", edLen, (long)strlen(edBuf), i); exit(1); } } } else { if (fgets(ioBuf, sizeof(ioBuf), fp) == NULL) { scanfOK = 0; } else { scanfOK = sscanf(ioBuf, "%d\n", &val) == 1 ? 1 : 0; } } if (!scanfOK) { if (feof(fp) && lostok > 0) { while (i <= end && lostok > 0) { --lostok; printf("message %d missing (ok due to -m [now %d])\n", i, lostok); i += increment; } if (i > end) break; } printf("scanf error in index i=%d\n", i); exit(1); } while (val > i && lostok > 0) { --lostok; printf("message %d missing (ok due to -m [now %d])\n", i, lostok); i += increment; } if (val != i) { if (val == i - increment && dupsPermitted) { --i; ++nDups; } else { printf("read value %d, but expected value %d\n", val, i); exit(1); } } } if (i - increment != end) { printf("lastrecord does not match. file: %d, expected %d\n", i - increment, end); exit(1); } int c = getc(fp); if (c == EOF) { reachedEOF = 1; } else { ungetc(c, fp); /* if duplicates are permitted, we need to do a final check if we have duplicates at the * end of file. */ if (dupsPermitted) { i = end; while (!feof(fp)) { if (bHaveExtraData) { edLen = 0; edBuf[0] = '\0'; if (fgets(ioBuf, sizeof(ioBuf), fp) == NULL) { scanfOK = 0; } else { scanfOK = sscanf(ioBuf, extraFmt, &val, &edLen, edBuf) == 3; } if (scanfOK && edLen != (int)strlen(edBuf)) { if (bAnticipateTruncation == 1) { if (edLen < (int)strlen(edBuf)) { printf( "extra data length specified %d, but " "actually is %ld in record %d (truncation was" " anticipated, but payload should have been " "smaller than data-length, not larger)\n", edLen, (long)strlen(edBuf), i); exit(1); } } else { printf( "extra data length specified %d, but actually " "is %ld in record %d\n", edLen, (long)strlen(edBuf), i); exit(1); } } } else { if (fgets(ioBuf, sizeof(ioBuf), fp) == NULL) { scanfOK = 0; } else { scanfOK = sscanf(ioBuf, "%d\n", &val) == 1 ? 1 : 0; } } if (!scanfOK || val != i) { reachedEOF = !scanfOK && feof(fp); goto breakIF; } } reachedEOF = feof(fp) ? 1 : 0; } else { reachedEOF = 0; } } breakIF: if (nDups != 0) printf("info: had %d duplicates (this is no error)\n", nDups); if (!reachedEOF) { printf("end of processing, but NOT end of file! First line of extra data is:\n"); for (c = fgetc(fp); c != '\n' && c != EOF; c = fgetc(fp)) putchar(c); putchar('\n'); exit(1); } exit(ret); }