Main Page | Modules | Data Structures | File List | Data Fields | Related Pages

mntd_volume_config.c

00001 /***************************************************************************
00002  * CVSID: $Id: mntd_volume_config.c,v 1.4 2004/04/06 20:49:14 stefanb Exp $
00003  *
00004  * mntd_volume_config.h : Config file parser based on expat
00005  *
00006  * Copyright (C) 2004 Stefan Bambach, <stefan@bambach.biz>
00007  *
00008  * Licensed under the GNU General Public License 2.0
00009  *
00010  * This program is free software; you can redistribute it and/or modify
00011  * it under the terms of the GNU General Public License as published by
00012  * the Free Software Foundation; either version 2 of the License, or
00013  * (at your option) any later version.
00014  *
00015  * This program is distributed in the hope that it will be useful,
00016  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00017  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00018  * GNU General Public License for more details.
00019  *
00020  * You should have received a copy of the GNU General Public License
00021  * along with this program; if not, write to the Free Software
00022  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
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     /* Grr, expat can't abort parsing */
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     // check abort flag
00149     if(pc->aborted) {
00150         return;
00151     }
00152     
00153     // set cdata buffer start
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         // TODO: handle elements data
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         // TODO: handle elements data
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     // Nasty hack
00188     g_assert((pc->depth)<MAX_DEPTH);
00189     
00190     // increment depth counter
00191     pc->depth++;        
00192     
00193     // store depth
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     // check abort flag
00214     if (pc->aborted) {
00215         return;
00216     }
00217     
00218     // finalize cdata buffer
00219     pc->cdata_buf[pc->cdata_buf_len]='\0';
00220     
00221     // TODO: handle data
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     // reset cdata offset
00231     pc->cdata_buf_len = 0;
00232     
00233     // decrement depth counter
00234     pc->depth--;
00235     
00236     // maintain curelem
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     // handle abort flag
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     // reading configuration file
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     // read config file data
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     // read xml data
00320     parser = XML_ParserCreate(NULL);
00321     
00322     // initialize parsing context
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     // parse xml data
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     // free parsing context
00361     if (parsing_context != NULL) {
00362         // TODO: store parsing context here
00363         free(parsing_context);
00364         parsing_context = NULL;
00365     }
00366     
00367     // free config file data
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     // free already stored base path
00392     if (pvm->base != NULL) {
00393         free(pvm->base);
00394         pvm->base = NULL;
00395     }
00396     
00397     // store new value
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 

Generated on Thu May 27 23:27:28 2004 for Mntd by doxygen 1.3.5