00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #ifdef HAVE_CONFIG_H
00027 # include <config.h>
00028 #endif
00029
00030 #include <stdlib.h>
00031 #include <glib.h>
00032 #include <expat.h>
00033
00034 #include "mntd_file.h"
00035 #include "mntd_volume_config.h"
00036 #include "mntd_volume_manager.h"
00037 #include "errmanager.h"
00038
00039
00049 #define MAX_DEPTH 32
00050
00052 #define CDATA_BUF_SIZE 1024
00053
00055 #define MAX_KEY_SIZE 128
00056
00058 enum
00059 {
00061 CURELEM_UNKNOWN = -1,
00062
00064 CURELEM_MNTD = 0,
00065
00067 CURELEM_MOUNTPATH = 1,
00068 };
00069
00070
00073 typedef struct
00074 {
00076 PVOLUMEMANAGER pvm;
00077
00079 XML_Parser parser;
00080
00082 char *config;
00083
00085 char cdata_buf[CDATA_BUF_SIZE];
00086
00088 int cdata_buf_len;
00089
00091 int depth;
00092
00094 int curelem;
00095
00097 int curelem_stack[MAX_DEPTH];
00098
00100 int aborted;
00101
00102 } ParsingContext;
00103
00104
00105 void mntd_volume_config_parsing_abort(ParsingContext* pc);
00106 void mntd_volume_config_start(ParsingContext *pc, const char *el, const char **attr);
00107 void mntd_volume_config_end(ParsingContext *pc, const char* el);
00108 void mntd_volume_config_cdata(ParsingContext *pc, const char* s, int len);
00109 int mntd_volume_config_store_base(PVOLUMEMANAGER pvm, const char *base);
00110
00111
00116 void
00117 mntd_volume_config_parsing_abort(ParsingContext* pc)
00118 {
00119 g_assert(pc!=NULL);
00120
00121
00122 MSG_ERR("Aborting parsing of document");
00123 pc->aborted = TRUE;
00124 }
00125
00126
00133 void
00134 mntd_volume_config_start(ParsingContext *pc, const char *el, const char **attr)
00135 {
00136 int i = 0;
00137
00138 g_assert(pc!=NULL);
00139 g_assert(el!=NULL);
00140 g_assert(attr!=NULL);
00141
00142 MSG_DEBUG("start: %s", el);
00143
00144 for (i=0; attr[i]; i+=2) {
00145 MSG_DEBUG(" %s='%s'", attr[i], attr[i+1]);
00146 }
00147
00148
00149 if(pc->aborted) {
00150 return;
00151 }
00152
00153
00154 pc->cdata_buf_len = 0;
00155
00156 if (strcmp(el, "mntd") == 0) {
00157 if( pc->curelem!=CURELEM_UNKNOWN ) {
00158 MSG_ERR("%s:%d:%d: Element <mntd> must be a top-level "
00159 "element",
00160 pc->config,
00161 XML_GetCurrentLineNumber(pc->parser),
00162 XML_GetCurrentColumnNumber(pc->parser));
00163 mntd_volume_config_parsing_abort(pc);
00164 }
00165 pc->curelem = CURELEM_MNTD;
00166
00167
00168 } else if (strcmp(el, "mountpath") == 0) {
00169 if( pc->curelem!=CURELEM_MNTD ) {
00170 MSG_ERR("%s:%d:%d: Element <mountpath> can only be inside <mntd>",
00171 pc->config,
00172 XML_GetCurrentLineNumber(pc->parser),
00173 XML_GetCurrentColumnNumber(pc->parser));
00174 mntd_volume_config_parsing_abort(pc);
00175 }
00176 pc->curelem = CURELEM_MOUNTPATH;
00177
00178
00179 } else {
00180 MSG_ERR("%s:%d:%d: Unknown element <%s>",
00181 pc->config,
00182 XML_GetCurrentLineNumber(pc->parser),
00183 XML_GetCurrentColumnNumber(pc->parser), el);
00184 mntd_volume_config_parsing_abort(pc);
00185 }
00186
00187
00188 g_assert((pc->depth)<MAX_DEPTH);
00189
00190
00191 pc->depth++;
00192
00193
00194 pc->curelem_stack[pc->depth] = pc->curelem;
00195
00196 return;
00197 }
00198
00199
00205 void
00206 mntd_volume_config_end(ParsingContext *pc, const char* el)
00207 {
00208 g_assert(pc!=NULL);
00209 g_assert(el!=NULL);
00210
00211 MSG_DEBUG("end: %s", el);
00212
00213
00214 if (pc->aborted) {
00215 return;
00216 }
00217
00218
00219 pc->cdata_buf[pc->cdata_buf_len]='\0';
00220
00221
00222 if (pc->curelem==CURELEM_MOUNTPATH) {
00223 MSG_DEBUG("content for mountpath='%s'", pc->cdata_buf);
00224 if(mntd_volume_config_store_base(pc->pvm, pc->cdata_buf) == -1) {
00225 MSG_ERR("Could not store new mountpath");
00226 mntd_volume_config_parsing_abort(pc);
00227 }
00228 }
00229
00230
00231 pc->cdata_buf_len = 0;
00232
00233
00234 pc->depth--;
00235
00236
00237 pc->curelem = pc->curelem_stack[pc->depth];
00238
00239 return;
00240 }
00241
00242
00249 void
00250 mntd_volume_config_cdata(ParsingContext *pc, const char* s, int len)
00251 {
00252 int bytes_left;
00253 int bytes_to_copy;
00254
00255 g_assert(pc!=NULL);
00256 g_assert(s!=NULL);
00257
00258
00259 if (pc->aborted) {
00260 return;
00261 }
00262
00263 bytes_left = CDATA_BUF_SIZE - pc->cdata_buf_len;
00264 if (len>bytes_left) {
00265 MSG_ERR("CDATA in element larger than %d", CDATA_BUF_SIZE);
00266 }
00267
00268 bytes_to_copy = len;
00269 if (bytes_to_copy>bytes_left) {
00270 bytes_to_copy = bytes_left;
00271 }
00272
00273 if (bytes_to_copy>0) {
00274 memcpy(pc->cdata_buf + pc->cdata_buf_len, s, bytes_to_copy);
00275 }
00276
00277 pc->cdata_buf_len += bytes_to_copy;
00278
00279 return;
00280 }
00281
00282
00289 int
00290 mntd_volume_config_parse(char *config, PVOLUMEMANAGER pvm)
00291 {
00292 int res = 0;
00293 char *data = NULL;
00294 XML_Parser parser = NULL;
00295 int size = 0;
00296 ParsingContext *parsing_context = NULL;
00297
00298 g_assert(pvm!=NULL);
00299
00300
00301 MSG_INF("Loading configuration from '%s'.", config);
00302 if(!mntd_file_is_file(config)) {
00303 MSG_EMERG("Couldn't read config file from '%s'", config);
00304 return -1;
00305 }
00306
00307 if((size = mntd_file_get_size(config)) == -1 ) {
00308 MSG_EMERG("Couldn't get config file size from '%s'", config);
00309 goto error;
00310 }
00311
00312
00313 data = mntd_file_read(config);
00314 if (data == NULL) {
00315 MSG_EMERG("Couldn't read config file from '%s'", config);
00316 goto error;
00317 }
00318
00319
00320 parser = XML_ParserCreate(NULL);
00321
00322
00323 parsing_context = (ParsingContext*) malloc(sizeof(ParsingContext));
00324 if (parsing_context == NULL) {
00325 MSG_EMERG("Out of memory.");
00326 goto error;
00327 }
00328 parsing_context->depth = 0;
00329 parsing_context->cdata_buf_len = 0;
00330 memset(parsing_context->cdata_buf, 0, sizeof(parsing_context->cdata_buf));
00331 parsing_context->curelem = CURELEM_UNKNOWN;
00332 parsing_context->aborted = FALSE;
00333 parsing_context->parser = parser;
00334 parsing_context->config = config;
00335 parsing_context->pvm = pvm;
00336
00337
00338 XML_SetElementHandler(parser,
00339 (XML_StartElementHandler) mntd_volume_config_start,
00340 (XML_EndElementHandler) mntd_volume_config_end);
00341 XML_SetCharacterDataHandler(parser,
00342 (XML_CharacterDataHandler) mntd_volume_config_cdata);
00343 XML_SetUserData(parser, parsing_context);
00344 if (XML_Parse(parser, data, size, 1) == XML_STATUS_ERROR) {
00345 MSG_EMERG("Parse error at line %d:\n%s\n",
00346 XML_GetCurrentLineNumber(parser),
00347 XML_ErrorString(XML_GetErrorCode(parser)));
00348 }
00349
00350 if (parsing_context->aborted == TRUE) {
00351 goto error;
00352 }
00353
00354 goto cleanup;
00355
00356 error:
00357 res = -1;
00358
00359 cleanup:
00360
00361 if (parsing_context != NULL) {
00362
00363 free(parsing_context);
00364 parsing_context = NULL;
00365 }
00366
00367
00368 if (data != NULL) {
00369 free(data);
00370 data = NULL;
00371 }
00372
00373 return res;
00374 }
00375
00376
00383 int
00384 mntd_volume_config_store_base(PVOLUMEMANAGER pvm, const char *base)
00385 {
00386 int res = 0;
00387 char *tmp = NULL;
00388
00389 g_assert(pvm!=NULL);
00390
00391
00392 if (pvm->base != NULL) {
00393 free(pvm->base);
00394 pvm->base = NULL;
00395 }
00396
00397
00398 if (pvm->base == NULL) {
00399 tmp = strdup(base);
00400 if (tmp == NULL) {
00401 goto error;
00402 }
00403 pvm->base = tmp;
00404 } else {
00405 goto error;
00406 }
00407
00408 goto cleanup;
00409
00410 error:
00411 if (tmp!=NULL) {
00412 free(tmp);
00413 tmp = NULL;
00414 }
00415 res = -1;
00416
00417 cleanup:
00418
00419 return res;
00420 }
00421
00422