*** pgsql/src/backend/access/transam/xlog.c 2010/04/07 06:12:52 1.390 --- pgsql/src/backend/access/transam/xlog.c 2010/04/07 10:58:49 1.391 *************** *** 7,13 **** * 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.389 2010/04/06 17:51:58 sriggs Exp $ * *------------------------------------------------------------------------- */ --- 7,13 ---- * 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 $ * *------------------------------------------------------------------------- */ *************** str_time(pg_time_t tnow) *** 4894,4899 **** --- 4894,4993 ---- } /* + * 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. * *************** readRecoveryCommandFile(void) *** 4926,4964 **** */ 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) { syntaxError = true; break; } if (strcmp(tok1, "restore_command") == 0) { --- 5020,5035 ---- */ while (fgets(cmdline, sizeof(cmdline), fd) != NULL) { char *tok1; char *tok2; ! if (!parseRecoveryCommandFileLine(cmdline, &tok1, &tok2)) { syntaxError = true; break; } + if (tok1 == NULL) + continue; if (strcmp(tok1, "restore_command") == 0) {