1.UCI概述
UCI主要是一种对底层配置文件处理的一种方法。
用于OpenWrt整个系统的配置集中化。很多后台服务有自己的配置文件,并且配置文件格式都不相同,OpenWrt系统中需要开启各种服务,为了解决配置不兼容的问题,统一采用uci格式的配置文件。
首先我们要清楚UCI的结构,以/etc/config/network下面一个配置节点为例
network整个文件的内容对应:配置文件包(package)
像上图这样一个配置节点我们称为:一个section,每个配置节点中包括配置类型、配置名、选项、值等信息。
以上图为例:interface我们叫做“配置类型”,mgnt我们叫做“配置名”,type、ip6assign等我们叫做选项(option)
它的默认访问路径为:/etc/config/下面的配置文件,
2.UCI命令
UCI命令支持通过UCI shell命令进行操作
常用的有uci show 、uci set 、uci get等 ,如uci show network
3.UCI-C使用方法
先来了解UCI结构的对应结构体:
UCI上下文结构体:贯穿查询、更改配置文件全过程
struct uci_context
{
/* 配置文件包列表 */
struct uci_list root;
/* 解析上下文,只用于错误处理 */
struct uci_parse_context *pctx;
/* 后端导入导出 */
struct uci_backend *backend;
struct uci_list backends;
/* uci 运行标识 */
enum uci_flags flags;
char *confdir;
char *savedir;
/* search path for delta files */
struct uci_list delta_path;
/* 私有数据 */
int err;
const char *func;
jmp_buf trap;
bool internal, nested;
char *buf;
int bufsz;
};
package对应的结构体如下(包结构体):它对应一个配置文件内容
struct uci_package
{
struct uci_element e;
struct uci_list sections;
struct uci_context *ctx;
bool has_delta;
char *path;
/* private: */
struct uci_backend *backend;
void *priv;
int n_section;
struct uci_list delta;
struct uci_list saved_delta;
};
section对应的结构体(节结构体):它对应配置文件中的节
struct uci_section
{
struct uci_element e;
struct uci_list options;
struct uci_package *package;
bool anonymous;
char *type;
};
option对应的结构体(选项结构体):对应配置文件里节中的 option 或者 list
struct uci_option
{
struct uci_element e;
struct uci_section *section;
enum uci_option_type type;
union {
struct uci_list list;
char *string;
} v;
};
元素指针结构体:元素位置指针结构,用来查询并保存对应位置元素
struct uci_ptr
{
enum uci_type target;
enum {
UCI_LOOKUP_DONE = (1 << 0),
UCI_LOOKUP_COMPLETE = (1 << 1),
UCI_LOOKUP_EXTENDED = (1 << 2),
} flags;
struct uci_package *p;
struct uci_section *s;
struct uci_option *o;
struct uci_element *last;
const char *package;
const char *section;
const char *option;
const char *value;
};
UCI 常用的C接口:
int uci_set(struct uci_context *ctx, struct uci_ptr *ptr) 设置uci值
int uci_del_list(struct uci_context *ctx, struct uci_ptr *ptr) 删除list option
int uci_add_list(struct uci_context *ctx, struct uci_ptr *ptr) 增加list option
int uci_delete(struct uci_context *ctx, struct uci_ptr *ptr) 删除节点(option)
int uci_lookup_ptr(struct uci_context *ctx, struct uci_ptr *ptr, char *str, bool extended) 查询元素指针
int uci_rename(struct uci_context *ctx, struct uci_ptr *ptr)
重命名节(option)
int uci_add_section(struct uci_context *ctx, struct uci_package *p, const char *type,
struct uci_section **res)
添加一个节
struct uci_context *uci_alloc_context(void) 分配上下文空间
void uci_free_context(struct uci_context *ctx) 释放上下文空间
int uci_load(struct uci_context *ctx, const char *name, struct uci_package **package)
加载配置到内存
int uci_set_confdir(struct uci_context *ctx, const char *dir)
设置配置目录
int uci_commit(struct uci_context *ctx, struct uci_package **package, bool overwrite)
提交修改的值
struct uci_option *uci_lookup_option(struct uci_context *ctx, struct uci_section *s, const char *name)
查询option指针
const char *uci_lookup_option_string(struct uci_context *ctx, struct uci_section *s, const char *name)
获取一个option string值
struct uci_section *uci_lookup_section(struct uci_context *ctx, struct uci_package *p, const char *name)
查询package中的section
struct uci_package * uci_lookup_package(struct uci_context *ctx, const char *name)
在上下文中获取package指针
C语言遍历配置文件实例:
struct uci_context *ctx = NULL;
struct uci_package *pkg = NULL;
struct uci_element *emt = NULL;
char old_vid_option[64]={0};
char value[8] = {0};
int vlan_exist_flag = 0;
ctx = uci_alloc_context();
if (!ctx) {
cw_log(LG_ERR, "SetLanTrunkInfo uci_alloc_context failed.");
goto err;
}
if(UCI_OK != uci_load(ctx, "network", &pkg)){
cw_log(LG_ERR, "SetLanTrunkInfo uci_load failed.");
goto err;
}
uci_foreach_element(&pkg->sections, emt) //遍历这个配置文件下的每一个section
{
struct uci_section *s = uci_to_section(emt); //获取每一个节点的指针
if(s==NULL)
continue;
if(!strncmp("interface",s->type)){ //s->type为配置类型,s->e.name为配置节点名称
/*自由发挥*/
}
}
if (pkg)
uci_unload(ctx,pkg);
if (ctx)
uci_free_context(ctx);