Hello Justin,
thanks for the feedback.
- Records cannot be continued across lines. + Records can be backslash-continued across lines.Maybe say: "lines ending with a backslash are logically continued on the next line", or similar.
I tried to change it along that.
Since it puts a blank there, it creates a "word" boundary, which I gather worked for your use case. But I wonder whether it's needed to add a space (or otherwise, document that lines cannot be split beween words?).
Hmmm. Ok, you are right. I hesitated while doing it. I removed the char instead, so that it does not add a word break.
Note, that also appears to affect the "username maps" file. So mention in that chapter, too. https://www.postgresql.org/docs/current/auth-username-maps.html
Indeed, the same tokenizer is used. I updated a sentence to point on continuations.
-- Fabien.
diff --git a/doc/src/sgml/client-auth.sgml b/doc/src/sgml/client-auth.sgml index 5f1eec78fb..4f947b0235 100644 --- a/doc/src/sgml/client-auth.sgml +++ b/doc/src/sgml/client-auth.sgml @@ -77,7 +77,8 @@ The general format of the <filename>pg_hba.conf</filename> file is a set of records, one per line. Blank lines are ignored, as is any text after the <literal>#</literal> comment character. - Records cannot be continued across lines. + Lines ending with a backslash are logically continued on the next + line, so a record can span several lines. A record is made up of a number of fields which are separated by spaces and/or tabs. Fields can contain white space if the field value is double-quoted. @@ -821,7 +822,7 @@ local db1,db2,@demodbs all md5 <synopsis> <replaceable>map-name</replaceable> <replaceable>system-username</replaceable> <replaceable>database-username</replaceable> </synopsis> - Comments and whitespace are handled in the same way as in + Comments, whitespace and continuations are handled in the same way as in <filename>pg_hba.conf</filename>. The <replaceable>map-name</replaceable> is an arbitrary name that will be used to refer to this mapping in <filename>pg_hba.conf</filename>. The other diff --git a/src/backend/libpq/hba.c b/src/backend/libpq/hba.c index da5189a4fa..bae20dbc06 100644 --- a/src/backend/libpq/hba.c +++ b/src/backend/libpq/hba.c @@ -486,8 +486,43 @@ tokenize_file(const char *filename, FILE *file, List **tok_lines, int elevel) char *lineptr; List *current_line = NIL; char *err_msg = NULL; + char *cur = rawline; + int len = sizeof(rawline); + int continuations = 0; - if (!fgets(rawline, sizeof(rawline), file)) + /* read input and handle simplistic backslash continuations */ + while ((cur = fgets(cur, len, file)) != NULL) + { + int curlen = strlen(cur); + char *curend = cur + curlen - 1; + + if (curlen == len - 1) + { + /* Line too long! */ + ereport(elevel, + (errcode(ERRCODE_CONFIG_FILE_ERROR), + errmsg("authentication file line too long"), + errcontext("line %d of configuration file \"%s\"", + line_number + continuations, filename))); + err_msg = "authentication file line too long"; + } + + /* Strip trailing linebreak from rawline */ + while (curend >= cur && (*curend == '\n' || *curend == '\r')) + *curend-- = '\0'; + + /* empty or not a continuation, we are done */ + if (curend < cur || *curend != '\\') + break; + + /* else we have a continuation, just remove it and loop */ + continuations++; + *curend = '\0'; + len -= (curend - cur); + cur = curend; + } + + if (cur == NULL) { int save_errno = errno; @@ -501,21 +536,6 @@ tokenize_file(const char *filename, FILE *file, List **tok_lines, int elevel) filename, strerror(save_errno)); rawline[0] = '\0'; } - if (strlen(rawline) == MAX_LINE - 1) - { - /* Line too long! */ - ereport(elevel, - (errcode(ERRCODE_CONFIG_FILE_ERROR), - errmsg("authentication file line too long"), - errcontext("line %d of configuration file \"%s\"", - line_number, filename))); - err_msg = "authentication file line too long"; - } - - /* Strip trailing linebreak from rawline */ - lineptr = rawline + strlen(rawline) - 1; - while (lineptr >= rawline && (*lineptr == '\n' || *lineptr == '\r')) - *lineptr-- = '\0'; /* Parse fields */ lineptr = rawline; @@ -543,7 +563,7 @@ tokenize_file(const char *filename, FILE *file, List **tok_lines, int elevel) *tok_lines = lappend(*tok_lines, tok_line); } - line_number++; + line_number += continuations + 1; } MemoryContextSwitchTo(oldcxt);