本文是根据代码实践以及查看别人的文章总结出来的内容,旨在今后使用时能快速上手,以应用目的为主。主要讲解的是关于uci的一些基本配置方法,主要涉及section和option,对list等一些复杂的配置暂时不包括,但是在看别人文章的时候发现以下文章讲的内容很全面,这里给出链接,以便今后对本文不涉及的内容做查询。
https://blog.csdn.net/qq_41453285/article/details/102527800
uci简介
统一配置接口(Unified Configuration Interface,UCI),是OpenWrt成功的关键技术之一,已经移植支持数千个软件。它采用纯文本文件来保存配置,并提供命令行和C语言编程调用接口进行管理。
uci结构
匿名section,如图一
config <section type>
<option type> <option value>
命名section,如图二
config <section type> <section name>
<option type> <option value>
config指的是配置文件的名字。
<section type>指的是配置section的类型,比如图中的wifi-iface和wifi-device。
<section name>指的是配置section的名称(别名),比如图中的“wifi0”和“wifi1”和“wifi2”等。这一项是可选的,如果没有这一项就是匿名section,针对这样的section是如何进行配置的呢,稍后的配置步骤中会有解答。
<option type>指的是配置选项(其实就是section的一种属性),从图中可以看出,option是属于section其中的,比如图中的“index”和“tyepe”这类的属性值。
<option value>指的是配置选项对应数据值,比如图中的“3”和“ath3”之类的值,<option value>和<option type>之间以空格分隔,<option value>通常都是字符串格式保存在配置文件中。
PS:命名规范就是字母数字下划线,尽量如此做,当然有更广泛的允许,此处不多说。
图一 图二
uci命令行使用
命令行总结
将一些常用的操作命令整理在如下表格:
操作 | 命令 | 说明 |
---|---|---|
增 | uci add test aNewSection | 增加<section type> aNewSection |
uci set test.@aNewSection[0].aNewOption=1 | 这里虽然使用的命令是uci set,但是因为set的对象是原本没有的option,所以是增加一个option的功能,增加的option要求一定要已经存在对应的section。在之前的section中增加 | |
删 | uci delete test.@aNewSection[0].aNewOption0 | 删除一个<option type> |
uci delete test.@aNewSection[0] | 删除一个<section type>,请注意这里删除section之后,连带section下的所有option都会被删除。 | |
查 | uci get test.@aNewSection[0].aNewOption0 | 查看某个<option type>的<option value> |
uci show test.@aNewSection[0].aNewOption0 | 查看某个<option type>这一行项目 | |
uci get test.@aNewSection[0] | 查看某个<section type> | |
uci show test.@aNewSection[0] | 查看某个<section type>具体项目值 | |
改 | uci rename test.@aNewSection[0]=aNewSection0 | 对匿名section重命名 |
uci rename test.aNewSection0.aNewOption=aNewOption0 | 对option重命名 | |
uci set test.aNewSection0.aNewOption0=2 | 这里使用的命令是uci set,因为set的对象是原本已经有的option,修改 |
注意:
1.section新建一定是匿名的,之后可以rename为它添加上名字。
2.任何的修改uci文件操作(增删改)都必须最后使用“uci commit <config>”命令使文件修改生效。
3.另外附上一些其他的uci命令用法,其中uci delete <config> 这个命令我试过,意思是删除一个配置文件(I guess),但是无论如何都无法删除,一直显示Invalid command。
uci命令行使用效果
实验基础:在/etc/config/目录下新建一个test文件,文件中已经写入了6个section,内容如图:
运行“增”命令
uci add test aNewSection
uci set test.@aNewSection[0].aNewOption=1
uci commit test
运行结果
运行“改”命令:
uci rename test.@aNewSection[0]=aNewSection0
uci rename test.aNewSection0.aNewOption=aNewOption0
uci set test.aNewSection0.aNewOption0=2
uci commit test
运行结果
运行“查”命令:
uci get test.@aNewSection[0].aNewOption0
uci show test.@aNewSection[0].aNewOption0
uci get test.@aNewSection[0]
uci show test.@aNewSection[0]
运行结果
运行“删”命令
uci delete test.@aNewSection[0].aNewOption0
uci delete test.@aNewSection[0]
uci commit test
运行结果
删除之后整个section都没有了。
这里可以看到如果删除第一个(index是0)section,后一个就会变成第一个(index是0),此时wifi-iface的section只有2个,如果删除第三个wifi-iface(index是2),就会报出无效参数的错误。
uci接口代码使用
接口总结
原生uci接口在文章开头的链接中可以找到,这里列出的是为了以后方便使用封装之后的接口。
函数名称 | 函数原型 | 函数说明 |
---|---|---|
my_uciInit | struct uci_context *my_uciInit() | 初始化并分配一个ctx |
my_uciDestroy | int my_uciDestroy(struct uci_context *ctx) | 释放一个ctx空间 |
my_uciAddSection | int my_uciAddSection(struct uci_context *ctx, const char *package, const char *sectionName) | 添加一个section |
my_uciSet | int my_uciSet(struct uci_context *ctx, char *package, char *option, char *value) | 添加或者修改一个option |
my_uciGet | int my_uciGet(struct uci_context *ctx, char *package, char *option, char *value) | 获取一个option的值 |
my_uciCommit | int my_uciCommit(struct uci_context *ctx, char *package) | 提交修改config |
my_uciDelete | int my_uciDelete(struct uci_context *ctx, char *package, char *option) | 删除一个section或者删除一个option |
uci_foreach_element | uci_foreach_element(struct uci_section *, struct uci_element *) | 原生遍历函数,注意不能在这个函数范围内做删除操作 |
接口使用实例
test_uci_foreach_element
int test_uci_foreach_element()
{
struct uci_context * ctx = NULL;
struct uci_package * pkg = NULL;
struct uci_element *e = NULL;
const char *value = NULL;
ctx = uci_alloc_context();
if (UCI_OK != uci_load(ctx, "wireless", &pkg))
{
uci_free_context(ctx);
return -1;
}
uci_foreach_element(&pkg->sections, e)
{
struct uci_section *s = uci_to_section(e);
if (0 == strncmp("wifi-iface", s->type, 10))
{
int enabled = 0;
int vap_index = -1;
char ssid[128] = {0};
value = uci_lookup_option_string(ctx, s, "index");
if (NULL != value)
{
vap_index = atoi(value);
}
value = uci_lookup_option_string(ctx, s, "enabled");
if (NULL != value)
{
enabled = atoi(value);
}
value = uci_lookup_option_string(ctx, s, "ssid");
if (NULL != value)
{
strcpy(ssid, value);
}
}
}
uci_unload(ctx, pkg);
uci_free_context(ctx);
return 0;
}
test_my_uciGet
/* uci get my_config_file.@global[0].md5_wireless */
int test_my_uciGet(char *md5_wireless)
{
int ret;
char option[128] = {0};
char value[128] = {0};
struct uci_context *ctx = NULL;
ctx = my_uciInit();
if (ctx == NULL)
{
printf("uci init error\n");
return -1;
}
snprintf(option, sizeof(option), "@global[0].md5_wireless");
ret = my_uciGet(ctx, "wifison", option , value);
if (ret != 0)
{
printf("uci get %s failed\n", option);
my_uciDestroy(ctx);
return -1;
}
strcpy(md5_wireless, value);
printf("md5_wireless is %s\n", md5_wireless);
my_uciDestroy(ctx);
return 0;
}
test_my_uciSet
/* uci set my_config_file.@global[0].md5_wireless */
int test_my_uciSet(char *md5_wireless)
{
int ret;
char option[128] = {0};
struct uci_context *ctx = NULL;
ctx = my_uciInit();
if (ctx == NULL)
{
printf("uci init error\n");
return -1;
}
snprintf(option, sizeof(option), "@global[0].md5_wireless");
ret = my_uciSet(ctx, "wifison", option, md5_wireless);
if (ret != 0)
{
printf("uci set %s failed\n", option);
my_uciCommit(ctx, "wifison");
my_uciDestroy(ctx);
return -1;
}
my_uciCommit(ctx, "wifison");
my_uciDestroy(ctx);
return 0;
}
test_my_uciAddSection
/* uci add my_config_file blacklist */
/* uci set my_config_file.@blacklist[0].macaddr */
int test_my_uciAddSection(char *macaddr)
{
char option[128] = {0};
char data[128] = {0};
struct uci_context *ctx = NULL;
int ret;
ctx = my_uciInit();
if (ctx == NULL)
{
printf("uci init error\n");
return -1;
}
ret = my_uciAddSection(ctx, "my_config_file", "blacklist");
if (ret != 0)
{
printf("uci add section failed\n");
}
snprintf(option, sizeof(option), "@blacklist[%d].macaddr", blacklist_num);
snprintf(data, sizeof(data), "%s", macaddr);
ret = my_uciSet(ctx, "my_config_file", option , data);
if (ret != 0)
{
printf("uci set %s failed\n", option);
}
my_uciCommit(ctx, "my_config_file");
my_uciDestroy(ctx);
return 0;
}
test_my_uciDelete_section
/* uci delete my_config_file.ath%d */
int test_my_uciDelete_section(void)
{
int i;
struct uci_context *ctx = NULL;
int ret;
ctx = my_uciInit();
if (ctx == NULL)
{
printf("uci init error\n");
return -1;
}
for (i = 0; i < VAP_MAX_NUM * RADIO_MAX_NUM; i ++)
{
char sectionName[128] = {0};
snprintf(sectionName, sizeof(sectionName), "ath%d", i);
ret = my_uciDelete(ctx, "my_config_file", sectionName);
if (ret != 0)
{
continue;
}
}
my_uciCommit(ctx, "my_config_file");
my_uciDestroy(ctx);
return 0;
}