37 #include "scfg.h" |
37 #include "scfg.h" |
38 |
38 |
39 #define xstreq(a,b) xmlStrEqual(BAD_CAST a, BAD_CAST b) |
39 #define xstreq(a,b) xmlStrEqual(BAD_CAST a, BAD_CAST b) |
40 |
40 |
41 |
41 |
42 #define print_error(...) \ |
42 #define print_error(lineno, ...) \ |
43 do {\ |
43 do {\ |
44 fprintf(stderr, "Error (sync.xml): " __VA_ARGS__); \ |
44 fprintf(stderr, "Error (sync.xml line %u): ", lineno); \ |
|
45 fprintf(stderr, __VA_ARGS__); \ |
45 fprintf(stderr, "Abort.\n"); \ |
46 fprintf(stderr, "Abort.\n"); \ |
46 } while(0); |
47 } while(0); |
47 #define print_warning(...) \ |
48 #define print_warning(lineno, ...) \ |
48 fprintf(stderr, "Warning (sync.xml): " __VA_ARGS__); |
49 do {\ |
|
50 fprintf(stderr, "Warning (sync.xml line %u): ", lineno); \ |
|
51 fprintf(stderr, __VA_ARGS__); \ |
|
52 } while(0); |
49 |
53 |
50 #ifdef _WIN32 |
54 #ifdef _WIN32 |
51 #define ENV_HOME getenv("USERPROFILE") |
55 #define ENV_HOME getenv("USERPROFILE") |
52 #else |
56 #else |
53 #define ENV_HOME getenv("HOME") |
57 #define ENV_HOME getenv("HOME") |
104 while(node && !ret) { |
108 while(node && !ret) { |
105 if(node->type == XML_ELEMENT_NODE) { |
109 if(node->type == XML_ELEMENT_NODE) { |
106 if(xstreq(node->name, "directory")) { |
110 if(xstreq(node->name, "directory")) { |
107 ret = scfg_load_directory(node); |
111 ret = scfg_load_directory(node); |
108 } else { |
112 } else { |
109 print_error("unknown config element: %s\n", node->name); |
113 print_error(node->line, |
|
114 "unknown config element: %s\n", node->name); |
110 ret = 1; |
115 ret = 1; |
111 } |
116 } |
112 } |
117 } |
113 node = node->next; |
118 node = node->next; |
114 } |
119 } |
116 xmlFreeDoc(doc); |
121 xmlFreeDoc(doc); |
117 free(file); |
122 free(file); |
118 return ret; |
123 return ret; |
119 } |
124 } |
120 |
125 |
121 static UcxList* add_regex_pattern(UcxList *list, char *value) { |
126 static UcxList* add_regex_pattern(UcxList *list, char *value, |
|
127 unsigned short xmlline) { |
122 regex_t *regex = malloc(sizeof(regex_t)); |
128 regex_t *regex = malloc(sizeof(regex_t)); |
123 if (regcomp(regex, value, REG_EXTENDED|REG_NOSUB)) { |
129 if (regcomp(regex, value, REG_EXTENDED|REG_NOSUB)) { |
124 fprintf(stderr, "Invalid regular expression (%s) ... skipped\n", value); |
130 print_warning(xmlline, |
|
131 "Invalid regular expression (%s) ... skipped\n", value); |
125 return list; |
132 return list; |
126 } else { |
133 } else { |
127 return ucx_list_append(list, regex); |
134 return ucx_list_append(list, regex); |
128 } |
135 } |
129 } |
136 } |
130 |
137 |
131 static int scfg_load_filter(xmlNode *node, UcxList **include, UcxList **exclude) { |
138 static int scfg_load_filter(xmlNode *node, |
|
139 UcxList **include, UcxList **exclude) { |
132 node = node->children; |
140 node = node->children; |
133 |
141 |
134 while(node) { |
142 while(node) { |
135 if(node->type == XML_ELEMENT_NODE) { |
143 if(node->type == XML_ELEMENT_NODE) { |
136 char *value = util_xml_get_text(node); |
144 char *value = util_xml_get_text(node); |
137 if(xstreq(node->name, "include")) { |
145 if(xstreq(node->name, "include")) { |
138 if(value) { |
146 if(value) { |
139 *include = add_regex_pattern(*include, value); |
147 *include = add_regex_pattern(*include, value, node->line); |
140 } |
148 } |
141 } else if(xstreq(node->name, "exclude")) { |
149 } else if(xstreq(node->name, "exclude")) { |
142 if(value) { |
150 if(value) { |
143 *exclude = add_regex_pattern(*exclude, value); |
151 *exclude = add_regex_pattern(*exclude, value, node->line); |
144 } |
152 } |
145 } else { |
153 } else { |
146 print_error("unknown filter config element: %s\n", node->name); |
154 print_error(node->line, |
|
155 "unknown filter config element: %s\n", node->name); |
147 return 1; |
156 return 1; |
148 } |
157 } |
149 if(!value) { |
158 if(!value) { |
150 print_error("missing value for filter: %s\n", node->name); |
159 print_error(node->line, |
|
160 "missing value for filter: %s\n", node->name); |
151 return 1; |
161 return 1; |
152 } |
162 } |
153 } |
163 } |
154 |
164 |
155 node = node->next; |
165 node = node->next; |
170 int max_retry = 0; |
180 int max_retry = 0; |
171 bool backuppull = false; |
181 bool backuppull = false; |
172 bool lockpull = false; |
182 bool lockpull = false; |
173 bool lockpush = false; |
183 bool lockpush = false; |
174 |
184 |
|
185 unsigned short parentlineno = node->line; |
175 node = node->children; |
186 node = node->children; |
176 while(node) { |
187 while(node) { |
177 if(node->type == XML_ELEMENT_NODE) { |
188 if(node->type == XML_ELEMENT_NODE) { |
178 char *value = util_xml_get_text(node); |
189 char *value = util_xml_get_text(node); |
179 /* every key needs a value */ |
190 /* every key needs a value */ |
180 if(!value) { |
191 if(!value) { |
181 /* TODO: maybe this should only be reported, if the key is valid |
192 /* TODO: maybe this should only be reported, if the key is valid |
182 * But this makes the code very ugly. |
193 * But this makes the code very ugly. |
183 */ |
194 */ |
184 print_error("missing value for directory element: %s\n", |
195 print_error(node->line, |
|
196 "missing value for directory element: %s\n", |
185 node->name); |
197 node->name); |
186 return 1; |
198 return 1; |
187 } |
199 } |
188 if(xstreq(node->name, "name")) { |
200 if(xstreq(node->name, "name")) { |
189 name = value; |
201 name = value; |
204 } else if(xstreq(node->name, "max-retry")) { |
216 } else if(xstreq(node->name, "max-retry")) { |
205 int64_t i; |
217 int64_t i; |
206 if(util_strtoint(value, &i) && i >= 0) { |
218 if(util_strtoint(value, &i) && i >= 0) { |
207 max_retry = (int)i; |
219 max_retry = (int)i; |
208 } else { |
220 } else { |
209 print_warning("unsigned integer value " |
221 print_warning(node->line, "unsigned integer value " |
210 "expected in <max-retry> element\n"); |
222 "expected in <max-retry> element\n"); |
211 } |
223 } |
212 } else if(xstreq(node->name, "backup-on-pull")) { |
224 } else if(xstreq(node->name, "backup-on-pull")) { |
213 backuppull = util_getboolean(value); |
225 backuppull = util_getboolean(value); |
214 } else if(xstreq(node->name, "lock-pull")) { |
226 } else if(xstreq(node->name, "lock-pull")) { |
215 lockpull = util_getboolean(value); |
227 lockpull = util_getboolean(value); |
216 } else if(xstreq(node->name, "lock-push")) { |
228 } else if(xstreq(node->name, "lock-push")) { |
217 lockpush = util_getboolean(value); |
229 lockpush = util_getboolean(value); |
218 } else { |
230 } else { |
219 print_error("unknown directory config element: %s\n", |
231 print_error(node->line, |
220 node->name); |
232 "unknown directory config element: %s\n", node->name); |
221 return 1; |
233 return 1; |
222 } |
234 } |
223 } |
235 } |
224 node = node->next; |
236 node = node->next; |
225 } |
237 } |
226 |
238 |
227 if(!name) { |
239 if(!name) { |
228 print_error("missing name element for directory\n"); |
240 print_error(parentlineno, "missing name element for directory\n"); |
229 return 1; |
241 return 1; |
230 } |
242 } |
231 if(!path) { |
243 if(!path) { |
232 print_error("missing path element for directory %s\n", name); |
244 print_error(parentlineno, |
|
245 "missing path element for directory %s\n", name); |
233 return 1; |
246 return 1; |
234 } |
247 } |
235 if(!repository) { |
248 if(!repository) { |
236 print_error("missing repository element for directory %s\n", name); |
249 print_error(parentlineno, |
|
250 "missing repository element for directory %s\n", name); |
237 return 1; |
251 return 1; |
238 } |
252 } |
239 if(!database) { |
253 if(!database) { |
240 print_error("missing database element for directory %s\n", name); |
254 print_error(parentlineno, |
|
255 "missing database element for directory %s\n", name); |
241 return 1; |
256 return 1; |
242 } |
257 } |
243 |
258 |
244 SyncDirectory *dir = malloc(sizeof(SyncDirectory)); |
259 SyncDirectory *dir = malloc(sizeof(SyncDirectory)); |
245 dir->name = strdup(name); |
260 dir->name = strdup(name); |