1 | /* Copyright (c) 2010, Oracle and/or its affiliates. |
2 | |
3 | This program is free software; you can redistribute it and/or modify |
4 | it under the terms of the GNU General Public License as published by |
5 | the Free Software Foundation; version 2 of the License. |
6 | |
7 | This program is distributed in the hope that it will be useful, |
8 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
9 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
10 | GNU General Public License for more details. |
11 | |
12 | You should have received a copy of the GNU General Public License |
13 | along with this program; if not, write to the Free Software Foundation, |
14 | 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA */ |
15 | |
16 | |
17 | #include "mariadb.h" |
18 | #include <ctype.h> |
19 | #include <string.h> |
20 | #include "sql_bootstrap.h" |
21 | |
22 | int read_bootstrap_query(char *query, int *query_length, |
23 | fgets_input_t input, fgets_fn_t fgets_fn, int *error) |
24 | { |
25 | char line_buffer[MAX_BOOTSTRAP_LINE_SIZE]; |
26 | const char *line; |
27 | size_t len; |
28 | size_t query_len= 0; |
29 | int fgets_error= 0; |
30 | *error= 0; |
31 | |
32 | for ( ; ; ) |
33 | { |
34 | line= (*fgets_fn)(line_buffer, sizeof(line_buffer), input, &fgets_error); |
35 | |
36 | if (error) |
37 | *error= fgets_error; |
38 | |
39 | if (fgets_error != 0) |
40 | return READ_BOOTSTRAP_ERROR; |
41 | |
42 | if (line == NULL) |
43 | return (query_len == 0) ? READ_BOOTSTRAP_EOF : READ_BOOTSTRAP_ERROR; |
44 | |
45 | len= strlen(line); |
46 | |
47 | /* |
48 | Remove trailing whitespace characters. |
49 | This assumes: |
50 | - no multibyte encoded character can be found at the very end of a line, |
51 | - whitespace characters from the "C" locale only. |
52 | which is sufficient for the kind of queries found |
53 | in the bootstrap scripts. |
54 | */ |
55 | while (len && (isspace(line[len - 1]))) |
56 | len--; |
57 | /* |
58 | Cleanly end the string, so we don't have to test len > x |
59 | all the time before reading line[x], in the code below. |
60 | */ |
61 | line_buffer[len]= '\0'; |
62 | |
63 | /* Skip blank lines */ |
64 | if (len == 0) |
65 | continue; |
66 | |
67 | /* Skip # comments */ |
68 | if (line[0] == '#') |
69 | continue; |
70 | |
71 | /* Skip -- comments */ |
72 | if ((line[0] == '-') && (line[1] == '-')) |
73 | continue; |
74 | |
75 | /* Skip delimiter, ignored. */ |
76 | if (strncmp(line, "delimiter" , 9) == 0) |
77 | continue; |
78 | |
79 | /* Append the current line to a multi line query. If the new line will make |
80 | the query too long, preserve the partial line to provide context for the |
81 | error message. |
82 | */ |
83 | if (query_len + len + 1 >= MAX_BOOTSTRAP_QUERY_SIZE) |
84 | { |
85 | size_t new_len= MAX_BOOTSTRAP_QUERY_SIZE - query_len - 1; |
86 | if ((new_len > 0) && (query_len < MAX_BOOTSTRAP_QUERY_SIZE)) |
87 | { |
88 | memcpy(query + query_len, line, new_len); |
89 | query_len+= new_len; |
90 | } |
91 | query[query_len]= '\0'; |
92 | *query_length= (int)query_len; |
93 | return READ_BOOTSTRAP_QUERY_SIZE; |
94 | } |
95 | |
96 | if (query_len != 0) |
97 | { |
98 | /* |
99 | Append a \n to the current line, if any, |
100 | to preserve the intended presentation. |
101 | */ |
102 | query[query_len++]= '\n'; |
103 | } |
104 | memcpy(query + query_len, line, len); |
105 | query_len+= len; |
106 | |
107 | if (line[len - 1] == ';') |
108 | { |
109 | /* |
110 | The last line is terminated by ';'. |
111 | Return the query found. |
112 | */ |
113 | query[query_len]= '\0'; |
114 | *query_length= (int)query_len; |
115 | return READ_BOOTSTRAP_SUCCESS; |
116 | } |
117 | } |
118 | } |
119 | |
120 | |