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;
 | |
| }
 | |
| 
 |