1398 lines
30 KiB
C
1398 lines
30 KiB
C
/*
|
|
* $Id$
|
|
*
|
|
Copyright (c) 2006-2020 Chung, Hyung-Hwan. All rights reserved.
|
|
|
|
Redistribution and use in source and binary forms, with or without
|
|
modification, are permitted provided that the following conditions
|
|
are met:
|
|
1. Redistributions of source code must retain the above copyright
|
|
notice, this list of conditions and the following disclaimer.
|
|
2. Redistributions in binary form must reproduce the above copyright
|
|
notice, this list of conditions and the following disclaimer in the
|
|
documentation and/or other materials provided with the distribution.
|
|
|
|
THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR
|
|
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
|
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
|
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
|
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
|
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
*/
|
|
|
|
#include "mod-uci.h"
|
|
/*
|
|
#include <hawk-str.h>
|
|
#include <hawk-rbt.h>
|
|
#include <hawk-chr.h>
|
|
#include <hawk-fmt.h>
|
|
*/
|
|
#include "../lib/hawk-prv.h"
|
|
|
|
#if defined(HAVE_UCI_H)
|
|
# include <uci.h>
|
|
#else
|
|
# error this module needs uci.h
|
|
#endif
|
|
|
|
typedef struct uctx_list_t uctx_list_t;
|
|
typedef struct uctx_node_t uctx_node_t;
|
|
|
|
struct uctx_node_t
|
|
{
|
|
int id;
|
|
struct uci_context* ctx;
|
|
uctx_node_t* prev;
|
|
uctx_node_t* next;
|
|
};
|
|
|
|
struct uctx_list_t
|
|
{
|
|
uctx_node_t* head;
|
|
uctx_node_t* tail;
|
|
uctx_node_t* free;
|
|
|
|
/* mapping table to map 'id' to 'node' */
|
|
struct
|
|
{
|
|
uctx_node_t** tab;
|
|
int capa;
|
|
int high;
|
|
} map;
|
|
|
|
int errnum;
|
|
};
|
|
|
|
static uctx_node_t* new_uctx_node (hawk_rtx_t* rtx, uctx_list_t* list)
|
|
{
|
|
/* create a new context node and append it to the list tail */
|
|
uctx_node_t* node;
|
|
|
|
node = HAWK_NULL;
|
|
|
|
if (list->free) node = list->free;
|
|
else
|
|
{
|
|
node = hawk_rtx_callocmem (rtx, HAWK_SIZEOF(*node));
|
|
if (!node) goto oops;
|
|
}
|
|
|
|
node->ctx = uci_alloc_context();
|
|
if (!node->ctx) goto oops;
|
|
|
|
if (node == list->free) list->free = node->next;
|
|
else
|
|
{
|
|
if (list->map.high <= list->map.capa)
|
|
{
|
|
int newcapa;
|
|
uctx_node_t** tmp;
|
|
|
|
newcapa = list->map.capa + 64;
|
|
if (newcapa < list->map.capa) goto oops; /* overflow */
|
|
|
|
tmp = (uctx_node_t**) hawk_rtx_reallocmem (
|
|
rtx, list->map.tab, HAWK_SIZEOF(*tmp) * newcapa);
|
|
if (!tmp) goto oops;
|
|
|
|
HAWK_MEMSET (&tmp[list->map.capa], 0,
|
|
HAWK_SIZEOF(*tmp) * (newcapa - list->map.capa));
|
|
|
|
list->map.tab = tmp;
|
|
list->map.capa = newcapa;
|
|
}
|
|
|
|
node->id = list->map.high;
|
|
HAWK_ASSERT (list->map.tab[node->id] == HAWK_NULL);
|
|
list->map.tab[node->id] = node;
|
|
list->map.high++;
|
|
}
|
|
|
|
/* append it to the tail */
|
|
node->next = HAWK_NULL;
|
|
node->prev = list->tail;
|
|
if (list->tail) list->tail->next = node;
|
|
else list->head = node;
|
|
list->tail = node;
|
|
|
|
return node;
|
|
|
|
oops:
|
|
if (node) hawk_rtx_freemem (rtx, node);
|
|
hawk_rtx_seterrnum (rtx, HAWK_NULL, HAWK_ENOMEM);
|
|
return HAWK_NULL;
|
|
}
|
|
|
|
static void free_uctx_node (hawk_rtx_t* rtx, uctx_list_t* list, uctx_node_t* node)
|
|
{
|
|
if (node->prev) node->prev->next = node->next;
|
|
if (node->next) node->next->prev = node->prev;
|
|
if (list->head == node) list->head = node->next;
|
|
if (list->tail == node) list->tail = node->prev;
|
|
|
|
list->map.tab[node->id] = HAWK_NULL;
|
|
|
|
if (node->ctx)
|
|
{
|
|
uci_free_context (node->ctx);
|
|
}
|
|
|
|
if (list->map.high == node->id + 1)
|
|
{
|
|
/* destroy the actual node if the node to be freed has the
|
|
* highest id */
|
|
hawk_rtx_freemem(rtx, node);
|
|
list->map.high--;
|
|
}
|
|
else
|
|
{
|
|
/* otherwise, chain the node to the free list */
|
|
node->ctx = HAWK_NULL;
|
|
node->next = list->free;
|
|
list->free = node;
|
|
}
|
|
|
|
/* however, i destroy the whole free list when all the nodes are
|
|
* chanined to the free list */
|
|
if (list->head == HAWK_NULL)
|
|
{
|
|
uctx_node_t* curnode;
|
|
|
|
while (list->free)
|
|
{
|
|
curnode = list->free;
|
|
list->free = list->free->next;
|
|
HAWK_ASSERT (curnode->ctx == HAWK_NULL);
|
|
hawk_rtx_freemem (rtx, curnode);
|
|
}
|
|
|
|
hawk_rtx_freemem (rtx, list->map.tab);
|
|
list->map.high = 0;
|
|
list->map.capa = 0;
|
|
list->map.tab = HAWK_NULL;
|
|
}
|
|
}
|
|
|
|
/* ------------------------------------------------------------------------ */
|
|
|
|
static int close_byid (hawk_rtx_t* rtx, uctx_list_t* list, hawk_int_t id)
|
|
{
|
|
int x = UCI_ERR_INVAL;
|
|
|
|
if (id >= 0 && id < list->map.high && list->map.tab[id])
|
|
{
|
|
free_uctx_node (rtx, list, list->map.tab[id]);
|
|
x = UCI_OK;
|
|
}
|
|
|
|
return -x;
|
|
}
|
|
|
|
static int load_byid (hawk_rtx_t* rtx, uctx_list_t* list, hawk_int_t id, hawk_bch_t* path)
|
|
{
|
|
int x = UCI_ERR_INVAL;
|
|
|
|
if (id >= 0 && id < list->map.high && list->map.tab[id])
|
|
{
|
|
x = uci_load(list->map.tab[id]->ctx, path, HAWK_NULL);
|
|
}
|
|
|
|
return -x;
|
|
}
|
|
|
|
static int unload_byid (hawk_rtx_t* rtx, uctx_list_t* list, hawk_int_t id)
|
|
{
|
|
int x = UCI_ERR_INVAL;
|
|
|
|
if (id >= 0 && id < list->map.high && list->map.tab[id])
|
|
{
|
|
x = uci_unload(list->map.tab[id]->ctx, HAWK_NULL);
|
|
return 0;
|
|
}
|
|
|
|
return -x;
|
|
}
|
|
|
|
static int save_byid (hawk_rtx_t* rtx, uctx_list_t* list, hawk_int_t id, hawk_bch_t* item)
|
|
{
|
|
int x = UCI_ERR_INVAL;
|
|
|
|
if (id >= 0 && id < list->map.high && list->map.tab[id])
|
|
{
|
|
struct uci_ptr ptr;
|
|
|
|
x = uci_lookup_ptr(list->map.tab[id]->ctx, &ptr, item, 1);
|
|
if (x == UCI_OK)
|
|
{
|
|
|
|
if (!ptr.value && (ptr.flags & UCI_LOOKUP_COMPLETE) && (ptr.last->type == UCI_TYPE_PACKAGE))
|
|
x = uci_save (list->map.tab[id]->ctx, ptr.p);
|
|
else
|
|
x = UCI_ERR_NOTFOUND;
|
|
}
|
|
}
|
|
|
|
return -x;
|
|
}
|
|
|
|
static int commit_byid (hawk_rtx_t* rtx, uctx_list_t* list, hawk_int_t id, hawk_bch_t* item)
|
|
{
|
|
int x = UCI_ERR_INVAL;
|
|
|
|
if (id >= 0 && id < list->map.high && list->map.tab[id])
|
|
{
|
|
struct uci_ptr ptr;
|
|
|
|
x = uci_lookup_ptr(list->map.tab[id]->ctx, &ptr, item, 1);
|
|
if (x == UCI_OK)
|
|
{
|
|
if (!ptr.value && (ptr.flags & UCI_LOOKUP_COMPLETE) && (ptr.last->type == UCI_TYPE_PACKAGE))
|
|
x = uci_commit (list->map.tab[id]->ctx, &ptr.p, 0);
|
|
else
|
|
x = UCI_ERR_NOTFOUND;
|
|
}
|
|
}
|
|
|
|
return -x;
|
|
}
|
|
|
|
static int revert_byid (hawk_rtx_t* rtx, uctx_list_t* list, hawk_int_t id, hawk_bch_t* item)
|
|
{
|
|
int x = UCI_ERR_INVAL;
|
|
|
|
if (id >= 0 && id < list->map.high && list->map.tab[id])
|
|
{
|
|
struct uci_ptr ptr;
|
|
|
|
x = uci_lookup_ptr(list->map.tab[id]->ctx, &ptr, item, 1);
|
|
if (x == UCI_OK)
|
|
{
|
|
if (!ptr.value && (ptr.flags & UCI_LOOKUP_COMPLETE))
|
|
x = uci_revert (list->map.tab[id]->ctx, &ptr);
|
|
else
|
|
x = UCI_ERR_NOTFOUND;
|
|
}
|
|
}
|
|
|
|
return -x;
|
|
}
|
|
|
|
static int delete_byid (hawk_rtx_t* rtx, uctx_list_t* list, hawk_int_t id, hawk_bch_t* item)
|
|
{
|
|
int x = UCI_ERR_INVAL;
|
|
|
|
if (id >= 0 && id < list->map.high && list->map.tab[id])
|
|
{
|
|
struct uci_ptr ptr;
|
|
|
|
x = uci_lookup_ptr(list->map.tab[id]->ctx, &ptr, item, 1);
|
|
if (x == UCI_OK)
|
|
{
|
|
if (!ptr.value && (ptr.flags & UCI_LOOKUP_COMPLETE))
|
|
x = uci_delete (list->map.tab[id]->ctx, &ptr);
|
|
else
|
|
x = UCI_ERR_NOTFOUND;
|
|
}
|
|
}
|
|
|
|
return -x;
|
|
}
|
|
|
|
static int rename_byid (hawk_rtx_t* rtx, uctx_list_t* list, hawk_int_t id, hawk_bch_t* item)
|
|
{
|
|
int x = UCI_ERR_INVAL;
|
|
|
|
if (id >= 0 && id < list->map.high && list->map.tab[id])
|
|
{
|
|
struct uci_ptr ptr;
|
|
|
|
x = uci_lookup_ptr(list->map.tab[id]->ctx, &ptr, item, 1);
|
|
if (x == UCI_OK)
|
|
{
|
|
if (ptr.value && (ptr.flags & UCI_LOOKUP_COMPLETE))
|
|
x = uci_rename (list->map.tab[id]->ctx, &ptr);
|
|
else
|
|
x = UCI_ERR_NOTFOUND;
|
|
}
|
|
}
|
|
|
|
return -x;
|
|
}
|
|
|
|
static int set_byid (hawk_rtx_t* rtx, uctx_list_t* list, hawk_int_t id, hawk_bch_t* item)
|
|
{
|
|
int x = UCI_ERR_INVAL;
|
|
|
|
if (id >= 0 && id < list->map.high && list->map.tab[id])
|
|
{
|
|
struct uci_ptr ptr;
|
|
|
|
x = uci_lookup_ptr(list->map.tab[id]->ctx, &ptr, item, 1);
|
|
if (x == UCI_OK)
|
|
{
|
|
x = ptr.value? uci_set (list->map.tab[id]->ctx, &ptr): UCI_ERR_INVAL;
|
|
}
|
|
}
|
|
|
|
return -x;
|
|
}
|
|
|
|
static int addsection_byid (hawk_rtx_t* rtx, uctx_list_t* list, hawk_int_t id, hawk_bch_t* item, hawk_bch_t* type)
|
|
{
|
|
int x = UCI_ERR_INVAL;
|
|
|
|
/* TODO: this looks like a wrong implementation */
|
|
if (id >= 0 && id < list->map.high && list->map.tab[id])
|
|
{
|
|
struct uci_ptr ptr;
|
|
|
|
x = uci_lookup_ptr(list->map.tab[id]->ctx, &ptr, item, 1);
|
|
if (x == UCI_OK)
|
|
{
|
|
/* add an unnamed section. use set to add a named section */
|
|
struct uci_section* s = HAWK_NULL;
|
|
if (!ptr.value && (ptr.flags & UCI_LOOKUP_COMPLETE) && (ptr.last->type == UCI_TYPE_PACKAGE))
|
|
{
|
|
x = uci_add_section(list->map.tab[id]->ctx, ptr.p, type, &s);
|
|
}
|
|
else x = UCI_ERR_INVAL;
|
|
}
|
|
}
|
|
|
|
return -x;
|
|
}
|
|
|
|
static int addlist_byid (hawk_rtx_t* rtx, uctx_list_t* list, hawk_int_t id, hawk_bch_t* item)
|
|
{
|
|
int x = UCI_ERR_INVAL;
|
|
|
|
if (id >= 0 && id < list->map.high && list->map.tab[id])
|
|
{
|
|
struct uci_ptr ptr;
|
|
|
|
x = uci_lookup_ptr(list->map.tab[id]->ctx, &ptr, item, 1);
|
|
if (x == UCI_OK)
|
|
{
|
|
x = ptr.value? uci_add_list (list->map.tab[id]->ctx, &ptr): UCI_ERR_INVAL;
|
|
}
|
|
}
|
|
|
|
return -x;
|
|
}
|
|
|
|
static int setconfdir_byid (
|
|
hawk_rtx_t* rtx, uctx_list_t* list, hawk_int_t id, hawk_bch_t* path)
|
|
{
|
|
int x = UCI_ERR_INVAL;
|
|
|
|
if (id >= 0 && id < list->map.high && list->map.tab[id])
|
|
{
|
|
x = uci_set_confdir (list->map.tab[id]->ctx, path);
|
|
}
|
|
|
|
return -x;
|
|
}
|
|
|
|
static int setsavedir_byid (
|
|
hawk_rtx_t* rtx, uctx_list_t* list, hawk_int_t id, hawk_bch_t* path)
|
|
{
|
|
int x = UCI_ERR_INVAL;
|
|
|
|
if (id >= 0 && id < list->map.high && list->map.tab[id])
|
|
{
|
|
x = uci_set_savedir (list->map.tab[id]->ctx, path);
|
|
}
|
|
|
|
return -x;
|
|
}
|
|
|
|
static int adddeltapath_byid (
|
|
hawk_rtx_t* rtx, uctx_list_t* list, hawk_int_t id, hawk_bch_t* path)
|
|
{
|
|
int x = UCI_ERR_INVAL;
|
|
|
|
if (id >= 0 && id < list->map.high && list->map.tab[id])
|
|
{
|
|
x = uci_add_delta_path (list->map.tab[id]->ctx, path);
|
|
}
|
|
|
|
return -x;
|
|
}
|
|
|
|
static int getsection_byid (hawk_rtx_t* rtx, uctx_list_t* list, hawk_int_t id, hawk_bch_t* tuple, hawk_val_ref_t* ref)
|
|
{
|
|
int x = UCI_ERR_INVAL;
|
|
|
|
if (id >= 0 && id < list->map.high && list->map.tab[id])
|
|
{
|
|
struct uci_ptr ptr;
|
|
|
|
x = uci_lookup_ptr(list->map.tab[id]->ctx, &ptr, tuple, 1);
|
|
if (x == UCI_OK)
|
|
{
|
|
/* ptr.value is not null if the tuple specified contains
|
|
assignment like network.wan.ifname=eth0 */
|
|
if (!ptr.value && (ptr.flags & UCI_LOOKUP_COMPLETE))
|
|
{
|
|
struct uci_element* e;
|
|
|
|
e = ptr.last;
|
|
if (e->type == UCI_TYPE_SECTION)
|
|
{
|
|
hawk_val_map_data_t md[3];
|
|
hawk_int_t lv;
|
|
hawk_val_t* tmp;
|
|
|
|
HAWK_MEMSET (md, 0, HAWK_SIZEOF(md));
|
|
|
|
md[0].key.ptr = HAWK_T("type");
|
|
md[0].key.len = 4;
|
|
md[0].type = HAWK_VAL_MAP_DATA_BCSTR;
|
|
md[0].vptr = ptr.s->type;
|
|
|
|
md[1].key.ptr = HAWK_T("name");
|
|
md[1].key.len = 4;
|
|
md[1].type = HAWK_VAL_MAP_DATA_BCSTR;
|
|
md[1].vptr = ptr.s->e.name; /* e->name == ptr.s->e.name */
|
|
|
|
md[2].key.ptr = HAWK_T("anon");
|
|
md[2].key.len = 4;
|
|
md[2].vptr = HAWK_VAL_MAP_DATA_INT;
|
|
lv = ptr.s->anonymous;
|
|
md[2].vptr = &lv;
|
|
|
|
tmp = hawk_rtx_makemapvalwithdata(rtx, md, 3);
|
|
if (tmp)
|
|
{
|
|
int n;
|
|
hawk_rtx_refupval (rtx, tmp);
|
|
n = hawk_rtx_setrefval (rtx, ref, tmp);
|
|
hawk_rtx_refdownval (rtx, tmp);
|
|
if (n <= -1) return -9999;
|
|
}
|
|
else x = UCI_ERR_MEM;
|
|
}
|
|
else x = UCI_ERR_NOTFOUND;
|
|
|
|
}
|
|
else x = UCI_ERR_NOTFOUND;
|
|
}
|
|
}
|
|
|
|
return -x;
|
|
}
|
|
|
|
static int getoption_byid (hawk_rtx_t* rtx, uctx_list_t* list, hawk_int_t id, hawk_bch_t* tuple, hawk_val_ref_t* ref)
|
|
{
|
|
int x = UCI_ERR_INVAL;
|
|
|
|
if (id >= 0 && id < list->map.high && list->map.tab[id])
|
|
{
|
|
struct uci_ptr ptr;
|
|
|
|
x = uci_lookup_ptr(list->map.tab[id]->ctx, &ptr, tuple, 1);
|
|
if (x == UCI_OK)
|
|
{
|
|
/* ptr.value is not null if the tuple specified contains
|
|
assignment like network.wan.ifname=eth0 */
|
|
if (!ptr.value && (ptr.flags & UCI_LOOKUP_COMPLETE))
|
|
{
|
|
struct uci_element* e;
|
|
|
|
e = ptr.last;
|
|
if (e->type == UCI_TYPE_OPTION)
|
|
{
|
|
struct uci_option* uo = ptr.o;
|
|
|
|
if (uo->type == UCI_TYPE_STRING)
|
|
{
|
|
hawk_val_t* map;
|
|
hawk_val_map_data_t md[2];
|
|
|
|
HAWK_MEMSET (md, 0, HAWK_SIZEOF(md));
|
|
|
|
md[0].key.ptr = HAWK_T("type");
|
|
md[0].key.len = 4;
|
|
md[0].type = HAWK_VAL_MAP_DATA_OOCSTR;
|
|
md[0].vptr = HAWK_T("string");
|
|
|
|
md[1].key.ptr = HAWK_T("value");
|
|
md[1].key.len = 5;
|
|
md[1].type = HAWK_VAL_MAP_DATA_BCSTR;
|
|
md[1].vptr = uo->v.string;
|
|
|
|
map = hawk_rtx_makemapvalwithdata(rtx, md, 2);
|
|
if (map)
|
|
{
|
|
int n;
|
|
hawk_rtx_refupval (rtx, map);
|
|
n = hawk_rtx_setrefval(rtx, ref, map);
|
|
hawk_rtx_refdownval (rtx, map);
|
|
if (n <= -1)
|
|
{
|
|
map = HAWK_NULL;
|
|
return -9999;
|
|
}
|
|
}
|
|
else x = UCI_ERR_MEM;
|
|
}
|
|
else if (uo->type == UCI_TYPE_LIST)
|
|
{
|
|
hawk_val_t* map, * fld;
|
|
hawk_val_map_data_t md[2];
|
|
struct uci_element* tmp;
|
|
hawk_int_t count;
|
|
|
|
count = 0;
|
|
uci_foreach_element(&uo->v.list, tmp) { count++; }
|
|
|
|
HAWK_MEMSET (md, 0, HAWK_SIZEOF(md));
|
|
|
|
md[0].key.ptr = HAWK_T("type");
|
|
md[0].key.len = 4;
|
|
md[0].type = HAWK_VAL_MAP_DATA_OOCSTR;
|
|
md[0].vptr = HAWK_T("list");
|
|
|
|
md[1].key.ptr = HAWK_T("count");
|
|
md[1].key.len = 5;
|
|
md[1].type = HAWK_VAL_MAP_DATA_INT;
|
|
md[1].vptr = &count;
|
|
|
|
map = hawk_rtx_makemapvalwithdata(rtx, md, 2);
|
|
if (map)
|
|
{
|
|
count = 1;
|
|
hawk_rtx_refupval (rtx, map);
|
|
|
|
uci_foreach_element(&uo->v.list, tmp)
|
|
{
|
|
const hawk_oocs_t* subsep;
|
|
hawk_oocs_t k[4];
|
|
hawk_ooch_t idxbuf[64];
|
|
hawk_ooch_t* kp;
|
|
hawk_oow_t kl;
|
|
|
|
fld = hawk_rtx_makestrvalwithbcstr(rtx, tmp->name);
|
|
if (!fld)
|
|
{
|
|
hawk_rtx_refdownval (rtx, map);
|
|
map = HAWK_NULL;
|
|
x = UCI_ERR_MEM;
|
|
break;
|
|
}
|
|
|
|
hawk_rtx_refupval (rtx, fld);
|
|
subsep = hawk_rtx_getsubsep(rtx);
|
|
|
|
k[0].ptr = HAWK_T("value");
|
|
k[0].len = 5;
|
|
k[1].ptr = subsep->ptr;
|
|
k[1].len = subsep->len;
|
|
k[2].ptr = idxbuf;
|
|
k[2].len = hawk_fmt_uintmax_to_oocstr(idxbuf, HAWK_COUNTOF(idxbuf), count, 10, -1, HAWK_T('\0'), HAWK_NULL);
|
|
k[3].ptr = HAWK_NULL;
|
|
k[3].len = 0;
|
|
|
|
kp = hawk_rtx_dupoocsarr(rtx, k, &kl);
|
|
if (!kp || hawk_rtx_setmapvalfld(rtx, map, kp, kl, fld) == HAWK_NULL)
|
|
{
|
|
if (kp) hawk_rtx_freemem (rtx, kp);
|
|
hawk_rtx_refdownval (rtx, fld);
|
|
hawk_rtx_refdownval (rtx, map);
|
|
map = HAWK_NULL;
|
|
x = UCI_ERR_MEM;
|
|
break;
|
|
}
|
|
|
|
hawk_rtx_freemem (rtx, kp);
|
|
hawk_rtx_refdownval (rtx, fld);
|
|
count++;
|
|
}
|
|
|
|
if (map)
|
|
{
|
|
int n;
|
|
n = hawk_rtx_setrefval(rtx, ref, map);
|
|
hawk_rtx_refdownval (rtx, map);
|
|
if (n <= -1)
|
|
{
|
|
map = HAWK_NULL;
|
|
return -9999;
|
|
}
|
|
}
|
|
}
|
|
else x = UCI_ERR_MEM;
|
|
}
|
|
else x = UCI_ERR_INVAL; /* uo->type */
|
|
}
|
|
else x = UCI_ERR_NOTFOUND; /* e->type */
|
|
}
|
|
else x = UCI_ERR_NOTFOUND;
|
|
}
|
|
}
|
|
|
|
return -x;
|
|
}
|
|
/* ------------------------------------------------------------------------ */
|
|
|
|
static HAWK_INLINE uctx_list_t* rtx_to_list (hawk_rtx_t* rtx, const hawk_fnc_info_t* fi)
|
|
{
|
|
hawk_rbt_pair_t* pair;
|
|
pair = hawk_rbt_search ((hawk_rbt_t*)fi->mod->ctx, &rtx, HAWK_SIZEOF(rtx));
|
|
HAWK_ASSERT (pair != HAWK_NULL);
|
|
return (uctx_list_t*)HAWK_RBT_VPTR(pair);
|
|
}
|
|
|
|
static int fnc_uci_errno (hawk_rtx_t* rtx, const hawk_fnc_info_t* fi)
|
|
{
|
|
uctx_list_t* list;
|
|
hawk_val_t* retv;
|
|
|
|
list = rtx_to_list (rtx, fi);
|
|
|
|
retv = hawk_rtx_makeintval(rtx, list->errnum);
|
|
if (!retv) return -1;
|
|
|
|
hawk_rtx_setretval (rtx, retv);
|
|
return 0;
|
|
}
|
|
|
|
static hawk_ooch_t* errmsg[] =
|
|
{
|
|
HAWK_T("no error"),
|
|
HAWK_T("out of memory"),
|
|
HAWK_T("invalid data"),
|
|
HAWK_T("not found"),
|
|
HAWK_T("I/O error"),
|
|
HAWK_T("parse error"),
|
|
HAWK_T("duplicate data"),
|
|
HAWK_T("unknown error")
|
|
};
|
|
|
|
static int fnc_uci_errstr (hawk_rtx_t* rtx, const hawk_fnc_info_t* fi)
|
|
{
|
|
uctx_list_t* list;
|
|
hawk_val_t* retv;
|
|
hawk_int_t errnum;
|
|
|
|
list = rtx_to_list (rtx, fi);
|
|
|
|
if (hawk_rtx_getnargs(rtx) <= 0 ||
|
|
hawk_rtx_valtoint(rtx, hawk_rtx_getarg (rtx, 0), &errnum) <= -1)
|
|
{
|
|
errnum = list->errnum;
|
|
}
|
|
|
|
if (errnum < 0 || errnum >= HAWK_COUNTOF(errmsg)) errnum = HAWK_COUNTOF(errmsg) - 1;
|
|
|
|
retv = hawk_rtx_makestrvalwithoocstr(rtx, errmsg[errnum]);
|
|
if (!retv) return -1;
|
|
|
|
hawk_rtx_setretval (rtx, retv);
|
|
return 0;
|
|
}
|
|
|
|
static int fnc_uci_open (hawk_rtx_t* rtx, const hawk_fnc_info_t* fi)
|
|
{
|
|
uctx_list_t* list;
|
|
uctx_node_t* node;
|
|
hawk_int_t ret;
|
|
hawk_val_t* retv;
|
|
|
|
list = rtx_to_list (rtx, fi);
|
|
node = new_uctx_node (rtx, list);
|
|
ret = node? node->id: -UCI_ERR_MEM;
|
|
|
|
if (ret <= -1)
|
|
{
|
|
list->errnum = -ret;
|
|
ret = -1;
|
|
}
|
|
|
|
retv = hawk_rtx_makeintval(rtx, ret);
|
|
if (!retv) return -1;
|
|
|
|
hawk_rtx_setretval (rtx, retv);
|
|
return 0;
|
|
}
|
|
|
|
static int fnc_uci_close (hawk_rtx_t* rtx, const hawk_fnc_info_t* fi)
|
|
{
|
|
uctx_list_t* list;
|
|
hawk_val_t* retv;
|
|
hawk_int_t id;
|
|
int ret;
|
|
|
|
list = rtx_to_list (rtx, fi);
|
|
|
|
ret = hawk_rtx_valtoint(rtx, hawk_rtx_getarg (rtx, 0), &id);
|
|
if (ret <= -1) ret = -UCI_ERR_INVAL;
|
|
else ret = close_byid(rtx, list, id);
|
|
|
|
if (ret <= -1)
|
|
{
|
|
list->errnum = -ret;
|
|
ret = -1;
|
|
}
|
|
|
|
retv = hawk_rtx_makeintval(rtx, ret);
|
|
if (!retv) return -1;
|
|
|
|
hawk_rtx_setretval (rtx, retv);
|
|
return 0;
|
|
}
|
|
|
|
static int fnc_uci_load (hawk_rtx_t* rtx, const hawk_fnc_info_t* fi)
|
|
{
|
|
uctx_list_t* list;
|
|
hawk_val_t* retv;
|
|
hawk_int_t id;
|
|
int ret;
|
|
|
|
list = rtx_to_list (rtx, fi);
|
|
|
|
ret = hawk_rtx_valtoint (rtx, hawk_rtx_getarg (rtx, 0), &id);
|
|
if (ret <= -1) ret = -UCI_ERR_INVAL;
|
|
else
|
|
{
|
|
hawk_bch_t* item;
|
|
|
|
item = hawk_rtx_valtobcstrdup(rtx, hawk_rtx_getarg(rtx, 1), HAWK_NULL);
|
|
if (item)
|
|
{
|
|
ret = load_byid(rtx, list, id, item);
|
|
hawk_rtx_freemem (rtx, item);
|
|
}
|
|
else ret = -UCI_ERR_MEM;
|
|
}
|
|
|
|
if (ret <= -1)
|
|
{
|
|
list->errnum = -ret;
|
|
ret = -1;
|
|
}
|
|
|
|
retv = hawk_rtx_makeintval(rtx, ret);
|
|
if (!retv) return -1;
|
|
|
|
hawk_rtx_setretval (rtx, retv);
|
|
return 0;
|
|
}
|
|
|
|
static int fnc_uci_unload (hawk_rtx_t* rtx, const hawk_fnc_info_t* fi)
|
|
{
|
|
uctx_list_t* list;
|
|
hawk_val_t* retv;
|
|
hawk_int_t id;
|
|
int ret;
|
|
|
|
list = rtx_to_list (rtx, fi);
|
|
|
|
ret = hawk_rtx_valtoint (rtx, hawk_rtx_getarg (rtx, 0), &id);
|
|
if (ret <= -1) ret = -UCI_ERR_INVAL;
|
|
else ret = unload_byid(rtx, list, id);
|
|
|
|
if (ret <= -1)
|
|
{
|
|
list->errnum = -ret;
|
|
ret = -1;
|
|
}
|
|
|
|
retv = hawk_rtx_makeintval(rtx, ret);
|
|
if (!retv) return -1;
|
|
|
|
hawk_rtx_setretval (rtx, retv);
|
|
return 0;
|
|
}
|
|
|
|
static int fnc_uci_save (hawk_rtx_t* rtx, const hawk_fnc_info_t* fi)
|
|
{
|
|
uctx_list_t* list;
|
|
hawk_val_t* retv;
|
|
hawk_int_t id;
|
|
int ret;
|
|
|
|
list = rtx_to_list (rtx, fi);
|
|
|
|
ret = hawk_rtx_valtoint (rtx, hawk_rtx_getarg (rtx, 0), &id);
|
|
if (ret <= -1) ret = -UCI_ERR_INVAL;
|
|
else
|
|
{
|
|
hawk_bch_t* item;
|
|
|
|
item = hawk_rtx_valtobcstrdup(rtx, hawk_rtx_getarg(rtx, 1), HAWK_NULL);
|
|
if (item)
|
|
{
|
|
ret = save_byid(rtx, list, id, item);
|
|
hawk_rtx_freemem (rtx, item);
|
|
}
|
|
else ret = -UCI_ERR_MEM;
|
|
}
|
|
|
|
if (ret <= -1)
|
|
{
|
|
list->errnum = -ret;
|
|
ret = -1;
|
|
}
|
|
|
|
retv = hawk_rtx_makeintval(rtx, ret);
|
|
if (!retv) return -1;
|
|
|
|
hawk_rtx_setretval (rtx, retv);
|
|
return 0;
|
|
}
|
|
|
|
static int fnc_uci_commit (hawk_rtx_t* rtx, const hawk_fnc_info_t* fi)
|
|
{
|
|
uctx_list_t* list;
|
|
hawk_val_t* retv;
|
|
hawk_int_t id;
|
|
int ret;
|
|
|
|
list = rtx_to_list (rtx, fi);
|
|
|
|
ret = hawk_rtx_valtoint (rtx, hawk_rtx_getarg (rtx, 0), &id);
|
|
if (ret <= -1) ret = -UCI_ERR_INVAL;
|
|
else
|
|
{
|
|
hawk_bch_t* item;
|
|
|
|
item = hawk_rtx_valtobcstrdup(rtx, hawk_rtx_getarg(rtx, 1), HAWK_NULL);
|
|
if (item)
|
|
{
|
|
ret = commit_byid(rtx, list, id, item);
|
|
hawk_rtx_freemem (rtx, item);
|
|
}
|
|
else ret = -UCI_ERR_MEM;
|
|
}
|
|
|
|
if (ret <= -1)
|
|
{
|
|
list->errnum = -ret;
|
|
ret = -1;
|
|
}
|
|
|
|
retv = hawk_rtx_makeintval(rtx, ret);
|
|
if (!retv) return -1;
|
|
|
|
hawk_rtx_setretval (rtx, retv);
|
|
return 0;
|
|
}
|
|
|
|
static int fnc_uci_revert (hawk_rtx_t* rtx, const hawk_fnc_info_t* fi)
|
|
{
|
|
uctx_list_t* list;
|
|
hawk_val_t* retv;
|
|
hawk_int_t id;
|
|
int ret;
|
|
|
|
list = rtx_to_list (rtx, fi);
|
|
|
|
ret = hawk_rtx_valtoint (rtx, hawk_rtx_getarg (rtx, 0), &id);
|
|
if (ret <= -1) ret = -UCI_ERR_INVAL;
|
|
else
|
|
{
|
|
hawk_bch_t* item;
|
|
|
|
item = hawk_rtx_valtobcstrdup(rtx, hawk_rtx_getarg(rtx, 1), HAWK_NULL);
|
|
if (item)
|
|
{
|
|
ret = revert_byid(rtx, list, id, item);
|
|
hawk_rtx_freemem (rtx, item);
|
|
}
|
|
else ret = -UCI_ERR_MEM;
|
|
}
|
|
|
|
if (ret <= -1)
|
|
{
|
|
list->errnum = -ret;
|
|
ret = -1;
|
|
}
|
|
|
|
retv = hawk_rtx_makeintval(rtx, ret);
|
|
if (!retv) return -1;
|
|
|
|
hawk_rtx_setretval (rtx, retv);
|
|
return 0;
|
|
}
|
|
|
|
static int fnc_uci_delete (hawk_rtx_t* rtx, const hawk_fnc_info_t* fi)
|
|
{
|
|
uctx_list_t* list;
|
|
hawk_val_t* retv;
|
|
hawk_int_t id;
|
|
int ret;
|
|
|
|
list = rtx_to_list (rtx, fi);
|
|
|
|
ret = hawk_rtx_valtoint (rtx, hawk_rtx_getarg (rtx, 0), &id);
|
|
if (ret <= -1) ret = -UCI_ERR_INVAL;
|
|
else
|
|
{
|
|
hawk_bch_t* item;
|
|
|
|
item = hawk_rtx_valtobcstrdup(rtx, hawk_rtx_getarg(rtx, 1), HAWK_NULL);
|
|
if (item)
|
|
{
|
|
ret = delete_byid(rtx, list, id, item);
|
|
hawk_rtx_freemem (rtx, item);
|
|
}
|
|
else ret = -UCI_ERR_MEM;
|
|
}
|
|
|
|
if (ret <= -1)
|
|
{
|
|
list->errnum = -ret;
|
|
ret = -1;
|
|
}
|
|
|
|
retv = hawk_rtx_makeintval(rtx, ret);
|
|
if (!retv) return -1;
|
|
|
|
hawk_rtx_setretval (rtx, retv);
|
|
return 0;
|
|
}
|
|
|
|
static int fnc_uci_rename (hawk_rtx_t* rtx, const hawk_fnc_info_t* fi)
|
|
{
|
|
uctx_list_t* list;
|
|
hawk_val_t* retv;
|
|
hawk_int_t id;
|
|
int ret;
|
|
|
|
list = rtx_to_list (rtx, fi);
|
|
|
|
ret = hawk_rtx_valtoint (rtx, hawk_rtx_getarg (rtx, 0), &id);
|
|
if (ret <= -1) ret = -UCI_ERR_INVAL;
|
|
else
|
|
{
|
|
hawk_bch_t* item;
|
|
|
|
item = hawk_rtx_valtobcstrdup(rtx, hawk_rtx_getarg(rtx, 1), HAWK_NULL);
|
|
if (item)
|
|
{
|
|
ret = rename_byid(rtx, list, id, item);
|
|
hawk_rtx_freemem (rtx, item);
|
|
}
|
|
else ret = -UCI_ERR_MEM;
|
|
}
|
|
|
|
if (ret <= -1)
|
|
{
|
|
list->errnum = -ret;
|
|
ret = -1;
|
|
}
|
|
|
|
retv = hawk_rtx_makeintval(rtx, ret);
|
|
if (!retv) return -1;
|
|
|
|
hawk_rtx_setretval (rtx, retv);
|
|
return 0;
|
|
}
|
|
|
|
static int fnc_uci_set (hawk_rtx_t* rtx, const hawk_fnc_info_t* fi)
|
|
{
|
|
uctx_list_t* list;
|
|
hawk_val_t* retv;
|
|
hawk_int_t id;
|
|
int ret;
|
|
|
|
list = rtx_to_list (rtx, fi);
|
|
|
|
ret = hawk_rtx_valtoint (rtx, hawk_rtx_getarg (rtx, 0), &id);
|
|
if (ret <= -1) ret = -UCI_ERR_INVAL;
|
|
else
|
|
{
|
|
hawk_bch_t* item;
|
|
|
|
item = hawk_rtx_valtobcstrdup(rtx, hawk_rtx_getarg(rtx, 1), HAWK_NULL);
|
|
if (item)
|
|
{
|
|
ret = set_byid(rtx, list, id, item);
|
|
hawk_rtx_freemem (rtx, item);
|
|
}
|
|
else ret = -UCI_ERR_MEM;
|
|
}
|
|
|
|
if (ret <= -1)
|
|
{
|
|
list->errnum = -ret;
|
|
ret = -1;
|
|
}
|
|
|
|
retv = hawk_rtx_makeintval(rtx, ret);
|
|
if (!retv) return -1;
|
|
|
|
hawk_rtx_setretval (rtx, retv);
|
|
return 0;
|
|
}
|
|
|
|
static int fnc_uci_addsection (hawk_rtx_t* rtx, const hawk_fnc_info_t* fi)
|
|
{
|
|
uctx_list_t* list;
|
|
hawk_val_t* retv;
|
|
hawk_int_t id;
|
|
int ret;
|
|
|
|
list = rtx_to_list (rtx, fi);
|
|
|
|
ret = hawk_rtx_valtoint (rtx, hawk_rtx_getarg (rtx, 0), &id);
|
|
if (ret <= -1) ret = -UCI_ERR_INVAL;
|
|
else
|
|
{
|
|
hawk_bch_t* item, * type;
|
|
|
|
item = hawk_rtx_valtobcstrdup(rtx, hawk_rtx_getarg(rtx, 1), HAWK_NULL);
|
|
type = hawk_rtx_valtobcstrdup(rtx, hawk_rtx_getarg(rtx, 2), HAWK_NULL);
|
|
if (item && type)
|
|
{
|
|
ret = addsection_byid(rtx, list, id, item, type);
|
|
}
|
|
else ret = -UCI_ERR_MEM;
|
|
|
|
if (type) hawk_rtx_freemem (rtx, type);
|
|
if (item) hawk_rtx_freemem (rtx, item);
|
|
}
|
|
|
|
if (ret <= -1)
|
|
{
|
|
list->errnum = -ret;
|
|
ret = -1;
|
|
}
|
|
|
|
retv = hawk_rtx_makeintval(rtx, ret);
|
|
if (!retv) return -1;
|
|
|
|
hawk_rtx_setretval (rtx, retv);
|
|
return 0;
|
|
}
|
|
|
|
static int fnc_uci_addlist (hawk_rtx_t* rtx, const hawk_fnc_info_t* fi)
|
|
{
|
|
uctx_list_t* list;
|
|
hawk_val_t* retv;
|
|
hawk_int_t id;
|
|
int ret;
|
|
|
|
list = rtx_to_list (rtx, fi);
|
|
|
|
ret = hawk_rtx_valtoint (rtx, hawk_rtx_getarg (rtx, 0), &id);
|
|
if (ret <= -1) ret = -UCI_ERR_INVAL;
|
|
else
|
|
{
|
|
hawk_bch_t* item;
|
|
|
|
item = hawk_rtx_valtobcstrdup(rtx, hawk_rtx_getarg(rtx, 1), HAWK_NULL);
|
|
if (item)
|
|
{
|
|
ret = addlist_byid(rtx, list, id, item);
|
|
hawk_rtx_freemem (rtx, item);
|
|
}
|
|
else ret = -UCI_ERR_MEM;
|
|
}
|
|
|
|
if (ret <= -1)
|
|
{
|
|
list->errnum = -ret;
|
|
ret = -1;
|
|
}
|
|
|
|
retv = hawk_rtx_makeintval(rtx, ret);
|
|
if (!retv) return -1;
|
|
|
|
hawk_rtx_setretval (rtx, retv);
|
|
return 0;
|
|
}
|
|
|
|
static int fnc_uci_setconfdir (hawk_rtx_t* rtx, const hawk_fnc_info_t* fi)
|
|
{
|
|
uctx_list_t* list;
|
|
hawk_val_t* retv;
|
|
hawk_int_t id;
|
|
int ret;
|
|
|
|
list = rtx_to_list (rtx, fi);
|
|
|
|
ret = hawk_rtx_valtoint (rtx, hawk_rtx_getarg (rtx, 0), &id);
|
|
if (ret <= -1) ret = -UCI_ERR_INVAL;
|
|
else
|
|
{
|
|
hawk_bch_t* item;
|
|
|
|
item = hawk_rtx_valtobcstrdup(rtx, hawk_rtx_getarg(rtx, 1), HAWK_NULL);
|
|
if (item)
|
|
{
|
|
ret = setconfdir_byid(rtx, list, id, item);
|
|
hawk_rtx_freemem (rtx, item);
|
|
}
|
|
else ret = -UCI_ERR_MEM;
|
|
}
|
|
|
|
if (ret <= -1)
|
|
{
|
|
list->errnum = -ret;
|
|
ret = -1;
|
|
}
|
|
|
|
retv = hawk_rtx_makeintval(rtx, ret);
|
|
if (!retv) return -1;
|
|
|
|
hawk_rtx_setretval (rtx, retv);
|
|
return 0;
|
|
}
|
|
|
|
|
|
static int fnc_uci_setsavedir (hawk_rtx_t* rtx, const hawk_fnc_info_t* fi)
|
|
{
|
|
uctx_list_t* list;
|
|
hawk_val_t* retv;
|
|
hawk_int_t id;
|
|
int ret;
|
|
|
|
list = rtx_to_list (rtx, fi);
|
|
|
|
ret = hawk_rtx_valtoint (rtx, hawk_rtx_getarg (rtx, 0), &id);
|
|
if (ret <= -1) ret = -UCI_ERR_INVAL;
|
|
else
|
|
{
|
|
hawk_bch_t* item;
|
|
|
|
item = hawk_rtx_valtobcstrdup(rtx, hawk_rtx_getarg(rtx, 1), HAWK_NULL);
|
|
if (item)
|
|
{
|
|
ret = setsavedir_byid(rtx, list, id, item);
|
|
hawk_rtx_freemem (rtx, item);
|
|
}
|
|
else ret = -UCI_ERR_MEM;
|
|
}
|
|
|
|
if (ret <= -1)
|
|
{
|
|
list->errnum = -ret;
|
|
ret = -1;
|
|
}
|
|
|
|
retv = hawk_rtx_makeintval(rtx, ret);
|
|
if (!retv) return -1;
|
|
|
|
hawk_rtx_setretval (rtx, retv);
|
|
return 0;
|
|
}
|
|
|
|
static int fnc_uci_adddeltapath (hawk_rtx_t* rtx, const hawk_fnc_info_t* fi)
|
|
{
|
|
uctx_list_t* list;
|
|
hawk_val_t* retv;
|
|
hawk_int_t id;
|
|
int ret;
|
|
|
|
list = rtx_to_list (rtx, fi);
|
|
|
|
ret = hawk_rtx_valtoint (rtx, hawk_rtx_getarg (rtx, 0), &id);
|
|
if (ret <= -1) ret = -UCI_ERR_INVAL;
|
|
else
|
|
{
|
|
hawk_bch_t* item;
|
|
|
|
item = hawk_rtx_valtobcstrdup(rtx, hawk_rtx_getarg(rtx, 1), HAWK_NULL);
|
|
if (item)
|
|
{
|
|
ret = adddeltapath_byid(rtx, list, id, item);
|
|
hawk_rtx_freemem (rtx, item);
|
|
}
|
|
else ret = -UCI_ERR_MEM;
|
|
}
|
|
|
|
if (ret <= -1)
|
|
{
|
|
list->errnum = -ret;
|
|
ret = -1;
|
|
}
|
|
|
|
retv = hawk_rtx_makeintval(rtx, ret);
|
|
if (!retv) return -1;
|
|
|
|
hawk_rtx_setretval (rtx, retv);
|
|
return 0;
|
|
}
|
|
|
|
static int fnc_uci_getoption (hawk_rtx_t* rtx, const hawk_fnc_info_t* fi)
|
|
{
|
|
uctx_list_t* list;
|
|
hawk_int_t id;
|
|
int ret;
|
|
|
|
list = rtx_to_list (rtx, fi);
|
|
|
|
ret = hawk_rtx_valtoint (rtx, hawk_rtx_getarg (rtx, 0), &id);
|
|
if (ret <= -1) ret = -UCI_ERR_INVAL;
|
|
else
|
|
{
|
|
hawk_bch_t* item;
|
|
|
|
item = hawk_rtx_valtobcstrdup(rtx, hawk_rtx_getarg(rtx, 1), HAWK_NULL);
|
|
if (item)
|
|
{
|
|
ret = getoption_byid(rtx, list, id, item, (hawk_val_ref_t*)hawk_rtx_getarg(rtx, 2));
|
|
hawk_rtx_freemem (rtx, item);
|
|
if (ret == -9999) return -1;
|
|
}
|
|
else ret = -UCI_ERR_MEM;
|
|
}
|
|
|
|
if (ret <= -1)
|
|
{
|
|
list->errnum = -ret;
|
|
ret = -1;
|
|
}
|
|
else ret = 0;
|
|
|
|
hawk_rtx_setretval (rtx, hawk_rtx_makeintval(rtx, ret));
|
|
return 0;
|
|
}
|
|
|
|
static int fnc_uci_getsection (hawk_rtx_t* rtx, const hawk_fnc_info_t* fi)
|
|
{
|
|
uctx_list_t* list;
|
|
hawk_int_t id;
|
|
int ret;
|
|
|
|
list = rtx_to_list (rtx, fi);
|
|
|
|
ret = hawk_rtx_valtoint(rtx, hawk_rtx_getarg(rtx, 0), &id);
|
|
if (ret <= -1) ret = -UCI_ERR_INVAL;
|
|
else
|
|
{
|
|
hawk_bch_t* item;
|
|
|
|
item = hawk_rtx_valtobcstrdup(rtx, hawk_rtx_getarg(rtx, 1), HAWK_NULL);
|
|
if (item)
|
|
{
|
|
ret = getsection_byid(rtx, list, id, item, (hawk_val_ref_t*)hawk_rtx_getarg(rtx, 2));
|
|
hawk_rtx_freemem (rtx, item);
|
|
if (ret == -9999) return -1;
|
|
}
|
|
else ret = -UCI_ERR_MEM;
|
|
}
|
|
|
|
if (ret <= -1)
|
|
{
|
|
list->errnum = -ret;
|
|
ret = -1;
|
|
}
|
|
else ret = 0;
|
|
|
|
hawk_rtx_setretval (rtx, hawk_rtx_makeintval(rtx, ret));
|
|
return 0;
|
|
}
|
|
|
|
/* ------------------------------------------------------------------------ */
|
|
|
|
static hawk_mod_fnc_tab_t fnctab[] =
|
|
{
|
|
{ HAWK_T("adddeltapath"), { { 2, 2, HAWK_NULL }, fnc_uci_adddeltapath, 0 } },
|
|
{ HAWK_T("addlist"), { { 2, 2, HAWK_NULL }, fnc_uci_addlist, 0 } },
|
|
{ HAWK_T("addsection"), { { 3, 3, HAWK_NULL }, fnc_uci_addsection, 0 } },
|
|
{ HAWK_T("close"), { { 1, 1, HAWK_NULL }, fnc_uci_close, 0 } },
|
|
{ HAWK_T("commit"), { { 2, 2, HAWK_NULL }, fnc_uci_commit, 0 } },
|
|
{ HAWK_T("delete"), { { 2, 2, HAWK_NULL }, fnc_uci_delete, 0 } },
|
|
{ HAWK_T("errno"), { { 0, 0, HAWK_NULL }, fnc_uci_errno, 0 } },
|
|
{ HAWK_T("errstr"), { { 0, 1, HAWK_NULL }, fnc_uci_errstr, 0 } },
|
|
{ HAWK_T("getoption"), { { 3, 3, HAWK_T("vvr")}, fnc_uci_getoption, 0 } },
|
|
{ HAWK_T("getsection"), { { 3, 3, HAWK_T("vvr")}, fnc_uci_getsection, 0 } },
|
|
{ HAWK_T("load"), { { 2, 2, HAWK_NULL }, fnc_uci_load, 0 } },
|
|
{ HAWK_T("open"), { { 0, 0, HAWK_NULL }, fnc_uci_open, 0 } },
|
|
{ HAWK_T("rename"), { { 2, 2, HAWK_NULL }, fnc_uci_rename, 0 } },
|
|
{ HAWK_T("revert"), { { 2, 2, HAWK_NULL }, fnc_uci_revert, 0 } },
|
|
{ HAWK_T("save"), { { 2, 2, HAWK_NULL }, fnc_uci_save, 0 } },
|
|
{ HAWK_T("set"), { { 2, 2, HAWK_NULL }, fnc_uci_set, 0 } },
|
|
{ HAWK_T("setconfdir"), { { 2, 2, HAWK_NULL }, fnc_uci_setconfdir, 0 } },
|
|
{ HAWK_T("setsavedir"), { { 2, 2, HAWK_NULL }, fnc_uci_setsavedir, 0 } },
|
|
{ HAWK_T("unload"), { { 1, 1, HAWK_NULL }, fnc_uci_unload, 0 } }
|
|
};
|
|
|
|
/* ------------------------------------------------------------------------ */
|
|
|
|
static int query (hawk_mod_t* mod, hawk_t* hawk, const hawk_ooch_t* name, hawk_mod_sym_t* sym)
|
|
{
|
|
return hawk_findmodsymfnc(hawk, fnctab, HAWK_COUNTOF(fnctab), name, sym);
|
|
}
|
|
|
|
static int init (hawk_mod_t* mod, hawk_rtx_t* rtx)
|
|
{
|
|
hawk_rbt_t* rbt;
|
|
uctx_list_t list;
|
|
|
|
rbt = (hawk_rbt_t*)mod->ctx;
|
|
|
|
HAWK_MEMSET (&list, 0, HAWK_SIZEOF(list));
|
|
if (hawk_rbt_insert(rbt, &rtx, HAWK_SIZEOF(rtx), &list, HAWK_SIZEOF(list)) == HAWK_NULL)
|
|
{
|
|
hawk_rtx_seterrnum (rtx, HAWK_NULL, HAWK_ENOMEM);
|
|
return -1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static void fini (hawk_mod_t* mod, hawk_rtx_t* rtx)
|
|
{
|
|
hawk_rbt_t* rbt;
|
|
hawk_rbt_pair_t* pair;
|
|
|
|
rbt = (hawk_rbt_t*)mod->ctx;
|
|
|
|
/* garbage clean-up */
|
|
pair = hawk_rbt_search (rbt, &rtx, HAWK_SIZEOF(rtx));
|
|
if (pair)
|
|
{
|
|
uctx_list_t* list;
|
|
uctx_node_t* node, * next;
|
|
|
|
list = HAWK_RBT_VPTR(pair);
|
|
node = list->head;
|
|
while (node)
|
|
{
|
|
next = node->next;
|
|
free_uctx_node (rtx, list, node);
|
|
node = next;
|
|
}
|
|
|
|
hawk_rbt_delete (rbt, &rtx, HAWK_SIZEOF(rtx));
|
|
}
|
|
}
|
|
|
|
static void unload (hawk_mod_t* mod, hawk_t* hawk)
|
|
{
|
|
hawk_rbt_t* rbt;
|
|
|
|
rbt = (hawk_rbt_t*)mod->ctx;
|
|
|
|
HAWK_ASSERT (HAWK_RBT_SIZE(rbt) == 0);
|
|
hawk_rbt_close (rbt);
|
|
}
|
|
|
|
int hawk_mod_uci (hawk_mod_t* mod, hawk_t* hawk)
|
|
{
|
|
hawk_rbt_t* rbt;
|
|
|
|
mod->query = query;
|
|
mod->unload = unload;
|
|
|
|
mod->init = init;
|
|
mod->fini = fini;
|
|
|
|
rbt = hawk_rbt_open(hawk_getgem(hawk), 0, 1, 1);
|
|
if (!rbt) return -1;
|
|
|
|
hawk_rbt_setstyle (rbt, hawk_get_rbt_style(HAWK_RBT_STYLE_INLINE_COPIERS));
|
|
|
|
mod->ctx = rbt;
|
|
return 0;
|
|
}
|
|
|