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.
This commit is contained in:
parent
370f770c15
commit
0f11ed5886
|
@ -1,4 +1,4 @@
|
||||||
<!-- $PostgreSQL: pgsql/doc/src/sgml/recovery-config.sgml,v 2.3 2010/03/18 09:17:18 heikki Exp $ -->
|
<!-- $PostgreSQL: pgsql/doc/src/sgml/recovery-config.sgml,v 2.4 2010/04/07 10:58:49 heikki Exp $ -->
|
||||||
|
|
||||||
<chapter Id="recovery-config">
|
<chapter Id="recovery-config">
|
||||||
<title>Recovery Configuration</title>
|
<title>Recovery Configuration</title>
|
||||||
|
@ -18,6 +18,14 @@
|
||||||
be changed once recovery has begun.
|
be changed once recovery has begun.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
Settings in <filename>recovery.conf</> are specified in the format
|
||||||
|
<literal>name = 'value'</>. One parameter is specified per line.
|
||||||
|
Hash marks (<literal>#</literal>) designate the rest of the
|
||||||
|
line as a comment. To embed a single quote in a parameter
|
||||||
|
value, write two quotes (<literal>''</>).
|
||||||
|
</para>
|
||||||
|
|
||||||
<sect1 id="archive-recovery-settings">
|
<sect1 id="archive-recovery-settings">
|
||||||
|
|
||||||
<title>Archive recovery settings</title>
|
<title>Archive recovery settings</title>
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
* Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group
|
* Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group
|
||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* 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 $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
|
@ -4893,6 +4893,100 @@ str_time(pg_time_t tnow)
|
||||||
return buf;
|
return buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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
|
* See if there is a recovery command file (recovery.conf), and if so
|
||||||
* read in parameters for archive recovery and XLOG streaming.
|
* read in parameters for archive recovery and XLOG streaming.
|
||||||
|
@ -4926,40 +5020,17 @@ readRecoveryCommandFile(void)
|
||||||
*/
|
*/
|
||||||
while (fgets(cmdline, sizeof(cmdline), fd) != NULL)
|
while (fgets(cmdline, sizeof(cmdline), fd) != NULL)
|
||||||
{
|
{
|
||||||
/* skip leading whitespace and check for # comment */
|
|
||||||
char *ptr;
|
|
||||||
char *tok1;
|
char *tok1;
|
||||||
char *tok2;
|
char *tok2;
|
||||||
|
|
||||||
for (ptr = cmdline; *ptr; ptr++)
|
if (!parseRecoveryCommandFileLine(cmdline, &tok1, &tok2))
|
||||||
{
|
{
|
||||||
if (!isspace((unsigned char) *ptr))
|
syntaxError = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (*ptr == '\0' || *ptr == '#')
|
if (tok1 == NULL)
|
||||||
continue;
|
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)
|
|
||||||
{
|
|
||||||
syntaxError = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (strcmp(tok1, "restore_command") == 0)
|
if (strcmp(tok1, "restore_command") == 0)
|
||||||
{
|
{
|
||||||
recoveryRestoreCommand = pstrdup(tok2);
|
recoveryRestoreCommand = pstrdup(tok2);
|
||||||
|
|
Loading…
Reference in New Issue