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 error_info[0] = '\0'; 164 165 err = ctx ? ctx->err : UCI_ERR_INVAL; 166 if ((err < 0) || (err >= UCI_ERR_LAST)) 167 err = UCI_ERR_UNKNOWN; 168 169 if (ctx && ctx->pctx && (err == UCI_ERR_PARSE)) { 170 snprintf(error_info, sizeof(error_info) - 1, " (%s) at line %d, byte %zu", 171 (ctx->pctx->reason ? ctx->pctx->reason : "unknown"), 172 ctx->pctx->line, ctx->pctx->byte); 173 } 174 175 if (!dest) { 176 strcat(error_info, "\n"); 177 fprintf(stderr, "%s%s%s%s%s%s", 178 (prefix ? prefix : ""), (prefix ? ": " : ""), 179 (ctx && ctx->func ? ctx->func : ""), (ctx && ctx->func ? ": " : ""), 180 uci_errstr[err], 181 error_info); 182 return; 183 } 184 185 err = asprintf(dest, "%s%s%s%s%s%s", 186 (prefix ? prefix : ""), (prefix ? ": " : ""), 187 (ctx && ctx->func ? ctx->func : ""), (ctx && ctx->func ? ": " : ""), 188 uci_errstr[err], 189 error_info); 190 191 if (err < 0) 192 *dest = NULL; 193 } 194 195 int uci_list_configs(struct uci_context *ctx, char ***list) 196 { 197 UCI_HANDLE_ERR(ctx); 198 UCI_ASSERT(ctx, list != NULL); 199 UCI_ASSERT(ctx, ctx->backend && ctx->backend->list_configs); 200 *list = ctx->backend->list_configs(ctx); 201 return 0; 202 } 203 204 int uci_commit(struct uci_context *ctx, struct uci_package **package, bool overwrite) 205 { 206 struct uci_package *p; 207 UCI_HANDLE_ERR(ctx); 208 UCI_ASSERT(ctx, package != NULL); 209 p = *package; 210 UCI_ASSERT(ctx, p != NULL); 211 UCI_ASSERT(ctx, p->backend && p->backend->commit); 212 p->backend->commit(ctx, package, overwrite); 213 return 0; 214 } 215 216 int uci_load(struct uci_context *ctx, const char *name, struct uci_package **package) 217 { 218 struct uci_package *p; 219 220 UCI_HANDLE_ERR(ctx); 221 UCI_ASSERT(ctx, ctx->backend && ctx->backend->load); 222 p = ctx->backend->load(ctx, name); 223 if (package) 224 *package = p; 225 226 return 0; 227 } 228 229 int uci_set_backend(struct uci_context *ctx, const char *name) 230 { 231 struct uci_element *e; 232 233 UCI_HANDLE_ERR(ctx); 234 UCI_ASSERT(ctx, name != NULL); 235 e = uci_lookup_list(&ctx->backends, name); 236 if (!e) 237 UCI_THROW(ctx, UCI_ERR_NOTFOUND); 238 ctx->backend = uci_to_backend(e); 239 return 0; 240 } 241
This page was automatically generated by LXR 0.3.1. • OpenWrt