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.23 2004/12/18 23:38:53 stefanb Exp $
00003  *
00004  * mntd_volume_config.h : Config file parser based on expat
00005  *
00006  * Copyright (C) 2004 Stefan Bambach, <sbambach@gmx.net>
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 "file.h"
00035 #include "mntd_volume_config.h"
00036 #include "mntd_volume_manager.h"
00037 #include "errmanager.h"
00038 #include "dbug_mem.h"
00039 
00040 
00050 #define MAX_DEPTH 32
00051 
00053 #define CDATA_BUF_SIZE  1024
00054 
00056 #define MAX_KEY_SIZE 128
00057 
00059 enum
00060 {
00062     CURELEM_UNKNOWN  = -1,
00063     
00065     CURELEM_MNTD = 0,
00066     
00068     CURELEM_MOUNTPATH = 1,
00069     
00071     CURELEM_USER = 2,
00072     
00074     CURELEM_GROUP = 3,
00075     
00077     CURELEM_WDIR = 4,
00078     
00080     CURELEM_PIDFILE = 5,
00081     
00083     CURELEM_FILESYSTEMS = 6,
00084     
00086     CURELEM_FILESYSTEM = 7,
00087     
00089     CURELEM_DBUS_RECONNECT = 8,
00090     
00092     CURELEM_LOGLEVEL = 9,
00093     
00095     CURELEM_UMOUNT_ON_EXIT = 10,
00096     
00098     CURELEM_MOUNTPREFIX = 11,
00099     
00100 };
00101 
00102 
00103 
00106 typedef struct
00107 {
00109     ConfigData *c;
00110     
00112     XML_Parser parser;
00113     
00115     char *config;
00116     
00118     char cdata_buf[CDATA_BUF_SIZE];
00119     
00121     int cdata_buf_len;
00122     
00124     int depth;
00125     
00127     int curelem;
00128     
00130     int curelem_stack[MAX_DEPTH];
00131     
00133     int aborted;
00134     
00135 } ParsingContext;
00136 
00137 
00138 
00139 void mntd_volume_config_parsing_abort(ParsingContext* pc);
00140 void mntd_volume_config_start(ParsingContext *pc, const char *el, const char **attr);
00141 void mntd_volume_config_end(ParsingContext *pc, const char* el);
00142 void mntd_volume_config_cdata(ParsingContext *pc, const char* s, int len);
00143 
00144 
00145 
00150 void 
00151 mntd_volume_config_parsing_abort(ParsingContext* pc)
00152 {
00153     g_assert(pc!=NULL);
00154     
00155     /* Grr, expat can't abort parsing */
00156     MSG_ERR("Aborting parsing of document");
00157     pc->aborted = TRUE;
00158 }
00159 
00160 
00161 
00168 void 
00169 mntd_volume_config_start(ParsingContext *pc, const char *el, const char **attr)
00170 {
00171     int i = 0;
00172     
00173     g_assert(pc!=NULL);
00174     g_assert(el!=NULL);
00175     g_assert(attr!=NULL);
00176     
00177     MSG_DEBUG("start: %s", el);
00178     
00179     for (i=0; attr[i]; i+=2) {
00180         MSG_DEBUG("    %s='%s'", attr[i], attr[i+1]);
00181     }
00182     
00183     // check abort flag
00184     if(pc->aborted) {
00185         return;
00186     }
00187     
00188     // set cdata buffer start
00189     pc->cdata_buf_len = 0;
00190     
00191     if (strcmp(el, "mntd") == 0) {
00192         if( pc->curelem!=CURELEM_UNKNOWN ) {
00193             MSG_ERR("%s:%d:%d: Element <mntd> must be a top-level "
00194                             "element", 
00195                             pc->config, 
00196                             XML_GetCurrentLineNumber(pc->parser), 
00197                             XML_GetCurrentColumnNumber(pc->parser));
00198             mntd_volume_config_parsing_abort(pc);
00199         }
00200         pc->curelem = CURELEM_MNTD;
00201         
00202     } else if (strcmp(el, "mountpath") == 0) {
00203         if( pc->curelem!=CURELEM_MNTD ) {
00204             MSG_ERR("%s:%d:%d: Element <mountpath> can only be inside <mntd>",
00205                             pc->config, 
00206                             XML_GetCurrentLineNumber(pc->parser), 
00207                             XML_GetCurrentColumnNumber(pc->parser));
00208             mntd_volume_config_parsing_abort(pc);
00209         }
00210         pc->curelem = CURELEM_MOUNTPATH;
00211         
00212     } else if (strcmp(el, "mountprefix") == 0) {
00213         if( pc->curelem!=CURELEM_MNTD ) {
00214             MSG_ERR("%s:%d:%d: Element <mountprefix> can only be inside <mntd>",
00215                             pc->config, 
00216                             XML_GetCurrentLineNumber(pc->parser), 
00217                             XML_GetCurrentColumnNumber(pc->parser));
00218             mntd_volume_config_parsing_abort(pc);
00219         }
00220         pc->curelem = CURELEM_MOUNTPREFIX;
00221         
00222     } else if (strcmp(el, "user") == 0) {
00223         if( pc->curelem!=CURELEM_MNTD ) {
00224             MSG_ERR("%s:%d:%d: Element <user> can only be inside <mntd>",
00225                             pc->config, 
00226                             XML_GetCurrentLineNumber(pc->parser), 
00227                             XML_GetCurrentColumnNumber(pc->parser));
00228             mntd_volume_config_parsing_abort(pc);
00229         }
00230         pc->curelem = CURELEM_USER;
00231         
00232     } else if (strcmp(el, "group") == 0) {
00233         if( pc->curelem!=CURELEM_MNTD ) {
00234             MSG_ERR("%s:%d:%d: Element <group> can only be inside <mntd>",
00235                             pc->config, 
00236                             XML_GetCurrentLineNumber(pc->parser), 
00237                             XML_GetCurrentColumnNumber(pc->parser));
00238             mntd_volume_config_parsing_abort(pc);
00239         }
00240         pc->curelem = CURELEM_GROUP;
00241         
00242     } else if (strcmp(el, "wdir") == 0) {
00243         if( pc->curelem!=CURELEM_MNTD ) {
00244             MSG_ERR("%s:%d:%d: Element <wdir> can only be inside <mntd>",
00245                             pc->config, 
00246                             XML_GetCurrentLineNumber(pc->parser), 
00247                             XML_GetCurrentColumnNumber(pc->parser));
00248             mntd_volume_config_parsing_abort(pc);
00249         }
00250         pc->curelem = CURELEM_WDIR;
00251         
00252     } else if (strcmp(el, "pidfile") == 0) {
00253         if( pc->curelem!=CURELEM_MNTD ) {
00254             MSG_ERR("%s:%d:%d: Element <pidfile> can only be inside <mntd>",
00255                             pc->config, 
00256                             XML_GetCurrentLineNumber(pc->parser), 
00257                             XML_GetCurrentColumnNumber(pc->parser));
00258             mntd_volume_config_parsing_abort(pc);
00259         }
00260         pc->curelem = CURELEM_PIDFILE;
00261         
00262     } else if (strcmp(el, "filesystems") == 0) {
00263         if( pc->curelem!=CURELEM_MNTD ) {
00264             MSG_ERR("%s:%d:%d: Element <filesystems> can only be inside <mntd>",
00265                             pc->config, 
00266                             XML_GetCurrentLineNumber(pc->parser), 
00267                             XML_GetCurrentColumnNumber(pc->parser));
00268             mntd_volume_config_parsing_abort(pc);
00269         }
00270         pc->curelem = CURELEM_FILESYSTEMS;
00271         
00272     } else if (strcmp(el, "filesystem") == 0) {
00273         if( pc->curelem!=CURELEM_FILESYSTEMS ) {
00274             MSG_ERR("%s:%d:%d: Element <filesystem> can only be inside <filesystems>",
00275                             pc->config, 
00276                             XML_GetCurrentLineNumber(pc->parser), 
00277                             XML_GetCurrentColumnNumber(pc->parser));
00278             mntd_volume_config_parsing_abort(pc);
00279         }
00280         gchar *fsname = NULL;
00281         gchar *fsoptions = NULL;
00282         for (i=0; attr[i]; i+=2) {
00283             if (strcmp(attr[i], "name") == 0) {
00284                 fsname = (gchar *) attr[i+1];
00285             } else if (strcmp(attr[i], "options") == 0) {
00286                 fsoptions = (gchar *) attr[i+1];
00287             } else {
00288                 MSG_INF("Unknown attribute '%s' for element '%s'.", attr[i], el);
00289             }
00290         }
00291         if (pc->c != NULL) {
00292             g_hash_table_insert(pc->c->filesystems, g_strdup(fsname), g_strdup(fsoptions));
00293         }
00294         pc->curelem = CURELEM_FILESYSTEM;
00295         
00296     } else if (strcmp(el, "dbus_reconnect") == 0) {
00297         if( pc->curelem!=CURELEM_MNTD ) {
00298             MSG_ERR("%s:%d:%d: Element <dbus_reconnect> can only be inside <mntd>",
00299                             pc->config, 
00300                             XML_GetCurrentLineNumber(pc->parser), 
00301                             XML_GetCurrentColumnNumber(pc->parser));
00302             mntd_volume_config_parsing_abort(pc);
00303         }
00304         pc->c->sleep_millis = SLEEP_MILLIS_DEFAULT;
00305         char *str_sleep_millis = NULL;
00306         for (i=0; attr[i]; i+=2) {
00307             if (strcmp(attr[i], "sleep_millis") == 0) {
00308                 str_sleep_millis = (char *) attr[i+1];
00309             } else {
00310                 MSG_INF("Unknown attribute '%s' for element '%s'.", attr[i], el);
00311             }
00312         }
00313         if (str_sleep_millis != NULL) {
00314             char *endptr = NULL;
00315             char *nptr = str_sleep_millis;
00316             int value = strtol(nptr, &endptr, 0);
00317             if (((value == 0) && (nptr == endptr)) || (value < 0)) {
00318                 MSG_WARNING("Invalid data for attribute 'sleep_millis' in <dbus_reconnect> (only numbers >= 0 allowed) -> using %d", SLEEP_MILLIS_DEFAULT);
00319             } else {
00320                 pc->c->sleep_millis = value;
00321             }
00322         } else {
00323             MSG_INF("Attribute 'sleep_millis' in <dbus_reconnect> not specified -> using %d", SLEEP_MILLIS_DEFAULT);
00324         }
00325         pc->curelem = CURELEM_DBUS_RECONNECT;
00326         
00327     } else if (strcmp(el, "loglevel") == 0) {
00328         if( pc->curelem!=CURELEM_MNTD ) {
00329             MSG_ERR("%s:%d:%d: Element <loglevel> can only be inside <mntd>",
00330                             pc->config, 
00331                             XML_GetCurrentLineNumber(pc->parser), 
00332                             XML_GetCurrentColumnNumber(pc->parser));
00333             mntd_volume_config_parsing_abort(pc);
00334         }
00335         pc->curelem = CURELEM_LOGLEVEL;
00336         
00337     } else if (strcmp(el, "umount_on_exit") == 0) {
00338         if( pc->curelem!=CURELEM_MNTD ) {
00339             MSG_ERR("%s:%d:%d: Element <umount_on_exit> can only be inside <mntd>",
00340                             pc->config, 
00341                             XML_GetCurrentLineNumber(pc->parser), 
00342                             XML_GetCurrentColumnNumber(pc->parser));
00343             mntd_volume_config_parsing_abort(pc);
00344         }
00345         pc->curelem = CURELEM_UMOUNT_ON_EXIT;
00346         
00347     } else {
00348         MSG_ERR("%s:%d:%d: Unknown element <%s>",
00349                         pc->config, 
00350                         XML_GetCurrentLineNumber(pc->parser), 
00351                         XML_GetCurrentColumnNumber(pc->parser), el);
00352         mntd_volume_config_parsing_abort(pc);
00353     }
00354     
00355     // Nasty hack
00356     g_assert((pc->depth)<MAX_DEPTH);
00357     
00358     // increment depth counter
00359     pc->depth++;        
00360     
00361     // store depth
00362     pc->curelem_stack[pc->depth] = pc->curelem;
00363     
00364     return;
00365 }
00366 
00367 
00368 
00374 void 
00375 mntd_volume_config_end(ParsingContext *pc, const char* el)
00376 {
00377     g_assert(pc!=NULL);
00378     g_assert(el!=NULL);
00379     
00380     MSG_DEBUG("end: %s", el);
00381     
00382     // check abort flag
00383     if (pc->aborted) {
00384         return;
00385     }
00386     
00387     // finalize cdata buffer
00388     pc->cdata_buf[pc->cdata_buf_len]='\0';
00389 
00390     // handle data
00391     if (pc->curelem==CURELEM_MOUNTPATH) {
00392         MSG_DEBUG("content for mountpath='%s'", pc->cdata_buf);
00393         pc->c->mountpath = strdup(pc->cdata_buf);
00394         
00395     } else if (pc->curelem==CURELEM_MOUNTPREFIX) {
00396         MSG_DEBUG("content for mountprefix='%s'", pc->cdata_buf);
00397         pc->c->mountprefix = strdup(pc->cdata_buf);
00398         
00399     } else if (pc->curelem==CURELEM_USER) {
00400         MSG_DEBUG("content for user='%s'", pc->cdata_buf);
00401         pc->c->user = strdup(pc->cdata_buf);
00402     
00403     } else if (pc->curelem==CURELEM_GROUP) {
00404         MSG_DEBUG("content for group='%s'", pc->cdata_buf);
00405         pc->c->group = strdup(pc->cdata_buf);
00406     
00407     } else if (pc->curelem==CURELEM_WDIR) {
00408         MSG_DEBUG("content for wdir='%s'", pc->cdata_buf);
00409         pc->c->wdir = strdup(pc->cdata_buf);
00410     
00411     } else if (pc->curelem==CURELEM_PIDFILE) {
00412         MSG_DEBUG("content for pidfile='%s'", pc->cdata_buf);
00413         MSG_DEBUG("Ignoring deprecated <pidfile>%s</pidfile> -> use commandline parameter instead", pc->cdata_buf);
00414     
00415     } else if (pc->curelem==CURELEM_DBUS_RECONNECT) {
00416         MSG_DEBUG("content for dbus_reconnect='%s'", pc->cdata_buf);
00417         char *endptr = NULL;
00418         char *nptr = pc->cdata_buf;
00419         int value = strtol(nptr, &endptr, 0);
00420         if ((value == 0) && (nptr == endptr)) {
00421             MSG_WARNING("Invalid data for <dbus_reconnect> in configfile (only numbers allowed) -> using -1");
00422             pc->c->dbus_reconnect = -1;
00423         } else {
00424             pc->c->dbus_reconnect = value;
00425         }
00426     
00427     } else if (pc->curelem==CURELEM_LOGLEVEL) {
00428         MSG_DEBUG("content for loglevel='%s'", pc->cdata_buf);
00429         char *endptr = NULL;
00430         char *nptr = pc->cdata_buf;
00431         int value = strtol(nptr, &endptr, 0);
00432         if ((value == 0) && (nptr == endptr)) {
00433             MSG_WARNING("Invalid data for <dbus_reconnect> in configfile (only numbers allowed) -> using %d", 
00434                 LOG_NOTICE);
00435             pc->c->loglevel = LOG_NOTICE;
00436         } else {
00437             if (value < LOG_EMERG) {
00438                 MSG_WARNING("option for loglevel out of range (%d <= loglevel <= %d) -> using %d", 
00439                     LOG_EMERG, LOG_DEBUG, LOG_EMERG);
00440                 pc->c->loglevel = LOG_EMERG;
00441             } else if (value > LOG_DEBUG) {
00442                 MSG_WARNING("option for loglevel out of range (%d <= loglevel <= %d) -> using %d", 
00443                     LOG_EMERG, LOG_DEBUG, LOG_DEBUG);
00444                 pc->c->loglevel = LOG_DEBUG;
00445             } else {
00446                 pc->c->loglevel = value;
00447             }
00448         }
00449     
00450     } else if (pc->curelem==CURELEM_UMOUNT_ON_EXIT) {
00451         MSG_DEBUG("content for umount_on_exit='%s'", pc->cdata_buf);
00452         if (strcasecmp(pc->cdata_buf, "true") == 0) {
00453             pc->c->umount_on_exit = UMOUNT_ON_EXIT_TRUE;
00454         } else if (strcasecmp(pc->cdata_buf, "false") == 0) {
00455             pc->c->umount_on_exit = UMOUNT_ON_EXIT_FALSE;
00456         } else if (strcasecmp(pc->cdata_buf, "readonly") == 0) {
00457             pc->c->umount_on_exit = UMOUNT_ON_EXIT_READONLY;
00458         } else {
00459             MSG_WARNING("Invalid data for <umount_on_exit> in configfile (only true|false|readonly allowed) -> using true");
00460             pc->c->umount_on_exit = UMOUNT_ON_EXIT_TRUE;
00461         }
00462 
00463     }
00464     
00465     // reset cdata offset
00466     pc->cdata_buf_len = 0;
00467     
00468     // decrement depth counter
00469     pc->depth--;
00470     
00471     // maintain curelem
00472     pc->curelem = pc->curelem_stack[pc->depth];
00473     
00474     return;
00475 }
00476 
00477 
00478 
00485 void 
00486 mntd_volume_config_cdata(ParsingContext *pc, const char* s, int len)
00487 {
00488     int bytes_left;
00489     int bytes_to_copy;
00490     
00491     g_assert(pc!=NULL);
00492     g_assert(s!=NULL);
00493     
00494     // handle abort flag
00495     if (pc->aborted) {
00496         return;
00497     }
00498     
00499     bytes_left = CDATA_BUF_SIZE - pc->cdata_buf_len;
00500     if (len>bytes_left) {
00501         MSG_ERR("CDATA in element larger than %d", CDATA_BUF_SIZE);
00502     }
00503     
00504     bytes_to_copy = len;
00505     if (bytes_to_copy>bytes_left) {
00506         bytes_to_copy = bytes_left;
00507     }
00508     
00509     if (bytes_to_copy>0) {
00510         memcpy(pc->cdata_buf + pc->cdata_buf_len, s, bytes_to_copy);
00511     }
00512     
00513     pc->cdata_buf_len += bytes_to_copy;
00514     
00515     return;
00516 }
00517 
00518 
00519 
00520 #ifdef DEBUG
00521 
00530 void print_hm_entry(gpointer key, gpointer value, gpointer user_data);
00531 void print_hm_entry(gpointer key, gpointer value, gpointer user_data)
00532 {
00533     MSG_INF("    %s='%s'", key, value);
00534 }
00535 #endif
00536 
00537 
00538 
00545 ConfigData *
00546 mntd_volume_config_parse(char *config, char *pidfile)
00547 {
00548     char *data = NULL;
00549     XML_Parser parser = NULL;
00550     int size = 0;
00551     ParsingContext *parsing_context = NULL;
00552     ConfigData *configdata = NULL;
00553     char *cwd = NULL;
00554     char *absfilepath = NULL;
00555 
00556     g_assert(config!=NULL);
00557     g_assert(pidfile!=NULL);
00558     
00559     configdata = (ConfigData *) malloc(sizeof(ConfigData));
00560     if (configdata==NULL) {
00561         MSG_EMERG("No memory for storing ConfigData");
00562         goto error;
00563     }
00564     
00565     // reading configuration file
00566     MSG_INF("Loading configuration from '%s'.", config);
00567     if(!sb_file_is_file(config)) {
00568         MSG_EMERG("Couldn't read config file from '%s'", config);
00569         goto error;
00570     }
00571     
00572     if((size = sb_file_get_size(config)) == -1 ) {
00573         MSG_EMERG("Couldn't get config file size from '%s'", config);
00574         goto error;
00575     }
00576     
00577     // read config file data
00578     data = sb_file_read(config);
00579     if (data == NULL) {
00580         MSG_EMERG("Couldn't read config file from '%s'", config);
00581         goto error;
00582     }
00583     
00584     // read xml data
00585     parser = XML_ParserCreate(NULL);
00586     
00587     // initialize parsing context
00588     parsing_context = (ParsingContext*) malloc(sizeof(ParsingContext));
00589     if (parsing_context == NULL) {
00590         MSG_EMERG("Out of memory.");
00591         goto error;
00592     }
00593     parsing_context->depth = 0;
00594     parsing_context->cdata_buf_len = 0;
00595     memset(parsing_context->cdata_buf, 0, sizeof(parsing_context->cdata_buf));
00596     parsing_context->curelem = CURELEM_UNKNOWN;
00597     parsing_context->aborted = FALSE;
00598     parsing_context->parser = parser;
00599     parsing_context->config = config;
00600     parsing_context->c = configdata;
00601     
00602     // clear ConfigData structure
00603     memset(configdata, 0, sizeof(ConfigData));
00604     
00605     // initialize ConfigData structure
00606     configdata->filesystems = g_hash_table_new_full(g_str_hash, g_str_equal, 
00607                                                                     g_free, g_free);
00608     // initialize ConfigData structure
00609     configdata->pidfile = strdup(pidfile);
00610     
00611     // store loaded config file
00612     if (g_path_is_absolute(config)) {
00613         configdata->absfilepath = strdup(config);
00614     } else {
00615         cwd = g_get_current_dir();
00616         if (cwd != NULL) {
00617             absfilepath = g_build_path(G_DIR_SEPARATOR_S, cwd, config, NULL);
00618             if (absfilepath != NULL) {
00619                 char *path = strdup(absfilepath);
00620                 if (path != NULL) {
00621                     configdata->absfilepath = path;
00622                 } else {
00623                     MSG_ERR("Out of memory.");
00624                     goto error;
00625                 }
00626             } else {
00627                 MSG_ERR("Out of memory.");
00628                 goto error;
00629             }
00630         } else {
00631             MSG_ERR("Out of memory.");
00632             goto error;
00633         }
00634     }
00635     
00636 
00637     // parse xml data
00638     XML_SetElementHandler(parser, 
00639                                 (XML_StartElementHandler) mntd_volume_config_start, 
00640                                 (XML_EndElementHandler) mntd_volume_config_end);
00641     XML_SetCharacterDataHandler(parser, 
00642                                 (XML_CharacterDataHandler) mntd_volume_config_cdata);
00643     XML_SetUserData(parser, parsing_context);
00644     if (XML_Parse(parser, data, size, 1) == XML_STATUS_ERROR) {
00645         MSG_EMERG("Parse error at line %d:\n%s\n",
00646                                                 XML_GetCurrentLineNumber(parser),
00647                                                 XML_ErrorString(XML_GetErrorCode(parser)));
00648     }
00649     
00650     if (parsing_context->aborted == TRUE) {
00651         goto error;
00652     }
00653     
00654     goto cleanup;
00655 
00656 error:
00657     // free configuration, if error detected
00658     if (configdata!=NULL) {
00659         free(configdata);
00660         configdata = NULL;
00661     }
00662     
00663 cleanup:
00664     // free parsing context
00665     if (parsing_context != NULL) {
00666         // TODO: store parsing context here
00667         free(parsing_context);
00668         parsing_context = NULL;
00669     }
00670     
00671     // free cwd
00672     if (cwd != NULL) {
00673         g_free(cwd);
00674         cwd = NULL;
00675     }
00676     
00677     // free absfilepath
00678     if (absfilepath != NULL) {
00679         g_free(absfilepath);
00680         absfilepath = NULL;
00681     }
00682     
00683     // free config file data
00684     if (data != NULL) {
00685         free(data);
00686         data = NULL;
00687     }
00688     
00689 #ifdef DEBUG
00690     if (configdata != NULL) {
00691         MSG_INF("----------- Configuration from '%s'", configdata->absfilepath);
00692         MSG_INF("mountpath='%s'", configdata->mountpath);
00693         MSG_INF("mountprefix='%s'", configdata->mountprefix);
00694         MSG_INF("user='%s'", configdata->user);
00695         MSG_INF("group='%s'", configdata->group);
00696         MSG_INF("wdir='%s'", configdata->wdir);
00697         MSG_INF("pidfile='%s'", configdata->pidfile);
00698         MSG_INF("filesystems");
00699         g_hash_table_foreach(configdata->filesystems, print_hm_entry, NULL);
00700         MSG_INF("dbus_reconnect='%d'", configdata->dbus_reconnect);
00701         MSG_INF("sleep_millis='%d'", configdata->sleep_millis);
00702         MSG_INF("loglevel='%d'", configdata->loglevel);
00703         MSG_INF("umount_on_exit='%s'", 
00704             (configdata->umount_on_exit==UMOUNT_ON_EXIT_TRUE)?"true":(
00705             (configdata->umount_on_exit==UMOUNT_ON_EXIT_FALSE)?"false":"readonly"));
00706         MSG_INF("absfilepath='%s'", configdata->absfilepath);
00707     }
00708 #endif
00709     
00710     return configdata;
00711 }
00712 
00713 
00714 
00720 int 
00721 mntd_volume_config_free(ConfigData **cfg)
00722 {
00723     ConfigData *configdata = *cfg;
00724     
00725     // check
00726     if (configdata == NULL) {
00727         return 0;
00728     }
00729     
00730     // free variable memory
00731     if (configdata->mountpath!=NULL) {
00732         free(configdata->mountpath);
00733     }
00734     if (configdata->user!=NULL) {
00735         free(configdata->user);
00736     }
00737     if (configdata->group!=NULL) {
00738         free(configdata->group);
00739     }
00740     if (configdata->wdir!=NULL) {
00741         free(configdata->wdir);
00742     }
00743     if (configdata->pidfile!=NULL) {
00744         free(configdata->pidfile);
00745     }
00746     if (configdata->filesystems!=NULL) {
00747         g_hash_table_destroy(configdata->filesystems);
00748     }
00749     if (configdata->absfilepath!=NULL) {
00750         free(configdata->absfilepath);
00751     }
00752 
00753     // clear ConfigData structure
00754     if (configdata != NULL) {
00755         memset(configdata, 0, sizeof(ConfigData));
00756         free(configdata);
00757         configdata = NULL;
00758     }
00759     
00760     // clear pointer to this instance
00761     *cfg = NULL;
00762     
00763     return 0;
00764 }
00765 
00766 
00767 
00777 void compare_filesystems(gpointer key, gpointer value, gpointer user_data);
00778 void compare_filesystems(gpointer key, gpointer value, gpointer user_data)
00779 {
00780     GHashTable *filesystems = (GHashTable *) user_data;
00781     gchar *o = NULL;
00782     
00783     o = g_hash_table_lookup(filesystems, key);
00784     if (o != NULL) {
00785         if (strcmp(value, o) != 0) {
00786             MSG_NOTICE("<%s> changed from '%s' to '%s' (used for next mount).", key, value, o);
00787         }
00788     }
00789 }
00790 
00791 
00792 
00799 int 
00800 mntd_volume_config_reload(ConfigData **cfg, char *pidfile)
00801 {
00802     int res = 0;
00803     ConfigData *oldcfgdata = *cfg;
00804     ConfigData *newcfgdata = NULL;
00805     
00806     g_assert(oldcfgdata!=NULL);
00807     
00808     newcfgdata = mntd_volume_config_parse(oldcfgdata->absfilepath, pidfile);
00809     if (newcfgdata != NULL) {
00810         
00811         // check for changed user
00812         if (strcmp(oldcfgdata->user, newcfgdata->user) != 0) {
00813             MSG_WARNING("Changing <user> at runtime not allowed.");
00814         }
00815         
00816         // check for changed group
00817         if (strcmp(oldcfgdata->group, newcfgdata->group) != 0) {
00818             MSG_WARNING("Changing <group> at runtime not allowed.");
00819         }
00820         
00821         // check for changed wdir
00822         if (strcmp(oldcfgdata->wdir, newcfgdata->wdir) != 0) {
00823             MSG_WARNING("Changing <wdir> at runtime not allowed.");
00824         }
00825         
00826         // check for changed pidfile
00827         if (strcmp(oldcfgdata->pidfile, newcfgdata->pidfile) != 0) {
00828             MSG_WARNING("Changing <pidfile> at runtime not allowed.");
00829         }
00830         
00831         // check for changed mountpath
00832         if (strcmp(oldcfgdata->mountpath, newcfgdata->mountpath) != 0) {
00833             MSG_WARNING("Changing <mountpath> not allowed at runtime.");
00834         }
00835         
00836         // check for changed dbus_reconnect
00837         if (oldcfgdata->dbus_reconnect != newcfgdata->dbus_reconnect) {
00838             MSG_NOTICE("<dbus_reconnect> changed from '%d' to '%d'.", 
00839                 oldcfgdata->dbus_reconnect, newcfgdata->dbus_reconnect);
00840             oldcfgdata->dbus_reconnect = newcfgdata->dbus_reconnect;
00841         }
00842         
00843         // check for changed sleep_millis
00844         if (oldcfgdata->sleep_millis != newcfgdata->sleep_millis) {
00845             MSG_NOTICE("<dbus_reconnect sleep_millis=?> changed from '%d' to '%d'.", 
00846                 oldcfgdata->sleep_millis, newcfgdata->sleep_millis);
00847             oldcfgdata->sleep_millis = newcfgdata->sleep_millis;
00848         }
00849         
00850         // check for changed loglevel
00851         if (oldcfgdata->loglevel != newcfgdata->loglevel) {
00852         #ifndef DEBUG
00853             // reinit with new loglevel
00854             MSG_NOTICE("<loglevel> changed from '%d' to '%d'.", 
00855                 oldcfgdata->loglevel, newcfgdata->loglevel);
00856             oldcfgdata->loglevel = newcfgdata->loglevel;
00857             emInit(oldcfgdata->loglevel, EM_TYPE_SYSLOG, NULL, NULL, NULL, PACKAGE);
00858         #else
00859             MSG_WARNING("<loglevel> changed from '%d' to '%d' -> ignored while debugging.", 
00860                 oldcfgdata->loglevel, newcfgdata->loglevel);
00861         #endif
00862         }
00863         
00864         // check for changed umount_on_exit
00865         if (oldcfgdata->umount_on_exit != newcfgdata->umount_on_exit) {
00866             MSG_NOTICE("<umount_on_exit> changed from '%d' to '%d'.", 
00867                 oldcfgdata->umount_on_exit, newcfgdata->umount_on_exit);
00868             oldcfgdata->umount_on_exit = newcfgdata->umount_on_exit;
00869         }
00870         
00871         // check for changed filesystems
00872         if (g_hash_table_size(oldcfgdata->filesystems) != 
00873             g_hash_table_size(newcfgdata->filesystems)) {
00874             MSG_NOTICE("<filesystems> changed from '%d' items to '%d' items (using new filesystems).", 
00875                 g_hash_table_size(oldcfgdata->filesystems),
00876                 g_hash_table_size(newcfgdata->filesystems));
00877         } else {
00878             // check each entry for changes
00879             g_hash_table_foreach(oldcfgdata->filesystems, compare_filesystems, 
00880                 newcfgdata->filesystems);
00881         }
00882         // free old hash map and use new one
00883         g_hash_table_destroy(oldcfgdata->filesystems);
00884         oldcfgdata->filesystems = newcfgdata->filesystems;
00885         
00886     } else {
00887         MSG_ERR("Out of memory.");
00888         goto error;
00889     }
00890     
00891     goto cleanup;
00892     
00893 error:
00894     res = -1;
00895     
00896 cleanup:
00897     return res;
00898 }
00899 
00900 
00901 

Generated on Wed Mar 30 13:43:26 2005 for Mntd by  doxygen 1.3.9.1