libamxo  4.3.4
Object Definition Language (ODL) parsing
amxo_parser_mibs.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 #include "amxo_parser_hooks_priv.h"
61 
62 typedef struct _mib_info {
63  amxc_htable_it_t hit;
64  char* expression;
65  char* file;
67 
68 static void amxo_parser_add_mib_info(amxc_htable_t* mibs,
69  const char* name,
70  const char* expression,
71  const char* file) {
72  mib_info_t* info = NULL;
73  when_true(amxc_htable_contains(mibs, name), exit);
74 
75  info = (mib_info_t*) calloc(1, sizeof(mib_info_t));
76  when_null(info, exit);
77 
78  info->expression = strdup(expression);
79  info->file = strdup(file);
80 
81  amxc_htable_insert(mibs, name, &info->hit);
82 
83 exit:
84  return;
85 }
86 
87 static FILE* amxo_parser_open_mib_file(char* name,
88  amxc_string_t* filename,
89  char** first_line) {
90  ssize_t read = 0;
91  size_t len = 0;
92  FILE* odlfile = fopen(amxc_string_get(filename, 0), "r");
93 
94  name[strlen(name) - 4] = 0;
95  read = getline(first_line, &len, odlfile);
96  if(read == -1) {
97  free(*first_line);
98  *first_line = NULL;
99  fclose(odlfile);
100  odlfile = NULL;
101  }
102 
103  return odlfile;
104 }
105 
107  struct dirent* ep,
108  amxc_string_t* filename,
109  char* first_line) {
110  bool retval = true;
111  const char* name = NULL;
112  const char* expression = NULL;
113  amxp_expr_t expr;
114 
115  name = basename(ep->d_name);
116  expression = name;
117  if(strncmp(first_line, "/*expr:", 7) == 0) {
118  first_line[ strlen(first_line) - 3 ] = 0;
119  expression = first_line + 7;
120  } else if(strncmp(first_line, "#expr:", 6) == 0) {
121  first_line[ strlen(first_line) - 3 ] = 0;
122  expression = first_line + 6;
123  }
124  if(amxp_expr_init(&expr, expression) == amxp_expr_status_ok) {
126  name,
127  expression,
128  amxc_string_get(filename, 0));
129  } else {
130  retval = false;
131  }
132  amxp_expr_clean(&expr);
133 
134  return retval;
135 }
136 
137 static int amxo_parser_scan(amxo_parser_t* parser,
138  const char* path) {
139  int retval = -1;
140  DIR* dp;
141  struct dirent* ep;
142  FILE* odlfile = NULL;
143  char* line = NULL;
144  amxc_string_t filename;
145 
146  amxc_string_init(&filename, 128);
147 
148  dp = opendir(path);
149  when_null(dp, exit);
150 
151  for(ep = readdir(dp); ep; ep = readdir(dp)) {
152  const char* extension = strstr(ep->d_name, ".odl");
153  if((extension == NULL) || (extension[4] != 0)) {
154  continue;
155  }
156 
157  amxc_string_reset(&filename);
158  amxc_string_setf(&filename, "%s/%s", path, ep->d_name);
159  odlfile = amxo_parser_open_mib_file(ep->d_name, &filename, &line);
160  if(odlfile == NULL) {
161  continue;
162  }
163 
164  amxo_parser_build_mib_info(parser, ep, &filename, line);
165  fclose(odlfile);
166  free(line);
167  line = NULL;
168  }
169  closedir(dp);
170 
171  retval = 0;
172 
173 exit:
174  amxc_string_clean(&filename);
175  return retval;
176 }
177 
178 void amxo_parser_del_mib_info(UNUSED const char* key,
179  amxc_htable_it_t* it) {
180  mib_info_t* info = amxc_htable_it_get_data(it, mib_info_t, hit);
181  free(info->expression);
182  free(info->file);
183  free(info);
184 }
185 
187  const char* path) {
188  int retval = -1;
189  char* current_wd = getcwd(NULL, 0);
190  char* real_path = NULL;
191  amxc_string_t res_path;
192  amxc_string_init(&res_path, 0);
193 
194  when_null(parser, exit);
195  when_str_empty(path, exit);
196 
197  real_path = realpath(path, NULL);
198  if(real_path != NULL) {
199  retval = amxo_parser_scan(parser, real_path);
200  }
201 
202 exit:
203  amxc_string_clean(&res_path);
204  free(current_wd);
205  free(real_path);
206  return retval;
207 }
208 
210  amxc_var_t* dirs) {
211  int retval = -1;
212  amxc_string_t res_path;
213  amxc_string_init(&res_path, 0);
214 
215  when_null(parser, exit);
216  if(dirs == NULL) {
217  dirs = amxo_parser_get_config(parser, "mib-dirs");
218  }
219  when_null(dirs, exit);
220  when_true(amxc_var_type_of(dirs) != AMXC_VAR_ID_LIST, exit);
221 
222  amxc_var_for_each(var_path, dirs) {
223  const char* path = amxc_var_constcast(cstring_t, var_path);
224  if(path == NULL) {
225  continue;
226  }
227  if(amxc_string_set_resolved(&res_path, path, &parser->config) > 0) {
228  path = amxc_string_get(&res_path, 0);
229  }
230  retval = amxo_parser_scan_mib_dir(parser, path);
231  if(retval != 0) {
232  break;
233  }
234  amxc_string_reset(&res_path);
235  }
236 
237 exit:
238  amxc_string_clean(&res_path);
239  return retval;
240 }
241 
243  const char* mib_name) {
244  const char* file = NULL;
245  mib_info_t* info = NULL;
246  amxc_htable_it_t* it = NULL;
247 
248  when_null(parser, exit);
249  when_str_empty(mib_name, exit);
250 
251  it = amxc_htable_get(&parser->mibs, mib_name);
252  while(it == NULL && parser->parent != NULL) {
253  parser = parser->parent;
254  it = amxc_htable_get(&parser->mibs, mib_name);
255  }
256  when_null(it, exit);
257  info = amxc_htable_it_get_data(it, mib_info_t, hit);
258 
259  file = info->file;
260 
261 exit:
262  return file;
263 }
264 
266  amxd_dm_t* dm,
267  const char* mib_name) {
268  int retval = -1;
269  amxd_status_t status = amxd_status_ok;
270  amxd_object_t* mib = NULL;
271 
272  when_null(parser, exit);
273  when_str_empty(mib_name, exit);
274  when_null(dm, exit);
275 
276  mib = amxd_dm_get_mib(dm, mib_name);
277  if(mib == NULL) {
278  const char* file = amxo_parser_get_mib_file(parser, mib_name);
279  amxd_object_t* root = amxd_dm_get_root(dm);
280  retval = amxo_parser_parse_file(parser, file, root);
281  when_true(retval != 0, exit);
282  }
283 
284  retval = status == amxd_status_ok ? 0 : -1;
285 
286 exit:
287  return retval;
288 
289 }
290 
292  amxd_object_t* object,
293  const char* mib_name) {
294  int retval = -1;
295  amxd_status_t status = amxd_status_ok;
296  amxd_dm_t* dm = NULL;
297 
298  when_null(parser, exit);
299  when_null(object, exit);
300  when_str_empty(mib_name, exit);
301 
302  dm = amxd_object_get_dm(object);
303  when_null(dm, exit);
304 
305  retval = amxo_parser_load_mib(parser, dm, mib_name);
306  when_failed(retval, exit);
307 
308  status = amxd_object_add_mib(object, mib_name);
309  retval = status == amxd_status_ok ? 0 : -1;
310 
311 exit:
312  return retval;
313 }
314 
316  amxd_object_t* object,
318  int retval = 0;
319 
320  when_null(parser, exit);
321  when_null(object, exit);
322  when_null(fn, exit);
323 
324  amxc_htable_for_each(it, (&parser->mibs)) {
325  const char* mib_name = amxc_htable_it_get_key(it);
326  mib_info_t* info = amxc_htable_it_get_data(it, mib_info_t, hit);
327  amxp_expr_t expr;
328  amxp_expr_init(&expr, info->expression);
329  if(fn(object, &expr)) {
330  if(amxo_parser_apply_mib(parser, object, mib_name) == 0) {
331  retval++;
332  }
333  }
334  amxp_expr_clean(&expr);
335  }
336 
337 exit:
338  return retval;
339 }
340 
342  amxd_object_t* object,
344  int retval = 0;
345 
346  when_null(parser, exit);
347  when_null(object, exit);
348  when_null(fn, exit);
349 
350  amxc_htable_for_each(it, (&parser->mibs)) {
351  const char* mib_name = amxc_htable_it_get_key(it);
352  mib_info_t* info = amxc_htable_it_get_data(it, mib_info_t, hit);
353  amxp_expr_t expr;
354  if(!amxd_object_has_mib(object, mib_name)) {
355  continue;
356  }
357  amxp_expr_init(&expr, info->expression);
358  if(!fn(object, &expr)) {
359  if(amxd_object_remove_mib(object, mib_name) == amxd_status_ok) {
360  retval++;
361  }
362  }
363  amxp_expr_clean(&expr);
364  }
365 
366 exit:
367  return retval;
368 }
369 
371  amxd_object_t* object,
373  int retval = 0;
374 
375  when_null(parser, exit);
376  when_null(object, exit);
377  when_null(fn, exit);
378 
379  amxc_htable_for_each(it, (&parser->mibs)) {
380  const char* mib_name = amxc_htable_it_get_key(it);
381  mib_info_t* info = amxc_htable_it_get_data(it, mib_info_t, hit);
382  amxp_expr_t expr;
383  amxp_expr_init(&expr, info->expression);
384  if(fn(object, &expr)) {
385  if(amxo_parser_apply_mib(parser, object, mib_name) == 0) {
386  retval++;
387  }
388  } else {
389  if(amxd_object_remove_mib(object, mib_name) == amxd_status_ok) {
390  retval++;
391  }
392  }
393  amxp_expr_clean(&expr);
394  }
395 
396 exit:
397  return retval;
398 }
bool(* amxo_evaluate_expr_fn_t)(amxd_object_t *object, amxp_expr_t *expr)
Definition: amxo_mibs.h:65
struct _mib_info mib_info_t
static bool amxo_parser_build_mib_info(amxo_parser_t *parser, struct dirent *ep, amxc_string_t *filename, char *first_line)
static void amxo_parser_add_mib_info(amxc_htable_t *mibs, const char *name, const char *expression, const char *file)
static int amxo_parser_scan(amxo_parser_t *parser, const char *path)
void amxo_parser_del_mib_info(UNUSED const char *key, amxc_htable_it_t *it)
static FILE * amxo_parser_open_mib_file(char *name, amxc_string_t *filename, char **first_line)
amxc_var_t * amxo_parser_get_config(amxo_parser_t *parser, const char *path)
Gets a configuration option.
int amxo_parser_remove_mibs(amxo_parser_t *parser, amxd_object_t *object, amxo_evaluate_expr_fn_t fn)
Removes zero, one or more MIBs from a data model object.
int amxo_parser_scan_mib_dir(amxo_parser_t *parser, const char *path)
Scans a directory for MIB odl files.
int amxo_parser_scan_mib_dirs(amxo_parser_t *parser, amxc_var_t *dirs)
Scans multiple directories for MIB odl files.
const char * amxo_parser_get_mib_file(amxo_parser_t *parser, const char *mib_name)
Get full path and file name of odl file describing a mib.
int amxo_parser_apply_mibs(amxo_parser_t *parser, amxd_object_t *object, amxo_evaluate_expr_fn_t fn)
Applies zero, one or more MIBs to a data model object.
int amxo_parser_apply_mib(amxo_parser_t *parser, amxd_object_t *object, const char *mib_name)
Unconditionally applies a MIB to a data model object.
int amxo_parser_load_mib(amxo_parser_t *parser, amxd_dm_t *dm, const char *mib_name)
Loads the mib definition.
int amxo_parser_add_mibs(amxo_parser_t *parser, amxd_object_t *object, amxo_evaluate_expr_fn_t fn)
Adds zero, one or more MIBs to a data model object.
int amxo_parser_parse_file(amxo_parser_t *parser, const char *file_path, amxd_object_t *object)
Parses an odl file.
The ODL parser structure.
Definition: amxo_types.h:245
amxc_htable_t mibs
Definition: amxo_types.h:282
amxc_var_t config
Definition: amxo_types.h:250
amxo_parser_t * parent
Definition: amxo_types.h:285
char * expression
amxc_htable_it_t hit
#define UNUSED
Definition: test_issue_48.c:84