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
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';
57 c=((unsigned char)(*src))&0xf;
58 if (c>9)
59 c+=7;
60 c+='0';
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
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
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
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;
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
535int 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) {
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) {
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) {
584 GWEN_FSLock_free(lck);
585 }
586 return rv;
587 }
588
590 if (rv<0) {
591 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
592 GWEN_SyncIo_free(sio);
593 if (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) {
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)
636 else if (strcasecmp(typeName, "char")==0)
638 else if (strcasecmp(typeName, "bin")==0)
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
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
978int GWEN_DB_ReadFromIo(GWEN_DB_NODE *n, GWEN_SYNCIO *sio, uint32_t dbflags)
979{
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
#define NULL
Definition: binreloc.c:300
GWEN_BUFFER * GWEN_Buffer_new(char *buffer, uint32_t size, uint32_t used, int take)
Definition: buffer.c:42
void GWEN_Buffer_Reset(GWEN_BUFFER *bf)
Definition: buffer.c:650
void GWEN_Buffer_Dump(GWEN_BUFFER *bf, unsigned int insert)
Definition: buffer.c:586
void GWEN_Buffer_free(GWEN_BUFFER *bf)
Definition: buffer.c:89
uint32_t GWEN_Buffer_GetUsedBytes(const GWEN_BUFFER *bf)
Definition: buffer.c:277
char * GWEN_Buffer_GetStart(const GWEN_BUFFER *bf)
Definition: buffer.c:235
int GWEN_Buffer_AppendByte(GWEN_BUFFER *bf, char c)
Definition: buffer.c:394
GWEN_DB_NODE * GWEN_DB_GetNode(GWEN_DB_NODE *n, const char *path, uint32_t flags)
Definition: db.c:840
GWEN_DB_NODE * GWEN_DB_ValueInt_new(int data)
Definition: db.c:119
GWEN_DB_NODE * GWEN_DB_GetGroup(GWEN_DB_NODE *n, uint32_t flags, const char *path)
Definition: db.c:1381
void GWEN_DB_Node_Append(GWEN_DB_NODE *parent, GWEN_DB_NODE *n)
Definition: db.c:220
GWEN_DB_NODE * GWEN_DB_ValueChar_new(const char *data)
Definition: db.c:130
GWEN_DB_NODE * GWEN_DB_ValueBin_new(const void *data, unsigned int datasize)
Definition: db.c:101
#define GWEN_DB_FLAGS_QUOTE_VALUES
Definition: db.h:127
#define GWEN_DB_DEFAULT_LOCK_TIMEOUT
Definition: db.h:218
#define GWEN_DB_FLAGS_WRITE_SUBGROUPS
Definition: db.h:129
#define GWEN_DB_NODE_FLAGS_VOLATILE
Definition: db.h:209
#define GWEN_DB_FLAGS_DETAILED_GROUPS
Definition: db.h:131
#define GWEN_DB_FLAGS_OMIT_TYPES
Definition: db.h:145
#define GWEN_DB_FLAGS_ADD_GROUP_NEWLINES
Definition: db.h:137
#define GWEN_DB_FLAGS_ESCAPE_CHARVALUES
Definition: db.h:149
#define GWEN_DB_FLAGS_INDEND
Definition: db.h:134
#define GWEN_DB_FLAGS_UNTIL_EMPTY_LINE
Definition: db.h:142
GWEN_DB_NODE_TYPE
Definition: db.h:233
@ GWEN_DB_NodeType_ValueInt
Definition: db.h:243
@ GWEN_DB_NodeType_Group
Definition: db.h:237
@ GWEN_DB_NodeType_ValueChar
Definition: db.h:241
@ GWEN_DB_NodeType_ValuePtr
Definition: db.h:247
@ GWEN_DB_NodeType_Var
Definition: db.h:239
@ GWEN_DB_NodeType_ValueBin
Definition: db.h:245
#define GWEN_DB_FLAGS_DOSMODE
Definition: db.h:165
#define GWEN_DB_FLAGS_USE_COLON
Definition: db.h:140
#define GWEN_DB_FLAGS_LOCKFILE
Definition: db.h:155
#define GWEN_DB_FLAGS_QUOTE_VARNAMES
Definition: db.h:125
#define GWEN_DB_FLAGS_APPEND_FILE
Definition: db.h:147
struct GWEN_DB_NODE GWEN_DB_NODE
Definition: db.h:228
#define GWEN_DB_FLAGS_ALLOW_EMPTY_STREAM
Definition: db.h:119
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
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
GWEN_DBIO * GWEN_DBIO_GetPlugin(const char *modname)
Definition: dbio.c:352
struct GWEN_DBIO GWEN_DBIO
Definition: dbio.h:43
int GWEN_DB_EscapeToBufferTolerant(const char *src, GWEN_BUFFER *buf)
Definition: dbrw.c:30
int GWEN_DB_ReadFromIo(GWEN_DB_NODE *n, GWEN_SYNCIO *sio, uint32_t dbflags)
Definition: dbrw.c:978
int GWEN_DB__ReadValues(GWEN_DB_NODE *n, uint32_t dbflags, const char *typeName, const char *varName, uint8_t *p)
Definition: dbrw.c:619
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
int GWEN_DB_ReadFromString(GWEN_DB_NODE *n, const char *str, int len, uint32_t dbflags)
Definition: dbrw.c:1035
int GWEN_DB_UnescapeToBufferTolerant(const char *src, GWEN_BUFFER *buf)
Definition: dbrw.c:74
int GWEN_DB_WriteToFastBuffer(GWEN_DB_NODE *node, GWEN_FAST_BUFFER *fb, uint32_t dbflags)
Definition: dbrw.c:497
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
int GWEN_DB_ReadFile(GWEN_DB_NODE *n, const char *fname, uint32_t dbflags)
Definition: dbrw.c:1003
int GWEN_DB_ReadFromFastBuffer(GWEN_DB_NODE *n, GWEN_FAST_BUFFER *fb, uint32_t dbflags)
Definition: dbrw.c:777
int GWEN_DB_WriteFile(GWEN_DB_NODE *n, const char *fname, uint32_t dbflags)
Definition: dbrw.c:535
int GWEN_DB_WriteToIo(GWEN_DB_NODE *node, GWEN_SYNCIO *sio, uint32_t dbflags)
Definition: dbrw.c:513
int GWEN_DB_WriteToBuffer(GWEN_DB_NODE *n, GWEN_BUFFER *buf, uint32_t dbflags)
Definition: dbrw.c:1061
int GWEN_DB_WriteGroupToIoLayer(GWEN_DB_NODE *node, GWEN_FAST_BUFFER *fb, uint32_t dbflags, int insert)
Definition: dbrw.c:185
#define DBG_DEBUG(dbg_logger, format, args...)
Definition: debug.h:214
#define DBG_WARN(dbg_logger, format, args...)
Definition: debug.h:125
#define DBG_VERBOUS(dbg_logger, format, args...)
Definition: debug.h:224
#define DBG_INFO(dbg_logger, format, args...)
Definition: debug.h:181
#define DBG_ERROR(dbg_logger, format, args...)
Definition: debug.h:97
#define GWEN_ERROR_BAD_DATA
Definition: error.h:121
#define GWEN_ERROR_GENERIC
Definition: error.h:62
#define GWEN_ERROR_NOT_SUPPORTED
Definition: error.h:109
#define GWEN_ERROR_EOF
Definition: error.h:96
void GWEN_FastBuffer_free(GWEN_FAST_BUFFER *fb)
Definition: fastbuffer.c:46
GWEN_FAST_BUFFER * GWEN_FastBuffer_new(uint32_t bsize, GWEN_SYNCIO *io)
Definition: fastbuffer.c:27
int GWEN_FastBuffer_ReadLineToBuffer(GWEN_FAST_BUFFER *fb, GWEN_BUFFER *buf)
Definition: fastbuffer.c:95
void GWEN_FastBuffer_AddFlags(GWEN_FAST_BUFFER *fb, uint32_t fl)
Definition: fastbuffer.c:178
#define GWEN_FAST_BUFFER_FLAGS_DOSMODE
Definition: fastbuffer.h:19
#define GWEN_FASTBUFFER_WRITEBYTE(fb, var, chr)
Definition: fastbuffer.h:134
#define GWEN_FASTBUFFER_FLUSH(fb, var)
Definition: fastbuffer.h:162
#define GWEN_FASTBUFFER_WRITELINE(fb, var, p)
Definition: fastbuffer.h:407
#define GWEN_FASTBUFFER_WRITEFORCED(fb, var, p, len)
Definition: fastbuffer.h:377
GWENHYWFAR_API void GWEN_FSLock_free(GWEN_FSLOCK *fl)
struct GWEN_FSLOCK GWEN_FSLOCK
Definition: fslock.h:59
GWENHYWFAR_API GWEN_FSLOCK * GWEN_FSLock_new(const char *fname, GWEN_FSLOCK_TYPE t)
GWEN_FSLOCK_RESULT
Definition: fslock.h:71
@ GWEN_FSLock_ResultOk
Definition: fslock.h:72
GWENHYWFAR_API GWEN_FSLOCK_RESULT GWEN_FSLock_Lock(GWEN_FSLOCK *fl, int timeout, uint32_t gid)
@ GWEN_FSLock_TypeFile
Definition: fslock.h:66
GWENHYWFAR_API GWEN_FSLOCK_RESULT GWEN_FSLock_Unlock(GWEN_FSLOCK *fl)
struct GWEN_BUFFER GWEN_BUFFER
A dynamically resizeable text buffer.
Definition: buffer.h:38
#define GWEN_LOGDOMAIN
Definition: logger.h:35
void * GWEN_Memory_malloc(size_t wsize)
Definition: memory.c:39
void GWEN_Memory_dealloc(void *p)
Definition: memory.c:69
#define GWEN_PATH_FLAGS_VARIABLE
Definition: path.h:111
int GWEN_SyncIo_Connect(GWEN_SYNCIO *sio)
Definition: syncio.c:97
void GWEN_SyncIo_AddFlags(GWEN_SYNCIO *sio, uint32_t fl)
Definition: syncio.c:179
void GWEN_SyncIo_free(GWEN_SYNCIO *sio)
Definition: syncio.c:78
int GWEN_SyncIo_Disconnect(GWEN_SYNCIO *sio)
Definition: syncio.c:109
struct GWEN_SYNCIO GWEN_SYNCIO
Definition: syncio.h:40
@ GWEN_SyncIo_File_CreationMode_CreateAlways
Definition: syncio_file.h:40
@ GWEN_SyncIo_File_CreationMode_OpenExisting
Definition: syncio_file.h:38
#define GWEN_SYNCIO_FILE_FLAGS_UWRITE
Definition: syncio_file.h:59
GWENHYWFAR_API GWEN_SYNCIO * GWEN_SyncIo_File_new(const char *path, GWEN_SYNCIO_FILE_CREATIONMODE cm)
#define GWEN_SYNCIO_FILE_FLAGS_READ
Definition: syncio_file.h:53
#define GWEN_SYNCIO_FILE_FLAGS_UREAD
Definition: syncio_file.h:58
#define GWEN_SYNCIO_FILE_FLAGS_APPEND
Definition: syncio_file.h:55
#define GWEN_SYNCIO_FILE_FLAGS_WRITE
Definition: syncio_file.h:54
GWEN_SYNCIO * GWEN_SyncIo_Memory_new(GWEN_BUFFER *buffer, int take)
Definition: syncio_memory.c:50
GWEN_SYNCIO * GWEN_SyncIo_Memory_fromBuffer(const uint8_t *buffer, int size)
Definition: syncio_memory.c:78
int GWEN_Text_EscapeToBufferTolerant(const char *src, GWEN_BUFFER *buf)
Definition: text.c:1471
int GWEN_Text_FromHexBuffer(const char *src, GWEN_BUFFER *buf)
Definition: text.c:897
char * GWEN_Text_ToHex(const char *src, unsigned l, char *buffer, unsigned int maxsize)
Definition: text.c:657
int GWEN_Text_NumToString(int num, char *buffer, unsigned int bufsize, int fillchar)
Definition: text.c:1243