1 /* 2 * libuci - Library for the Unified Configuration Interface 3 * Copyright (C) 2008 Felix Fietkau <nbd@openwrt.org> 4 * 5 * This program is free software; you can redistribute it and/or modify 6 * it under the terms of the GNU Lesser General Public License version 2.1 7 * as published by the Free Software Foundation 8 * 9 * This program is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU Lesser General Public License for more details. 13 */ 14 15 /* 16 * This file contains some common code for the uci library 17 */ 18 19 #define _GNU_SOURCE 20 #include <sys/types.h> 21 #include <stdbool.h> 22 #include <string.h> 23 #include <stdlib.h> 24 #include <stdio.h> 25 #include <dlfcn.h> 26 #include <glob.h> 27 #include "uci.h" 28 29 static const char *uci_errstr[] = { 30 [UCI_OK] = "Success", 31 [UCI_ERR_MEM] = "Out of memory", 32 [UCI_ERR_INVAL] = "Invalid argument", 33 [UCI_ERR_NOTFOUND] = "Entry not found", 34 [UCI_ERR_IO] = "I/O error", 35 [UCI_ERR_PARSE] = "Parse error", 36 [UCI_ERR_DUPLICATE] = "Duplicate entry", 37 [UCI_ERR_UNKNOWN] = "Unknown error", 38 }; 39 40 #include "uci_internal.h" 41 #include "list.c" 42 43 __private const char *uci_confdir = UCI_CONFDIR; 44 __private const char *uci_conf2dir = UCI_CONF2DIR; 45 __private const char *uci_savedir = UCI_SAVEDIR; 46 47 /* exported functions */ 48 struct uci_context *uci_alloc_context(void) 49 { 50 struct uci_context *ctx; 51 52 ctx = (struct uci_context *) calloc(1, sizeof(struct uci_context)); 53 if (!ctx) 54 return NULL; 55 56 uci_list_init(&ctx->root); 57 uci_list_init(&ctx->delta_path); 58 uci_list_init(&ctx->backends); 59 ctx->flags = UCI_FLAG_STRICT | UCI_FLAG_SAVED_DELTA; 60 61 ctx->confdir = (char *) uci_confdir; 62 ctx->conf2dir = (char *) uci_conf2dir; 63 ctx->savedir = (char *) uci_savedir; 64 uci_add_delta_path(ctx, uci_savedir); 65 66 uci_list_add(&ctx->backends, &uci_file_backend.e.list); 67 ctx->backend = &uci_file_backend; 68 69 return ctx; 70 } 71 72 void uci_free_context(struct uci_context *ctx) 73 { 74 struct uci_element *e, *tmp; 75 76 if (ctx->confdir != uci_confdir) 77 free(ctx->confdir); 78 if (ctx->savedir != uci_savedir) 79 free(ctx->savedir); 80 81 uci_cleanup(ctx); 82 UCI_TRAP_SAVE(ctx, ignore); 83 uci_foreach_element_safe(&ctx->root, tmp, e) { 84 struct uci_package *p = uci_to_package(e); 85 uci_free_package(&p); 86 } 87 uci_foreach_element_safe(&ctx->delta_path, tmp, e) { 88 uci_free_element(e); 89 } 90 UCI_TRAP_RESTORE(ctx); 91 free(ctx); 92 93 ignore: 94 return; 95 } 96 97 int uci_set_conf2dir(struct uci_context *ctx, const char *dir) 98 { 99 char *cdir; 100 101 if (!dir || !dir[0]) 102 cdir = NULL; 103 else if ((cdir = strdup(dir)) == NULL) 104 return UCI_ERR_MEM; 105 106 if (ctx->conf2dir != uci_conf2dir) 107 free(ctx->conf2dir); 108 ctx->conf2dir = cdir; 109 110 return 0; 111 } 112 113 int uci_set_confdir(struct uci_context *ctx, const char *dir) 114 { 115 char *cdir; 116 117 UCI_HANDLE_ERR(ctx); 118 UCI_ASSERT(ctx, dir != NULL); 119 120 cdir = uci_strdup(ctx, dir); 121 if (ctx->confdir != uci_confdir) 122 free(ctx->confdir); 123 ctx->confdir = cdir; 124 return 0; 125 } 126 127 __private void uci_cleanup(struct uci_context *ctx) 128 { 129 struct uci_parse_context *pctx; 130 131 if (ctx->buf) { 132 free(ctx->buf); 133 ctx->buf = NULL; 134 ctx->bufsz = 0; 135 } 136 137 pctx = ctx->pctx; 138 if (!pctx) 139 return; 140 141 ctx->pctx = NULL; 142 if (pctx->package) 143 uci_free_package(&pctx->package); 144 145 if (pctx->buf) 146 free(pctx->buf); 147 148 free(pctx); 149 } 150 151 void 152 uci_perror(struct uci_context *ctx, const char *str) 153 { 154 uci_get_errorstr(ctx, NULL, str); 155 } 156 157 void 158 uci_get_errorstr(struct uci_context *ctx, char **dest, const char *prefix) 159 { 160 static char error_info[128] = { 0 }; 161 int err; 162 163 err = ctx ? ctx->err : UCI_ERR_INVAL; 164 if ((err < 0) || (err >= UCI_ERR_LAST)) 165 err = UCI_ERR_UNKNOWN; 166 167 if (ctx && ctx->pctx && (err == UCI_ERR_PARSE)) { 168 snprintf(error_info, sizeof(error_info) - 1, " (%s) at line %d, byte %zu", 169 (ctx->pctx->reason ? ctx->pctx->reason : "unknown"), 170 ctx->pctx->line, ctx->pctx->byte); 171 } 172 173 if (!dest) { 174 strcat(error_info, "\n"); 175 fprintf(stderr, "%s%s%s%s%s%s", 176 (prefix ? prefix : ""), (prefix ? ": " : ""), 177 (ctx && ctx->func ? ctx->func : ""), (ctx && ctx->func ? ": " : ""), 178 uci_errstr[err], 179 error_info); 180 return; 181 } 182 183 err = asprintf(dest, "%s%s%s%s%s%s", 184 (prefix ? prefix : ""), (prefix ? ": " : ""), 185 (ctx && ctx->func ? ctx->func : ""), (ctx && ctx->func ? ": " : ""), 186 uci_errstr[err], 187 error_info); 188 189 if (err < 0) 190 *dest = NULL; 191 } 192 193 int uci_list_configs(struct uci_context *ctx, char ***list) 194 { 195 UCI_HANDLE_ERR(ctx); 196 UCI_ASSERT(ctx, list != NULL); 197 UCI_ASSERT(ctx, ctx->backend && ctx->backend->list_configs); 198 *list = ctx->backend->list_configs(ctx); 199 return 0; 200 } 201 202 int uci_commit(struct uci_context *ctx, struct uci_package **package, bool overwrite) 203 { 204 struct uci_package *p; 205 UCI_HANDLE_ERR(ctx); 206 UCI_ASSERT(ctx, package != NULL); 207 p = *package; 208 UCI_ASSERT(ctx, p != NULL); 209 UCI_ASSERT(ctx, p->backend && p->backend->commit); 210 p->backend->commit(ctx, package, overwrite); 211 return 0; 212 } 213 214 int uci_load(struct uci_context *ctx, const char *name, struct uci_package **package) 215 { 216 struct uci_package *p; 217 218 UCI_HANDLE_ERR(ctx); 219 UCI_ASSERT(ctx, ctx->backend && ctx->backend->load); 220 p = ctx->backend->load(ctx, name); 221 if (package) 222 *package = p; 223 224 return 0; 225 } 226 227 int uci_set_backend(struct uci_context *ctx, const char *name) 228 { 229 struct uci_element *e; 230 231 UCI_HANDLE_ERR(ctx); 232 UCI_ASSERT(ctx, name != NULL); 233 e = uci_lookup_list(&ctx->backends, name); 234 if (!e) 235 UCI_THROW(ctx, UCI_ERR_NOTFOUND); 236 ctx->backend = uci_to_backend(e); 237 return 0; 238 } 239
This page was automatically generated by LXR 0.3.1. • OpenWrt