gwenhywfar  4.7.0beta
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
689  if (quotes) {
690  if (*p=='"') {
691  p++;
692  break;
693  }
694  else
695  GWEN_Buffer_AppendByte(wbuf, *p);
696  }
697  else {
698  if (*p==',' || *p==';' || *p=='#')
699  break;
700  else if (*p=='"') {
701  DBG_INFO(GWEN_LOGDOMAIN, "Unexpected quotation mark (Line: [%s], parsed: [%s]",
702  pDebug, GWEN_Buffer_GetStart(wbuf));
703  GWEN_Buffer_free(wbuf);
704  return GWEN_ERROR_BAD_DATA;
705  }
706  else
707  GWEN_Buffer_AppendByte(wbuf, *p);
708  }
709  p++;
710  }
711 
712  v=GWEN_Buffer_GetStart(wbuf);
713  if (nodeType==GWEN_DB_NodeType_ValueInt) {
714  int i;
715 
716  if (1!=sscanf(v, "%d", &i)) {
717  DBG_INFO(GWEN_LOGDOMAIN, "Not an integer value [%s]", v);
718  GWEN_Buffer_free(wbuf);
719  return GWEN_ERROR_BAD_DATA;
720  }
721  dbVal=GWEN_DB_ValueInt_new(i);
722  }
723  else if (nodeType==GWEN_DB_NodeType_ValueChar)
724  dbVal=GWEN_DB_ValueChar_new(v);
725  else if (nodeType==GWEN_DB_NodeType_ValueBin) {
726  GWEN_BUFFER *bbuf;
727  int rv;
728 
729  bbuf=GWEN_Buffer_new(0, (GWEN_Buffer_GetUsedBytes(wbuf)/2)+1, 0, 1);
730  rv=GWEN_Text_FromHexBuffer(v, bbuf);
731  if (rv) {
732  DBG_INFO(GWEN_LOGDOMAIN, "Bad bin value [%s]", v);
733  GWEN_Buffer_free(bbuf);
734  GWEN_Buffer_free(wbuf);
735  return GWEN_ERROR_BAD_DATA;
736  }
739  GWEN_Buffer_free(bbuf);
740  }
741  else {
742  /* should never reach this point */
743  assert(0);
744  }
745  GWEN_DB_Node_Append(dbVar, dbVal);
746 
747  /* skip blanks if any */
748  while(*p && isspace(*p))
749  p++;
750  if (!*p || *p==';' || *p=='#')
751  break;
752  else if (*p!=',') {
753  DBG_INFO(GWEN_LOGDOMAIN, "Unexpected character [%s]", p);
754  GWEN_Buffer_free(wbuf);
755  return GWEN_ERROR_BAD_DATA;
756  }
757  p++;
758  GWEN_Buffer_Reset(wbuf);
759  }
760 
761  GWEN_Buffer_free(wbuf);
762  return 0;
763 }
764 
765 
766 
768  GWEN_FAST_BUFFER *fb,
769  uint32_t dbflags) {
770  GWEN_BUFFER *lbuf;
771  GWEN_BUFFER *tbuf;
772  int level=0;
773  int someLinesRead=0;
774 
775  lbuf=GWEN_Buffer_new(0, 128, 0, 1);
776  tbuf=GWEN_Buffer_new(0, 128, 0, 1);
777 
778  for (;;) {
779  int rv;
780  uint8_t *p;
781 
783  if (rv<0) {
784  if (rv==GWEN_ERROR_EOF) {
785  if (!someLinesRead && !(dbflags & GWEN_DB_FLAGS_ALLOW_EMPTY_STREAM)){
786  DBG_INFO(GWEN_LOGDOMAIN, "Unexpected EOF (%d)", rv);
787  GWEN_Buffer_free(tbuf);
788  GWEN_Buffer_free(lbuf);
789  return rv;
790  }
791  break;
792  }
793  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
794  GWEN_Buffer_free(tbuf);
795  GWEN_Buffer_free(lbuf);
796  return rv;
797  }
798 
799  if (GWEN_Buffer_GetUsedBytes(lbuf)==0) {
800  if (dbflags & GWEN_DB_FLAGS_UNTIL_EMPTY_LINE) {
801  break;
802  }
803  }
804  else {
805  someLinesRead=1;
806  p=(uint8_t*)GWEN_Buffer_GetStart(lbuf);
807  while(*p && isspace(*p))
808  p++;
809  if (*p) {
810  uint8_t *p1begin=NULL, *p1end=NULL;
811  uint8_t *p2begin=NULL, *p2end=NULL;
812 
813  /* non-empty line */
814  if (*p=='}') {
815  /* found end of current group */
816  if (level<1) {
817  DBG_INFO(GWEN_LOGDOMAIN, "Unbalanced number of curly bracket");
818  GWEN_Buffer_free(tbuf);
819  GWEN_Buffer_free(lbuf);
820  return GWEN_ERROR_BAD_DATA;
821  }
822  n=n->parent;
823  assert(n); /* internal error if parent not found */
824  assert(n->typ==GWEN_DB_NodeType_Group); /* internal error if parent is not a group */
825  level--;
826  }
827  else if (*p=='#') {
828  /* comment only line */
829  }
830  else {
831  p1begin=p;
832  /* read first token */
833  while(*p && !isspace(*p) &&
834  *p!='{' &&
835  *p!=((dbflags & GWEN_DB_FLAGS_USE_COLON)?':':'=') &&
836  *p!='}' &&
837  *p!=',' &&
838  *p!=';')
839  p++;
840  if (!*p) {
841  DBG_INFO(GWEN_LOGDOMAIN, "Missing 2nd token (first: \"%s\")", p1begin);
842  GWEN_Buffer_Dump(lbuf, 2);
843  GWEN_Buffer_free(tbuf);
844  GWEN_Buffer_free(lbuf);
845  return GWEN_ERROR_BAD_DATA;
846  }
847  p1end=p;
848 
849  /* get to start of 2nd token */
850  while(*p && isspace(*p))
851  p++;
852  if (!*p) {
853  DBG_INFO(GWEN_LOGDOMAIN, "Missing 2nd token");
854  GWEN_Buffer_free(tbuf);
855  GWEN_Buffer_free(lbuf);
856  return GWEN_ERROR_BAD_DATA;
857  }
858 
859  if (*p=='{') {
860  GWEN_DB_NODE *newGr;
861 
862  /* found start of group */
863  *p1end=0;
864  rv=GWEN_DB_UnescapeToBufferTolerant((const char*)p1begin, tbuf);
865  if (rv<0) {
866  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
867  GWEN_Buffer_free(tbuf);
868  GWEN_Buffer_free(lbuf);
869  return rv;
870  }
871  newGr=GWEN_DB_GetGroup(n, dbflags, GWEN_Buffer_GetStart(tbuf));
872  if (newGr==NULL) {
873  DBG_INFO(GWEN_LOGDOMAIN, "Could not create group [%s]", GWEN_Buffer_GetStart(tbuf));
874  GWEN_Buffer_free(tbuf);
875  GWEN_Buffer_free(lbuf);
876  return GWEN_ERROR_GENERIC;
877  }
878  GWEN_Buffer_Reset(tbuf);
879  n=newGr;
880  level++;
881  }
882  else if (*p=='=' || *p==':') {
883  /* found short variable definition */
884  *p1end=0;
885  p++;
886  rv=GWEN_DB__ReadValues(n, dbflags, NULL, (const char*)p1begin, p);
887  if (rv) {
888  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
889  GWEN_Buffer_free(tbuf);
890  GWEN_Buffer_free(lbuf);
891  return rv;
892  }
893  }
894  else if (*p==',' || *p==';') {
895  DBG_INFO(GWEN_LOGDOMAIN, "Unexpected delimiter found");
896  GWEN_Buffer_free(tbuf);
897  GWEN_Buffer_free(lbuf);
898  return GWEN_ERROR_BAD_DATA;
899  }
900  else {
901  /* 2nd token, so this should be a standard variable definition */
902  p2begin=p;
903  while(*p &&
904  !isspace(*p) &&
905  *p!='{' &&
906  *p!=((dbflags & GWEN_DB_FLAGS_USE_COLON)?':':'=') &&
907  *p!='}' &&
908  *p!=',' &&
909  *p!=';')
910  p++;
911  if (!*p) {
912  DBG_INFO(GWEN_LOGDOMAIN, "Missing 2nd token [%s], [%s]", p1begin, p2begin);
913  GWEN_Buffer_free(tbuf);
914  GWEN_Buffer_free(lbuf);
915  return GWEN_ERROR_BAD_DATA;
916  }
917  p2end=p;
918  if (isspace(*p)) {
919  while(*p && isspace(*p))
920  p++;
921  if (!*p) {
922  DBG_INFO(GWEN_LOGDOMAIN, "Missing 2nd token");
923  GWEN_Buffer_free(tbuf);
924  GWEN_Buffer_free(lbuf);
925  return GWEN_ERROR_BAD_DATA;
926  }
927  }
928  if (*p!='=' && *p!=':') {
929  DBG_INFO(GWEN_LOGDOMAIN, "Equation mark expected");
930  GWEN_Buffer_free(tbuf);
931  GWEN_Buffer_free(lbuf);
932  return GWEN_ERROR_BAD_DATA;
933  }
934  p++;
935 
936  *p1end=0;
937  *p2end=0;
938  rv=GWEN_DB__ReadValues(n, dbflags, (const char*)p1begin, (const char*)p2begin, p);
939  if (rv) {
940  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
941  GWEN_Buffer_free(tbuf);
942  GWEN_Buffer_free(lbuf);
943  return rv;
944  }
945  }
946  }
947  }
948  }
949  GWEN_Buffer_Reset(lbuf);
950  }
951 
952  if (level) {
953  DBG_INFO(GWEN_LOGDOMAIN, "Unbalanced number of curly bracket (too few)");
954  GWEN_Buffer_free(tbuf);
955  GWEN_Buffer_free(lbuf);
956  return GWEN_ERROR_BAD_DATA;
957  }
958 
959  GWEN_Buffer_free(tbuf);
960  GWEN_Buffer_free(lbuf);
961 
962  return 0;
963 }
964 
965 
966 
967 int GWEN_DB_ReadFromIo(GWEN_DB_NODE *n, GWEN_SYNCIO *sio, uint32_t dbflags) {
968  GWEN_FAST_BUFFER *fb;
969  int rv;
970 
971  /* prepare fast buffer */
972  fb=GWEN_FastBuffer_new(1024, sio);
973  if (dbflags & GWEN_DB_FLAGS_DOSMODE)
975 
976  /* read from it */
977  rv=GWEN_DB_ReadFromFastBuffer(n, fb, dbflags);
978  if (rv<0) {
979  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
981  return rv;
982  }
983 
985 
986  return 0;
987 }
988 
989 
990 
992  const char *fname,
993  uint32_t dbflags) {
994  GWEN_SYNCIO *sio;
995  int rv;
996 
999  rv=GWEN_SyncIo_Connect(sio);
1000  if (rv<0) {
1001  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
1002  GWEN_SyncIo_free(sio);
1003  return rv;
1004  }
1005 
1006  /* read from it */
1007  rv=GWEN_DB_ReadFromIo(n, sio, dbflags);
1008  if (rv<0) {
1009  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
1011  GWEN_SyncIo_free(sio);
1012  return rv;
1013  }
1014 
1016  GWEN_SyncIo_free(sio);
1017  return 0;
1018 }
1019 
1020 
1021 
1023  const char *str,
1024  int len,
1025  uint32_t dbflags) {
1026  GWEN_SYNCIO *sio;
1027  int rv;
1028 
1029  if (len==0)
1030  len=strlen(str);
1031 
1032  sio=GWEN_SyncIo_Memory_fromBuffer((const uint8_t*) str, len);
1033  rv=GWEN_DB_ReadFromIo(n, sio, dbflags);
1034  if (rv<0) {
1035  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
1036  GWEN_SyncIo_free(sio);
1037  return rv;
1038  }
1039 
1040  GWEN_SyncIo_free(sio);
1041 
1042  return 0;
1043 }
1044 
1045 
1046 
1048  GWEN_BUFFER *buf,
1049  uint32_t dbflags) {
1050  GWEN_SYNCIO *sio;
1051  int rv;
1052 
1053  /* create SyncIO, don't take over buf */
1054  sio=GWEN_SyncIo_Memory_new(buf, 0);
1055  rv=GWEN_DB_WriteToIo(n, sio, dbflags);
1056  if (rv<0) {
1057  DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
1058  GWEN_SyncIo_free(sio);
1059  return rv;
1060  }
1061 
1062  GWEN_SyncIo_free(sio);
1063  return 0;
1064 }
1065 
1066 
1067 
1068 
1069 
1070 
1071 
1072 
1073 
1074 
1075 
1076