OpenCBM
configuration.c
Go to the documentation of this file.
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version
5  * 2 of the License, or (at your option) any later version.
6  *
7  * Copyright 2007-2009 Spiro Trikaliotis
8  *
9  */
10 
20 #include "arch.h"
21 #include "configuration.h"
22 #include "libmisc.h"
23 
24 #include <assert.h>
25 #include <errno.h>
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <string.h>
29 
37 #define ASSUMED_MAX_LINE_LENGTH 256
38 
41 
53  char * Name;
54  char * Value;
55  char * Comment;
56 };
57 
58 
61 
72  char * Name;
73  char * Comment;
74 };
75 
79 typedef
82  const char * FileName;
83  const char * FileNameForWrite;
85  unsigned int Changed;
87 
123 entry_alloc_new(opencbm_configuration_section_t * CurrentSection,
124  opencbm_configuration_entry_t * PreviousEntry,
125  const char * EntryName,
126  const char * Value,
127  const char * Comment)
128 {
129  opencbm_configuration_entry_t * newEntry = NULL;
130 
131  assert(CurrentSection != NULL);
132 
133  do {
134  newEntry = malloc(sizeof(*newEntry));
135 
136  if (newEntry == NULL)
137  break;
138 
139  memset(newEntry, 0, sizeof(*newEntry));
140  newEntry->Comment = cbmlibmisc_strdup(Comment);
141  newEntry->Name = cbmlibmisc_strdup(EntryName);
142  newEntry->Next = NULL;
143 
144  if (Value) {
145  newEntry->Value = cbmlibmisc_strdup(Value);
146  }
147  else {
148  newEntry->Value = NULL;
149  }
150 
151  if (PreviousEntry != NULL) {
152  PreviousEntry->Next = newEntry;
153  }
154  else {
155  newEntry->Next = CurrentSection->Entries;
156  CurrentSection->Entries = newEntry;
157  }
158 
159  } while (0);
160 
161  return newEntry;
162 }
163 
173 configuration_entry_free(opencbm_configuration_entry_t * Entry)
174 {
175  opencbm_configuration_entry_t * next_entry = NULL;
176 
177  assert(Entry != NULL);
178 
179  if (Entry != NULL) {
180  next_entry = Entry->Next;
181 
182  cbmlibmisc_strfree(Entry->Comment);
183  cbmlibmisc_strfree(Entry->Name);
184  cbmlibmisc_strfree(Entry->Value);
185 
186  free(Entry);
187  }
188 
189  return next_entry;
190 }
191 
224 section_alloc_new(opencbm_configuration_t * Configuration,
225  opencbm_configuration_section_t * PreviousSection,
226  const char * const SectionName,
227  const char * const Comment)
228 {
229  opencbm_configuration_section_t * newSection = NULL;
230 
231  do {
232  newSection = malloc(sizeof(*newSection));
233 
234  if (newSection == NULL) {
235  break;
236  }
237 
238  memset(newSection, 0, sizeof(*newSection));
239  newSection->Entries = NULL;
240  newSection->Comment = cbmlibmisc_strdup(Comment);
241  newSection->Next = NULL;
242 
243  if (SectionName) {
244  newSection->Name = cbmlibmisc_strdup(SectionName);
245  }
246  else {
247  newSection->Name = NULL;
248  }
249 
250  if (PreviousSection != NULL) {
251  PreviousSection->Next = newSection;
252  }
253  else {
254  newSection->Next = Configuration->Sections;
255  Configuration->Sections = newSection;
256  }
257 
258  } while (0);
259 
260  return newSection;
261 }
262 
272 configuration_section_free(opencbm_configuration_section_t * Section)
273 {
274  opencbm_configuration_section_t * next_section = NULL;
275 
276  assert(Section != NULL);
277 
278  if (Section != NULL) {
280 
281  next_section = Section->Next;
282 
283  entry = Section->Entries;
284 
285  while (entry) {
286  entry = configuration_entry_free(entry);
287  }
288 
289  cbmlibmisc_strfree(Section->Comment);
290  cbmlibmisc_strfree(Section->Name);
291 
292  free(Section);
293  }
294 
295  return next_section;
296 }
297 
311 static unsigned int
312 configuration_read_line_handle_comment(char * Buffer, char ** Comment)
313 {
314  unsigned int handledComment = 0;
315  char * commentBuffer = NULL;
316 
317  do {
318  if (Comment == NULL || Buffer == NULL || *Buffer == 0)
319  break;
320 
321  commentBuffer = malloc(strlen(Buffer) + 1);
322 
323  if (commentBuffer == NULL) {
324  break;
325  }
326 
327  strcpy(commentBuffer, Buffer);
328 
329  *Comment = commentBuffer;
330 
331  handledComment = 1;
332 
333  } while (0);
334 
335  return handledComment;
336 }
337 
341 static char *
342 read_a_complete_line(FILE * File)
343 {
344  char * buffer = NULL;
345  char * addbuffer = NULL;
346 
347  unsigned int error = 1;
348 
349  do {
350  unsigned int bufferLength;
351 
353 
354  if (addbuffer == NULL) {
355  break;
356  }
357 
358  if (fgets(addbuffer, ASSUMED_MAX_LINE_LENGTH, File) == NULL) {
359 
360  /* error or EOF, quit */
361 
362  error = ferror(File) ? 1 : 0;
363  break;
364  }
365 
366  /* add the addbuffer to the buffer */
367 
368  if (buffer == NULL) {
369  buffer = addbuffer;
370  addbuffer = NULL;
371  }
372  else {
373  char * tmpbuffer = cbmlibmisc_strcat(buffer, addbuffer);
374 
375  cbmlibmisc_strfree(addbuffer);
376  addbuffer = NULL;
377 
378  cbmlibmisc_strfree(buffer);
379 
380  buffer = tmpbuffer;
381 
382  if (tmpbuffer == NULL) {
383  break;
384  }
385 
386  }
387 
388  /* If there is a newline, the line is complete */
389 
390  bufferLength = strlen(buffer);
391 
392  if ( (bufferLength > 0) && buffer[bufferLength - 1] == '\n')
393  {
394  buffer[bufferLength - 1] = 0;
395 
396  error = 0;
397  break;
398  }
399  } while (1);
400 
401  if (error) {
402  cbmlibmisc_strfree(buffer);
403  buffer = NULL;
404  }
405  else {
406 
407  if (buffer == NULL) {
408  buffer = cbmlibmisc_strdup("");
409  }
410  }
411 
412  cbmlibmisc_strfree(addbuffer);
413 
414  return buffer;
415 }
416 
440 static char *
441 configuration_read_line(opencbm_configuration_handle Handle, char ** Comment, FILE * ConfigFile)
442 {
443  char * buffer = NULL;
444  char * ret = NULL;
445 
446  do {
447  if (Comment) {
448  *Comment = NULL;
449  }
450 
451  /* If we already reached the end of file, abort here */
452 
453  if (feof(ConfigFile))
454  break;
455 
456  /* If we got an error, abort here */
457 
458  if (ferror(ConfigFile))
459  break;
460 
461  /* Read in a line */
462 
463  buffer = read_a_complete_line(ConfigFile);
464 
465  if (buffer == NULL) {
466  break;
467  }
468 
469  if (buffer[0] == '#') {
470  if (configuration_read_line_handle_comment(buffer, Comment)) {
471  cbmlibmisc_strfree(buffer);
472  break;
473  }
474  }
475  else {
476  char *p;
477 
478  ret = buffer;
479 
480  /* search for a comment and trim it if it exists */
481 
482  p = strchr(buffer, '#');
483 
484  /* If there is no comment, begin at the end of line */
485 
486  if (p == NULL)
487  p = buffer + strlen(buffer);
488 
489  while (p && (p > buffer))
490  {
491  /* trim any spaces from the right, if available */
492 
493  switch (*--p)
494  {
495  case ' ':
496  case '\t':
497  case 13:
498  case 10:
499  break;
500 
501  default:
502  configuration_read_line_handle_comment(++p, Comment);
503  *p = 0;
504  p = NULL;
505  }
506  }
507 
508  if (p == buffer)
509  *p = 0;
510 
511  break;
512  }
513 
514  } while (0);
515 
516  return ret;
517 }
518 
534 static int
535 opencbm_configuration_parse_file(opencbm_configuration_handle Handle, FILE * ConfigFile)
536 {
537  int error = 1;
538 
539  do {
540  opencbm_configuration_section_t * currentSection = NULL;
541  opencbm_configuration_entry_t * previousEntry = NULL;
542  char * line = NULL;
543 
544  /* First, check if we successfully opened the configuration file */
545 
546  if (Handle == NULL)
547  break;
548 
549  assert(ConfigFile != NULL);
550 
551  /* Seek to the beginning of the file */
552 
553  fseek(ConfigFile, 0, SEEK_SET);
554 
555 
556  Handle->Sections = section_alloc_new(Handle, NULL, NULL, "");
557  if (Handle->Sections == NULL) {
558  break;
559  }
560 
561  currentSection = Handle->Sections;
562 
563  /* Now, search section after section */
564 
565  do {
566  char * comment = NULL;
567 
568  if (line) {
569  cbmlibmisc_strfree(line);
570  }
571 
572  line = configuration_read_line(Handle, &comment, ConfigFile);
573 
574  /* assume an error, if not cleared later */
575 
576  error = 1;
577 
578  if (line == NULL && comment == NULL) {
579 
580  /* The end of the file has been reached */
581 
582  error = 0;
583  break;
584  }
585 
586  /* Check if we found a new section */
587 
588  if (line && (line[0] == '['))
589  {
590  char * sectionName = NULL;
591  char * p;
592 
593  sectionName = cbmlibmisc_strdup(&line[1]);
594  if (sectionName == NULL)
595  break;
596 
597  p = strrchr(sectionName, ']');
598 
599  /* This is tricky. If the current line has no closing bracket,
600  * we will ignore this. Thus, this function will "correct"
601  * this error. Note that this correction can be performed in
602  * an incorrect way. However, changes are higher the user
603  * will recognise this change and find out that he has done
604  * something wrong.
605  */
606  if (p != 0) {
607  *p = 0;
608  }
609 
610  /* a new section starts */
611 
612  currentSection = section_alloc_new(Handle, currentSection, sectionName, comment);
613  cbmlibmisc_strfree(sectionName);
614 
615  if (currentSection == NULL) {
616  break;
617  }
618 
619  /* make sure to add the new entries to this section, not after
620  * the last entry of the previous section
621  */
622  previousEntry = NULL;
623 
624  error = 0;
625  }
626  else {
627  char * entryName = NULL;
628  char * value = NULL;
629 
630  /* this line is (still) part of the current section */
631 
632  if (line) {
633  char * p;
634 
635  /* process the entry */
636 
637  p = strchr(line, '=');
638 
639  if (p == NULL) {
640 
641  /* the line is not formatted correctly. It is no real entry! */
642 
643  value = cbmlibmisc_strdup(line);
644  }
645  else {
646  /* split the line into entry name and value */
647 
648  *p = 0;
649  entryName = cbmlibmisc_strdup(line);
650  value = cbmlibmisc_strdup(p+1);
651  }
652  }
653 
654  previousEntry = entry_alloc_new(currentSection, previousEntry,
655  entryName, value, comment);
656 
657  cbmlibmisc_strfree(entryName);
658  cbmlibmisc_strfree(value);
659  cbmlibmisc_strfree(comment);
660  comment = NULL;
661 
662  if (previousEntry == NULL) {
663  break;
664  }
665 
666  error = 0;
667  }
668 
669  cbmlibmisc_strfree(comment);
670 
671  } while ( ! error);
672 
673  if (line) {
674  cbmlibmisc_strfree(line);
675  }
676 
677  } while (0);
678 
679  return error;
680 }
681 
695 static int
696 opencbm_configuration_write_file(opencbm_configuration_handle Handle)
697 {
698  FILE * configfile = NULL;
699 
700  int error = 0;
701 
702  do {
703  opencbm_configuration_section_t * currentSection;
704 
705  /* First, check if we successfully opened the configuration file */
706 
707  if (Handle == NULL)
708  break;
709 
710  configfile = fopen(Handle->FileNameForWrite, "wt");
711 
712  if (configfile == NULL) {
713  error = 1;
714  break;
715  }
716 
717  /* Seek to the beginning of the file */
718 
719  fseek(configfile, 0, SEEK_SET);
720 
721  for (currentSection = Handle->Sections;
722  (currentSection != NULL) && (error == 0);
723  currentSection = currentSection->Next) {
724 
725  opencbm_configuration_entry_t * currentEntry;
726 
727  /*
728  * Process all section names but the first one.
729  * The first section is special as it is no real section
730  */
731  if (currentSection != Handle->Sections) {
732  if (fprintf(configfile, "[%s]%s\n",
733  currentSection->Name, currentSection->Comment) < 0)
734  {
735  error = 1;
736  }
737  }
738 
739  for (currentEntry = currentSection->Entries;
740  (currentEntry != NULL) && (error == 0);
741  currentEntry = currentEntry->Next)
742  {
743  if (fprintf(configfile, "%s%s%s%s\n",
744  (currentEntry->Name ? currentEntry->Name : ""),
745  (currentEntry->Name && *(currentEntry->Name)) ? "=" : "",
746  (currentEntry->Value ? currentEntry->Value : ""),
747  currentEntry->Comment) < 0)
748  {
749  error = 1;
750  }
751  }
752  }
753 
754  } while (0);
755 
756  if (configfile) {
757  fclose(configfile);
758  }
759 
760  do {
761  if (error != 0) {
762  break;
763  }
764 
765  if (Handle == NULL || Handle->FileName == NULL || Handle->FileNameForWrite == NULL) {
766  error = 1;
767  break;
768  }
769 
770  if (arch_unlink(Handle->FileName)) {
771  error = 1;
772  break;
773  }
774 
775  if (rename(Handle->FileNameForWrite, Handle->FileName)) {
776  error = 1;
777  break;
778  }
779 
780  } while(0);
781 
782  return error;
783 }
784 
804 opencbm_configuration_open(const char * Filename)
805 {
807  unsigned int error = 1;
808 
809  FILE * configFile = NULL;
810 
811  do {
812  handle = malloc(sizeof(*handle));
813 
814  if (!handle) {
815  break;
816  }
817 
818  memset(handle, 0, sizeof(*handle));
819 
820  handle->Sections = NULL;
821 
822  handle->FileName = cbmlibmisc_strdup(Filename);
823  handle->FileNameForWrite = cbmlibmisc_strcat(handle->FileName, ".tmp");
824  handle->Changed = 0;
825 
826  if ( (handle->FileName == NULL) || (handle->FileNameForWrite == NULL)) {
827  break;
828  }
829 
830  configFile = fopen(handle->FileName, "rt");
831 
832  if (configFile == NULL) {
833  break;
834  }
835 
836  opencbm_configuration_parse_file(handle, configFile);
837 
838  fclose(configFile);
839 
840  error = 0;
841 
842  } while (0);
843 
844  if (error && handle) {
845  cbmlibmisc_strfree(handle->FileName);
847  free(handle);
848  handle = NULL;
849  }
850 
851  return handle;
852 }
853 
854 
869 opencbm_configuration_create(const char * Filename)
870 {
871  opencbm_configuration_handle handle = NULL;
872 
873  do {
874  handle = opencbm_configuration_open(Filename);
875 
876  if (handle == NULL) {
877 
878  FILE * filehandle;
879  filehandle = fopen(Filename, "wt");
880 
881  if (filehandle == NULL)
882  break;
883 
884  fclose(filehandle);
885 
886  handle = opencbm_configuration_open(Filename);
887  if (handle == NULL)
888  break;
889  }
890 
891  } while (0);
892 
893  return handle;
894 }
895 
902 static void
903 opencbm_configuration_free_all(opencbm_configuration_handle Handle)
904 {
906 
907  section = Handle->Sections;
908 
909  while (section != NULL)
910  {
911  section = configuration_section_free(section);
912  }
913 
914  cbmlibmisc_strfree(Handle->FileName);
916 
917  free(Handle);
918 }
919 
933 int
935 {
936  int error = 0;
937 
938  do {
939  if (Handle == NULL) {
940  break;
941  }
942 
943  if (Handle->Changed) {
944  error = opencbm_configuration_write_file(Handle);
945  }
946 
947  } while(0);
948 
949  return error;
950 }
951 
966 int
968 {
969  int error = 0;
970 
971  do {
972  if (Handle == NULL) {
973  break;
974  }
975 
976  error = opencbm_configuration_flush(Handle);
977 
978  opencbm_configuration_free_all(Handle);
979 
980  } while(0);
981 
982  return error;
983 }
984 
1007 opencbm_configuration_find_section(opencbm_configuration_handle Handle,
1008  const char Section[],
1009  unsigned int Create,
1010  opencbm_configuration_section_t ** PreviousSection)
1011 {
1012  opencbm_configuration_section_t *currentSection = NULL;
1013  opencbm_configuration_section_t *lastSection = NULL;
1014 
1015  do {
1016  /* Check if there is a section given */
1017 
1018  if (Section == NULL) {
1019  break;
1020  }
1021 
1022  for (currentSection = Handle->Sections;
1023  currentSection != NULL;
1024  currentSection = currentSection->Next)
1025  {
1026  int foundSection = 0;
1027 
1028  if (currentSection->Name == NULL) {
1029  foundSection = Section == NULL;
1030  }
1031  else {
1032  if (Section) {
1033  foundSection = (strcmp(currentSection->Name, Section) == 0);
1034  }
1035  }
1036 
1037  if (foundSection) {
1038  break;
1039  }
1040 
1041  lastSection = currentSection;
1042  }
1043 
1044  if (Create && currentSection == NULL) {
1045 
1046  /* there was no section with that name, generate a new one */
1047 
1048  currentSection = section_alloc_new(Handle, lastSection, Section, NULL);
1049  }
1050 
1051  } while(0);
1052 
1053  return currentSection;
1054 }
1055 
1089 opencbm_configuration_find_data_ex(opencbm_configuration_handle Handle,
1090  const char Section[], const char Entry[],
1091  unsigned int Create,
1092  opencbm_configuration_entry_t ** LastEntry,
1093  opencbm_configuration_section_t ** LastSection)
1094 {
1095  opencbm_configuration_section_t *currentSection = NULL;
1096  opencbm_configuration_section_t *lastSection = NULL;
1097  opencbm_configuration_entry_t *lastEntry = NULL;
1098 
1099  opencbm_configuration_entry_t * currentEntry = NULL;
1100 
1101  assert(LastEntry != NULL);
1102  assert(LastSection != NULL);
1103 
1104  do {
1105  *LastEntry = NULL;
1106  *LastSection = NULL;
1107 
1108  /* Check if there is a section and an entry given */
1109 
1110  if (Section == NULL || Entry == NULL) {
1111  break;
1112  }
1113 
1114  currentSection = opencbm_configuration_find_section(Handle, Section, Create, &lastSection);
1115 
1116  if (currentSection == NULL) {
1117  break;
1118  }
1119 
1120  *LastSection = currentSection;
1121 
1122  {
1123  for (currentEntry = currentSection->Entries;
1124  currentEntry != NULL;
1125  currentEntry = currentEntry->Next)
1126  {
1127  if (strcmp(currentEntry->Name, Entry) == 0) {
1128  break;
1129  }
1130 
1131  /* This if() ensures that we do not add the line after
1132  * some comments which most probably are meant for the next
1133  * section.
1134  */
1135  if (currentEntry->Name != NULL) {
1136  lastEntry = currentEntry;
1137  *LastEntry = currentEntry;
1138  }
1139  }
1140  }
1141 
1142  if (currentEntry || Create == 0) {
1143  break;
1144  }
1145 
1146  if (currentSection == NULL) {
1147 
1148  /* there was no section with that name, generate a new one */
1149 
1150  currentSection = section_alloc_new(Handle, lastSection, Section, NULL);
1151  }
1152 
1153  currentEntry = entry_alloc_new(currentSection, lastEntry, Entry, NULL, NULL);
1154 
1155  } while(0);
1156 
1157  return currentEntry;
1158 }
1159 
1185 opencbm_configuration_find_data(opencbm_configuration_handle Handle,
1186  const char Section[], const char Entry[],
1187  unsigned int Create)
1188 {
1189  opencbm_configuration_entry_t * last_entry;
1191 
1192  return opencbm_configuration_find_data_ex(Handle, Section, Entry, Create, &last_entry, &section);
1193 }
1194 
1225 int
1227  const char Section[], const char Entry[],
1228  char ** ReturnBuffer)
1229 {
1230  unsigned int error = 1;
1231 
1232  do {
1234  opencbm_configuration_find_data(Handle, Section, Entry, 0);
1235 
1236  if (entry == NULL) {
1237  break;
1238  }
1239 
1240  /* If ReturnBufferLength is 0, we only wanted to find out if
1241  * that entry existed. Thus, report "no error" and quit.
1242  */
1243 
1244  if (ReturnBuffer != 0) {
1245 
1246  char * p = cbmlibmisc_strdup(entry->Value);
1247 
1248  if (p != NULL) {
1249  *ReturnBuffer = p;
1250  error = 0;
1251  }
1252  }
1253 
1254  } while (0);
1255 
1256  return error;
1257 }
1258 
1259 
1284 int
1287  void * Data)
1288 {
1289  unsigned int error = 0;
1290 
1291  do {
1292  opencbm_configuration_section_t *currentSection = NULL;
1293 
1294  for (currentSection = Handle->Sections;
1295  currentSection != NULL;
1296  currentSection = currentSection->Next)
1297  {
1298  error = error || Callback( Handle, currentSection->Name, Data);
1299  }
1300 
1301  } while (0);
1302 
1303  return error;
1304 }
1305 
1334 int
1336  const char Section[],
1338  void * Data)
1339 {
1340  unsigned int error = 0;
1341 
1342  do {
1343  opencbm_configuration_entry_t * currentEntry = NULL;
1344  opencbm_configuration_section_t * currentSection;
1345 
1346  currentSection = opencbm_configuration_find_section(Handle,
1347  Section, 0, NULL);
1348 
1349  if ( ! currentSection ) {
1350  error = 0;
1351  break;
1352  }
1353 
1354  for (currentEntry = currentSection->Entries;
1355  currentEntry != NULL;
1356  currentEntry = currentEntry->Next)
1357  {
1358  error = error || Callback( Handle, currentSection->Name, currentEntry->Name, Data);
1359  }
1360 
1361  } while (0);
1362 
1363  return error;
1364 }
1365 
1389 int
1391  const char Section[], const char Entry[],
1392  const char Value[])
1393 {
1394  unsigned int error = 1;
1395 
1396  do {
1397  char * newValue = NULL;
1398 
1400  opencbm_configuration_find_data(Handle, Section, Entry, 1);
1401 
1402  if (entry == NULL) {
1403  break;
1404  }
1405 
1406  Handle->Changed = 1;
1407 
1408  newValue = cbmlibmisc_strdup(Value);
1409 
1410  if (newValue == NULL) {
1411  break;
1412  }
1413 
1414  cbmlibmisc_strfree(entry->Value);
1415  entry->Value = newValue;
1416 
1417  error = 0;
1418 
1419  } while (0);
1420 
1421  return error;
1422 }
1423 
1443 int
1445  const char Section[])
1446 {
1447  opencbm_configuration_section_t * section = NULL;
1448  opencbm_configuration_section_t * previous_section = NULL;
1449 
1450  int error = 1;
1451 
1452  do {
1453  section = opencbm_configuration_find_section(Handle, Section, 0, &previous_section);
1454 
1455  if ( ! section ) {
1456  break;
1457  }
1458 
1459  if (previous_section == NULL) {
1460  Handle->Sections = configuration_section_free(section);
1461  }
1462  else {
1463  assert( previous_section->Next == section );
1464 
1465  previous_section->Next = configuration_section_free(section);
1466  }
1467 
1468  error = 0;
1469 
1470  } while (0);
1471 
1472  return error;
1473 }
1474 
1497 int
1499  const char Section[], const char EntryName[])
1500 {
1501  int error = 1;
1502 
1503  do {
1505  opencbm_configuration_entry_t * last_entry;
1507 
1508  entry = opencbm_configuration_find_data_ex(Handle, Section, EntryName, 0,
1509  &last_entry, &section);
1510 
1511  if ( ! entry ) {
1512  break;
1513  }
1514 
1515  assert(section->Entries == entry);
1516 
1517  if (last_entry == NULL) {
1518  /*
1519  * this entry is the first one in this section.
1520  * Thus, update the section structure
1521  */
1522  section->Entries = configuration_entry_free(entry);
1523  }
1524  else {
1525  /* remove the entry from the list, and free its memory */
1526  last_entry->Next = configuration_entry_free(entry);
1527  }
1528 
1529  error = 0;
1530 
1531  } while (0);
1532 
1533  return error;
1534 }
1535 
1536 /* #define OPENCBM_STANDALONE_TEST 1 */
1537 
1538 #ifdef OPENCBM_STANDALONE_TEST
1539 
1540 #if 0
1541  #ifndef NDEBUG
1542  #include <crtdbg.h>
1543  #endif
1544 #endif
1545 
1546 static void
1547 EnableCrtDebug(void)
1548 {
1549 #if 0
1550 #ifndef NDEBUG
1551  int tmpFlag;
1552 
1553  // Get current flag
1554  tmpFlag = _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG);
1555 
1556  // Turn on leak-checking bit
1557  tmpFlag |= _CRTDBG_LEAK_CHECK_DF;
1558  tmpFlag |= _CRTDBG_CHECK_ALWAYS_DF;
1559 
1560  tmpFlag |= _CRTDBG_ALLOC_MEM_DF;
1561 
1562  // Set flag to the new value
1563  _CrtSetDbgFlag(tmpFlag);
1564 #endif
1565 #endif
1566 }
1567 
1568 static unsigned int started_an_op = 0;
1569 
1570 static void
1571 OpSuccess(void)
1572 {
1573  fprintf(stderr, "success.\n\n");
1574  fflush(stderr);
1575  started_an_op = 0;
1576 }
1577 
1578 static void
1579 OpFail(void)
1580 {
1581  fprintf(stderr, "FAILED!\n\n");
1582  fflush(stderr);
1583  started_an_op = 0;
1584 }
1585 
1586 static void
1587 OpEnd(void)
1588 {
1589  if (started_an_op)
1590  OpSuccess();
1591 }
1592 
1593 static void
1594 OpStart(const char * const Operation)
1595 {
1596  OpEnd();
1597 
1598  started_an_op = 1;
1599 
1600  fprintf(stderr, "%s() ... ", Operation);
1601  fflush(stderr);
1602 }
1603 
1604 static int enum_data_callback(opencbm_configuration_handle Handle,
1605  const char Section[],
1606  const char Entry[],
1607  void * Data)
1608 {
1609  int error = 0;
1610 
1611  fprintf(stderr, "\n enum_data_callback(Handle, %s, %s, 0x%p\n", Section, Entry, Data);
1612  fflush(stderr);
1613 
1614  return error;
1615 }
1616 
1617 static int enum_sections_callback(opencbm_configuration_handle Handle,
1618  const char Section[],
1619  void * Data)
1620 {
1621  int error = 0;
1622 
1623  fprintf(stderr, "\n enum_sections_callback(Handle, %s, 0x%p\n", Section, Data);
1624  fflush(stderr);
1625  opencbm_configuration_enum_data(Handle, Section, enum_data_callback, Data);
1626 
1627  return error;
1628 }
1629 
1639 int ARCH_MAINDECL main(void)
1640 {
1641  int errorcode = EXIT_FAILURE;
1642 
1643  EnableCrtDebug();
1644 
1645  do {
1646  char * buffer;
1647 
1648  opencbm_configuration_handle handle = NULL;
1649 
1650  OpStart("opencbm_configuration_create()");
1651  handle = opencbm_configuration_create("TestFile.inf");
1652 
1653  if (handle == NULL) {
1654  break;
1655  }
1656 
1657 
1658  OpStart("opencbm_configuration_set_data(\"SectTest\", \"EntryTest\", \"VALUE\")");
1659  if (opencbm_configuration_set_data(handle, "SectTest", "EntryTest", "VALUE")) {
1660  break;
1661  }
1662 
1663  OpStart("opencbm_configuration_set_data(\"SectTest\", \"NewTest\", \"AnotherVALUE\")");
1664  if (opencbm_configuration_set_data(handle, "SectTest", "NewTest", "AnotherVALUE")) {
1665  break;
1666  }
1667 
1668 
1669  OpStart("opencbm_configuration_get_data(handle, \"SectTest\", \"NewTest\")");
1670  if (opencbm_configuration_get_data(handle, "SectTest", "NewTest", &buffer) != 0) {
1671  break;
1672  }
1673  OpEnd();
1674  fprintf(stderr, " returned: %s\n", buffer);
1675 
1676 
1677  OpStart("opencbm_configuration_set_data(\"NewSect\", \"AEntryTest\", \"aVALUE\")");
1678  if (opencbm_configuration_set_data(handle, "NewSect", "AEntryTest", "aVALUE")) {
1679  break;
1680  }
1681 
1682  OpStart("opencbm_configuration_set_data(\"NewSect\", \"BNewTest\", \"bAnotherVALUE\")");
1683  if (opencbm_configuration_set_data(handle, "NewSect", "BNewTest", "bAnotherVALUE")) {
1684  break;
1685  }
1686 
1687 
1688  OpStart("opencbm_configuration_set_data(\"SectTest\", \"NewTest\", \"RewrittenVALUE\")");
1689  if (opencbm_configuration_set_data(handle, "SectTest", "NewTest", "RewrittenVALUE")) {
1690  break;
1691  }
1692 
1693 
1694  OpStart("opencbm_configuration_get_data(handle, \"SectTest\", \"NewTest\")");
1695  if (opencbm_configuration_get_data(handle, "SectTest", "NewTest", &buffer) != 0) {
1696  break;
1697  }
1698  OpEnd();
1699  fprintf(stderr, " returned: %s\n", buffer);
1700 
1701  OpStart("opencbm_configuration_enum_sections(handle, ..., NULL)");
1702  opencbm_configuration_enum_sections(handle, enum_sections_callback, NULL);
1703  OpEnd();
1704 
1705  OpStart("opencbm_configuration_enum_sections(handle, ..., 0x12345678)");
1706  opencbm_configuration_enum_sections(handle, enum_sections_callback, 0x12345678);
1707  OpEnd();
1708 #if 0
1709 
1710 
1711 int
1714  void * Data)
1715 #endif
1716 
1717  OpStart("opencbm_configuration_close()");
1718  if (opencbm_configuration_close(handle) != 0) {
1719  break;
1720  }
1721 
1722  errorcode = EXIT_SUCCESS;
1723 
1724  } while(0);
1725 
1726  if (errorcode == EXIT_SUCCESS) {
1727  OpEnd();
1728  }
1729  else {
1730  OpFail();
1731  }
1732 
1733  return errorcode;
1734 }
1735 
1736 #endif /* #ifdef OPENCBM_STANDALONE_TEST */
struct opencbm_configuration_s opencbm_configuration_t
char * cbmlibmisc_strdup(const char *const OldString)
Duplicate a given string.
Definition: libstring.c:84
void cbmlibmisc_strfree(const char *String)
Free a string.
Definition: libstring.c:172
char * Name
Definition: configuration.c:53
int ARCH_MAINDECL main(int argc, char **argv)
Initialize the xum1541 device This function tries to find and identify the xum1541 device...
Definition: usbcfg.c:38
char * Comment
Definition: configuration.c:55
opencbm_configuration_handle opencbm_configuration_create(const char *Filename)
Creates the configuration file for reading and writing.
int opencbm_configuration_get_data(opencbm_configuration_handle Handle, const char Section[], const char Entry[], char **ReturnBuffer)
Read data from the configuration file.
opencbm_configuration_section_t * Next
Definition: configuration.c:70
int opencbm_configuration_set_data(opencbm_configuration_handle Handle, const char Section[], const char Entry[], const char Value[])
Write/Change data to/in the configuration file.
#define ASSUMED_MAX_LINE_LENGTH
the maximum line length we expect in a configuration file
Definition: configuration.c:37
char * cbmlibmisc_stralloc(unsigned int Length)
allocate memory for a string of a given size
Definition: libstring.c:41
Shared library / DLL for accessing the driver Read configuration file.
char * cbmlibmisc_strcat(const char *First, const char *Second)
Concatenate two strings.
Definition: libstring.c:202
opencbm_configuration_entry_t * Entries
Definition: configuration.c:71
const char * FileNameForWrite
Definition: configuration.c:83
int opencbm_configuration_enum_data(opencbm_configuration_handle Handle, const char Section[], opencbm_configuration_enum_data_callback_t Callback, void *Data)
Enumerate data in the configuration file.
Definition: configuration.c:51
opencbm_configuration_entry_t * Next
Definition: configuration.c:52
int opencbm_configuration_enum_data_callback_t(opencbm_configuration_handle Handle, const char Section[], const char Entry[], void *Context)
Callback type for entry enumeration.
Definition: configuration.h:72
int opencbm_configuration_section_remove(opencbm_configuration_handle Handle, const char Section[])
Remove a complete section from the configuration file.
opencbm_configuration_handle opencbm_configuration_open(const char *Filename)
Open the configuration file.
int opencbm_configuration_flush(opencbm_configuration_handle Handle)
Flush the configuration file.
Define makros and functions which account for differences between the different architectures.
int opencbm_configuration_enum_sections_callback_t(opencbm_configuration_handle Handle, const char Section[], void *Context)
Callback type for section enumeration.
Definition: configuration.h:45
char * Value
Definition: configuration.c:54
opencbm_configuration_section_t * Sections
Definition: configuration.c:81
Some functions for string handling.
int opencbm_configuration_entry_remove(opencbm_configuration_handle Handle, const char Section[], const char EntryName[])
Remove an entry from the configuration file.
int opencbm_configuration_enum_sections(opencbm_configuration_handle Handle, opencbm_configuration_enum_sections_callback_t Callback, void *Data)
Enumerate sections in the configuration file.
int opencbm_configuration_close(opencbm_configuration_handle Handle)
Close the configuration file.