libamxo  4.3.4
Object Definition Language (ODL) parsing
amxo_save.c
Go to the documentation of this file.
1 /****************************************************************************
2 **
3 ** SPDX-License-Identifier: BSD-2-Clause-Patent
4 **
5 ** SPDX-FileCopyrightText: Copyright (c) 2023 SoftAtHome
6 **
7 ** Redistribution and use in source and binary forms, with or without modification,
8 ** are permitted provided that the following conditions are met:
9 **
10 ** 1. Redistributions of source code must retain the above copyright notice,
11 ** this list of conditions and the following disclaimer.
12 **
13 ** 2. Redistributions in binary form must reproduce the above copyright notice,
14 ** this list of conditions and the following disclaimer in the documentation
15 ** and/or other materials provided with the distribution.
16 **
17 ** Subject to the terms and conditions of this license, each copyright holder
18 ** and contributor hereby grants to those receiving rights under this license
19 ** a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable
20 ** (except for failure to satisfy the conditions of this license) patent license
21 ** to make, have made, use, offer to sell, sell, import, and otherwise transfer
22 ** this software, where such license applies only to those patent claims, already
23 ** acquired or hereafter acquired, licensable by such copyright holder or contributor
24 ** that are necessarily infringed by:
25 **
26 ** (a) their Contribution(s) (the licensed copyrights of copyright holders and
27 ** non-copyrightable additions of contributors, in source or binary form) alone;
28 ** or
29 **
30 ** (b) combination of their Contribution(s) with the work of authorship to which
31 ** such Contribution(s) was added by such copyright holder or contributor, if,
32 ** at the time the Contribution is added, such addition causes such combination
33 ** to be necessarily infringed. The patent license shall not apply to any other
34 ** combinations which include the Contribution.
35 **
36 ** Except as expressly stated above, no rights or licenses from any copyright
37 ** holder or contributor is granted under this license, whether expressly, by
38 ** implication, estoppel or otherwise.
39 **
40 ** DISCLAIMER
41 **
42 ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
43 ** AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
44 ** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
45 ** ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
46 ** LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
47 ** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
48 ** SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
49 ** CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
50 ** OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
51 ** USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
52 **
53 ****************************************************************************/
54 
55 #ifndef _GNU_SOURCE
56 #define _GNU_SOURCE
57 #endif
58 
59 #include "amxo_parser_priv.h"
60 
61 #define PARAM_ATTR(param, attr_name) \
62  amxc_var_dyncast(bool, \
63  amxc_var_get_path(param, \
64  attr_name, \
65  AMXC_VAR_FLAG_DEFAULT))
66 
67 #define PARAM_NAME(param) \
68  amxc_var_constcast(cstring_t, \
69  amxc_var_get_path(param, \
70  "name", \
71  AMXC_VAR_FLAG_DEFAULT))
72 
73 #define PARAM_FLAGS(param) \
74  amxc_var_constcast(amxc_llist_t, \
75  amxc_var_get_path(param, \
76  "flags", \
77  AMXC_VAR_FLAG_DEFAULT))
78 
79 #define PARAM_VALUE(param) \
80  amxc_var_get_path(param, \
81  "value", \
82  AMXC_VAR_FLAG_DEFAULT)
83 
84 static size_t buffer_size = 16348;
85 static int indentation = 0;
86 
87 static int amxo_parser_save_object_tree(int fd,
88  amxd_object_t* object,
89  uint32_t depth,
90  amxc_string_t* buffer);
91 
92 static int amxo_parser_save_value(int fd,
93  amxc_var_t* value,
94  amxc_string_t* buffer,
95  const char* termination);
96 
97 static int amxo_parser_write(int fd, const char* buf, size_t bytes) {
98  int retval = 0;
99  size_t length = 0;
100  ssize_t written = 0;
101  while(length != bytes) {
102  written = write(fd, buf + length, bytes - length);
103  if(written < 0) {
104  retval = errno;
105  break;
106  }
107  length += written;
108  }
109 
110  return retval;
111 }
112 
113 static void amxo_parser_indent(amxc_string_t* buffer) {
114  static const char* spaces = "\t\t\t\t\t\t\t\t\t\t";
115 
116  if(indentation > 0) {
117  amxc_string_append(buffer, spaces, indentation > 10 ? 10 : indentation);
118  }
119 }
120 
121 static int amxo_parser_flush_buffer(int fd, amxc_string_t* buffer) {
122  int retval = 0;
123  const char* buf = amxc_string_get(buffer, 0);
124  size_t length = amxc_string_text_length(buffer);
125 
126  retval = amxo_parser_write(fd, buf, length);
127 
128  amxc_string_reset(buffer);
129  return retval;
130 }
131 
132 static void amxo_parser_writef(int fd,
133  amxc_string_t* buffer,
134  const char* fmt,
135  ...) {
136  va_list args;
137 
138  va_start(args, fmt);
139  amxc_string_vappendf(buffer, fmt, args);
140  va_end(args);
141 
142  if(amxc_string_text_length(buffer) > buffer_size) {
143  amxo_parser_flush_buffer(fd, buffer);
144  }
145 }
146 
148  const char* filename,
149  bool temp) {
150  char* full_name = NULL;
151  amxc_string_t full_path;
152 
153  amxc_string_init(&full_path, 128);
154  amxc_string_appendf(&full_path, "%s%s", filename, temp ? ".tmp" : "");
155  amxc_string_resolve(&full_path, &pctx->config);
156  full_name = amxc_string_take_buffer(&full_path);
157  amxc_string_clean(&full_path);
158 
159  return full_name;
160 }
161 
162 static int amxo_parser_copy(int dest_fd, int source_fd) {
163  int retval = 0;
164 
165  ssize_t length = 0;
166  char buffer[1024];
167 
168  length = read(source_fd, buffer, 1024);
169  while(length > 0) {
170  retval = amxo_parser_write(dest_fd, buffer, (size_t) length);
171  when_failed(retval, exit);
172  length = read(source_fd, buffer, 1024);
173  }
174 
175 exit:
176  return retval;
177 }
178 
180  const char* filename,
181  bool append) {
182  int fd = -1;
183  char* full_path_tmp = amxo_parser_build_filename(pctx, filename, true);
184  char* full_path = amxo_parser_build_filename(pctx, filename, false);
185  char* real_path = NULL;
186  int open_flags = O_CREAT | O_WRONLY | O_TRUNC;
187  int mode_flags = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH;
188 
189  if(append) {
190  real_path = realpath(full_path, NULL);
191  when_null(real_path, exit);
192  }
193  fd = open(full_path_tmp, open_flags, mode_flags);
194  when_true(fd == -1, exit);
195 
196  if(append) {
197  int orig_fd = open(real_path, O_RDONLY);
198  if(orig_fd == -1) {
199  close(fd);
200  fd = -1;
201  goto exit;
202  }
203  if(amxo_parser_copy(fd, orig_fd) != 0) {
204  close(orig_fd);
205  close(fd);
206  fd = -1;
207  goto exit;
208  }
209  close(orig_fd);
210  }
211 
212 exit:
213  free(full_path_tmp);
214  free(full_path);
215  free(real_path);
216  return fd;
217 }
218 
220  amxc_var_t* value,
221  amxc_string_t* buffer) {
222  int retval = -1;
223  const char* sep = ",";
224 
225  amxo_parser_indent(buffer);
226  amxc_var_for_each(val, value) {
227  const char* key = amxc_var_key(val);
228  if(amxc_var_get_next(val) == NULL) {
229  sep = "";
230  }
231 
232  if(strchr(key, '.') != NULL) {
233  amxo_parser_writef(fd, buffer, "\"'%s'\" = ", key);
234  } else {
235  amxo_parser_writef(fd, buffer, "\"%s\" = ", key);
236  }
237 
238  retval = amxo_parser_save_value(fd, val, buffer, sep);
239  when_true(retval < 0, exit);
240  }
241  retval = 0;
242 
243 exit:
244  return retval;
245 }
246 
248  amxc_var_t* value,
249  amxc_string_t* buffer) {
250  int retval = -1;
251  const char* sep = ",";
252 
253  amxc_var_for_each(val, value) {
254  if(amxc_var_get_next(val) == NULL) {
255  sep = "";
256  }
257  amxo_parser_indent(buffer);
258  retval = amxo_parser_save_value(fd, val, buffer, sep);
259  amxo_parser_writef(fd, buffer, "\n");
260  when_true(retval < 0, exit);
261  }
262  retval = 0;
263 
264 exit:
265  return retval;
266 }
267 
268 static void amxo_parser_escape_value(amxc_string_t* value) {
269  amxc_string_esc(value);
270 }
271 
272 static int amxo_parser_save_value(int fd,
273  amxc_var_t* value,
274  amxc_string_t* buffer,
275  const char* termination) {
276  int type = amxc_var_type_of(value);
277  int retval = 0;
278  char* txt = NULL;
279  switch(type) {
280  case AMXC_VAR_ID_INT8:
281  case AMXC_VAR_ID_INT16:
282  case AMXC_VAR_ID_INT32:
283  case AMXC_VAR_ID_INT64:
284  case AMXC_VAR_ID_UINT8:
285  case AMXC_VAR_ID_UINT16:
286  case AMXC_VAR_ID_UINT32:
287  case AMXC_VAR_ID_UINT64:
288  case AMXC_VAR_ID_BOOL:
289  txt = amxc_var_dyncast(cstring_t, value);
290  amxo_parser_writef(fd, buffer, "%s%s", txt, termination);
291  free(txt);
292  break;
293  case AMXC_VAR_ID_TIMESTAMP:
294  txt = amxc_var_dyncast(cstring_t, value);
295  amxo_parser_writef(fd, buffer, "\"%s\"%s", txt, termination);
296  free(txt);
297  break;
298  case AMXC_VAR_ID_CSTRING:
299  case AMXC_VAR_ID_SSV_STRING:
300  case AMXC_VAR_ID_CSV_STRING: {
301  amxc_string_t str_value;
302  amxc_string_init(&str_value, 0);
303  amxc_string_set(&str_value, amxc_var_constcast(cstring_t, value));
304  amxo_parser_escape_value(&str_value);
305  amxo_parser_writef(fd, buffer, "\"%s\"%s", amxc_string_get(&str_value, 0), termination);
306  amxc_string_clean(&str_value);
307  }
308  break;
309  case AMXC_VAR_ID_HTABLE:
310  amxo_parser_writef(fd, buffer, "{\n");
311  indentation++;
312  amxo_parser_save_table_config(fd, value, buffer);
313  indentation--;
314  amxo_parser_writef(fd, buffer, "}%s\n", termination);
315  break;
316  case AMXC_VAR_ID_LIST:
317  amxo_parser_writef(fd, buffer, "[\n");
318  indentation++;
319  amxo_parser_save_list_config(fd, value, buffer);
320  indentation--;
321  amxo_parser_indent(buffer);
322  amxo_parser_writef(fd, buffer, "]%s\n", termination);
323  break;
324  default:
325  retval = -1;
326  break;
327  }
328 
329  return retval;
330 }
331 
333  amxc_var_t* config,
334  amxc_string_t* buffer) {
335  int retval = 0;
336  amxo_parser_writef(fd, buffer, "%%config {\n");
337  indentation++;
338  amxc_var_for_each(val, config) {
339  const char* key = amxc_var_key(val);
340  amxo_parser_indent(buffer);
341  if(strchr(key, '.') != NULL) {
342  amxo_parser_writef(fd, buffer, "\"'%s'\" = ", key);
343  } else {
344  amxo_parser_writef(fd, buffer, "\"%s\" = ", key);
345  }
346 
347  retval = amxo_parser_save_value(fd, val, buffer, ";");
348  when_true(retval < 0, exit);
349  }
350  indentation--;
351  amxo_parser_writef(fd, buffer, "}\n");
352 
353 exit:
354  return retval;
355 }
356 
357 static bool amxo_parser_is_creation_parameter(const amxc_llist_t* flags) {
358  bool retval = false;
359  amxc_llist_for_each(it, flags) {
360  amxc_var_t* flag = amxc_var_from_llist_it(it);
361  if(strcmp(GET_CHAR(flag, NULL), "odl-creation-param") == 0) {
362  retval = true;
363  break;
364  }
365  }
366 
367  return retval;
368 }
369 
370 static bool amxo_parser_has_key_params(const amxc_htable_t* params) {
371  bool retval = false;
372 
373  amxc_htable_for_each(it, params) {
374  amxc_var_t* param = amxc_var_from_htable_it(it);
375  const amxc_llist_t* flags = amxc_var_constcast(amxc_llist_t,
376  GET_ARG(param, "flags"));
377 
378  if(PARAM_ATTR(param, "attributes.key")) {
379  retval = true;
380  break;
381  }
382 
384  retval = true;
385  break;
386  }
387  }
388 
389  return retval;
390 }
391 
392 static int amxo_parser_instance_header(int fd,
393  amxd_object_t* object,
394  amxc_string_t* buffer) {
395  int retval = 0;
396  const amxc_htable_t* ht_params = NULL;
397  amxc_var_t params;
398  const char* inst_name = amxd_object_get_name(object, AMXD_OBJECT_NAMED);
399 
400  amxo_parser_indent(buffer);
401  amxo_parser_writef(fd, buffer, "instance add(%d", amxd_object_get_index(object));
402  if(amxd_name_is_valid(inst_name)) {
403  amxo_parser_writef(fd, buffer, ", '%s'", inst_name);
404  }
405 
406  amxc_var_init(&params);
407  amxd_object_describe_params(object, &params, amxd_dm_access_public);
408  ht_params = amxc_var_constcast(amxc_htable_t, &params);
409  if(amxo_parser_has_key_params(ht_params)) {
410  amxc_htable_for_each(it, ht_params) {
411  amxc_var_t* param = amxc_var_from_htable_it(it);
412  const char* name = amxc_htable_it_get_key(it);
413  amxc_var_t* value = PARAM_VALUE(param);
414  bool is_key_param = PARAM_ATTR(param, "attributes.key");
415  bool is_creation_param = amxo_parser_is_creation_parameter(PARAM_FLAGS(param));
416  if(!is_key_param && !is_creation_param) {
417  continue;
418  }
419  amxo_parser_writef(fd, buffer, ", '%s' = ", name);
420  retval = amxo_parser_save_value(fd, value, buffer, "");
421  when_true(retval < 0, exit);
422  }
423  }
424  amxo_parser_writef(fd, buffer, ") {\n");
425 
426 exit:
427  amxc_var_clean(&params);
428  return retval;
429 }
430 
432  amxd_object_t* object,
433  amxc_string_t* buffer) {
434  int retval = 0;
435  if(amxd_object_get_type(object) != amxd_object_root) {
436  retval = amxo_parser_open_parent_tree(fd,
437  amxd_object_get_parent(object),
438  buffer);
439  when_true(retval < 0, exit);
440  }
441 
442  if(amxd_object_get_type(object) == amxd_object_root) {
443  goto exit;
444  }
445 
446  if(amxd_object_get_type(object) == amxd_object_instance) {
447  amxo_parser_instance_header(fd, object, buffer);
448  } else {
449  amxo_parser_indent(buffer);
450  amxo_parser_writef(fd, buffer,
451  "object '%s' {\n",
452  amxd_object_get_name(object, AMXD_OBJECT_NAMED));
453  }
454  indentation++;
455 
456 exit:
457  return retval;
458 }
459 
460 static int amxo_parser_save_mibs(int fd,
461  amxd_object_t* object,
462  amxc_string_t* buffer) {
463  int retval = 0;
464  amxc_array_it_t* it = amxc_array_get_first(&object->mib_names);
465  while(it) {
466  const char* name = (const char*) amxc_array_it_get_data(it);
467  amxo_parser_indent(buffer);
468  amxo_parser_writef(fd, buffer, "extend using mib '%s';\n", name);
469  it = amxc_array_it_get_next(it);
470  }
471 
472  return retval;
473 }
474 
476  amxc_var_t* param,
477  amxc_string_t* buffer) {
478  int retval = 0;
479  const amxc_llist_t* flags = PARAM_FLAGS(param);
480  const char* sep = "";
481  amxo_parser_writef(fd, buffer, " {\n");
482  indentation++;
483  amxo_parser_indent(buffer);
484  amxo_parser_writef(fd, buffer, "userflags ");
485  amxc_llist_iterate(it, flags) {
486  amxc_var_t* var_flag = amxc_var_from_llist_it(it);
487  const char* flag = amxc_var_constcast(cstring_t, var_flag);
488  amxo_parser_writef(fd, buffer, "%s %%%s", sep, flag);
489  sep = ",";
490  }
491  amxo_parser_writef(fd, buffer, ";\n");
492  indentation--;
493  amxo_parser_indent(buffer);
494  amxo_parser_writef(fd, buffer, "}\n");
495 
496  return retval;
497 }
498 
499 static bool amxo_parser_must_save_param(amxd_object_t* object, amxc_var_t* param) {
500  amxc_var_t* attrs = GET_ARG(param, "attributes");
501  bool is_templ_param = GET_BOOL(attrs, "template");
502  bool is_inst_param = GET_BOOL(attrs, "instance");
503  bool is_key_param = GET_BOOL(attrs, "key");
504  bool is_persist_param = GET_BOOL(attrs, "persistent");
505  bool is_creation_param = amxo_parser_is_creation_parameter(PARAM_FLAGS(param));
506  bool must_save = true;
507 
508  if(amxd_object_get_type(object) == amxd_object_template) {
509  if(is_key_param || is_creation_param ||
510  !is_persist_param || !is_templ_param) {
511  must_save = false;
512  }
513  } else if(amxd_object_get_type(object) == amxd_object_instance) {
514  if(is_key_param || is_creation_param ||
515  !is_persist_param || !is_inst_param) {
516  must_save = false;
517  }
518  } else {
519  if(!is_persist_param) {
520  must_save = false;
521  }
522  }
523 
524  return must_save;
525 }
526 
527 static int amxo_parser_save_params(int fd,
528  amxd_object_t* object,
529  amxc_string_t* buffer) {
530  int retval = 0;
531  const amxc_htable_t* ht_params = NULL;
532  amxc_var_t params;
533  amxc_var_init(&params);
534 
535  amxd_object_describe_params(object, &params, amxd_dm_access_private);
536  ht_params = amxc_var_constcast(amxc_htable_t, &params);
537 
538  amxc_htable_for_each(it, ht_params) {
539  amxc_var_t* param = amxc_var_from_htable_it(it);
540  const char* name = PARAM_NAME(param);
541  amxc_var_t* value = PARAM_VALUE(param);
542  const amxc_llist_t* flags = PARAM_FLAGS(param);
543 
544  if(!amxo_parser_must_save_param(object, param)) {
545  continue;
546  }
547 
548  amxo_parser_indent(buffer);
549  amxo_parser_writef(fd, buffer, "parameter '%s' = ", name);
550  retval = amxo_parser_save_value(fd, value, buffer, "");
551  when_true(retval < 0, exit);
552  if(!amxc_llist_is_empty(flags)) {
553  amxo_parser_save_param_flags(fd, param, buffer);
554  } else {
555  amxo_parser_writef(fd, buffer, ";\n");
556  }
557  }
558 
559 exit:
560  amxc_var_clean(&params);
561  return retval;
562 }
563 
564 static int amxo_parser_save_leave(int fd,
565  amxc_llist_it_t* it,
566  uint32_t depth,
567  amxc_string_t* buffer) {
568  int retval = 0;
569  amxd_object_t* obj = amxc_container_of(it, amxd_object_t, it);
570  if(!amxd_object_is_attr_set(obj, amxd_oattr_persistent) &&
571  ( amxd_object_get_type(obj) != amxd_object_template)) {
572  goto exit;
573  }
574  if(amxd_object_get_type(obj) == amxd_object_instance) {
575  amxo_parser_instance_header(fd, obj, buffer);
576  } else {
577  amxo_parser_indent(buffer);
578  amxo_parser_writef(fd, buffer,
579  "object '%s' {\n",
580  amxd_object_get_name(obj, AMXD_OBJECT_NAMED));
581 
582  }
583  indentation++;
584  retval = amxo_parser_save_object_tree(fd, obj, depth, buffer);
585  when_true(retval < 0, exit);
586  indentation--;
587  amxo_parser_indent(buffer);
588  amxo_parser_writef(fd, buffer, "}\n");
589 
590 exit:
591  return retval;
592 }
593 
595  amxd_object_t* object,
596  uint32_t depth,
597  amxc_string_t* buffer) {
598  int retval = 0;
599 
600  if(amxd_object_get_type(object) != amxd_object_root) {
601  retval = amxo_parser_save_mibs(fd, object, buffer);
602  when_failed(retval, exit);
603  retval = amxo_parser_save_params(fd, object, buffer);
604  when_failed(retval, exit);
605  if(depth != UINT32_MAX) {
606  depth--;
607 
608  }
609  when_true(depth == 0, exit);
610  }
611 
612  if(amxd_object_get_type(object) == amxd_object_template) {
613  amxd_object_for_each(instance, it, object) {
614  retval = amxo_parser_save_leave(fd, it, depth, buffer);
615  when_failed(retval, exit);
616  }
617  } else {
618  amxd_object_for_each(child, it, object) {
619  retval = amxo_parser_save_leave(fd, it, depth, buffer);
620  when_failed(retval, exit);
621  }
622  }
623 
624 exit:
625  return retval;
626 }
627 
629  amxd_object_t* object,
630  amxc_string_t* buffer) {
631  int retval = 0;
632  if(amxd_object_get_type(object) == amxd_object_root) {
633  goto exit;
634  }
635 
636  indentation--;
637  amxo_parser_indent(buffer);
638  amxo_parser_writef(fd, buffer, "}\n");
639 
640  retval = amxo_parser_close_parent_tree(fd,
641  amxd_object_get_parent(object),
642  buffer);
643 
644 exit:
645  return retval;
646 }
647 
648 static int amxo_parser_save_tree(int fd,
649  amxd_object_t* object,
650  uint32_t depth,
651  amxc_string_t* buffer) {
652  int retval = 0;
653  amxo_parser_writef(fd, buffer, "%%populate {\n");
654  indentation++;
655 
656  retval = amxo_parser_open_parent_tree(fd, object, buffer);
657  when_failed(retval, exit);
658  retval = amxo_parser_save_object_tree(fd, object, depth, buffer);
659  when_failed(retval, exit);
660  retval = amxo_parser_close_parent_tree(fd, object, buffer);
661  when_failed(retval, exit);
662 
663  indentation--;
664  amxo_parser_writef(fd, buffer, "}\n");
665 
666 exit:
667  return retval;
668 }
669 
671  const char* filename,
672  int fd) {
673  char* full_path_tmp = amxo_parser_build_filename(pctx, filename, true);
674 
675  close(fd);
676  unlink(full_path_tmp);
677  free(full_path_tmp);
678 }
679 
681  const char* filename,
682  int fd) {
683  int retval = 0;
684  char* full_path_tmp = amxo_parser_build_filename(pctx, filename, true);
685  char* full_path = amxo_parser_build_filename(pctx, filename, false);
686 
687  retval = fsync(fd);
688  when_failed(retval, exit);
689  retval = close(fd);
690  when_failed(retval, exit);
691  retval = rename(full_path_tmp, full_path);
692  when_failed(retval, exit);
693 
694 exit:
695  free(full_path_tmp);
696  free(full_path);
697  return retval;
698 }
699 
701  const char* filename,
702  amxd_object_t* object,
703  uint32_t depth,
704  amxc_var_t* config,
705  bool append) {
706  int retval = -1;
707  int fd = -1;
708  amxc_string_t buffer;
709 
710  if(GETP_ARG(&pctx->config, "odl.buffer-size") != NULL) {
711  buffer_size = GETP_INT32(&pctx->config, "odl.buffer-size");
712  }
713  amxc_string_init(&buffer, buffer_size + 1024);
714 
715  when_null(pctx, exit);
716  when_str_empty(filename, exit);
717 
718  indentation = 0;
719  pctx->status = amxd_status_ok;
720  fd = amxo_parser_open_file(pctx, filename, append);
721  when_true(fd < 0, exit);
722  if((config != NULL) && (amxc_var_type_of(config) == AMXC_VAR_ID_HTABLE)) {
723  retval = amxo_parser_save_config_options(fd, config, &buffer);
724  when_true(retval < 0, exit);
725  }
726 
727  if(object != NULL) {
728  retval = amxo_parser_save_tree(fd, object, depth, &buffer);
729  when_true(retval < 0, exit);
730  }
731 
732  amxo_parser_flush_buffer(fd, &buffer);
733 
734 exit:
735  if(fd >= 0) {
736  if(retval < 0) {
737  amxo_parser_remove_file(pctx, filename, fd);
738  } else {
739  amxo_parser_close_file(pctx, filename, fd);
740  }
741  } else {
742  retval = -1;
743  }
744  amxc_string_clean(&buffer);
745  return retval;
746 }
747 
749  const char* filename,
750  amxc_var_t* config,
751  bool append) {
752  return amxo_parser_save(pctx, filename, NULL, 0, config, append);
753 }
754 
756  const char* filename,
757  amxd_object_t* object,
758  bool append) {
759  return amxo_parser_save(pctx, filename, object, UINT32_MAX, NULL, append);
760 }
#define PARAM_FLAGS(param)
Definition: amxo_save.c:73
static int amxo_parser_save_config_options(int fd, amxc_var_t *config, amxc_string_t *buffer)
Definition: amxo_save.c:332
#define PARAM_NAME(param)
Definition: amxo_save.c:67
static int amxo_parser_save_value(int fd, amxc_var_t *value, amxc_string_t *buffer, const char *termination)
Definition: amxo_save.c:272
static char * amxo_parser_build_filename(amxo_parser_t *pctx, const char *filename, bool temp)
Definition: amxo_save.c:147
#define PARAM_ATTR(param, attr_name)
Definition: amxo_save.c:61
static void amxo_parser_indent(amxc_string_t *buffer)
Definition: amxo_save.c:113
static void amxo_parser_escape_value(amxc_string_t *value)
Definition: amxo_save.c:268
static int indentation
Definition: amxo_save.c:85
static int amxo_parser_flush_buffer(int fd, amxc_string_t *buffer)
Definition: amxo_save.c:121
static int amxo_parser_save_list_config(int fd, amxc_var_t *value, amxc_string_t *buffer)
Definition: amxo_save.c:247
static int amxo_parser_copy(int dest_fd, int source_fd)
Definition: amxo_save.c:162
static int amxo_parser_instance_header(int fd, amxd_object_t *object, amxc_string_t *buffer)
Definition: amxo_save.c:392
static void amxo_parser_writef(int fd, amxc_string_t *buffer, const char *fmt,...)
Definition: amxo_save.c:132
static bool amxo_parser_must_save_param(amxd_object_t *object, amxc_var_t *param)
Definition: amxo_save.c:499
static int amxo_parser_save_tree(int fd, amxd_object_t *object, uint32_t depth, amxc_string_t *buffer)
Definition: amxo_save.c:648
static int amxo_parser_write(int fd, const char *buf, size_t bytes)
Definition: amxo_save.c:97
static int amxo_parser_save_leave(int fd, amxc_llist_it_t *it, uint32_t depth, amxc_string_t *buffer)
Definition: amxo_save.c:564
static int amxo_parser_open_file(amxo_parser_t *pctx, const char *filename, bool append)
Definition: amxo_save.c:179
static size_t buffer_size
Definition: amxo_save.c:84
static int amxo_parser_save_param_flags(int fd, amxc_var_t *param, amxc_string_t *buffer)
Definition: amxo_save.c:475
int amxo_parser_save_object(amxo_parser_t *pctx, const char *filename, amxd_object_t *object, bool append)
Definition: amxo_save.c:755
static int amxo_parser_close_file(amxo_parser_t *pctx, const char *filename, int fd)
Definition: amxo_save.c:680
static void amxo_parser_remove_file(amxo_parser_t *pctx, const char *filename, int fd)
Definition: amxo_save.c:670
#define PARAM_VALUE(param)
Definition: amxo_save.c:79
int amxo_parser_save_config(amxo_parser_t *pctx, const char *filename, amxc_var_t *config, bool append)
Definition: amxo_save.c:748
static bool amxo_parser_is_creation_parameter(const amxc_llist_t *flags)
Definition: amxo_save.c:357
int amxo_parser_save(amxo_parser_t *pctx, const char *filename, amxd_object_t *object, uint32_t depth, amxc_var_t *config, bool append)
Definition: amxo_save.c:700
static int amxo_parser_save_table_config(int fd, amxc_var_t *value, amxc_string_t *buffer)
Definition: amxo_save.c:219
static bool amxo_parser_has_key_params(const amxc_htable_t *params)
Definition: amxo_save.c:370
static int amxo_parser_open_parent_tree(int fd, amxd_object_t *object, amxc_string_t *buffer)
Definition: amxo_save.c:431
static int amxo_parser_save_mibs(int fd, amxd_object_t *object, amxc_string_t *buffer)
Definition: amxo_save.c:460
static int amxo_parser_close_parent_tree(int fd, amxd_object_t *object, amxc_string_t *buffer)
Definition: amxo_save.c:628
static int amxo_parser_save_object_tree(int fd, amxd_object_t *object, uint32_t depth, amxc_string_t *buffer)
Definition: amxo_save.c:594
static int amxo_parser_save_params(int fd, amxd_object_t *object, amxc_string_t *buffer)
Definition: amxo_save.c:527
config
The ODL parser structure.
Definition: amxo_types.h:245
amxc_var_t config
Definition: amxo_types.h:250
amxd_status_t status
Definition: amxo_types.h:258