Adding upstream version 3.1.0+dfsg.
Signed-off-by: Daniel Baumann <daniel@debian.org>
This commit is contained in:
parent
64dbec996d
commit
cfcebb1a7d
569 changed files with 205393 additions and 0 deletions
301
tools/lint/common.c
Normal file
301
tools/lint/common.c
Normal file
|
@ -0,0 +1,301 @@
|
|||
/**
|
||||
* @file common.c
|
||||
* @author Radek Krejci <rkrejci@cesnet.cz>
|
||||
* @author Adam Piecek <piecek@cesnet.cz>
|
||||
* @brief libyang's yanglint tool - common functions for both interactive and non-interactive mode.
|
||||
*
|
||||
* Copyright (c) 2023 CESNET, z.s.p.o.
|
||||
*
|
||||
* This source code is licensed under BSD 3-Clause License (the "License").
|
||||
* You may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://opensource.org/licenses/BSD-3-Clause
|
||||
*/
|
||||
|
||||
#define _GNU_SOURCE
|
||||
#define _POSIX_C_SOURCE 200809L /* strdup, strndup */
|
||||
|
||||
#include "common.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include "compat.h"
|
||||
#include "libyang.h"
|
||||
#include "plugins_exts.h"
|
||||
#include "yl_opt.h"
|
||||
|
||||
void
|
||||
yl_log(ly_bool err, const char *format, ...)
|
||||
{
|
||||
char msg[256];
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, format);
|
||||
vsnprintf(msg, 256, format, ap);
|
||||
va_end(ap);
|
||||
|
||||
fprintf(stderr, "YANGLINT[%c]: %s\n", err ? 'E' : 'W', msg);
|
||||
}
|
||||
|
||||
int
|
||||
parse_schema_path(const char *path, char **dir, char **module)
|
||||
{
|
||||
char *p;
|
||||
|
||||
assert(dir);
|
||||
assert(module);
|
||||
|
||||
/* split the path to dirname and basename for further work */
|
||||
*dir = strdup(path);
|
||||
/* FIXME: this is broken on Windows */
|
||||
*module = strrchr(*dir, '/');
|
||||
if (!(*module)) {
|
||||
*module = *dir;
|
||||
*dir = strdup("./");
|
||||
} else {
|
||||
*module[0] = '\0'; /* break the dir */
|
||||
*module = strdup((*module) + 1);
|
||||
}
|
||||
/* get the pure module name without suffix or revision part of the filename */
|
||||
if ((p = strchr(*module, '@'))) {
|
||||
/* revision */
|
||||
*p = '\0';
|
||||
} else if ((p = strrchr(*module, '.'))) {
|
||||
/* fileformat suffix */
|
||||
*p = '\0';
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
get_input(const char *filepath, LYS_INFORMAT *format_schema, LYD_FORMAT *format_data, struct ly_in **in)
|
||||
{
|
||||
struct stat st;
|
||||
|
||||
/* check that the filepath exists and is a regular file */
|
||||
if (stat(filepath, &st) == -1) {
|
||||
YLMSG_E("Unable to use input filepath (%s) - %s.", filepath, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
if (!S_ISREG(st.st_mode)) {
|
||||
YLMSG_E("Provided input file (%s) is not a regular file.", filepath);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (get_format(filepath, format_schema, format_data)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (in && ly_in_new_filepath(filepath, 0, in)) {
|
||||
YLMSG_E("Unable to process input file.");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
LYS_INFORMAT
|
||||
get_schema_format(const char *filename)
|
||||
{
|
||||
char *ptr;
|
||||
|
||||
if ((ptr = strrchr(filename, '.')) != NULL) {
|
||||
++ptr;
|
||||
if (!strcmp(ptr, "yang")) {
|
||||
return LYS_IN_YANG;
|
||||
} else if (!strcmp(ptr, "yin")) {
|
||||
return LYS_IN_YIN;
|
||||
} else {
|
||||
return LYS_IN_UNKNOWN;
|
||||
}
|
||||
} else {
|
||||
return LYS_IN_UNKNOWN;
|
||||
}
|
||||
}
|
||||
|
||||
LYD_FORMAT
|
||||
get_data_format(const char *filename)
|
||||
{
|
||||
char *ptr;
|
||||
|
||||
if ((ptr = strrchr(filename, '.')) != NULL) {
|
||||
++ptr;
|
||||
if (!strcmp(ptr, "xml")) {
|
||||
return LYD_XML;
|
||||
} else if (!strcmp(ptr, "json")) {
|
||||
return LYD_JSON;
|
||||
} else if (!strcmp(ptr, "lyb")) {
|
||||
return LYD_LYB;
|
||||
} else {
|
||||
return LYD_UNKNOWN;
|
||||
}
|
||||
} else {
|
||||
return LYD_UNKNOWN;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
get_format(const char *filepath, LYS_INFORMAT *schema_form, LYD_FORMAT *data_form)
|
||||
{
|
||||
LYS_INFORMAT schema;
|
||||
LYD_FORMAT data;
|
||||
|
||||
schema = !schema_form || !*schema_form ? LYS_IN_UNKNOWN : *schema_form;
|
||||
data = !data_form || !*data_form ? LYD_UNKNOWN : *data_form;
|
||||
|
||||
if (!schema) {
|
||||
schema = get_schema_format(filepath);
|
||||
}
|
||||
if (!data) {
|
||||
data = get_data_format(filepath);
|
||||
}
|
||||
|
||||
if (!schema && !data) {
|
||||
YLMSG_E("Input schema format for %s file not recognized.", filepath);
|
||||
return -1;
|
||||
} else if (!data && !schema) {
|
||||
YLMSG_E("Input data format for %s file not recognized.", filepath);
|
||||
return -1;
|
||||
}
|
||||
assert(schema || data);
|
||||
|
||||
if (schema_form) {
|
||||
*schema_form = schema;
|
||||
}
|
||||
if (data_form) {
|
||||
*data_form = data;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
const struct lysc_node *
|
||||
find_schema_path(const struct ly_ctx *ctx, const char *schema_path)
|
||||
{
|
||||
const char *end, *module_name_end;
|
||||
char *module_name = NULL;
|
||||
const struct lysc_node *node = NULL, *parent_node = NULL, *parent_node_tmp = NULL;
|
||||
const struct lys_module *module;
|
||||
size_t node_name_len;
|
||||
ly_bool found_exact_match = 0;
|
||||
|
||||
/* iterate over each '/' in the path */
|
||||
while (schema_path) {
|
||||
/* example: schema_path = /listen/endpoint
|
||||
* end == NULL for endpoint, end exists for listen */
|
||||
end = strchr(schema_path + 1, '/');
|
||||
if (end) {
|
||||
node_name_len = end - schema_path - 1;
|
||||
} else {
|
||||
node_name_len = strlen(schema_path + 1);
|
||||
}
|
||||
|
||||
/* ex: schema_path = /ietf-interfaces:interfaces/interface/ietf-ip:ipv4 */
|
||||
module_name_end = strchr(schema_path, ':');
|
||||
if (module_name_end && (!end || (module_name_end < end))) {
|
||||
/* only get module's name, if it is in the current scope */
|
||||
free(module_name);
|
||||
/* - 1 because module_name_end points to ':' */
|
||||
module_name = strndup(schema_path + 1, module_name_end - schema_path - 1);
|
||||
if (!module_name) {
|
||||
YLMSG_E("Memory allocation failed (%s:%d, %s).", __FILE__, __LINE__, strerror(errno));
|
||||
parent_node = NULL;
|
||||
goto cleanup;
|
||||
}
|
||||
/* move the pointer to the beginning of the node's name - 1 */
|
||||
schema_path = module_name_end;
|
||||
|
||||
/* recalculate the length of the node's name, because the module prefix mustn't be compared later */
|
||||
if (module_name_end < end) {
|
||||
node_name_len = end - module_name_end - 1;
|
||||
} else if (!end) {
|
||||
node_name_len = strlen(module_name_end + 1);
|
||||
}
|
||||
}
|
||||
|
||||
module = ly_ctx_get_module_implemented(ctx, module_name);
|
||||
if (!module) {
|
||||
/* unknown module name */
|
||||
parent_node = NULL;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* iterate over the node's siblings / module's top level containers */
|
||||
while ((node = lys_getnext(node, parent_node, module->compiled, LYS_GETNEXT_WITHCASE | LYS_GETNEXT_WITHCHOICE))) {
|
||||
if (end && !strncmp(node->name, schema_path + 1, node_name_len) && (node->name[node_name_len] == '\0')) {
|
||||
/* check if the whole node's name matches and it's not just a common prefix */
|
||||
parent_node = node;
|
||||
break;
|
||||
} else if (!strncmp(node->name, schema_path + 1, node_name_len)) {
|
||||
/* do the same here, however if there is no exact match, use the last node with the same prefix */
|
||||
if (strlen(node->name) == node_name_len) {
|
||||
parent_node = node;
|
||||
found_exact_match = 1;
|
||||
break;
|
||||
} else {
|
||||
parent_node_tmp = node;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!end && !found_exact_match) {
|
||||
/* no exact match */
|
||||
parent_node = parent_node_tmp;
|
||||
}
|
||||
found_exact_match = 0;
|
||||
|
||||
/* next iter */
|
||||
schema_path = strchr(schema_path + 1, '/');
|
||||
}
|
||||
|
||||
cleanup:
|
||||
free(module_name);
|
||||
return parent_node;
|
||||
}
|
||||
|
||||
LY_ERR
|
||||
ext_data_clb(const struct lysc_ext_instance *ext, void *user_data, void **ext_data, ly_bool *ext_data_free)
|
||||
{
|
||||
struct ly_ctx *ctx;
|
||||
struct lyd_node *data = NULL;
|
||||
|
||||
ctx = ext->module->ctx;
|
||||
if (user_data) {
|
||||
lyd_parse_data_path(ctx, user_data, LYD_XML, LYD_PARSE_STRICT, LYD_VALIDATE_PRESENT, &data);
|
||||
}
|
||||
|
||||
*ext_data = data;
|
||||
*ext_data_free = 1;
|
||||
return LY_SUCCESS;
|
||||
}
|
||||
|
||||
LY_ERR
|
||||
searchpath_strcat(char **searchpaths, const char *path)
|
||||
{
|
||||
uint64_t len;
|
||||
char *new;
|
||||
|
||||
if (!(*searchpaths)) {
|
||||
*searchpaths = strdup(path);
|
||||
return LY_SUCCESS;
|
||||
}
|
||||
|
||||
len = strlen(*searchpaths) + strlen(path) + strlen(PATH_SEPARATOR);
|
||||
new = realloc(*searchpaths, sizeof(char) * len + 1);
|
||||
if (!new) {
|
||||
return LY_EMEM;
|
||||
}
|
||||
strcat(new, PATH_SEPARATOR);
|
||||
strcat(new, path);
|
||||
*searchpaths = new;
|
||||
|
||||
return LY_SUCCESS;
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue