Ejemplo n.º 1
0
static void
test_move1(void **state)
{
    struct state *st = (*state);
    const char *xml1 = "<df xmlns=\"urn:libyang:tests:defaults\">"
                         "<llist>1</llist>"
                         "<llist>2</llist>"
                       "</df>";
    const char *xml2 = "<df xmlns=\"urn:libyang:tests:defaults\">"
                         "<llist>2</llist>"
                         "<llist>1</llist>"
                       "</df>";
    char *str;
    struct lyd_difflist *diff;

    assert_ptr_not_equal((st->first = lyd_parse_mem(st->ctx, xml1, LYD_XML, LYD_OPT_CONFIG)), NULL);
    assert_ptr_not_equal((st->second = lyd_parse_mem(st->ctx, xml2, LYD_XML, LYD_OPT_CONFIG)), NULL);

    assert_ptr_not_equal((diff = lyd_diff(st->first, st->second, 0)), NULL);
    assert_ptr_not_equal(diff->type, NULL);

    assert_int_equal(diff->type[0], LYD_DIFF_MOVEDAFTER1);
    assert_ptr_not_equal(diff->first[0], NULL);
    assert_string_equal((str = lyd_path(diff->first[0])), "/defaults:df/llist[.='1']");
    free(str);
    assert_ptr_not_equal(diff->second[0], NULL);
    assert_string_equal((str = lyd_path(diff->second[0])), "/defaults:df/llist[.='2']");
    free(str);

    assert_int_equal(diff->type[1], LYD_DIFF_END);

    lyd_free_diff(diff);
}
Ejemplo n.º 2
0
static void
test_diff2(void **state)
{
    struct state *st = (*state);
    const char *xml1 = "<df xmlns=\"urn:libyang:tests:defaults\">"
                         "<list><name>a</name><value>1</value></list>"
                         "<list><name>b</name><value>2</value></list>"
                       "</df>";
    const char *xml2 = "<df xmlns=\"urn:libyang:tests:defaults\">"
                         "<list><name>b</name><value>-2</value></list>"
                         "<list><name>c</name><value>3</value></list>"
                       "</df>";
    char *str;
    struct lyd_difflist *diff;

    assert_ptr_not_equal((st->first = lyd_parse_mem(st->ctx, xml1, LYD_XML, LYD_OPT_CONFIG)), NULL);
    assert_ptr_not_equal((st->second = lyd_parse_mem(st->ctx, xml2, LYD_XML, LYD_OPT_CONFIG)), NULL);

    assert_ptr_not_equal((diff = lyd_diff(st->first, st->second, 0)), NULL);
    assert_ptr_not_equal(diff->type, NULL);

    assert_int_equal(diff->type[0], LYD_DIFF_CHANGED);
    assert_ptr_not_equal(diff->first[0], NULL);
    assert_string_equal((str = lyd_path(diff->first[0])), "/defaults:df/list[name=\'b\']/value");
    free(str);
    assert_ptr_not_equal(diff->second[0], NULL);
    assert_string_equal((str = lyd_path(diff->second[0])), "/defaults:df/list[name=\'b\']/value");
    free(str);

    assert_int_equal(diff->type[1], LYD_DIFF_DELETED);
    assert_ptr_not_equal(diff->first[1], NULL);
    assert_string_equal((str = lyd_path(diff->first[1])), "/defaults:df/list[name=\'a\']");
    free(str);
    assert_ptr_equal(diff->second[1], NULL);

    assert_int_equal(diff->type[2], LYD_DIFF_CREATED);
    assert_ptr_not_equal(diff->first[2], NULL);
    assert_string_equal((str = lyd_path(diff->first[2])), "/defaults:df");
    free(str);
    assert_ptr_not_equal(diff->second[2], NULL);
    assert_string_equal((str = lyd_path(diff->second[2])), "/defaults:df/list[name=\'c\']");
    free(str);

    assert_int_equal(diff->type[3], LYD_DIFF_END);

    lyd_free_diff(diff);
}
Ejemplo n.º 3
0
static void
test_diff1(void **state)
{
    struct state *st = (*state);
    const char *xml1 = "<df xmlns=\"urn:libyang:tests:defaults\">"
                        "<foo>42</foo>"
                      "</df><hidden xmlns=\"urn:libyang:tests:defaults\">"
                        "<foo>42</foo><baz>42</baz></hidden>";
    const char *xml2 = "<df xmlns=\"urn:libyang:tests:defaults\">"
                        "<foo>41</foo><b1_1>42</b1_1>"
                      "</df>";
    char *str;
    struct lyd_difflist *diff;

    assert_ptr_not_equal((st->first = lyd_parse_mem(st->ctx, xml1, LYD_XML, LYD_OPT_CONFIG)), NULL);
    assert_ptr_not_equal((st->second = lyd_parse_mem(st->ctx, xml2, LYD_XML, LYD_OPT_CONFIG)), NULL);

    assert_ptr_not_equal((diff = lyd_diff(st->first, st->second, 0)), NULL);
    assert_ptr_not_equal(diff->type, NULL);

    assert_int_equal(diff->type[0], LYD_DIFF_CHANGED);
    assert_ptr_not_equal(diff->first[0], NULL);
    assert_string_equal((str = lyd_path(diff->first[0])), "/defaults:df/foo");
    free(str);
    assert_ptr_not_equal(diff->second[0], NULL);
    assert_string_equal((str = lyd_path(diff->second[0])), "/defaults:df/foo");
    free(str);

    assert_int_equal(diff->type[1], LYD_DIFF_DELETED);
    assert_ptr_not_equal(diff->first[1], NULL);
    assert_string_equal((str = lyd_path(diff->first[1])), "/defaults:hidden");
    free(str);
    assert_ptr_equal(diff->second[1], NULL);

    assert_int_equal(diff->type[2], LYD_DIFF_CREATED);
    assert_ptr_not_equal(diff->first[2], NULL);
    assert_string_equal((str = lyd_path(diff->first[2])), "/defaults:df");
    free(str);
    assert_ptr_not_equal(diff->second[2], NULL);
    assert_string_equal((str = lyd_path(diff->second[2])), "/defaults:df/b1_1");
    free(str);

    assert_int_equal(diff->type[3], LYD_DIFF_END);

    lyd_free_diff(diff);
}
Ejemplo n.º 4
0
static void
test_wd1(void **state)
{
    struct state *st = (*state);
    const char *xml = "<df xmlns=\"urn:libyang:tests:defaults\">"
                        "<foo>41</foo><dllist>4</dllist>"
                      "</df>";
    char *str;
    struct lyd_difflist *diff;

    st->first = NULL;
    lyd_validate(&st->first, LYD_OPT_CONFIG, st->ctx);
    assert_ptr_not_equal(st->first, NULL);
    assert_ptr_not_equal((st->second = lyd_parse_mem(st->ctx, xml, LYD_XML, LYD_OPT_CONFIG)), NULL);

    assert_ptr_not_equal((diff = lyd_diff(st->first, st->second, LYD_DIFFOPT_WITHDEFAULTS)), NULL);
    assert_ptr_not_equal(diff->type, NULL);

    assert_int_equal(diff->type[0], LYD_DIFF_CHANGED);
    assert_ptr_not_equal(diff->first[0], NULL);
    assert_string_equal((str = lyd_path(diff->first[0])), "/defaults:df/foo");
    assert_int_equal(((struct lyd_node_leaf_list*)diff->first[0])->value.int32, 42);
    free(str);
    assert_ptr_not_equal(diff->second[0], NULL);
    assert_string_equal((str = lyd_path(diff->second[0])), "/defaults:df/foo");
    assert_int_equal(((struct lyd_node_leaf_list*)diff->second[0])->value.int32, 41);
    free(str);

    assert_int_equal(diff->type[1], LYD_DIFF_DELETED);
    assert_ptr_not_equal(diff->first[1], NULL);
    assert_string_equal((str = lyd_path(diff->first[1])), "/defaults:df/dllist[.='1']");
    free(str);
    assert_ptr_equal(diff->second[1], NULL);

    assert_int_equal(diff->type[2], LYD_DIFF_DELETED);
    assert_ptr_not_equal(diff->first[2], NULL);
    assert_string_equal((str = lyd_path(diff->first[2])), "/defaults:df/dllist[.='2']");
    free(str);
    assert_ptr_equal(diff->second[2], NULL);

    assert_int_equal(diff->type[3], LYD_DIFF_DELETED);
    assert_ptr_not_equal(diff->first[3], NULL);
    assert_string_equal((str = lyd_path(diff->first[3])), "/defaults:df/dllist[.='3']");
    free(str);
    assert_ptr_equal(diff->second[3], NULL);

    assert_int_equal(diff->type[4], LYD_DIFF_CREATED);
    assert_ptr_not_equal(diff->first[4], NULL);
    assert_string_equal((str = lyd_path(diff->first[4])), "/defaults:df");
    free(str);
    assert_ptr_not_equal(diff->second[4], NULL);
    assert_string_equal((str = lyd_path(diff->second[4])), "/defaults:df/dllist[.='4']");
    free(str);

    assert_int_equal(diff->type[5], LYD_DIFF_END);

    lyd_free_diff(diff);
}
Ejemplo n.º 5
0
int
__wrap_sr_get_item_next(sr_session_ctx_t *session, sr_val_iter_t *iter, sr_val_t **value)
{
    static struct ly_set *ietf_if_set = NULL;
    const char *xpath = (const char *)iter;
    char *path;
    (void)session;

    if (!strcmp(xpath, "/ietf-interfaces:*//.")) {
        if (!ietf_if_set) {
            ietf_if_set = lyd_find_path(data, xpath);
        }

        if (!ietf_if_set->number) {
            ly_set_free(ietf_if_set);
            ietf_if_set = NULL;
            return SR_ERR_NOT_FOUND;
        }

        path = lyd_path(ietf_if_set->set.d[0]);
        *value = calloc(1, sizeof **value);
        op_set_srval(ietf_if_set->set.d[0], path, 1, *value, NULL);
        (*value)->dflt = ietf_if_set->set.d[0]->dflt;
        free(path);

        --ietf_if_set->number;
        if (ietf_if_set->number) {
            memmove(ietf_if_set->set.d, ietf_if_set->set.d + 1, ietf_if_set->number * sizeof(void *));
        }
    } else {
        *value = NULL;
        return SR_ERR_NOT_FOUND;
    }

    return SR_ERR_OK;
}
Ejemplo n.º 6
0
/**
 * @brief Import content of the specified datastore for the given module from a file
 * referenced by the descriptor 'fd_in'
 */
static int
srcfg_import_datastore(struct ly_ctx *ly_ctx, int fd_in, const char *module_name, srcfg_datastore_t datastore,
                       LYD_FORMAT format, bool permanent)
{
    int rc = SR_ERR_INTERNAL;
    unsigned i = 0;
    struct lyd_node *new_data_tree = NULL;
    struct lyd_node *current_data_tree = NULL;
    struct lyd_difflist *diff = NULL;
    char *first_xpath = NULL, *second_xpath = NULL;
    char *input_data = NULL;
    int ret = 0;
    struct stat info;

    CHECK_NULL_ARG2(ly_ctx, module_name);

    /* parse input data */
    ret = fstat(fd_in, &info);
    CHECK_NOT_MINUS1_LOG_GOTO(ret, rc, SR_ERR_INTERNAL, cleanup,
                              "Unable to obtain input file info: %s.", sr_strerror_safe(errno));
    ly_errno = LY_SUCCESS;
    if (S_ISREG(info.st_mode)) {
        /* load (using mmap) and parse the input data in one step */
        new_data_tree = lyd_parse_fd(ly_ctx, fd_in, format, LYD_OPT_STRICT | LYD_OPT_CONFIG);
    } else { /* most likely STDIN */
        /* load input data into the memory first */
        ret = srcfg_read_file_content(fd_in, &input_data);
        CHECK_RC_MSG_GOTO(ret, cleanup, "Unable to read the input data.");
        /* parse the input data stored inside memory buffer */
        new_data_tree = lyd_parse_mem(ly_ctx, input_data, format, LYD_OPT_STRICT | LYD_OPT_CONFIG);
    }
    if (NULL == new_data_tree && LY_SUCCESS != ly_errno) {
        SR_LOG_ERR("Unable to parse the input data: %s", ly_errmsg());
        goto cleanup;
    }

    /* validate input data */
    if (NULL != new_data_tree) {
        ret = lyd_validate(&new_data_tree, LYD_OPT_STRICT | LYD_OPT_CONFIG | LYD_WD_IMPL_TAG);
        CHECK_ZERO_LOG_GOTO(ret, rc, SR_ERR_INTERNAL, cleanup, "Input data are not valid: %s", ly_errmsg());
    }

    /* remove default nodes */
    lyd_wd_cleanup(&new_data_tree, 0);

    /* get data tree of currently stored configuration */
    rc = srcfg_get_module_data(ly_ctx, module_name, &current_data_tree);
    if (SR_ERR_OK != rc) {
        goto cleanup;
    }

    /* get the list of changes made by the user */
    diff = lyd_diff(current_data_tree, new_data_tree, 0);
    if (NULL == diff) {
        SR_LOG_ERR("Unable to get the list of changes: %s", ly_errmsg());
        goto cleanup;
    }

    /* iterate over the list of differences and for each issue corresponding Sysrepo command(s) */
    while (diff->type && LYD_DIFF_END != diff->type[i]) {
        if (NULL != diff->first[i]) {
            first_xpath = lyd_path(diff->first[i]);
            if (NULL == first_xpath) {
                SR_LOG_ERR("Error returned from lyd_path: %s.", ly_errmsg());
                goto cleanup;
            }
        }
        if (NULL != diff->second[i]) {
            second_xpath = lyd_path(diff->second[i]);
            if (NULL == second_xpath) {
                free(first_xpath);
                first_xpath = NULL;
                SR_LOG_ERR("Error returned from lyd_path: %s.", ly_errmsg());
                goto cleanup;
            }
        }
        switch (diff->type[i]) {
            case LYD_DIFF_DELETED:
                SR_LOG_DBG("<LYD_DIFF_DELETED> node: %s", first_xpath);
                rc = srcfg_convert_lydiff_deleted(first_xpath);
                break;
            case LYD_DIFF_CHANGED:
                SR_LOG_DBG("<LYD_DIFF_CHANGED> orig: %s, new: %s", first_xpath, second_xpath);
                rc = srcfg_convert_lydiff_changed(first_xpath, diff->second[i]);
                break;
            case LYD_DIFF_MOVEDAFTER1:
                SR_LOG_DBG("<LYD_DIFF_MOVEDAFTER1> moved: %s, after: %s", first_xpath, second_xpath);
                rc = srcfg_convert_lydiff_movedafter(first_xpath, second_xpath);
                break;
            case LYD_DIFF_CREATED:
                SR_LOG_DBG("<LYD_DIFF_CREATED> parent: %s, new node: %s", first_xpath, second_xpath);
                rc = srcfg_convert_lydiff_created(diff->second[i]);
                break;
            case LYD_DIFF_MOVEDAFTER2:
                SR_LOG_DBG("<LYD_DIFF_MOVEDAFTER2> after: %s, this new node was inserted: %s", first_xpath, second_xpath);
                rc = srcfg_convert_lydiff_movedafter(second_xpath, first_xpath);
                break;
            default:
                assert(0 && "not reachable");
        }
        free(first_xpath);
        free(second_xpath);
        first_xpath = second_xpath = NULL;
        if (SR_ERR_OK != rc) {
            goto cleanup;
        }
        ++i;
    }
    if (0 == i) {
        SR_LOG_DBG_MSG("No changes were made.");
    } else {
        /* commit the changes */
        rc = sr_commit(srcfg_session);
        if (SR_ERR_OK != rc) {
            SR_LOG_ERR("Error returned from sr_commit: %s.", sr_strerror(rc));
            goto cleanup;
        }
        if (SRCFG_STORE_RUNNING == datastore && permanent) {
            /* copy running datastore data into the startup datastore */
            rc = sr_copy_config(srcfg_session, module_name, SR_DS_RUNNING, SR_DS_STARTUP);
            if (SR_ERR_OK != rc) {
                SR_LOG_ERR("Error returned from sr_copy_config: %s.", sr_strerror(rc));
                goto cleanup;
            }
        }
    }

    rc = SR_ERR_OK;

cleanup:
    if (NULL != diff) {
        lyd_free_diff(diff);
    }
    if (NULL != current_data_tree) {
        lyd_free_withsiblings(current_data_tree);
    }
    if (NULL != new_data_tree) {
        lyd_free_withsiblings(new_data_tree);
    }
    if (input_data) {
        free(input_data);
    }
    return rc;
}
Ejemplo n.º 7
0
/**
 * @brief Convert data tree difference of type LYD_DIFF_CREATED to corresponding set of Sysrepo public API calls.
 */
static int
srcfg_convert_lydiff_created(struct lyd_node *node)
{
    int rc = SR_ERR_INTERNAL;
    struct lyd_node *elem = node;
    bool process_children = true;
    sr_val_t value = { 0, SR_UNKNOWN_T };
    struct lyd_node_leaf_list *data_leaf = NULL;
    struct lys_node_list *slist = NULL;
    char *xpath = NULL, *delim = NULL;

    CHECK_NULL_ARG(node);

    /* non-recursive DFS post-order */
    do {
        /* go as deep as possible */
        if (process_children) {
            while (!(elem->schema->nodetype & (LYS_LEAF | LYS_LEAFLIST | LYS_ANYXML)) && elem->child) {
                elem = elem->child;
            }
        }

        /* get appropriate xpath and value */
        free(xpath);
        xpath = value.xpath = NULL;
        value.type = SR_UNKNOWN_T;
        switch (elem->schema->nodetype) {
            case LYS_LEAF: /* e.g.: /test-module:user[name='nameE']/name */
                /* get value */
                data_leaf = (struct lyd_node_leaf_list *)elem;
                value.type = sr_libyang_leaf_get_type(data_leaf);
                rc = sr_libyang_leaf_copy_value(data_leaf, &value);
                if (SR_ERR_OK != rc) {
                    SR_LOG_ERR("Error returned from sr_libyang_leaf_copy_value: %s.", sr_strerror(rc));
                    goto cleanup;
                }
                /* get xpath */
                xpath = lyd_path(elem);
                if (NULL == xpath) {
                    SR_LOG_ERR("Error returned from lyd_path: %s.", ly_errmsg());
                    goto cleanup;
                }
                /* key value of a list cannot be set directly */
                if (elem->parent && (elem->parent->schema->nodetype == LYS_LIST)) {
                    slist = (struct lys_node_list *)elem->parent->schema;
                    for (unsigned i = 0; i < slist->keys_size; ++i) {
                        if (slist->keys[i]->name == elem->schema->name) {
                            /* key */
                            if (i == 0) {
                                delim = strrchr(xpath, '/');
                                if (delim) {
                                    *delim = '\0';
                                }
                                goto set_value;
                            } else {
                                /* create list instance (directly) only once - with the first key */
                                goto next_node;
                            }
                        }
                    }
                }
                break;

            case LYS_LEAFLIST: /* e.g.: /test-module:main/numbers[.='10'] */
                /* get value */
                data_leaf = (struct lyd_node_leaf_list *)elem;
                value.type = sr_libyang_leaf_get_type(data_leaf);
                rc = sr_libyang_leaf_copy_value(data_leaf, &value);
                if (SR_ERR_OK != rc) {
                    SR_LOG_ERR("Error returned from sr_libyang_leaf_copy_value: %s.", sr_strerror(rc));
                    goto cleanup;
                }
                /* get xpath */
                xpath = lyd_path(elem);
                if (NULL == xpath) {
                    SR_LOG_ERR("Error returned from lyd_path: %s.", ly_errmsg());
                    goto cleanup;
                }
                /* strip away the predicate */
                delim = strrchr(xpath, '[');
                if (delim) {
                    *delim = '\0';
                }
                break;

            case LYS_ANYXML:
                SR_LOG_ERR_MSG("The anyxml statement is not yet supported by Sysrepo.");
                goto cleanup;

            case LYS_CONTAINER:
                /* explicitly create only presence containers */
                if (((struct lys_node_container *)elem->schema)->presence) {
                    xpath = lyd_path(elem);
                } else {
                    goto next_node;
                }
                break;

            default:
                /* no data to set */
                goto next_node;
        }

set_value:
        /* set value */
        rc = sr_set_item(srcfg_session, xpath, SR_UNKNOWN_T != value.type ? &value : NULL, SR_EDIT_DEFAULT);
        if (SR_ERR_OK != rc) {
            SR_LOG_ERR("Error returned from sr_set_item: %s.", sr_strerror(rc));
            goto cleanup;
        }

next_node:
        /* backtracking + automatically moving to the next sibling if there is any */
        if (elem != node) {
            if (elem->next) {
                elem = elem->next;
                process_children = true;
            } else {
                assert(elem->parent);
                elem = elem->parent;
                process_children = false;
            }
        } else {
            break;
        }
    } while (true);

    rc = SR_ERR_OK;

cleanup:
    if (NULL != xpath) {
        free(xpath);
    }
    sr_free_val_content(&value);
    return rc;
}