diff options
author | Heikki Linnakangas <heikki.linnakangas@iki.fi> | 2010-04-07 10:58:49 +0000 |
---|---|---|
committer | Heikki Linnakangas <heikki.linnakangas@iki.fi> | 2010-04-07 10:58:49 +0000 |
commit | 0f11ed5886ce797d816177f5a915a22d85dd7400 (patch) | |
tree | cb652ecb8a5e0a0b7f2760929ca82fb605d32ac4 /src/backend/access/transam/xlog.c | |
parent | 370f770c15a4c08094298685887d8a512267c369 (diff) | |
download | postgresql-0f11ed5886ce797d816177f5a915a22d85dd7400.tar.gz postgresql-0f11ed5886ce797d816177f5a915a22d85dd7400.zip |
Allow quotes to be escaped in recovery.conf, by doubling them. This patch
also makes the parsing a little bit stricter, rejecting garbage after the
parameter value and values with missing ending quotes, for example.
Diffstat (limited to 'src/backend/access/transam/xlog.c')
-rw-r--r-- | src/backend/access/transam/xlog.c | 125 |
1 files changed, 98 insertions, 27 deletions
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c index 592419d3567..12392f8cfc0 100644 --- a/src/backend/access/transam/xlog.c +++ b/src/backend/access/transam/xlog.c @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/backend/access/transam/xlog.c,v 1.390 2010/04/07 06:12:52 heikki Exp $ + * $PostgreSQL: pgsql/src/backend/access/transam/xlog.c,v 1.391 2010/04/07 10:58:49 heikki Exp $ * *------------------------------------------------------------------------- */ @@ -4894,6 +4894,100 @@ str_time(pg_time_t tnow) } /* + * Parse one line from recovery.conf. 'cmdline' is the raw line from the + * file. If the line is parsed successfully, returns true, false indicates + * syntax error. On success, *key_p and *value_p are set to the parameter + * name and value on the line, respectively. If the line is an empty line, + * consisting entirely of whitespace and comments, function returns true + * and *keyp_p and *value_p are set to NULL. + * + * The pointers returned in *key_p and *value_p point to an internal buffer + * that is valid only until the next call of parseRecoveryCommandFile(). + */ +static bool +parseRecoveryCommandFileLine(char *cmdline, char **key_p, char **value_p) +{ + char *ptr; + char *bufp; + char *key; + char *value; + static char *buf = NULL; + + *key_p = *value_p = NULL; + + /* + * Allocate the buffer on first use. It's used to hold both the + * parameter name and value. + */ + if (buf == NULL) + buf = malloc(MAXPGPATH + 1); + bufp = buf; + + /* Skip any whitespace at the beginning of line */ + for (ptr = cmdline; *ptr; ptr++) + { + if (!isspace((unsigned char) *ptr)) + break; + } + /* Ignore empty lines */ + if (*ptr == '\0' || *ptr == '#') + return true; + + /* Read the parameter name */ + key = bufp; + while (*ptr && !isspace((unsigned char) *ptr) && + *ptr != '=' && *ptr != '\'') + *(bufp++) = *(ptr++); + *(bufp++) = '\0'; + + /* Skip to the beginning quote of the parameter value */ + ptr = strchr(ptr, '\''); + if (!ptr) + return false; + ptr++; + + /* Read the parameter value to *bufp. Collapse any '' escapes as we go. */ + value = bufp; + for (;;) + { + if (*ptr == '\'') + { + ptr++; + if (*ptr == '\'') + *(bufp++) = '\''; + else + { + /* end of parameter */ + *bufp = '\0'; + break; + } + } + else if (*ptr == '\0') + return false; /* unterminated quoted string */ + else + *(bufp++) = *ptr; + + ptr++; + } + *(bufp++) = '\0'; + + /* Check that there's no garbage after the value */ + while (*ptr) + { + if (*ptr == '#') + break; + if (!isspace((unsigned char) *ptr)) + return false; + ptr++; + } + + /* Success! */ + *key_p = key; + *value_p = value; + return true; +} + +/* * See if there is a recovery command file (recovery.conf), and if so * read in parameters for archive recovery and XLOG streaming. * @@ -4926,39 +5020,16 @@ readRecoveryCommandFile(void) */ while (fgets(cmdline, sizeof(cmdline), fd) != NULL) { - /* skip leading whitespace and check for # comment */ - char *ptr; char *tok1; char *tok2; - for (ptr = cmdline; *ptr; ptr++) - { - if (!isspace((unsigned char) *ptr)) - break; - } - if (*ptr == '\0' || *ptr == '#') - continue; - - /* identify the quoted parameter value */ - tok1 = strtok(ptr, "'"); - if (!tok1) - { - syntaxError = true; - break; - } - tok2 = strtok(NULL, "'"); - if (!tok2) - { - syntaxError = true; - break; - } - /* reparse to get just the parameter name */ - tok1 = strtok(ptr, " \t="); - if (!tok1) + if (!parseRecoveryCommandFileLine(cmdline, &tok1, &tok2)) { syntaxError = true; break; } + if (tok1 == NULL) + continue; if (strcmp(tok1, "restore_command") == 0) { |