diff --git a/apps/backend/backend_commit.c b/apps/backend/backend_commit.c index 61e9a246..d7c2d6c3 100644 --- a/apps/backend/backend_commit.c +++ b/apps/backend/backend_commit.c @@ -285,7 +285,7 @@ candidate_commit(clicon_handle h, /* Optionally write (potentially modified) tree back to candidate */ if (clicon_option_bool(h, "CLICON_TRANSACTION_MOD")){ - if ((ret = xmldb_put(h, candidate, OP_REPLACE, td->td_target, NULL)) < 0) + if ((ret = xmldb_put(h, candidate, OP_REPLACE, td->td_target, cbret)) < 0) goto done; if (ret == 0) goto fail; diff --git a/datastore/text/clixon_xmldb_text.c b/datastore/text/clixon_xmldb_text.c index 42210170..c4d2d1b4 100644 --- a/datastore/text/clixon_xmldb_text.c +++ b/datastore/text/clixon_xmldb_text.c @@ -572,7 +572,10 @@ text_get(xmldb_handle xh, * @param[in] x0p Parent of x0 * @param[in] x1 xml tree which modifies base * @param[in] op OP_MERGE, OP_REPLACE, OP_REMOVE, etc - * @param[out] cbret Initialized cligen buffer. Contains return XML or "". + * @param[out] cbret Initialized cligen buffer. Contains return XML if retval is 0. + * @retval -1 Error + * @retval 0 Failed (cbret set) + * @retval 1 OK * Assume x0 and x1 are same on entry and that y is the spec * @see text_modify_top */ @@ -598,6 +601,7 @@ text_modify(struct text_handle *th, yang_stmt *yc; /* yang child */ cxobj **x0vec = NULL; int i; + int ret; assert(x1 && xml_type(x1) == CX_ELMNT); assert(y0); @@ -613,7 +617,7 @@ text_modify(struct text_handle *th, if (x0){ if (netconf_data_exists(cbret, "Data already exists; cannot create new resource") < 0) goto done; - goto ok; + goto fail; } case OP_NONE: /* fall thru */ case OP_MERGE: @@ -658,7 +662,7 @@ text_modify(struct text_handle *th, if (x0==NULL){ if (netconf_data_missing(cbret, "Data does not exist; cannot delete resource") < 0) goto done; - goto ok; + goto fail; } case OP_REMOVE: /* fall thru */ if (x0){ @@ -675,7 +679,7 @@ text_modify(struct text_handle *th, if (x0){ if (netconf_data_exists(cbret, "Data already exists; cannot create new resource") < 0) goto done; - goto ok; + goto fail; } case OP_REPLACE: /* fall thru */ if (x0){ @@ -738,18 +742,18 @@ text_modify(struct text_handle *th, while ((x1c = xml_child_each(x1, x1c, CX_ELMNT)) != NULL) { x1cname = xml_name(x1c); yc = yang_find_datanode(y0, x1cname); - if (text_modify(th, x0vec[i++], (yang_node*)yc, x0, x1c, op, cbret) < 0) + if ((ret = text_modify(th, x0vec[i++], (yang_node*)yc, x0, x1c, op, cbret)) < 0) goto done; /* If xml return - ie netconf error xml tree, then stop and return OK */ - if (cbuf_len(cbret)) - goto ok; + if (ret == 0) + goto fail; } break; case OP_DELETE: if (x0==NULL){ if (netconf_data_missing(cbret, "Data does not exist; cannot delete resource") < 0) goto done; - goto ok; + goto fail; } case OP_REMOVE: /* fall thru */ if (x0) @@ -760,21 +764,26 @@ text_modify(struct text_handle *th, } /* CONTAINER switch op */ } /* else Y_CONTAINER */ xml_sort(x0p, NULL); - ok: - retval = 0; + retval = 1; done: if (x0vec) free(x0vec); return retval; + fail: /* cbret set */ + retval = 0; + goto done; } /* text_modify */ /*! Modify a top-level base tree x0 with modification tree x1 - * @param[in] th text handle - * @param[in] x0 Base xml tree (can be NULL in add scenarios) - * @param[in] x1 xml tree which modifies base + * @param[in] th text handle + * @param[in] x0 Base xml tree (can be NULL in add scenarios) + * @param[in] x1 xml tree which modifies base * @param[in] yspec Top-level yang spec (if y is NULL) - * @param[in] op OP_MERGE, OP_REPLACE, OP_REMOVE, etc - * @param[out] cbret Initialized cligen buffer. Contains return XML or "". + * @param[in] op OP_MERGE, OP_REPLACE, OP_REMOVE, etc + * @param[out] cbret Initialized cligen buffer. Contains return XML if retval is 0. + * @retval -1 Error + * @retval 0 Failed (cbret set) + * @retval 1 OK * @see text_modify */ static int @@ -792,6 +801,7 @@ text_modify_top(struct text_handle *th, yang_stmt *yc; /* yang child */ yang_stmt *ymod;/* yang module */ char *opstr; + int ret; /* Assure top-levels are 'config' */ assert(x0 && strcmp(xml_name(x0),"config")==0); @@ -820,7 +830,7 @@ text_modify_top(struct text_handle *th, case OP_DELETE: if (netconf_data_missing(cbret, "Data does not exist; cannot delete resource") < 0) goto done; - goto ok; + goto fail; break; default: break; @@ -849,21 +859,24 @@ text_modify_top(struct text_handle *th, if (yc == NULL){ if (netconf_unknown_element(cbret, "application", x1cname, "Unassigned yang spec") < 0) goto done; - goto ok; + goto fail; } /* See if there is a corresponding node in the base tree */ if (match_base_child(x0, x1c, &x0c, yc) < 0) goto done; - if (text_modify(th, x0c, (yang_node*)yc, x0, x1c, op, cbret) < 0) + if ((ret = text_modify(th, x0c, (yang_node*)yc, x0, x1c, op, cbret)) < 0) goto done; /* If xml return - ie netconf error xml tree, then stop and return OK */ - if (cbuf_len(cbret)) - goto ok; + if (ret == 0) + goto fail; } - ok: - retval = 0; + // ok: + retval = 1; done: return retval; + fail: /* cbret set */ + retval = 0; + goto done; } /* text_modify_top */ /*! For containers without presence and no children(except attrs), remove @@ -923,14 +936,11 @@ text_put(xmldb_handle xh, yang_spec *yspec; cxobj *x0 = NULL; struct db_element *de = NULL; - int cbretlocal = 0; /* Set if cbret is NULL on entry */ + int ret; if (cbret == NULL){ - if ((cbret = cbuf_new()) == NULL){ - clicon_err(OE_XML, errno, "cbuf_new"); - goto done; - } - cbretlocal++; + clicon_err(OE_XML, EINVAL, "cbret is NULL"); + goto done; } if ((yspec = th->th_yangspec) == NULL){ clicon_err(OE_YANG, ENOENT, "No yang spec"); @@ -991,10 +1001,10 @@ text_put(xmldb_handle xh, * Modify base tree x with modification x1. This is where the * new tree is made. */ - if (text_modify_top(th, x0, x1, yspec, op, cbret) < 0) + if ((ret = text_modify_top(th, x0, x1, yspec, op, cbret)) < 0) goto done; /* If xml return - ie netconf error xml tree, then stop and return OK */ - if (cbuf_len(cbret)) + if (ret == 0) goto fail; /* Remove NONE nodes if all subs recursively are also NONE */ @@ -1047,8 +1057,6 @@ text_put(xmldb_handle xh, goto done; retval = 1; done: - if (cbretlocal && cbret) - cbuf_free(cbret); if (f != NULL) fclose(f); if (dbfile) @@ -1408,6 +1416,8 @@ main(int argc, char *yangmod; /* yang file */ yang_spec *yspec = NULL; clicon_handle h; + cbuf *cbret = NULL; + int ret; if ((h = clicon_handle_init()) == NULL) goto done; @@ -1456,13 +1466,21 @@ main(int argc, op = OP_REMOVE; else usage(argv[0]); - if (xmldb_put(h, db, op, NULL, xn, NULL) < 1) + if ((cbret = cbuf_new()) == NULL){ + clicon_err(OE_UNIX, errno, "cbuf_new"); goto done; + } + if ((ret = xmldb_put(h, db, op, NULL, xn, cbret)) < 0) + goto done; + if (ret == 0) + fprintf(stderr, "%s\n", cbuf_get(cbret)); } else usage(argv[0]); printf("\n"); done: + if (cbret) + cbuf_free(cbret); return 0; } diff --git a/example/example_backend.c b/example/example_backend.c index 7c09ee3d..a322ad1e 100644 --- a/example/example_backend.c +++ b/example/example_backend.c @@ -260,6 +260,7 @@ example_reset(clicon_handle h, int retval = -1; cxobj *xt = NULL; int ret; + cbuf *cbret = NULL; if (xml_parse_string("" "loex:loopback" @@ -268,15 +269,22 @@ example_reset(clicon_handle h, /* Replace parent w first child */ if (xml_rootchild(xt, 0, &xt) < 0) goto done; + if ((cbret = cbuf_new()) == NULL){ + clicon_err(OE_UNIX, errno, "cbuf_new"); + goto done; + } /* Merge user reset state */ - if ((ret = xmldb_put(h, (char*)db, OP_MERGE, xt, NULL)) < 0) + if ((ret = xmldb_put(h, (char*)db, OP_MERGE, xt, cbret)) < 0) goto done; if (ret == 0){ - clicon_err(OE_XML, 0, "Error when writing to XML database"); + clicon_err(OE_XML, 0, "Error when writing to XML database: %s", + cbuf_get(cbret)); goto done; } retval = 0; done: + if (cbret) + cbuf_free(cbret); if (xt != NULL) xml_free(xt); return retval; diff --git a/lib/src/clixon_xml_db.c b/lib/src/clixon_xml_db.c index 8fb5da70..73959bf7 100644 --- a/lib/src/clixon_xml_db.c +++ b/lib/src/clixon_xml_db.c @@ -379,7 +379,7 @@ xmldb_get(clicon_handle h, * @param[in] db running or candidate * @param[in] op Top-level operation, can be superceded by other op in tree * @param[in] xt xml-tree. Top-level symbol is dummy - * @param[out] cbret Initialized cligen buffer or NULL. On exit contains XML or "". + * @param[out] cbret Initialized cligen buffer. On exit contains XML if retval == 0 * @retval 1 OK * @retval 0 Failed, cbret contains error xml message * @retval -1 Error