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