From: Felix Fietkau Date: Sun, 20 Jan 2008 15:10:32 +0000 (+0100) Subject: better config file handling X-Git-Url: http://git.archive.openwrt.org/?p=project%2Fuci.git;a=commitdiff_plain;h=f57d582f15c0ead3b600cb999ca298390957f597 better config file handling --- diff --git a/Makefile b/Makefile index bf194d1..b33f6fa 100644 --- a/Makefile +++ b/Makefile @@ -5,8 +5,8 @@ all: parsetest parsetest: libuci.o test.o $(CC) $(CFLAGS) -o $@ $^ -libuci.o: libuci.c parse.c libuci.h list.c err.h -test.o: test.c libuci.h +libuci.o: libuci.c parse.c uci.h list.c err.h +test.o: test.c uci.h clean: rm -f parsetest *.o diff --git a/libuci.c b/libuci.c index 4dfffff..262ca69 100644 --- a/libuci.c +++ b/libuci.c @@ -21,7 +21,7 @@ #include #include #include -#include "libuci.h" +#include "uci.h" #define DEBUG #include "err.h" @@ -31,6 +31,7 @@ static const char *uci_errstr[] = { [UCI_ERR_MEM] = "Out of memory", [UCI_ERR_INVAL] = "Invalid argument", [UCI_ERR_NOTFOUND] = "Entry not found", + [UCI_ERR_IO] = "I/O error", [UCI_ERR_PARSE] = "Parse error", [UCI_ERR_UNKNOWN] = "Unknown error", }; diff --git a/libuci.h b/libuci.h deleted file mode 100644 index de96f45..0000000 --- a/libuci.h +++ /dev/null @@ -1,139 +0,0 @@ -/* - * libuci - Library for the Unified Configuration Interface - * Copyright (C) 2008 Felix Fietkau - * - * this program is free software; you can redistribute it and/or modify - * it under the terms of the gnu lesser general public license version 2.1 - * as published by the free software foundation - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#ifndef __LIBUCI_H -#define __LIBUCI_H - -#include -#include - -enum -{ - UCI_OK = 0, - UCI_ERR_MEM, - UCI_ERR_INVAL, - UCI_ERR_NOTFOUND, - UCI_ERR_PARSE, - UCI_ERR_UNKNOWN, - UCI_ERR_LAST -}; - -struct uci_list -{ - void *next; - void *prev; -}; - -struct uci_config; -struct uci_section; -struct uci_option; -struct uci_parse_context; - - -/** - * uci_alloc: Allocate a new uci context - */ -extern struct uci_context *uci_alloc(void); - -/** - * uci_perror: Print the last uci error that occured - * @ctx: uci context - * @str: string to print before the error message - */ -extern void uci_perror(struct uci_context *ctx, const char *str); - -/** - * uci_parse: Parse an uci config file and store it in the uci context - * - * @ctx: uci context - * @name: name of the config file (relative to the config directory) - */ -int uci_parse(struct uci_context *ctx, const char *name); - -/** - * uci_cleanup: Clean up after an error - * - * @ctx: uci context - */ -int uci_cleanup(struct uci_context *ctx); - - -/* UCI data structures */ - -struct uci_context -{ - struct uci_list root; - - /* for error handling only */ - struct uci_parse_context *pctx; - - /* private: */ - int errno; - jmp_buf trap; - jmp_buf trap_saved; - int saved; -}; - -struct uci_parse_context -{ - int line; - int byte; - - /* private: */ - struct uci_config *cfg; - FILE *file; - char *buf; - int bufsz; -}; - -struct uci_config -{ - struct uci_list list; - struct uci_list sections; - struct uci_context *ctx; - char *name; -}; - -struct uci_section -{ - struct uci_list list; - struct uci_list options; - struct uci_config *config; - char *type; - char *name; -}; - -struct uci_option -{ - struct uci_list list; - struct uci_section *section; - char *name; - char *value; -}; - -/* linked list handling */ -#ifndef offsetof -#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER) -#endif - -#define uci_list_empty(list) (list->next == ptr) -#define uci_list_entry(_type, _ptr) \ - ((struct uci_ ## _type *) ((char *)(_ptr) - offsetof(struct uci_ ## _type,list))) - -#define uci_foreach_entry(_type, _list, _ptr) \ - for(_ptr = uci_list_entry(_type, (_list)->next); \ - &_ptr->list != (_list); \ - _ptr = uci_list_entry(_type, _ptr->list.next)) - -#endif diff --git a/parse.c b/parse.c index 9dd7126..5fc4661 100644 --- a/parse.c +++ b/parse.c @@ -16,6 +16,7 @@ * This file contains the code for parsing uci config files */ +#include #include #define LINEBUF 128 @@ -267,9 +268,11 @@ static void uci_parse_line(struct uci_context *ctx) } } -int uci_parse(struct uci_context *ctx, const char *name) +int uci_load(struct uci_context *ctx, const char *name) { struct uci_parse_context *pctx; + struct stat statbuf; + char *filename; UCI_HANDLE_ERR(ctx); UCI_ASSERT(ctx, name != NULL); @@ -280,11 +283,26 @@ int uci_parse(struct uci_context *ctx, const char *name) pctx = (struct uci_parse_context *) uci_malloc(ctx, sizeof(struct uci_parse_context)); ctx->pctx = pctx; - /* TODO: use /etc/config/ */ - pctx->file = fopen(name, "r"); - if (!pctx->file) + switch (name[0]) { + case '.': + case '/': + /* absolute/relative path outside of /etc/config */ + filename = (char *) name; + break; + default: + filename = uci_malloc(ctx, strlen(name) + sizeof(UCI_CONFDIR) + 2); + sprintf(filename, UCI_CONFDIR "/%s", name); + break; + } + + if ((stat(filename, &statbuf) < 0) || + ((statbuf.st_mode & S_IFMT) != S_IFREG)) UCI_THROW(ctx, UCI_ERR_NOTFOUND); + pctx->file = fopen(filename, "r"); + if (!pctx->file) + UCI_THROW(ctx, UCI_ERR_IO); + pctx->cfg = uci_alloc_file(ctx, name); while (!feof(pctx->file)) { diff --git a/test.c b/test.c index 53b2a6a..caf773b 100644 --- a/test.c +++ b/test.c @@ -10,7 +10,7 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. */ -#include "libuci.h" +#include "uci.h" int main(int argc, char **argv) { @@ -21,7 +21,7 @@ int main(int argc, char **argv) return 1; } - if (uci_parse(ctx, argv[1])) { + if (uci_load(ctx, argv[1])) { uci_perror(ctx, "uci_parse"); return 1; } diff --git a/uci.h b/uci.h new file mode 100644 index 0000000..4706255 --- /dev/null +++ b/uci.h @@ -0,0 +1,142 @@ +/* + * libuci - Library for the Unified Configuration Interface + * Copyright (C) 2008 Felix Fietkau + * + * this program is free software; you can redistribute it and/or modify + * it under the terms of the gnu lesser general public license version 2.1 + * as published by the free software foundation + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef __LIBUCI_H +#define __LIBUCI_H + +#include +#include + +#define UCI_CONFDIR "/etc/config" + +enum +{ + UCI_OK = 0, + UCI_ERR_MEM, + UCI_ERR_INVAL, + UCI_ERR_NOTFOUND, + UCI_ERR_IO, + UCI_ERR_PARSE, + UCI_ERR_UNKNOWN, + UCI_ERR_LAST +}; + +struct uci_list +{ + void *next; + void *prev; +}; + +struct uci_config; +struct uci_section; +struct uci_option; +struct uci_parse_context; + + +/** + * uci_alloc: Allocate a new uci context + */ +extern struct uci_context *uci_alloc(void); + +/** + * uci_perror: Print the last uci error that occured + * @ctx: uci context + * @str: string to print before the error message + */ +extern void uci_perror(struct uci_context *ctx, const char *str); + +/** + * uci_load: Parse an uci config file and store it in the uci context + * + * @ctx: uci context + * @name: name of the config file (relative to the config directory) + */ +int uci_load(struct uci_context *ctx, const char *name); + +/** + * uci_cleanup: Clean up after an error + * + * @ctx: uci context + */ +int uci_cleanup(struct uci_context *ctx); + + +/* UCI data structures */ + +struct uci_context +{ + struct uci_list root; + + /* for error handling only */ + struct uci_parse_context *pctx; + + /* private: */ + int errno; + jmp_buf trap; + jmp_buf trap_saved; + int saved; +}; + +struct uci_parse_context +{ + int line; + int byte; + + /* private: */ + struct uci_config *cfg; + FILE *file; + char *buf; + int bufsz; +}; + +struct uci_config +{ + struct uci_list list; + struct uci_list sections; + struct uci_context *ctx; + char *name; +}; + +struct uci_section +{ + struct uci_list list; + struct uci_list options; + struct uci_config *config; + char *type; + char *name; +}; + +struct uci_option +{ + struct uci_list list; + struct uci_section *section; + char *name; + char *value; +}; + +/* linked list handling */ +#ifndef offsetof +#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER) +#endif + +#define uci_list_empty(list) (list->next == ptr) +#define uci_list_entry(_type, _ptr) \ + ((struct uci_ ## _type *) ((char *)(_ptr) - offsetof(struct uci_ ## _type,list))) + +#define uci_foreach_entry(_type, _list, _ptr) \ + for(_ptr = uci_list_entry(_type, (_list)->next); \ + &_ptr->list != (_list); \ + _ptr = uci_list_entry(_type, _ptr->list.next)) + +#endif