本文是根據代碼實踐以及查看別人的文章總結出來的內容,旨在今后使用時能快速上手,以應用目的為主。主要講解的是關於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;
}