nfs-ganesha 1.4
|
00001 /* ---------------------------------------------------------------------------- 00002 * Copyright CEA/DAM/DIF (2007) 00003 * contributeur : Thomas LEIBOVICI thomas.leibovici@cea.fr 00004 * 00005 * This program is free software; you can redistribute it and/or 00006 * modify it under the terms of the GNU Lesser General Public 00007 * License as published by the Free Software Foundation; either 00008 * version 3 of the License, or (at your option) any later version. 00009 * 00010 * This program is distributed in the hope that it will be useful, 00011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00013 * Lesser General Public License for more details. 00014 * 00015 * You should have received a copy of the GNU Lesser General Public 00016 * License along with this library; if not, write to the Free Software 00017 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 00018 * 00019 * --------------------------------------- 00020 */ 00021 #include "config.h" 00022 #include "config_parsing.h" 00023 #include "analyse.h" 00024 #include <stdio.h> 00025 #include <errno.h> 00026 00027 #if HAVE_STRING_H 00028 #include <string.h> 00029 #endif 00030 00031 /* case unsensitivity */ 00032 #define STRNCMP strncasecmp 00033 00034 typedef struct config_struct_t 00035 { 00036 00037 /* Syntax tree */ 00038 00039 list_items *syntax_tree; 00040 00041 } config_struct_t; 00042 00043 /*************************************** 00044 * ACCES AUX VARIABLES EXTERNES 00045 ***************************************/ 00046 00047 /* fichier d'entree du lexer */ 00048 extern FILE *ganesha_yyin; 00049 00050 /* routine de parsing */ 00051 int ganesha_yyparse(); 00052 00053 /* routine de reinitialization */ 00054 void ganesha_yyreset(void); 00055 00056 /* indique le fichier parse (pour la trace en cas d'erreur) */ 00057 void ganesha_yy_set_current_file(char *file); 00058 00059 /* variable renseignee lors du parsing */ 00060 extern list_items *program_result; 00061 00062 /* message d'erreur */ 00063 extern char extern_errormsg[1024]; 00064 00065 /* config_ParseFile: 00066 * Reads the content of a configuration file and 00067 * stores it in a memory structure. 00068 */ 00069 config_file_t config_ParseFile(char *file_path) 00070 { 00071 00072 FILE *configuration_file; 00073 config_struct_t *output_struct; 00074 00075 /* Inits error message */ 00076 00077 extern_errormsg[0] = '\0'; 00078 00079 /* Sanity check */ 00080 00081 if(!file_path || !file_path[0]) 00082 { 00083 strcpy(extern_errormsg, "Invalid arguments"); 00084 return NULL; 00085 } 00086 00087 /* First, opens the file. */ 00088 00089 configuration_file = fopen(file_path, "r"); 00090 00091 if(!configuration_file) 00092 { 00093 strcpy(extern_errormsg, strerror(errno)); 00094 return NULL; 00095 } 00096 00097 /* Then, parse the file. */ 00098 program_result = NULL; 00099 00100 ganesha_yyreset(); 00101 00102 ganesha_yy_set_current_file(file_path); 00103 ganesha_yyin = configuration_file; 00104 00105 if(ganesha_yyparse()) 00106 { 00107 fclose(configuration_file); 00108 return NULL; 00109 } 00110 00113 /* Finally, build the output struct. */ 00114 00115 output_struct = (config_struct_t *) malloc(sizeof(config_struct_t)); 00116 00117 if(!output_struct) 00118 { 00119 strcpy(extern_errormsg, strerror(errno)); 00120 fclose(configuration_file); 00121 return NULL; 00122 } 00123 00124 output_struct->syntax_tree = program_result; 00125 00126 /* converts pointer to pointer */ 00127 fclose(configuration_file); 00128 return (config_file_t) output_struct; 00129 00130 } 00131 00132 /* If config_ParseFile returns a NULL pointer, 00133 * config_GetErrorMsg returns a detailled message 00134 * to indicate the reason for this error. 00135 */ 00136 char *config_GetErrorMsg() 00137 { 00138 00139 return extern_errormsg; 00140 00141 } 00142 00148 void config_Print(FILE * output, config_file_t config) 00149 { 00150 00151 /* sanity check */ 00152 if(!config) 00153 return; 00154 00155 config_print_list(output, ((config_struct_t *) config)->syntax_tree); 00156 00157 } 00158 00164 void config_Free(config_file_t config) 00165 { 00166 00167 config_struct_t *config_struct = (config_struct_t *) config; 00168 00169 if(!config_struct) 00170 return; 00171 00172 config_free_list(config_struct->syntax_tree); 00173 00174 free(config_struct); 00175 00176 return; 00177 00178 } 00179 00184 int config_GetNbBlocks(config_file_t config) 00185 { 00186 00187 config_struct_t *config_struct = (config_struct_t *) config; 00188 00189 if(!config_struct) 00190 return -EFAULT; 00191 00192 /* on regarde si la liste est vide */ 00193 if(!(*config_struct->syntax_tree)) 00194 { 00195 return 0; 00196 } 00197 /* on compte le nombre d'elements */ 00198 else 00199 { 00200 /* il y a au moins un element : le premier */ 00201 generic_item *curr_block = (*config_struct->syntax_tree); 00202 int nb = 1; 00203 00204 while((curr_block = curr_block->next) != NULL) 00205 { 00206 nb++; 00207 } 00208 00209 return nb; 00210 } 00211 } 00212 00213 /* retrieves a given block from the config file, from its index */ 00214 config_item_t config_GetBlockByIndex(config_file_t config, unsigned int block_no) 00215 { 00216 config_struct_t *config_struct = (config_struct_t *) config; 00217 generic_item *curr_block; 00218 unsigned int i; 00219 00220 if(!config_struct->syntax_tree || !(*config_struct->syntax_tree)) 00221 return NULL; 00222 00223 for(i = 0, curr_block = (*config_struct->syntax_tree); 00224 curr_block != NULL; curr_block = curr_block->next, i++) 00225 { 00226 if(i == block_no) 00227 return (config_item_t) curr_block; 00228 } 00229 00230 /* not found */ 00231 return NULL; 00232 } 00233 00234 /* Return the name of a block */ 00235 char *config_GetBlockName(config_item_t block) 00236 { 00237 generic_item *curr_block = (generic_item *) block; 00238 00239 if(!curr_block || (curr_block->type != TYPE_BLOCK)) 00240 return NULL; 00241 00242 return curr_block->item.block.block_name; 00243 } 00244 00245 /* Indicates how many items are defines in a block */ 00246 int config_GetNbItems(config_item_t block) 00247 { 00248 generic_item *the_block = (generic_item *) block; 00249 00250 if(!the_block || (the_block->type != TYPE_BLOCK)) 00251 return -1; 00252 00253 /* on regarde si la liste est vide */ 00254 if(!(the_block->item.block.block_content)) 00255 { 00256 return 0; 00257 } 00258 /* on compte le nombre d'elements */ 00259 else 00260 { 00261 /* il y a au moins un element : le premier */ 00262 generic_item *curr_block = the_block->item.block.block_content; 00263 int nb = 1; 00264 00265 while((curr_block = curr_block->next) != NULL) 00266 { 00267 nb++; 00268 } 00269 00270 return nb; 00271 } 00272 00273 } 00274 00275 /* retrieves a given block from the config file, from its index */ 00276 config_item_t config_GetItemByIndex(config_item_t block, unsigned int item_no) 00277 { 00278 generic_item *the_block = (generic_item *) block; 00279 generic_item *curr_item; 00280 unsigned int i; 00281 00282 if(!the_block || (the_block->type != TYPE_BLOCK)) 00283 return NULL; 00284 00285 for(i = 0, curr_item = the_block->item.block.block_content; 00286 curr_item != NULL; curr_item = curr_item->next, i++) 00287 { 00288 if(i == item_no) 00289 return (config_item_t) curr_item; 00290 } 00291 00292 /* not found */ 00293 return NULL; 00294 } 00295 00296 /* indicates which type of item it is */ 00297 config_item_type config_ItemType(config_item_t item) 00298 { 00299 generic_item *the_item = (generic_item *) item; 00300 00301 if(the_item->type == TYPE_BLOCK) 00302 return CONFIG_ITEM_BLOCK; 00303 else if(the_item->type == TYPE_AFFECT) 00304 return CONFIG_ITEM_VAR; 00305 else 00306 return 0; 00307 } 00308 00309 /* Retrieves a key-value peer from a CONFIG_ITEM_VAR */ 00310 int config_GetKeyValue(config_item_t item, char **var_name, char **var_value) 00311 { 00312 generic_item *var = (generic_item *) item; 00313 00314 if(!var || (var->type != TYPE_AFFECT)) 00315 return -1; 00316 00317 *var_name = var->item.affect.varname; 00318 *var_value = var->item.affect.varvalue; 00319 00320 return 0; 00321 } 00322 00323 /* get an item from a list with the given name */ 00324 static generic_item *GetItemFromList(generic_item * list, const char *name) 00325 { 00326 generic_item *curr; 00327 00328 if(!list) 00329 return NULL; 00330 00331 for(curr = list; curr != NULL; curr = curr->next) 00332 { 00333 if((curr->type == TYPE_BLOCK) 00334 && !STRNCMP(curr->item.block.block_name, name, MAXSTRLEN)) 00335 return curr; 00336 if((curr->type == TYPE_AFFECT) 00337 && !STRNCMP(curr->item.affect.varname, name, MAXSTRLEN)) 00338 return curr; 00339 } 00340 /* not found */ 00341 return NULL; 00342 00343 } 00344 00349 static int CheckDuplicateEntry(generic_item * list, const char *name) 00350 { 00351 generic_item *curr; 00352 unsigned int found=0; 00353 00354 if(!list) 00355 return 0; 00356 00357 for(curr = list; curr != NULL; curr = curr->next) 00358 { 00359 if((curr->type == TYPE_BLOCK) 00360 && !STRNCMP(curr->item.block.block_name, name, MAXSTRLEN)) 00361 found++; 00362 if((curr->type == TYPE_AFFECT) 00363 && !STRNCMP(curr->item.affect.varname, name, MAXSTRLEN)) 00364 found++; 00365 if ( found > 1 ) 00366 break; 00367 } 00368 return ( found > 1 ); 00369 } 00370 00371 /* Returns the block with the specified name. This name can be "BLOCK::SUBBLOCK::SUBBLOCK" */ 00372 config_item_t internal_FindItemByName(config_file_t config, const char *name, int * unique) 00373 { 00374 config_struct_t *config_struct = (config_struct_t *) config; 00375 generic_item *block; 00376 generic_item *list; 00377 char *separ; 00378 char *current; 00379 char tmp_name[MAXSTRLEN]; 00380 00381 /* connot be found if empty */ 00382 if(!config_struct->syntax_tree || !(*config_struct->syntax_tree)) 00383 return NULL; 00384 00385 list = *config_struct->syntax_tree; 00386 00387 strncpy(tmp_name, name, MAXSTRLEN); 00388 tmp_name[MAXSTRLEN - 1] = '\0'; 00389 current = tmp_name; 00390 00391 while(current) 00392 { 00393 /* first, split the name into BLOCK/SUBBLOC/SUBBLOC */ 00394 separ = strstr(current, "::"); 00395 00396 /* it is a whole name */ 00397 if(!separ) 00398 { 00399 if (unique) { 00400 *unique = !CheckDuplicateEntry(list, current); 00401 sprintf(extern_errormsg, "Configuration item '%s' is not unique", name); 00402 } 00403 return (config_item_t) GetItemFromList(list, current); 00404 } 00405 else 00406 { 00407 /* split the name */ 00408 *separ = '\0'; 00409 00410 if((separ - tmp_name) < MAXSTRLEN - 2) 00411 separ += 2; 00412 else 00413 return NULL; /* overflow */ 00414 00415 block = GetItemFromList(list, current); 00416 00417 /* not found or not a block ? */ 00418 if(!block || (block->type != TYPE_BLOCK)) 00419 return NULL; 00420 00421 list = block->item.block.block_content; 00422 00423 /* "::" was found, must have something after */ 00424 current = separ; 00425 } 00426 } 00427 00428 /* not found */ 00429 return NULL; 00430 } 00431 00432 config_item_t config_FindItemByName(config_file_t config, const char *name) 00433 { 00434 return internal_FindItemByName(config, name, NULL); 00435 } 00436 00437 config_item_t config_FindItemByName_CheckUnique(config_file_t config, const char *name, int * unique) 00438 { 00439 return internal_FindItemByName(config, name, unique); 00440 } 00441 00442 /* Directly returns the value of the key with the specified name. 00443 * This name can be "BLOCK::SUBBLOCK::SUBBLOCK::VARNAME" 00444 */ 00445 char *config_FindKeyValueByName(config_file_t config, const char *key_name) 00446 { 00447 generic_item *var; 00448 00449 var = (generic_item *) config_FindItemByName(config, key_name); 00450 00451 if(!var || (var->type != TYPE_AFFECT)) 00452 return NULL; 00453 else 00454 return var->item.affect.varvalue; 00455 00456 } 00457 00458 /* Returns a block or variable with the specified name from the given block" */ 00459 config_item_t config_GetItemByName(config_item_t block, const char *name) 00460 { 00461 generic_item *curr_block = (generic_item *) block; 00462 generic_item *list; 00463 char *separ; 00464 char *current; 00465 char tmp_name[MAXSTRLEN]; 00466 00467 /* cannot be found if empty or non block */ 00468 if(!curr_block || (curr_block->type != TYPE_BLOCK)) 00469 return NULL; 00470 00471 list = curr_block->item.block.block_content; 00472 00473 strncpy(tmp_name, name, MAXSTRLEN); 00474 tmp_name[MAXSTRLEN - 1] = '\0'; 00475 current = tmp_name; 00476 00477 while(current) 00478 { 00479 /* first, split the name into BLOCK/SUBBLOC/SUBBLOC */ 00480 separ = strstr(current, "::"); 00481 00482 /* it is a whole name */ 00483 if(!separ) 00484 return (config_item_t) GetItemFromList(list, current); 00485 else 00486 { 00487 /* split the name */ 00488 *separ = '\0'; 00489 00490 if((separ - tmp_name) < MAXSTRLEN - 2) 00491 separ += 2; 00492 else 00493 return NULL; /* overflow */ 00494 00495 curr_block = GetItemFromList(list, current); 00496 00497 /* not found or not a block ? */ 00498 if(!curr_block || (curr_block->type != TYPE_BLOCK)) 00499 return NULL; 00500 00501 list = curr_block->item.block.block_content; 00502 00503 /* "::" was found, must have something after */ 00504 current = separ; 00505 } 00506 } 00507 00508 /* not found */ 00509 return NULL; 00510 00511 } 00512 00513 /* Directly returns the value of the key with the specified name 00514 * relative to the given block. 00515 */ 00516 char *config_GetKeyValueByName(config_item_t block, const char *key_name) 00517 { 00518 generic_item *var; 00519 00520 var = (generic_item *) config_GetItemByName(block, key_name); 00521 00522 if(!var || (var->type != TYPE_AFFECT)) 00523 return NULL; 00524 else 00525 return var->item.affect.varvalue; 00526 00527 }