From 32667d683339a981218b668df7247fc3a1116fb7 Mon Sep 17 00:00:00 2001 From: Kern Sibbald Date: Wed, 21 Nov 2012 18:26:37 +0100 Subject: [PATCH] Make bfgets handle very long lines --- bacula/src/lib/bsys.c | 51 +++++++++++++++++++++++++++++++++++++++++ bacula/src/lib/lex.c | 6 +++-- bacula/src/lib/lex.h | 6 ++--- bacula/src/lib/protos.h | 3 ++- 4 files changed, 59 insertions(+), 7 deletions(-) diff --git a/bacula/src/lib/bsys.c b/bacula/src/lib/bsys.c index fdee8f6090..7900e3cf58 100644 --- a/bacula/src/lib/bsys.c +++ b/bacula/src/lib/bsys.c @@ -689,6 +689,57 @@ char *bfgets(char *s, int size, FILE *fd) return s; } +/* + * Bacula's implementation of fgets(). The difference is that it handles + * being interrupted by a signal (e.g. a SIGCHLD) and it has a + * different calling sequence which implements input lines of + * up to a million characters. + */ +char *bfgets(POOLMEM *&s, FILE *fd) +{ + int ch; + int soft_max; + int i = 0; + + s[0] = 0; + soft_max = sizeof_pool_memory(s) - 10; + for ( ;; ) { + do { + errno = 0; + ch = fgetc(fd); + } while (ch == EOF && ferror(fd) && (errno == EINTR || errno == EAGAIN)); + if (ch == EOF) { + if (i == 0) { + return NULL; + } else { + return s; + } + } + if (i > soft_max) { + /* Insanity check */ + if (soft_max > 1000000) { + return s; + } + s = check_pool_memory_size(s, soft_max+10000); + soft_max = sizeof_pool_memory(s) - 10; + } + s[i++] = ch; + s[i] = 0; + if (ch == '\r') { /* Support for Mac/Windows file format */ + ch = fgetc(fd); + if (ch != '\n') { /* Mac (\r only) */ + (void)ungetc(ch, fd); /* Push next character back to fd */ + } + s[i-1] = '\n'; + break; + } + if (ch == '\n') { + break; + } + } + return s; +} + /* * Make a "unique" filename. It is important that if * called again with the same "what" that the result diff --git a/bacula/src/lib/lex.c b/bacula/src/lib/lex.c index 4e2558a8b0..cd9d7c5dae 100644 --- a/bacula/src/lib/lex.c +++ b/bacula/src/lib/lex.c @@ -139,6 +139,8 @@ LEX *lex_close_file(LEX *lf) } Dmsg1(dbglvl, "Close cfg file %s\n", lf->fname); free(lf->fname); + free_memory(lf->line); + lf->line = NULL; if (of) { of->options = lf->options; /* preserve options */ memcpy(lf, of, sizeof(LEX)); @@ -170,7 +172,6 @@ LEX *lex_open_file(LEX *lf, const char *filename, LEX_ERROR_HANDLER *scan_error) BPIPE *bpipe = NULL; char *fname = bstrdup(filename); - if (fname[0] == '|') { if ((bpipe = open_bpipe(fname+1, 0, "rb")) == NULL) { free(fname); @@ -206,6 +207,7 @@ LEX *lex_open_file(LEX *lf, const char *filename, LEX_ERROR_HANDLER *scan_error) lf->fd = fd; lf->bpipe = bpipe; lf->fname = fname; + lf->line = get_memory(5000); lf->state = lex_none; lf->ch = L_EOL; Dmsg1(dbglvl, "Return lex=%x\n", lf); @@ -225,7 +227,7 @@ int lex_get_char(LEX *lf) " You may have a open double quote without the closing double quote.\n")); } if (lf->ch == L_EOL) { - if (bfgets(lf->line, MAXSTRING, lf->fd) == NULL) { + if (bfgets(lf->line, lf->fd) == NULL) { lf->ch = L_EOF; if (lf->next) { lex_close_file(lf); diff --git a/bacula/src/lib/lex.h b/bacula/src/lib/lex.h index 115a60ac7f..b2a55c5f8b 100644 --- a/bacula/src/lib/lex.h +++ b/bacula/src/lib/lex.h @@ -1,7 +1,7 @@ /* Bacula® - The Network Backup Solution - Copyright (C) 2000-2007 Free Software Foundation Europe e.V. + Copyright (C) 2000-2012 Free Software Foundation Europe e.V. The main author of Bacula is Kern Sibbald, with contributions from many others, a complete list can be found in the file AUTHORS. @@ -32,8 +32,6 @@ * * Kern Sibbald, MM * - * Version $Id$ - * */ #ifndef _LEX_H @@ -106,7 +104,7 @@ typedef struct s_lex_context { int options; /* scan options */ char *fname; /* filename */ FILE *fd; /* file descriptor */ - char line[MAXSTRING]; /* input line */ + POOLMEM *line; /* input line */ char str[MAXSTRING]; /* string being scanned */ int str_len; /* length of string */ int line_no; /* file line number */ diff --git a/bacula/src/lib/protos.h b/bacula/src/lib/protos.h index 548799f641..d04c84746d 100644 --- a/bacula/src/lib/protos.h +++ b/bacula/src/lib/protos.h @@ -1,7 +1,7 @@ /* Bacula® - The Network Backup Solution - Copyright (C) 2000-2010 Free Software Foundation Europe e.V. + Copyright (C) 2000-2012 Free Software Foundation Europe e.V. The main author of Bacula is Kern Sibbald, with contributions from many others, a complete list can be found in the file AUTHORS. @@ -72,6 +72,7 @@ int delete_pid_file (char *dir, const char *progname, int port); void drop (char *uid, char *gid, bool keep_readall_caps); int bmicrosleep (int32_t sec, int32_t usec); char *bfgets (char *s, int size, FILE *fd); +char *bfgets (POOLMEM *&s, FILE *fd); void make_unique_filename (POOLMEM **name, int Id, char *what); #ifndef HAVE_STRTOLL long long int strtoll (const char *ptr, char **endptr, int base); -- 2.39.2