gwenhywfar  4.99.8beta
dbrw.c
Go to the documentation of this file.
1 /***************************************************************************
2  begin : Tue Sep 09 2003
3  copyright : (C) 2003-2010 by Martin Preuss
4  email : martin@libchipcard.de
5 
6  ***************************************************************************
7  * *
8  * This library is free software; you can redistribute it and/or *
9  * modify it under the terms of the GNU Lesser General Public *
10  * License as published by the Free Software Foundation; either *
11  * version 2.1 of the License, or (at your option) any later version. *
12  * *
13  * This library is distributed in the hope that it will be useful, *
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
16  * Lesser General Public License for more details. *
17  * *
18  * You should have received a copy of the GNU Lesser General Public *
19  * License along with this library; if not, write to the Free Software *
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, *
21  * MA 02111-1307 USA *
22  * *
23  ***************************************************************************/
24 
25 
26 /* This file is included from db.c */
27 
28 
29 
30 int GWEN_DB_EscapeToBufferTolerant(const char *src, GWEN_BUFFER *buf) {
31  while(*src) {
32  unsigned char x;
33 
34  x=(unsigned char)*src;
35  if (!(
36  (x>='A' && x<='Z') ||
37  (x>='a' && x<='z') ||
38  (x>='0' && x<='9') ||
39  x=='%' ||
40  x=='.' ||
41  x==',' ||
42  x=='.' ||
43  x=='_' ||
44  x=='-' ||
45  x=='*' ||
46  x=='?'
47  )) {
48  unsigned char c;
49 
50  GWEN_Buffer_AppendByte(buf, '&');
51  c=(((unsigned char)(*src))>>4)&0xf;
52  if (c>9)
53  c+=7;
54  c+='0';
55  GWEN_Buffer_AppendByte(buf, c);
56  c=((unsigned char)(*src))&0xf;
57  if (c>9)
58  c+=7;
59  c+='0';
60  GWEN_Buffer_AppendByte(buf, c);
61  }
62  else
63  GWEN_Buffer_AppendByte(buf, *src);
64 
65  src++;
66  } /* while */
67 
68  return 0;
69 }
70 
71 
72 
73 int GWEN_DB_UnescapeToBufferTolerant(const char *src, GWEN_BUFFER *buf) {
74  while(*src) {
75  int charHandled;
76 
77  charHandled=0;
78  if (*src=='&') {
79  if (strlen(src)>2) {
80  unsigned char d1, d2;
81  unsigned char c;
82 
83  if (isxdigit((int)src[1]) && isxdigit((int)src[2])) {
84  /* skip '%' */
85  src++;
86  /* read first digit */
87  d1=(unsigned char)(toupper(*src));
88 
89  /* get second digit */
90  src++;
91  d2=(unsigned char)(toupper(*src));
92  /* compute character */
93  d1-='0';
94  if (d1>9)
95  d1-=7;
96  c=(d1<<4)&0xf0;
97  d2-='0';
98  if (d2>9)
99  d2-=7;
100  c+=(d2&0xf);
101  /* store character */
102  GWEN_Buffer_AppendByte(buf, (char)c);
103  charHandled=1;
104  }
105  }
106  }
107  if (!charHandled)
108  GWEN_Buffer_AppendByte(buf, *src);
109  src++;
110  } /* while */
111 
112  return 0;
113 }
114 
115 
116 
117 
118 
119 
121  const char *fname,
122  const char *type,
123  GWEN_DB_NODE *params,
124  uint32_t dbflags) {
125  GWEN_SYNCIO *sio;
126  GWEN_DBIO *dbio;
127  int rv;
128 
129  dbio=GWEN_DBIO_GetPlugin(type);
130  if (!dbio) {
131  DBG_ERROR(GWEN_LOGDOMAIN, "Plugin \"%s\" is not supported", type);
133  }
134 
137  rv=GWEN_SyncIo_Connect(sio);
138  if (rv<0) {
139  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
140  GWEN_SyncIo_free(sio);
141  return rv;
142  }
143 
144  rv=GWEN_DBIO_Import(dbio, sio, db, params, dbflags);
145  if (rv<0) {
146  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
147  }
149  GWEN_SyncIo_free(sio);
150 
151  return rv;
152 }
153 
154 
155 
157  const char *fname,
158  const char *type,
159  GWEN_DB_NODE *params,
160  uint32_t dbflags) {
161  int rv;
162  GWEN_DBIO *dbio;
163 
164  dbio=GWEN_DBIO_GetPlugin(type);
165  if (!dbio) {
166  DBG_ERROR(GWEN_LOGDOMAIN, "Plugin \"%s\" is not supported", type);
168  }
169 
170  rv=GWEN_DBIO_ExportToFile(dbio, fname, db, params, dbflags);
171  if (rv) {
172  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
173  return rv;
174  }
175 
176  return 0;
177 }
178 
179 
180 
182  GWEN_FAST_BUFFER *fb,
183  uint32_t dbflags,
184  int insert) {
185  GWEN_DB_NODE *n;
186  GWEN_DB_NODE *cn;
187  int i;
188  int err;
189  int lastWasVar;
190 
191  lastWasVar=0;
192 
193  n=GWEN_DB_Node_List_First(node->children);
194  while(n) {
195  if (!(n->nodeFlags & GWEN_DB_NODE_FLAGS_VOLATILE)) {
196  DBG_VERBOUS(GWEN_LOGDOMAIN, "Writing node");
197  switch(n->typ) {
199  if (dbflags & GWEN_DB_FLAGS_WRITE_SUBGROUPS) {
200  GWEN_BUFFER *tbuf;
201 
202  if (dbflags & GWEN_DB_FLAGS_ADD_GROUP_NEWLINES) {
203  if (lastWasVar) {
204  /* only insert newline if the last one before this group was a
205  * variable */
206  GWEN_FASTBUFFER_WRITELINE(fb, err, "");
207  if (err<0) {
208  DBG_INFO(GWEN_LOGDOMAIN, "called from here");
209  return err;
210  }
211  }
212  }
213 
214  /* indend */
215  if (dbflags & GWEN_DB_FLAGS_INDEND) {
216  for (i=0; i<insert; i++) {
217  GWEN_FASTBUFFER_WRITEBYTE(fb, err, ' ');
218  if (err<0) {
219  DBG_INFO(GWEN_LOGDOMAIN, "called from here");
220  return err;
221  }
222  } /* for */
223  } /* if indend */
224 
225  tbuf=GWEN_Buffer_new(0, 128, 0, 1);
226  err=GWEN_DB_EscapeToBufferTolerant(n->data.dataName, tbuf);
227  if (err<0) {
228  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", err);
229  GWEN_Buffer_free(tbuf);
230  return err;
231  }
232 
234  GWEN_Buffer_GetStart(tbuf),
236  GWEN_Buffer_free(tbuf);
237  if (err<0) {
238  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", err);
239  return err;
240  }
241  GWEN_FASTBUFFER_WRITELINE(fb, err, " {");
242  if (err<0) {
243  DBG_INFO(GWEN_LOGDOMAIN, "called from here");
244  return err;
245  }
246  err=GWEN_DB_WriteGroupToIoLayer(n, fb, dbflags, insert+2);
247  if (err<0)
248  return err;
249 
250  /* indend */
251  if (dbflags & GWEN_DB_FLAGS_INDEND) {
252  for (i=0; i<insert; i++) {
253  GWEN_FASTBUFFER_WRITEBYTE(fb, err, ' ');
254  if (err<0) {
255  DBG_INFO(GWEN_LOGDOMAIN, "called from here");
256  return err;
257  }
258  } /* for */
259  } /* if indend */
260 
261  if (dbflags & GWEN_DB_FLAGS_DETAILED_GROUPS) {
262  GWEN_FASTBUFFER_WRITEFORCED(fb, err, "} #", -1);
263  if (err<0) {
264  DBG_INFO(GWEN_LOGDOMAIN, "called from here");
265  return err;
266  }
267  GWEN_FASTBUFFER_WRITELINE(fb, err, n->data.dataName);
268  if (err<0) {
269  DBG_INFO(GWEN_LOGDOMAIN, "called from here");
270  return err;
271  }
272  } /* if detailed groups */
273  else {
274  GWEN_FASTBUFFER_WRITELINE(fb, err, "}");
275  if (err<0) {
276  DBG_INFO(GWEN_LOGDOMAIN, "called from here");
277  return err;
278  }
279  }
280  if (dbflags & GWEN_DB_FLAGS_ADD_GROUP_NEWLINES) {
281  if (GWEN_DB_Node_List_Next(n)) {
282  /* only insert newline if something
283  * is following on the same level */
284  GWEN_FASTBUFFER_WRITELINE(fb, err, "");
285  if (err<0) {
286  DBG_INFO(GWEN_LOGDOMAIN, "called from here");
287  return err;
288  }
289  }
290  }
291  }
292  lastWasVar=0;
293  break;
294 
296  cn=GWEN_DB_Node_List_First(n->children);
297  if (cn) {
298  char *typname;
299  int namewritten;
300  int values;
301 
302  typname=0;
303  namewritten=0;
304  values=0;
305  while(cn) {
306  char numbuffer[32];
307  char *binbuffer=NULL;
308  unsigned int bbsize;
309  const char *pvalue=NULL;
310  GWEN_BUFFER *vbuf=NULL;
311 
312  switch(cn->typ) {
314  typname="char ";
315  pvalue=cn->data.dataChar;
316  if (dbflags & GWEN_DB_FLAGS_ESCAPE_CHARVALUES) {
317  vbuf=GWEN_Buffer_new(0, strlen(pvalue)+32, 0, 1);
318  if (GWEN_Text_EscapeToBufferTolerant(pvalue, vbuf)) {
319  DBG_INFO(GWEN_LOGDOMAIN, "called from here");
320  GWEN_Buffer_free(vbuf);
321  return 1;
322  }
323  pvalue=GWEN_Buffer_GetStart(vbuf);
324  }
325  break;
326 
328  typname="int ";
329  if (GWEN_Text_NumToString(cn->data.dataInt,
330  numbuffer,
331  sizeof(numbuffer)-1,
332  0)<1) {
333  DBG_ERROR(GWEN_LOGDOMAIN, "Error writing numeric value");
334  return GWEN_ERROR_GENERIC;
335  }
336  pvalue=numbuffer;
337  break;
338 
340  bbsize=cn->dataSize*2+1;
341  binbuffer=(char*)GWEN_Memory_malloc(bbsize);
342  assert(binbuffer);
343  typname="bin ";
344  if (!GWEN_Text_ToHex(cn->data.dataBin,
345  cn->dataSize,
346  binbuffer,
347  bbsize)) {
348  DBG_ERROR(GWEN_LOGDOMAIN, "Error writing binary value");
349  return GWEN_ERROR_GENERIC;
350  }
351  pvalue=binbuffer;
352  break;
353 
355  DBG_DEBUG(GWEN_LOGDOMAIN, "Not writing ptr type");
356  break;
357 
358  default:
359  DBG_DEBUG(GWEN_LOGDOMAIN, "Unhandled type [%d]", cn->typ);
360  break;
361  }
362 
363  if (pvalue) {
364  if (!namewritten) {
365  /* write name */
366  /* indend */
367  if (dbflags & GWEN_DB_FLAGS_INDEND) {
368  for (i=0; i<insert; i++) {
369  GWEN_FASTBUFFER_WRITEBYTE(fb, err, ' ');
370  if (err<0) {
371  DBG_INFO(GWEN_LOGDOMAIN, "called from here");
372  GWEN_Memory_dealloc(binbuffer);
373  GWEN_Buffer_free(vbuf);
374  return 1;
375  }
376  } /* for */
377  } /* if indend */
378  if (!(dbflags & GWEN_DB_FLAGS_OMIT_TYPES)) {
379  GWEN_FASTBUFFER_WRITEFORCED(fb, err, typname, -1);
380  if (err<0) {
381  DBG_INFO(GWEN_LOGDOMAIN, "called from here");
382  GWEN_Memory_dealloc(binbuffer);
383  GWEN_Buffer_free(vbuf);
384  return 1;
385  }
386  }
387  if (dbflags & GWEN_DB_FLAGS_QUOTE_VARNAMES) {
388  GWEN_FASTBUFFER_WRITEBYTE(fb, err, '\"');
389  if (err<0) {
390  DBG_INFO(GWEN_LOGDOMAIN, "called from here");
391  GWEN_Memory_dealloc(binbuffer);
392  GWEN_Buffer_free(vbuf);
393  return 1;
394  }
395  }
396  GWEN_FASTBUFFER_WRITEFORCED(fb, err, n->data.dataName, -1);
397  if (err<0) {
398  DBG_INFO(GWEN_LOGDOMAIN, "called from here");
399  GWEN_Memory_dealloc(binbuffer);
400  GWEN_Buffer_free(vbuf);
401  return 1;
402  }
403  if (dbflags & GWEN_DB_FLAGS_QUOTE_VARNAMES) {
404  GWEN_FASTBUFFER_WRITEBYTE(fb, err, '\"');
405  if (err<0) {
406  DBG_INFO(GWEN_LOGDOMAIN, "called from here");
407  GWEN_Memory_dealloc(binbuffer);
408  GWEN_Buffer_free(vbuf);
409  return 1;
410  }
411  }
412  GWEN_FASTBUFFER_WRITEFORCED(fb, err, ((dbflags & GWEN_DB_FLAGS_USE_COLON)?": ":"="), -1);
413  if (err<0) {
414  DBG_INFO(GWEN_LOGDOMAIN, "called from here");
415  GWEN_Memory_dealloc(binbuffer);
416  GWEN_Buffer_free(vbuf);
417  return 1;
418  }
419  namewritten=1;
420  } /* if !namewritten */
421 
422  if (values) {
423  GWEN_FASTBUFFER_WRITEFORCED(fb, err, ", ", -1);
424  if (err<0) {
425  DBG_INFO(GWEN_LOGDOMAIN, "called from here");
426  GWEN_Memory_dealloc(binbuffer);
427  GWEN_Buffer_free(vbuf);
428  return 1;
429  }
430  }
431  values++;
432  if (dbflags & GWEN_DB_FLAGS_QUOTE_VALUES) {
433  GWEN_FASTBUFFER_WRITEBYTE(fb, err, '\"');
434  if (err<0) {
435  DBG_INFO(GWEN_LOGDOMAIN, "called from here");
436  GWEN_Memory_dealloc(binbuffer);
437  GWEN_Buffer_free(vbuf);
438  return 1;
439  }
440  }
441 
442  GWEN_FASTBUFFER_WRITEFORCED(fb, err, pvalue, -1);
443  if (err<0) {
444  DBG_INFO(GWEN_LOGDOMAIN, "called from here");
445  GWEN_Memory_dealloc(binbuffer);
446  GWEN_Buffer_free(vbuf);
447  return 1;
448  }
449 
450  if (dbflags & GWEN_DB_FLAGS_QUOTE_VALUES) {
451  GWEN_FASTBUFFER_WRITEBYTE(fb, err, '\"');
452  if (err<0) {
453  DBG_INFO(GWEN_LOGDOMAIN, "called from here");
454  GWEN_Memory_dealloc(binbuffer);
455  GWEN_Buffer_free(vbuf);
456  return 1;
457  }
458  }
459  } /* if pvalue */
460 
461  GWEN_Memory_dealloc(binbuffer);
462  GWEN_Buffer_free(vbuf);
463  cn=GWEN_DB_Node_List_Next(cn);
464  } /* while cn */
465 
466  if (namewritten) {
467  GWEN_FASTBUFFER_WRITELINE(fb, err, "");
468  if (err<0) {
469  DBG_INFO(GWEN_LOGDOMAIN, "called from here");
470  return GWEN_ERROR_GENERIC;
471  }
472  }
473  } /* if children */
474  lastWasVar=1;
475  break;
476 
477  default:
478  DBG_WARN(GWEN_LOGDOMAIN, "[unhandled node type %d]", n->typ);
479  } /* switch */
480  } /* if not volatile */
481  else {
482  DBG_DEBUG(GWEN_LOGDOMAIN, "Node is volatile, not writing it");
483  }
484  n=GWEN_DB_Node_List_Next(n);
485  } /* while */
486 
487  return 0;
488 }
489 
490 
491 
493  GWEN_FAST_BUFFER *fb,
494  uint32_t dbflags) {
495  int rv;
496 
497  rv=GWEN_DB_WriteGroupToIoLayer(node, fb, dbflags, 0);
498  if (rv<0) {
499  return rv;
500  }
501  GWEN_FASTBUFFER_FLUSH(fb, rv);
502  return rv;
503 }
504 
505 
506 
508  GWEN_SYNCIO *sio,
509  uint32_t dbflags) {
510  int rv;
511  GWEN_FAST_BUFFER *fb;
512 
513  fb=GWEN_FastBuffer_new(512, sio);
514  if (dbflags & GWEN_DB_FLAGS_DOSMODE)
516  rv=GWEN_DB_WriteGroupToIoLayer(node, fb, dbflags, 0);
517  if (rv<0) {
519  return rv;
520  }
521  GWEN_FASTBUFFER_FLUSH(fb, rv);
523  return rv;
524 }
525 
526 
527 
528 int GWEN_DB_WriteFile(GWEN_DB_NODE *n, const char *fname, uint32_t dbflags) {
529  int rv;
530  GWEN_FSLOCK *lck=0;
531  GWEN_SYNCIO *sio;
532 
533  /* if locking requested */
534  if (dbflags & GWEN_DB_FLAGS_LOCKFILE) {
535  GWEN_FSLOCK_RESULT res;
536 
538  assert(lck);
540  if (res!=GWEN_FSLock_ResultOk) {
542  "Could not apply lock to file \"%s\" (%d)",
543  fname, res);
544  GWEN_FSLock_free(lck);
545  return -1;
546  }
547  }
548 
549  /* open file */
551  if (dbflags & GWEN_DB_FLAGS_APPEND_FILE)
558  rv=GWEN_SyncIo_Connect(sio);
559  if (rv<0) {
560  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
561  GWEN_SyncIo_free(sio);
562  if (lck) {
563  GWEN_FSLock_Unlock(lck);
564  GWEN_FSLock_free(lck);
565  }
566  return rv;
567  }
568 
569  rv=GWEN_DB_WriteToIo(n, sio, dbflags);
570  if (rv<0) {
571  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
573  GWEN_SyncIo_free(sio);
574  if (lck) {
575  GWEN_FSLock_Unlock(lck);
576  GWEN_FSLock_free(lck);
577  }
578  return rv;
579  }
580 
581  rv=GWEN_SyncIo_Disconnect(sio);
582  if (rv<0) {
583  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
584  GWEN_SyncIo_free(sio);
585  if (lck) {
586  GWEN_FSLock_Unlock(lck);
587  GWEN_FSLock_free(lck);
588  }
589  return rv;
590  }
591  GWEN_SyncIo_free(sio);
592 
593  /* remove lock, if any */
594  if (lck) {
595  GWEN_FSLOCK_RESULT res;
596 
597  res=GWEN_FSLock_Unlock(lck);
598  if (res!=GWEN_FSLock_ResultOk) {
600  "Could not remove lock on file \"%s\" (%d)",
601  fname, res);
602  }
603  GWEN_FSLock_free(lck);
604  }
605 
606  return 0;
607 }
608 
609 
610 
612  uint32_t dbflags,
613  const char *typeName,
614  const char *varName,
615  uint8_t *p) {
617  GWEN_DB_NODE *dbVar;
618  GWEN_BUFFER *wbuf;
619  uint8_t *pDebug;
620 
621  pDebug=p;
622 
623  if (typeName==NULL)
624  typeName="char";
625  if (strcasecmp(typeName, "int")==0)
626  nodeType=GWEN_DB_NodeType_ValueInt;
627  else if (strcasecmp(typeName, "char")==0)
629  else if (strcasecmp(typeName, "bin")==0)
630  nodeType=GWEN_DB_NodeType_ValueBin;
631  else {
632  DBG_ERROR(GWEN_LOGDOMAIN, "Unknown type \"%s\"", typeName);
633  return GWEN_ERROR_BAD_DATA;
634  }
635 
636  dbVar=GWEN_DB_GetNode(n, varName, dbflags | GWEN_PATH_FLAGS_VARIABLE);
637  if (dbVar==NULL) {
638  DBG_INFO(GWEN_LOGDOMAIN, "Variable [%s] is not available", varName);
639  return GWEN_ERROR_GENERIC;
640  }
641 
642  wbuf=GWEN_Buffer_new(0, 32, 0, 1);
643  for (;;) {
644  int quotes=0;
645  GWEN_DB_NODE *dbVal=NULL;
646  const char *v;
647 
648  while(*p && isspace(*p))
649  p++;
650  if (!*p) {
651  DBG_INFO(GWEN_LOGDOMAIN, "Missing value");
652  GWEN_Buffer_free(wbuf);
653  return GWEN_ERROR_BAD_DATA;
654  }
655 
656  if (*p=='"') {
657  quotes=1;
658  p++;
659  }
660 
661  while(*p) {
662  if (*p=='%') {
663  uint8_t c;
664  uint8_t cHex;
665 
666  /* get first nibble */
667  p++;
668  if (!*p) {
669  DBG_INFO(GWEN_LOGDOMAIN, "Incomplete escape sequence");
670  GWEN_Buffer_free(wbuf);
671  return GWEN_ERROR_BAD_DATA;
672  }
673  c=toupper(*p)-'0';
674  if (c>9) c-=7;
675  cHex=c<<4;
676 
677  p++;
678  if (!*p) {
679  DBG_INFO(GWEN_LOGDOMAIN, "Incomplete escape sequence");
680  GWEN_Buffer_free(wbuf);
681  return GWEN_ERROR_BAD_DATA;
682  }
683  c=toupper(*p)-'0';
684  if (c>9) c-=7;
685  cHex|=c;
686  GWEN_Buffer_AppendByte(wbuf, cHex);
687  }
688  else if (quotes) {
689  if (*p=='"') {
690  p++;
691  break;
692  }
693  else
694  GWEN_Buffer_AppendByte(wbuf, *p);
695  }
696  else {
697  if (*p==',' || *p==';' || *p=='#')
698  break;
699  else if (*p=='"') {
700  DBG_INFO(GWEN_LOGDOMAIN, "Unexpected quotation mark (Line: [%s], parsed: [%s]",
701  pDebug, GWEN_Buffer_GetStart(wbuf));
702  GWEN_Buffer_free(wbuf);
703  return GWEN_ERROR_BAD_DATA;
704  }
705  else
706  GWEN_Buffer_AppendByte(wbuf, *p);
707  }
708  p++;
709  }
710 
711  v=GWEN_Buffer_GetStart(wbuf);
712  if (nodeType==GWEN_DB_NodeType_ValueInt) {
713  int i;
714 
715  if (1!=sscanf(v, "%d", &i)) {
716  DBG_INFO(GWEN_LOGDOMAIN, "Not an integer value [%s]", v);
717  GWEN_Buffer_free(wbuf);
718  return GWEN_ERROR_BAD_DATA;
719  }
720  dbVal=GWEN_DB_ValueInt_new(i);
721  }
722  else if (nodeType==GWEN_DB_NodeType_ValueChar)
723  dbVal=GWEN_DB_ValueChar_new(v);
724  else if (nodeType==GWEN_DB_NodeType_ValueBin) {
725  GWEN_BUFFER *bbuf;
726  int rv;
727 
728  bbuf=GWEN_Buffer_new(0, (GWEN_Buffer_GetUsedBytes(wbuf)/2)+1, 0, 1);
729  rv=GWEN_Text_FromHexBuffer(v, bbuf);
730  if (rv) {
731  DBG_INFO(GWEN_LOGDOMAIN, "Bad bin value [%s]", v);
732  GWEN_Buffer_free(bbuf);
733  GWEN_Buffer_free(wbuf);
734  return GWEN_ERROR_BAD_DATA;
735  }
738  GWEN_Buffer_free(bbuf);
739  }
740  else {
741  /* should never reach this point */
742  assert(0);
743  }
744  GWEN_DB_Node_Append(dbVar, dbVal);
745 
746  /* skip blanks if any */
747  while(*p && isspace(*p))
748  p++;
749  if (!*p || *p==';' || *p=='#')
750  break;
751  else if (*p!=',') {
752  DBG_INFO(GWEN_LOGDOMAIN, "Unexpected character [%s]", p);
753  GWEN_Buffer_free(wbuf);
754  return GWEN_ERROR_BAD_DATA;
755  }
756  p++;
757  GWEN_Buffer_Reset(wbuf);
758  }
759 
760  GWEN_Buffer_free(wbuf);
761  return 0;
762 }
763 
764 
765 
767  GWEN_FAST_BUFFER *fb,
768  uint32_t dbflags) {
769  GWEN_BUFFER *lbuf;
770  GWEN_BUFFER *tbuf;
771  int level=0;
772  int someLinesRead=0;
773 
774  lbuf=GWEN_Buffer_new(0, 128, 0, 1);
775  tbuf=GWEN_Buffer_new(0, 128, 0, 1);
776 
777  for (;;) {
778  int rv;
779  uint8_t *p;
780 
782  if (rv<0) {
783  if (rv==GWEN_ERROR_EOF) {
784  if (!someLinesRead && !(dbflags & GWEN_DB_FLAGS_ALLOW_EMPTY_STREAM)) {
785  DBG_INFO(GWEN_LOGDOMAIN, "Unexpected EOF (%d)", rv);
786  GWEN_Buffer_free(tbuf);
787  GWEN_Buffer_free(lbuf);
788  return rv;
789  }
790  break;
791  }
792  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
793  GWEN_Buffer_free(tbuf);
794  GWEN_Buffer_free(lbuf);
795  return rv;
796  }
797 
798  if (GWEN_Buffer_GetUsedBytes(lbuf)==0) {
799  if (dbflags & GWEN_DB_FLAGS_UNTIL_EMPTY_LINE) {
800  break;
801  }
802  }
803  else {
804  someLinesRead=1;
805  p=(uint8_t*)GWEN_Buffer_GetStart(lbuf);
806  while(*p && isspace(*p))
807  p++;
808  if (*p) {
809  uint8_t *p1begin=NULL, *p1end=NULL;
810  uint8_t *p2begin=NULL, *p2end=NULL;
811 
812  /* non-empty line */
813  if (*p=='}') {
814  /* found end of current group */
815  if (level<1) {
816  DBG_INFO(GWEN_LOGDOMAIN, "Unbalanced number of curly bracket");
817  GWEN_Buffer_free(tbuf);
818  GWEN_Buffer_free(lbuf);
819  return GWEN_ERROR_BAD_DATA;
820  }
821  n=n->parent;
822  assert(n); /* internal error if parent not found */
823  assert(n->typ==GWEN_DB_NodeType_Group); /* internal error if parent is not a group */
824  level--;
825  }
826  else if (*p=='#') {
827  /* comment only line */
828  }
829  else {
830  p1begin=p;
831  /* read first token */
832  while(*p && !isspace(*p) &&
833  *p!='{' &&
834  *p!=((dbflags & GWEN_DB_FLAGS_USE_COLON)?':':'=') &&
835  *p!='}' &&
836  *p!=',' &&
837  *p!=';')
838  p++;
839  if (!*p) {
840  DBG_INFO(GWEN_LOGDOMAIN, "Missing 2nd token (first: \"%s\")", p1begin);
841  GWEN_Buffer_Dump(lbuf, 2);
842  GWEN_Buffer_free(tbuf);
843  GWEN_Buffer_free(lbuf);
844  return GWEN_ERROR_BAD_DATA;
845  }
846  p1end=p;
847 
848  /* get to start of 2nd token */
849  while(*p && isspace(*p))
850  p++;
851  if (!*p) {
852  DBG_INFO(GWEN_LOGDOMAIN, "Missing 2nd token");
853  GWEN_Buffer_free(tbuf);
854  GWEN_Buffer_free(lbuf);
855  return GWEN_ERROR_BAD_DATA;
856  }
857 
858  if (*p=='{') {
859  GWEN_DB_NODE *newGr;
860 
861  /* found start of group */
862  *p1end=0;
863  rv=GWEN_DB_UnescapeToBufferTolerant((const char*)p1begin, tbuf);
864  if (rv<0) {
865  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
866  GWEN_Buffer_free(tbuf);
867  GWEN_Buffer_free(lbuf);
868  return rv;
869  }
870  newGr=GWEN_DB_GetGroup(n, dbflags, GWEN_Buffer_GetStart(tbuf));
871  if (newGr==NULL) {
872  DBG_INFO(GWEN_LOGDOMAIN, "Could not create group [%s]", GWEN_Buffer_GetStart(tbuf));
873  GWEN_Buffer_free(tbuf);
874  GWEN_Buffer_free(lbuf);
875  return GWEN_ERROR_GENERIC;
876  }
877  GWEN_Buffer_Reset(tbuf);
878  n=newGr;
879  level++;
880  }
881  else if (*p=='=' || *p==':') {
882  /* found short variable definition */
883  *p1end=0;
884  p++;
885  rv=GWEN_DB__ReadValues(n, dbflags, NULL, (const char*)p1begin, p);
886  if (rv) {
887  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
888  GWEN_Buffer_free(tbuf);
889  GWEN_Buffer_free(lbuf);
890  return rv;
891  }
892  }
893  else if (*p==',' || *p==';') {
894  DBG_INFO(GWEN_LOGDOMAIN, "Unexpected delimiter found");
895  GWEN_Buffer_free(tbuf);
896  GWEN_Buffer_free(lbuf);
897  return GWEN_ERROR_BAD_DATA;
898  }
899  else {
900  /* 2nd token, so this should be a standard variable definition */
901  p2begin=p;
902  while(*p &&
903  !isspace(*p) &&
904  *p!='{' &&
905  *p!=((dbflags & GWEN_DB_FLAGS_USE_COLON)?':':'=') &&
906  *p!='}' &&
907  *p!=',' &&
908  *p!=';')
909  p++;
910  if (!*p) {
911  DBG_INFO(GWEN_LOGDOMAIN, "Missing 2nd token [%s], [%s]", p1begin, p2begin);
912  GWEN_Buffer_free(tbuf);
913  GWEN_Buffer_free(lbuf);
914  return GWEN_ERROR_BAD_DATA;
915  }
916  p2end=p;
917  if (isspace(*p)) {
918  while(*p && isspace(*p))
919  p++;
920  if (!*p) {
921  DBG_INFO(GWEN_LOGDOMAIN, "Missing 2nd token");
922  GWEN_Buffer_free(tbuf);
923  GWEN_Buffer_free(lbuf);
924  return GWEN_ERROR_BAD_DATA;
925  }
926  }
927  if (*p!='=' && *p!=':') {
928  DBG_INFO(GWEN_LOGDOMAIN, "Equation mark expected");
929  GWEN_Buffer_free(tbuf);
930  GWEN_Buffer_free(lbuf);
931  return GWEN_ERROR_BAD_DATA;
932  }
933  p++;
934 
935  *p1end=0;
936  *p2end=0;
937  rv=GWEN_DB__ReadValues(n, dbflags, (const char*)p1begin, (const char*)p2begin, p);
938  if (rv) {
939  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
940  GWEN_Buffer_free(tbuf);
941  GWEN_Buffer_free(lbuf);
942  return rv;
943  }
944  }
945  }
946  }
947  }
948  GWEN_Buffer_Reset(lbuf);
949  }
950 
951  if (level) {
952  DBG_INFO(GWEN_LOGDOMAIN, "Unbalanced number of curly bracket (too few)");
953  GWEN_Buffer_free(tbuf);
954  GWEN_Buffer_free(lbuf);
955  return GWEN_ERROR_BAD_DATA;
956  }
957 
958  GWEN_Buffer_free(tbuf);
959  GWEN_Buffer_free(lbuf);
960 
961  return 0;
962 }
963 
964 
965 
966 int GWEN_DB_ReadFromIo(GWEN_DB_NODE *n, GWEN_SYNCIO *sio, uint32_t dbflags) {
967  GWEN_FAST_BUFFER *fb;
968  int rv;
969 
970  /* prepare fast buffer */
971  fb=GWEN_FastBuffer_new(1024, sio);
972  if (dbflags & GWEN_DB_FLAGS_DOSMODE)
974 
975  /* read from it */
976  rv=GWEN_DB_ReadFromFastBuffer(n, fb, dbflags);
977  if (rv<0) {
978  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
980  return rv;
981  }
982 
984 
985  return 0;
986 }
987 
988 
989 
991  const char *fname,
992  uint32_t dbflags) {
993  GWEN_SYNCIO *sio;
994  int rv;
995 
998  rv=GWEN_SyncIo_Connect(sio);
999  if (rv<0) {
1000  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
1001  GWEN_SyncIo_free(sio);
1002  return rv;
1003  }
1004 
1005  /* read from it */
1006  rv=GWEN_DB_ReadFromIo(n, sio, dbflags);
1007  if (rv<0) {
1008  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
1010  GWEN_SyncIo_free(sio);
1011  return rv;
1012  }
1013 
1015  GWEN_SyncIo_free(sio);
1016  return 0;
1017 }
1018 
1019 
1020 
1022  const char *str,
1023  int len,
1024  uint32_t dbflags) {
1025  GWEN_SYNCIO *sio;
1026  int rv;
1027 
1028  if (len==0)
1029  len=strlen(str);
1030 
1031  sio=GWEN_SyncIo_Memory_fromBuffer((const uint8_t*) str, len);
1032  rv=GWEN_DB_ReadFromIo(n, sio, dbflags);
1033  if (rv<0) {
1034  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
1035  GWEN_SyncIo_free(sio);
1036  return rv;
1037  }
1038 
1039  GWEN_SyncIo_free(sio);
1040 
1041  return 0;
1042 }
1043 
1044 
1045 
1047  GWEN_BUFFER *buf,
1048  uint32_t dbflags) {
1049  GWEN_SYNCIO *sio;
1050  int rv;
1051 
1052  /* create SyncIO, don't take over buf */
1053  sio=GWEN_SyncIo_Memory_new(buf, 0);
1054  rv=GWEN_DB_WriteToIo(n, sio, dbflags);
1055  if (rv<0) {
1056  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
1057  GWEN_SyncIo_free(sio);
1058  return rv;
1059  }
1060 
1061  GWEN_SyncIo_free(sio);
1062  return 0;
1063 }
1064 
1065 
1066 
1067 
1068 
1069 
1070 
1071 
1072 
1073 
1074 
1075 
int GWEN_DB_WriteToBuffer(GWEN_DB_NODE *n, GWEN_BUFFER *buf, uint32_t dbflags)
Definition: dbrw.c:1046
GWENHYWFAR_API void GWEN_FSLock_free(GWEN_FSLOCK *fl)
char * GWEN_Buffer_GetStart(const GWEN_BUFFER *bf)
Definition: buffer.c:223
int GWEN_SyncIo_Connect(GWEN_SYNCIO *sio)
Definition: syncio.c:94
struct GWEN_DB_NODE GWEN_DB_NODE
Definition: db.h:228
#define GWEN_SYNCIO_FILE_FLAGS_WRITE
Definition: syncio_file.h:54
uint32_t GWEN_Buffer_GetUsedBytes(const GWEN_BUFFER *bf)
Definition: buffer.c:266
#define GWEN_SYNCIO_FILE_FLAGS_READ
Definition: syncio_file.h:53
int GWEN_DB__ReadValues(GWEN_DB_NODE *n, uint32_t dbflags, const char *typeName, const char *varName, uint8_t *p)
Definition: dbrw.c:611
#define GWEN_DB_FLAGS_DETAILED_GROUPS
Definition: db.h:131
#define GWEN_DB_FLAGS_INDEND
Definition: db.h:134
#define GWEN_DB_FLAGS_UNTIL_EMPTY_LINE
Definition: db.h:142
#define GWEN_DB_FLAGS_OMIT_TYPES
Definition: db.h:145
#define NULL
Definition: binreloc.c:290
int GWEN_FastBuffer_ReadLineToBuffer(GWEN_FAST_BUFFER *fb, GWEN_BUFFER *buf)
Definition: fastbuffer.c:92
void GWEN_Memory_dealloc(void *p)
Definition: memory.c:472
#define GWEN_SYNCIO_FILE_FLAGS_UREAD
Definition: syncio_file.h:58
int GWEN_Text_EscapeToBufferTolerant(const char *src, GWEN_BUFFER *buf)
Definition: text.c:1419
#define DBG_VERBOUS(dbg_logger, format, args...)
Definition: debug.h:200
int GWEN_DB_UnescapeToBufferTolerant(const char *src, GWEN_BUFFER *buf)
Definition: dbrw.c:73
#define GWEN_DB_FLAGS_WRITE_SUBGROUPS
Definition: db.h:129
void GWEN_FastBuffer_free(GWEN_FAST_BUFFER *fb)
Definition: fastbuffer.c:45
#define DBG_WARN(dbg_logger, format, args...)
Definition: debug.h:118
int GWEN_DB_ReadFromString(GWEN_DB_NODE *n, const char *str, int len, uint32_t dbflags)
Definition: dbrw.c:1021
int GWEN_DB_WriteToFastBuffer(GWEN_DB_NODE *node, GWEN_FAST_BUFFER *fb, uint32_t dbflags)
Definition: dbrw.c:492
#define GWEN_LOGDOMAIN
Definition: logger.h:35
GWEN_BUFFER * GWEN_Buffer_new(char *buffer, uint32_t size, uint32_t used, int take)
Definition: buffer.c:38
#define GWEN_DB_FLAGS_QUOTE_VARNAMES
Definition: db.h:125
void GWEN_Buffer_Dump(GWEN_BUFFER *bf, unsigned int insert)
Definition: buffer.c:621
void GWEN_Buffer_Reset(GWEN_BUFFER *bf)
Definition: buffer.c:684
#define GWEN_FASTBUFFER_FLUSH(fb, var)
Definition: fastbuffer.h:162
#define GWEN_DB_DEFAULT_LOCK_TIMEOUT
Definition: db.h:218
GWEN_DB_NODE * GWEN_DB_ValueBin_new(const void *data, unsigned int datasize)
Definition: db.c:81
GWEN_DB_NODE * GWEN_DB_GetNode(GWEN_DB_NODE *n, const char *path, uint32_t flags)
Definition: db.c:772
#define GWEN_ERROR_BAD_DATA
Definition: error.h:121
struct GWEN_SYNCIO GWEN_SYNCIO
Definition: syncio.h:40
GWENHYWFAR_API GWEN_FSLOCK * GWEN_FSLock_new(const char *fname, GWEN_FSLOCK_TYPE t)
int GWEN_DB_ReadFromFastBuffer(GWEN_DB_NODE *n, GWEN_FAST_BUFFER *fb, uint32_t dbflags)
Definition: dbrw.c:766
GWEN_SYNCIO * GWEN_SyncIo_Memory_new(GWEN_BUFFER *buffer, int take)
Definition: syncio_memory.c:50
int GWEN_DBIO_Import(GWEN_DBIO *dbio, GWEN_SYNCIO *sio, GWEN_DB_NODE *db, GWEN_DB_NODE *params, uint32_t flags)
Definition: dbio.c:242
#define DBG_DEBUG(dbg_logger, format, args...)
Definition: debug.h:192
int GWEN_DB_WriteToIo(GWEN_DB_NODE *node, GWEN_SYNCIO *sio, uint32_t dbflags)
Definition: dbrw.c:507
#define GWEN_DB_FLAGS_QUOTE_VALUES
Definition: db.h:127
void GWEN_DB_Node_Append(GWEN_DB_NODE *parent, GWEN_DB_NODE *n)
Definition: db.c:175
int GWEN_DB_WriteFileAs(GWEN_DB_NODE *db, const char *fname, const char *type, GWEN_DB_NODE *params, uint32_t dbflags)
Definition: dbrw.c:156
#define GWEN_PATH_FLAGS_VARIABLE
Definition: path.h:111
void * GWEN_Memory_malloc(size_t wsize)
Definition: memory.c:385
#define GWEN_ERROR_GENERIC
Definition: error.h:62
int GWEN_Buffer_AppendByte(GWEN_BUFFER *bf, char c)
Definition: buffer.c:380
GWEN_FSLOCK_RESULT
Definition: fslock.h:71
#define GWEN_SYNCIO_FILE_FLAGS_UWRITE
Definition: syncio_file.h:59
GWENHYWFAR_API GWEN_FSLOCK_RESULT GWEN_FSLock_Lock(GWEN_FSLOCK *fl, int timeout, uint32_t gid)
#define GWEN_DB_FLAGS_APPEND_FILE
Definition: db.h:147
#define GWEN_FAST_BUFFER_FLAGS_DOSMODE
Definition: fastbuffer.h:19
GWEN_DB_NODE * GWEN_DB_GetGroup(GWEN_DB_NODE *n, uint32_t flags, const char *path)
Definition: db.c:1260
GWEN_DB_NODE * GWEN_DB_ValueChar_new(const char *data)
Definition: db.c:108
GWEN_SYNCIO * GWEN_SyncIo_Memory_fromBuffer(const uint8_t *buffer, int size)
Definition: syncio_memory.c:77
void GWEN_Buffer_free(GWEN_BUFFER *bf)
Definition: buffer.c:83
struct GWEN_BUFFER GWEN_BUFFER
A dynamically resizeable text buffer.
Definition: buffer.h:41
void GWEN_SyncIo_free(GWEN_SYNCIO *sio)
Definition: syncio.c:76
#define GWEN_DB_FLAGS_USE_COLON
Definition: db.h:140
void GWEN_SyncIo_AddFlags(GWEN_SYNCIO *sio, uint32_t fl)
Definition: syncio.c:169
int GWEN_Text_NumToString(int num, char *buffer, unsigned int bufsize, int fillchar)
Definition: text.c:1196
#define DBG_ERROR(dbg_logger, format, args...)
Definition: debug.h:97
int GWEN_DB_ReadFileAs(GWEN_DB_NODE *db, const char *fname, const char *type, GWEN_DB_NODE *params, uint32_t dbflags)
Definition: dbrw.c:120
#define GWEN_ERROR_EOF
Definition: error.h:96
char * GWEN_Text_ToHex(const char *src, unsigned l, char *buffer, unsigned int maxsize)
Definition: text.c:622
struct GWEN_DBIO GWEN_DBIO
Definition: dbio.h:43
#define GWEN_FASTBUFFER_WRITEFORCED(fb, var, p, len)
Definition: fastbuffer.h:377
int GWEN_SyncIo_Disconnect(GWEN_SYNCIO *sio)
Definition: syncio.c:105
int GWEN_DB_ReadFromIo(GWEN_DB_NODE *n, GWEN_SYNCIO *sio, uint32_t dbflags)
Definition: dbrw.c:966
#define GWEN_ERROR_NOT_SUPPORTED
Definition: error.h:109
#define GWEN_DB_FLAGS_LOCKFILE
Definition: db.h:155
#define GWEN_FASTBUFFER_WRITEBYTE(fb, var, chr)
Definition: fastbuffer.h:134
#define DBG_INFO(dbg_logger, format, args...)
Definition: debug.h:164
int GWEN_DB_EscapeToBufferTolerant(const char *src, GWEN_BUFFER *buf)
Definition: dbrw.c:30
#define GWEN_DB_NODE_FLAGS_VOLATILE
Definition: db.h:209
#define GWEN_DB_FLAGS_DOSMODE
Definition: db.h:165
GWEN_DB_NODE_TYPE
Definition: db.h:233
int GWEN_DB_ReadFile(GWEN_DB_NODE *n, const char *fname, uint32_t dbflags)
Definition: dbrw.c:990
#define GWEN_DB_FLAGS_ESCAPE_CHARVALUES
Definition: db.h:149
struct GWEN_FSLOCK GWEN_FSLOCK
Definition: fslock.h:59
#define GWEN_DB_FLAGS_ADD_GROUP_NEWLINES
Definition: db.h:137
GWENHYWFAR_API GWEN_SYNCIO * GWEN_SyncIo_File_new(const char *path, GWEN_SYNCIO_FILE_CREATIONMODE cm)
#define GWEN_FASTBUFFER_WRITELINE(fb, var, p)
Definition: fastbuffer.h:407
int GWEN_DB_WriteGroupToIoLayer(GWEN_DB_NODE *node, GWEN_FAST_BUFFER *fb, uint32_t dbflags, int insert)
Definition: dbrw.c:181
int GWEN_DB_WriteFile(GWEN_DB_NODE *n, const char *fname, uint32_t dbflags)
Definition: dbrw.c:528
void GWEN_FastBuffer_AddFlags(GWEN_FAST_BUFFER *fb, uint32_t fl)
Definition: fastbuffer.c:172
GWENHYWFAR_API GWEN_FSLOCK_RESULT GWEN_FSLock_Unlock(GWEN_FSLOCK *fl)
int GWEN_Text_FromHexBuffer(const char *src, GWEN_BUFFER *buf)
Definition: text.c:858
GWEN_FAST_BUFFER * GWEN_FastBuffer_new(uint32_t bsize, GWEN_SYNCIO *io)
Definition: fastbuffer.c:27
int GWEN_DBIO_ExportToFile(GWEN_DBIO *dbio, const char *fname, GWEN_DB_NODE *db, GWEN_DB_NODE *params, uint32_t dbflags)
Definition: dbio.c:361
GWEN_DBIO * GWEN_DBIO_GetPlugin(const char *modname)
Definition: dbio.c:334
GWEN_DB_NODE * GWEN_DB_ValueInt_new(int data)
Definition: db.c:98
#define GWEN_SYNCIO_FILE_FLAGS_APPEND
Definition: syncio_file.h:55
#define GWEN_DB_FLAGS_ALLOW_EMPTY_STREAM
Definition: db.h:119