解释分析细致讲解一下这段代码int ncds_file_editconfig_internal (struct ncds_ds *ds, NC_DATASTORE target, char config) { struct ncds_ds_file * file_ds = (struct ncds_ds_file )ds; xmlDocPtr config_doc, datastore_doc; xmlNodePtr target_ds, tmp_target_ds, aux_node, root; int retval = EXIT_SUCCESS, ret; char aux = NULL; const char configp; LOCK(file_ds,ret); if (ret) { return EXIT_FAILURE; } DBG("enter %s/%d\n", func,LINE); if(file_fill_dsnodes(file_ds)) { UNLOCK(file_ds); ERROR("%s: file_ds->running_all/startup_all/candidate_all is NULL\n", func); return EXIT_FAILURE; } DBG("%s step1\n", func); file_rollback_store(file_ds); switch(target) { case NC_DATASTORE_RUNNING: target_ds = file_ds->running; break; case NC_DATASTORE_STARTUP: target_ds = file_ds->startup; break; case NC_DATASTORE_CANDIDATE: target_ds = file_ds->candidate; break; default: UNLOCK(file_ds); ERROR("%s: invalid target.", func); return EXIT_FAILURE; break; } if (strncmp(config, "<?xml", 5) == 0) { if ((configp = strchr(config, '>')) == NULL) { UNLOCK(file_ds); ERROR("%s: invalid config.", func); return EXIT_FAILURE; } ++configp; while (*configp == ' ' || *configp == '\n' || configp == '\t') { ++configp; } } else { configp = config; } if (asprintf(&aux, "<config>%s</config>", configp) == -1) { UNLOCK(file_ds); ERROR("asprintf() failed (%s:%d).", FILE, LINE); return EXIT_FAILURE; } if ((config_doc = xmlReadMemory (aux, strlen(aux), NULL, NULL, NC_XMLREAD_OPTIONS)) == NULL) { UNLOCK(file_ds); free(aux); ERROR("%s: Reading xml data failed!", func); return EXIT_FAILURE; } free(aux); root = xmlDocGetRootElement(config_doc); for (aux_node = root->children; aux_node != NULL; aux_node = root->children) { xmlUnlinkNode(aux_node); xmlAddNextSibling(config_doc->last, aux_node); } aux_node = root->next; xmlUnlinkNode(root); xmlFreeNode(root); datastore_doc = xmlNewDoc (BAD_CAST "1.0"); xmlDocSetRootElement(datastore_doc, xmlCopyNode(target_ds->children, 1)); if (target_ds->children) { for (root = target_ds->children->next; root != NULL; root = aux_node) { aux_node = root->next; xmlAddNextSibling(datastore_doc->last, xmlCopyNode(root, 1)); } } retval = edit_config_internal(datastore_doc, config_doc, (struct ncds_ds)file_ds, NC_EDIT_DEFOP_NOTSET); if (EXIT_SUCCESS == retval) { #if 1 while ((aux_node = target_ds->children) != NULL) { xmlUnlinkNode(aux_node); xmlFreeNode(aux_node); } xmlAddChildList(target_ds, xmlCopyNodeList(datastore_doc->children)); if (file_sync(file_ds)) { retval = EXIT_FAILURE; } #endif } else { retval = EXIT_FAILURE; } UNLOCK(file_ds); xmlFreeDoc (datastore_doc); xmlFreeDoc (config_doc); return retval; }
时间: 2024-04-21 09:26:09 浏览: 167
这段代码是一个函数,函数名为 ncds_file_editconfig_internal,它的作用是编辑一个 data store 文件。函数的参数有三个,分别是一个指向 ncds_ds 结构体的指针 ds,一个 NC_DATASTORE 类型的 target,以及一个 char 类型的 config。该函数返回一个整数值。
函数开始时,它将传入的 ds 强制转换为 struct ncds_ds_file 类型的指针 file_ds,并定义了一些变量,如 xmlDocPtr 类型的指针 config_doc 和 datastore_doc,以及 xmlNodePtr 类型的指针 target_ds、tmp_target_ds、aux_node 和 root,以及 int 类型的变量 retval 和 ret,以及 char 类型的变量 aux 和 configp。
接下来,函数会对 file_ds 作加锁操作,并检查加锁是否成功。如果加锁失败,则返回 EXIT_FAILURE。
然后,函数会输出一条日志,表明函数已经进入到了这个代码块中。接着,函数会调用 file_fill_dsnodes 函数,如果该函数返回值不为 0,说明 file_ds 的成员变量 running_all、startup_all 和 candidate_all 为空,此时函数会解锁 file_ds,并输出错误日志,最终返回 EXIT_FAILURE。
然后,函数会调用 file_rollback_store 函数,该函数的作用是将 file_ds 的 candidate 数据库回滚到 running 或 startup 数据库中。接着,函数会根据传入的 target 值来确定 target_ds 的值,如果 target 不是 NC_DATASTORE_RUNNING、NC_DATASTORE_STARTUP 或 NC_DATASTORE_CANDIDATE 中的一个,则函数会解锁 file_ds,并输出错误日志,最终返回 EXIT_FAILURE。
接下来,函数会判断 config 是否以 "<?xml" 开头,如果是,则将 configp 指向 config 中第一个 ">" 的下一个字符,并将 configp 中的空格、制表符和换行符过滤掉;否则,将 configp 指向 config。接着,函数会调用 asprintf 函数来构造一个新的字符串 aux,将 configp 包装成一个 XML 标签,然后将其读入到 config_doc 中,如果读入失败,则函数会释放锁并返回 EXIT_FAILURE。
接下来,函数会提取 config_doc 中的根节点 root,并将它的子节点从 root 中分离出来,然后将这些子节点添加到 config_doc 的最后一个节点后面。接着,函数会新建一个名为 "1.0" 的 XML 文档 datastore_doc,并将 target_ds 的子节点添加到 datastore_doc 中。然后,函数会遍历 target_ds 的子节点,将它们添加到 datastore_doc 的最后一个节点后面。
接下来,函数会调用 edit_config_internal 函数来编辑 datastore_doc 和 config_doc,其中 edit_config_internal 函数是另一个函数,我们无法得知它的实现细节,但是它的作用是将 config_doc 中的配置应用到 datastore_doc 中。如果 edit_config_internal 函数返回值为 EXIT_SUCCESS,则将 datastore_doc 中的子节点添加到 target_ds 中,并调用 file_sync 函数来将修改同步到文件系统中。如果 file_sync 函数返回值不为 0,则函数返回 EXIT_FAILURE。
最后,函数会解锁 file_ds,并释放 config_doc 和 datastore_doc 所占用的内存,并返回 retval。
阅读全文