1. 程式人生 > >C程式碼呼叫uci的API讀openwrt配置檔案指南

C程式碼呼叫uci的API讀openwrt配置檔案指南

實戰背景

倘若我們自己寫了一個應用程式,也想用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

執行截圖

這裡寫圖片描述