|
7 | 7 | * Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group
|
8 | 8 | * Portions Copyright (c) 1994, Regents of the University of California
|
9 | 9 | *
|
10 |
| - * $PostgreSQL: pgsql/src/backend/access/transam/xlog.c,v 1.390 2010/04/07 06:12:52 heikki Exp $ |
| 10 | + * $PostgreSQL: pgsql/src/backend/access/transam/xlog.c,v 1.391 2010/04/07 10:58:49 heikki Exp $ |
11 | 11 | *
|
12 | 12 | *-------------------------------------------------------------------------
|
13 | 13 | */
|
@@ -4893,6 +4893,100 @@ str_time(pg_time_t tnow)
|
4893 | 4893 | return buf;
|
4894 | 4894 | }
|
4895 | 4895 |
|
| 4896 | +/* |
| 4897 | + * Parse one line from recovery.conf. 'cmdline' is the raw line from the |
| 4898 | + * file. If the line is parsed successfully, returns true, false indicates |
| 4899 | + * syntax error. On success, *key_p and *value_p are set to the parameter |
| 4900 | + * name and value on the line, respectively. If the line is an empty line, |
| 4901 | + * consisting entirely of whitespace and comments, function returns true |
| 4902 | + * and *keyp_p and *value_p are set to NULL. |
| 4903 | + * |
| 4904 | + * The pointers returned in *key_p and *value_p point to an internal buffer |
| 4905 | + * that is valid only until the next call of parseRecoveryCommandFile(). |
| 4906 | + */ |
| 4907 | +static bool |
| 4908 | +parseRecoveryCommandFileLine(char *cmdline, char **key_p, char **value_p) |
| 4909 | +{ |
| 4910 | + char *ptr; |
| 4911 | + char *bufp; |
| 4912 | + char *key; |
| 4913 | + char *value; |
| 4914 | + static char *buf = NULL; |
| 4915 | + |
| 4916 | + *key_p = *value_p = NULL; |
| 4917 | + |
| 4918 | + /* |
| 4919 | + * Allocate the buffer on first use. It's used to hold both the |
| 4920 | + * parameter name and value. |
| 4921 | + */ |
| 4922 | + if (buf == NULL) |
| 4923 | + buf = malloc(MAXPGPATH + 1); |
| 4924 | + bufp = buf; |
| 4925 | + |
| 4926 | + /* Skip any whitespace at the beginning of line */ |
| 4927 | + for (ptr = cmdline; *ptr; ptr++) |
| 4928 | + { |
| 4929 | + if (!isspace((unsigned char) *ptr)) |
| 4930 | + break; |
| 4931 | + } |
| 4932 | + /* Ignore empty lines */ |
| 4933 | + if (*ptr == '\0' || *ptr == '#') |
| 4934 | + return true; |
| 4935 | + |
| 4936 | + /* Read the parameter name */ |
| 4937 | + key = bufp; |
| 4938 | + while (*ptr && !isspace((unsigned char) *ptr) && |
| 4939 | + *ptr != '=' && *ptr != '\'') |
| 4940 | + *(bufp++) = *(ptr++); |
| 4941 | + *(bufp++) = '\0'; |
| 4942 | + |
| 4943 | + /* Skip to the beginning quote of the parameter value */ |
| 4944 | + ptr = strchr(ptr, '\''); |
| 4945 | + if (!ptr) |
| 4946 | + return false; |
| 4947 | + ptr++; |
| 4948 | + |
| 4949 | + /* Read the parameter value to *bufp. Collapse any '' escapes as we go. */ |
| 4950 | + value = bufp; |
| 4951 | + for (;;) |
| 4952 | + { |
| 4953 | + if (*ptr == '\'') |
| 4954 | + { |
| 4955 | + ptr++; |
| 4956 | + if (*ptr == '\'') |
| 4957 | + *(bufp++) = '\''; |
| 4958 | + else |
| 4959 | + { |
| 4960 | + /* end of parameter */ |
| 4961 | + *bufp = '\0'; |
| 4962 | + break; |
| 4963 | + } |
| 4964 | + } |
| 4965 | + else if (*ptr == '\0') |
| 4966 | + return false; /* unterminated quoted string */ |
| 4967 | + else |
| 4968 | + *(bufp++) = *ptr; |
| 4969 | + |
| 4970 | + ptr++; |
| 4971 | + } |
| 4972 | + *(bufp++) = '\0'; |
| 4973 | + |
| 4974 | + /* Check that there's no garbage after the value */ |
| 4975 | + while (*ptr) |
| 4976 | + { |
| 4977 | + if (*ptr == '#') |
| 4978 | + break; |
| 4979 | + if (!isspace((unsigned char) *ptr)) |
| 4980 | + return false; |
| 4981 | + ptr++; |
| 4982 | + } |
| 4983 | + |
| 4984 | + /* Success! */ |
| 4985 | + *key_p = key; |
| 4986 | + *value_p = value; |
| 4987 | + return true; |
| 4988 | +} |
| 4989 | + |
4896 | 4990 | /*
|
4897 | 4991 | * See if there is a recovery command file (recovery.conf), and if so
|
4898 | 4992 | * read in parameters for archive recovery and XLOG streaming.
|
@@ -4926,39 +5020,16 @@ readRecoveryCommandFile(void)
|
4926 | 5020 | */
|
4927 | 5021 | while (fgets(cmdline, sizeof(cmdline), fd) != NULL)
|
4928 | 5022 | {
|
4929 |
| - /* skip leading whitespace and check for # comment */ |
4930 |
| - char *ptr; |
4931 | 5023 | char *tok1;
|
4932 | 5024 | char *tok2;
|
4933 | 5025 |
|
4934 |
| - for (ptr = cmdline; *ptr; ptr++) |
4935 |
| - { |
4936 |
| - if (!isspace((unsigned char) *ptr)) |
4937 |
| - break; |
4938 |
| - } |
4939 |
| - if (*ptr == '\0' || *ptr == '#') |
4940 |
| - continue; |
4941 |
| - |
4942 |
| - /* identify the quoted parameter value */ |
4943 |
| - tok1 = strtok(ptr, "'"); |
4944 |
| - if (!tok1) |
4945 |
| - { |
4946 |
| - syntaxError = true; |
4947 |
| - break; |
4948 |
| - } |
4949 |
| - tok2 = strtok(NULL, "'"); |
4950 |
| - if (!tok2) |
4951 |
| - { |
4952 |
| - syntaxError = true; |
4953 |
| - break; |
4954 |
| - } |
4955 |
| - /* reparse to get just the parameter name */ |
4956 |
| - tok1 = strtok(ptr, " \t="); |
4957 |
| - if (!tok1) |
| 5026 | + if (!parseRecoveryCommandFileLine(cmdline, &tok1, &tok2)) |
4958 | 5027 | {
|
4959 | 5028 | syntaxError = true;
|
4960 | 5029 | break;
|
4961 | 5030 | }
|
| 5031 | + if (tok1 == NULL) |
| 5032 | + continue; |
4962 | 5033 |
|
4963 | 5034 | if (strcmp(tok1, "restore_command") == 0)
|
4964 | 5035 | {
|
|
0 commit comments