C程式碼呼叫uci的API讀openwrt配置檔案指南
阿新 • • 發佈:2019-02-18
實戰背景
倘若我們自己寫了一個應用程式,也想用uci來集中化管理配置該應用的配置檔案,怎麼辦呢?
看了arvik的上一篇部落格後相信新手能很快的使用uci對某個配置檔案進行配置,只是如何讓我們的應用程式讀取配置檔案內容呢,本篇arvik將解答這個問題。
簡單的基本關係
圖解
這裡畫一個圖讓大家大致瞭解配置檔案的內容和uci的幾個基本結構之間的對應關係。(例舉檔案為uhttpd的配置檔案)
幾個結構體
struct uci_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;
};
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
struct uci_section:節結構體,它對應配置檔案中的節
struct uci_section
{
struct uci_element e;
struct uci_list options;
struct uci_package *package;
bool anonymous;
char *type;
};
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
struct uci_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;
};
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
struct uci_ptr:元素位置指標結構,用來查詢並儲存對應位置元素
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;
};
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
struct uci_context: 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;
};
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
幾個基本API函式
uci_alloc_context:動態申請一個uci上下文結構
struct uci_context *uci_alloc_context(void);
- 1
uci_free_contex:釋放由uci_alloc_context申請的uci上下文結構且包括它的所有資料
void uci_free_context(struct uci_context *ctx);
- 1
uci_lookup_ptr:由給定的元組查詢元素。填充ptr結構體中的p,s,o,last
/**
* uci_lookup_ptr: 分離一個uci元組字串且查詢對應元素樹
* @ctx: uci context結構體指標
* @ptr: 存放元素查詢結果的結構體指標
* @str: 待查詢的uci元組字串
* @extended: 允許擴充套件語法查詢
*
*如果extended被設為ture,則uci_lookup_ptr支援下列擴充套件語法:
*
*例子:
* network.@interface[0].ifname ('ifname' option of the first interface section)
* network.@interface[-1] (last interface section)
* Note: 有必要的話uci_lookup_ptr將會自動載入配置檔案包
* @str 不能是一個const型別指標,它在使用的過程中將會被更改且用於將字串填寫到@ptr中,因此
* 它只要@ptr還在使用,它就必須是可用的
*
* 這個函式在指定包元組的的字串未被找到時返回UCI_ERR_NOTFOUND,否則返回UCI_OK
*
* 記住在查詢其他部分失敗的情況,如果它們同樣被指定,包括section和option,同樣會返回UCI_OK,
* 但是ptr->flags * UCI_LOOKUP_COMPLETE標誌位不會被置位
*/
int uci_lookup_ptr(struct uci_context *ctx, struct uci_ptr *ptr, char *str, bool extended);
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
只需由以上3個API就可以對一個uci標準配置檔案進行簡單的讀取了。
程式碼實戰
下面就寫一個例項程式碼試試吧
/***********************************
author:arvik
email:[email protected]
csdn:http://blog.csdn.net/u012819339
************************************/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "uci.h"
int main()
{
struct uci_context *c;
struct uci_ptr p;
char *a = strdup("arvik_testconfig.main.home");
c = uci_alloc_context();
if(UCI_OK != uci_lookup_ptr(c, &p, a, true))
{
uci_perror(c, "no found!\n");
return -1;
}
printf("%s\n", p.o->v.string);
uci_free_context(c);
free(a);
return(0);
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
效果:
root@OpenWrt:/# arvik_uci_test
/www
- 1
- 2
執行截圖