標籤:
【智能路由器】系列文章串連
http://blog.csdn.net/u012819339/article/category/5803489
上篇部落格講解了命令列下uci的使用方法,本篇部落格arvik將簡單剖析uci部分源碼,帶領大家使用c語言調用uci的API來讀取設定檔。
實戰背景
倘若我們自己寫了一個應用程式,也想用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;};
struct uci_section:節結構體,它對應設定檔中的節
struct uci_section{ struct uci_element e; struct uci_list options; struct uci_package *package; bool anonymous; char *type;};
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;};
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;};
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;};
幾個基本API函數
uci_alloc_context:動態申請一個uci上下文結構
struct uci_context *uci_alloc_context(void);
uci_free_contex:釋放由uci_alloc_context申請的uci上下文結構且包括它的所有資料
void uci_free_context(struct uci_context *ctx);
uci_lookup_ptr:由給定的元組尋找元素
/** * 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);
只需由以上3個API就可以對一個uci標準設定檔進行簡單的讀取了。
代碼實戰
下面就寫一個執行個體代碼試試吧
/***********************************author:arvikemail:[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);}
效果:
root@OpenWrt:/# arvik_uci_test /www
運行:
【智能路由器】系列文章串連
http://blog.csdn.net/u012819339/article/category/5803489
【智能路由器】C代碼調用uci的API讀openwrt設定檔指南