00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033 int GWEN_DB_EscapeToBufferTolerant(const char *src, GWEN_BUFFER *buf) {
00034 while(*src) {
00035 unsigned char x;
00036
00037 x=(unsigned char)*src;
00038 if (!(
00039 (x>='A' && x<='Z') ||
00040 (x>='a' && x<='z') ||
00041 (x>='0' && x<='9') ||
00042 x=='%' ||
00043 x=='.' ||
00044 x==',' ||
00045 x=='.' ||
00046 x=='_' ||
00047 x=='-' ||
00048 x=='*' ||
00049 x=='?'
00050 )) {
00051 unsigned char c;
00052
00053 GWEN_Buffer_AppendByte(buf, '&');
00054 c=(((unsigned char)(*src))>>4)&0xf;
00055 if (c>9)
00056 c+=7;
00057 c+='0';
00058 GWEN_Buffer_AppendByte(buf, c);
00059 c=((unsigned char)(*src))&0xf;
00060 if (c>9)
00061 c+=7;
00062 c+='0';
00063 GWEN_Buffer_AppendByte(buf, c);
00064 }
00065 else
00066 GWEN_Buffer_AppendByte(buf, *src);
00067
00068 src++;
00069 }
00070
00071 return 0;
00072 }
00073
00074
00075
00076 int GWEN_DB_UnescapeToBufferTolerant(const char *src, GWEN_BUFFER *buf) {
00077 while(*src) {
00078 const char *srcBak;
00079 int charHandled;
00080
00081 srcBak=src;
00082 charHandled=0;
00083 if (*src=='&') {
00084 if (strlen(src)>2) {
00085 unsigned char d1, d2;
00086 unsigned char c;
00087
00088 if (isxdigit((int)src[1]) && isxdigit((int)src[2])) {
00089
00090 src++;
00091
00092 d1=(unsigned char)(toupper(*src));
00093
00094
00095 src++;
00096 d2=(unsigned char)(toupper(*src));
00097
00098 d1-='0';
00099 if (d1>9)
00100 d1-=7;
00101 c=(d1<<4)&0xf0;
00102 d2-='0';
00103 if (d2>9)
00104 d2-=7;
00105 c+=(d2&0xf);
00106
00107 GWEN_Buffer_AppendByte(buf, (char)c);
00108 charHandled=1;
00109 }
00110 }
00111 }
00112 if (!charHandled)
00113 GWEN_Buffer_AppendByte(buf, *src);
00114 src++;
00115 }
00116
00117 return 0;
00118 }
00119
00120
00121
00122
00123
00124
00125 int GWEN_DB_ReadFileAs(GWEN_DB_NODE *db,
00126 const char *fname,
00127 const char *type,
00128 GWEN_DB_NODE *params,
00129 uint32_t dbflags,
00130 uint32_t guiid,
00131 int msecs){
00132 GWEN_IO_LAYER *io;
00133 GWEN_DBIO *dbio;
00134 int fd;
00135 int rv;
00136
00137 dbio=GWEN_DBIO_GetPlugin(type);
00138 if (!dbio) {
00139 DBG_ERROR(GWEN_LOGDOMAIN, "Plugin \"%s\" is not supported", type);
00140 return GWEN_ERROR_NOT_SUPPORTED;
00141 }
00142
00143 fd=open(fname, O_RDONLY);
00144 if (fd==-1) {
00145 DBG_ERROR(GWEN_LOGDOMAIN, "open(%s, O_RDONLY): %s", fname, strerror(errno));
00146 return GWEN_ERROR_IO;
00147 }
00148
00149
00150 io=GWEN_Io_LayerFile_new(fd, -1);
00151 assert(io);
00152
00153 rv=GWEN_Io_Manager_RegisterLayer(io);
00154 if (rv) {
00155 DBG_ERROR(GWEN_LOGDOMAIN, "Internal error: Could not register io layer (%d)", rv);
00156 GWEN_Io_Layer_DisconnectRecursively(io, NULL, GWEN_IO_REQUEST_FLAGS_FORCE, guiid, msecs);
00157 GWEN_Io_Layer_free(io);
00158 return rv;
00159 }
00160
00161 rv=GWEN_DBIO_Import(dbio, io, db, params, dbflags, guiid, msecs);
00162 if (rv) {
00163 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
00164 }
00165 GWEN_Io_Layer_DisconnectRecursively(io, NULL, GWEN_IO_REQUEST_FLAGS_FORCE, guiid, msecs);
00166 GWEN_Io_Layer_free(io);
00167
00168 return rv;
00169 }
00170
00171
00172
00173 int GWEN_DB_WriteFileAs(GWEN_DB_NODE *db,
00174 const char *fname,
00175 const char *type,
00176 GWEN_DB_NODE *params,
00177 uint32_t dbflags,
00178 uint32_t guiid,
00179 int msecs){
00180 int rv;
00181 GWEN_DBIO *dbio;
00182
00183 dbio=GWEN_DBIO_GetPlugin(type);
00184 if (!dbio) {
00185 DBG_ERROR(GWEN_LOGDOMAIN, "Plugin \"%s\" is not supported", type);
00186 return GWEN_ERROR_NOT_SUPPORTED;
00187 }
00188
00189 rv=GWEN_DBIO_ExportToFile(dbio, fname, db, params, dbflags, guiid, msecs);
00190 if (rv) {
00191 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
00192 return rv;
00193 }
00194
00195 return 0;
00196 }
00197
00198
00199
00200 int GWEN_DB_WriteGroupToIoLayer(GWEN_DB_NODE *node,
00201 GWEN_FAST_BUFFER *fb,
00202 uint32_t dbflags,
00203 int insert) {
00204 GWEN_DB_NODE *n;
00205 GWEN_DB_NODE *cn;
00206 int i;
00207 int err;
00208 int lastWasVar;
00209
00210 lastWasVar=0;
00211
00212 n=GWEN_DB_Node_List_First(node->children);
00213 while(n) {
00214 if (!(n->nodeFlags & GWEN_DB_NODE_FLAGS_VOLATILE)) {
00215 DBG_VERBOUS(GWEN_LOGDOMAIN, "Writing node");
00216 switch(n->typ) {
00217 case GWEN_DB_NodeType_Group:
00218 if (dbflags & GWEN_DB_FLAGS_WRITE_SUBGROUPS) {
00219 GWEN_BUFFER *tbuf;
00220
00221 if (dbflags & GWEN_DB_FLAGS_ADD_GROUP_NEWLINES) {
00222 if (lastWasVar) {
00223
00224
00225 GWEN_FASTBUFFER_WRITELINE(fb, err, "");
00226 if (err<0) {
00227 DBG_INFO(GWEN_LOGDOMAIN, "called from here");
00228 return err;
00229 }
00230 }
00231 }
00232
00233
00234 if (dbflags & GWEN_DB_FLAGS_INDEND) {
00235 for (i=0; i<insert; i++) {
00236 GWEN_FASTBUFFER_WRITEBYTE(fb, err, ' ');
00237 if (err<0) {
00238 DBG_INFO(GWEN_LOGDOMAIN, "called from here");
00239 return err;
00240 }
00241 }
00242 }
00243
00244 tbuf=GWEN_Buffer_new(0, 128, 0, 1);
00245 err=GWEN_DB_EscapeToBufferTolerant(n->data.dataName, tbuf);
00246 if (err<0) {
00247 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", err);
00248 GWEN_Buffer_free(tbuf);
00249 return err;
00250 }
00251
00252 GWEN_FASTBUFFER_WRITEFORCED(fb, err,
00253 GWEN_Buffer_GetStart(tbuf),
00254 GWEN_Buffer_GetUsedBytes(tbuf));
00255 GWEN_Buffer_free(tbuf);
00256 if (err<0) {
00257 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", err);
00258 return err;
00259 }
00260 GWEN_FASTBUFFER_WRITELINE(fb, err, " {");
00261 if (err<0) {
00262 DBG_INFO(GWEN_LOGDOMAIN, "called from here");
00263 return err;
00264 }
00265 err=GWEN_DB_WriteGroupToIoLayer(n, fb, dbflags, insert+2);
00266 if (err<0)
00267 return err;
00268
00269
00270 if (dbflags & GWEN_DB_FLAGS_INDEND) {
00271 for (i=0; i<insert; i++) {
00272 GWEN_FASTBUFFER_WRITEBYTE(fb, err, ' ');
00273 if (err<0) {
00274 DBG_INFO(GWEN_LOGDOMAIN, "called from here");
00275 return err;
00276 }
00277 }
00278 }
00279
00280 if (dbflags & GWEN_DB_FLAGS_DETAILED_GROUPS) {
00281 GWEN_FASTBUFFER_WRITEFORCED(fb, err, "} #", -1);
00282 if (err<0) {
00283 DBG_INFO(GWEN_LOGDOMAIN, "called from here");
00284 return err;
00285 }
00286 GWEN_FASTBUFFER_WRITELINE(fb, err, n->data.dataName);
00287 if (err<0) {
00288 DBG_INFO(GWEN_LOGDOMAIN, "called from here");
00289 return err;
00290 }
00291 }
00292 else {
00293 GWEN_FASTBUFFER_WRITELINE(fb, err, "}");
00294 if (err<0) {
00295 DBG_INFO(GWEN_LOGDOMAIN, "called from here");
00296 return err;
00297 }
00298 }
00299 if (dbflags & GWEN_DB_FLAGS_ADD_GROUP_NEWLINES) {
00300 if (GWEN_DB_Node_List_Next(n)) {
00301
00302
00303 GWEN_FASTBUFFER_WRITELINE(fb, err, "");
00304 if (err<0) {
00305 DBG_INFO(GWEN_LOGDOMAIN, "called from here");
00306 return err;
00307 }
00308 }
00309 }
00310 }
00311 lastWasVar=0;
00312 break;
00313
00314 case GWEN_DB_NodeType_Var:
00315 cn=GWEN_DB_Node_List_First(n->children);
00316 if (cn) {
00317 char *typname;
00318 int namewritten;
00319 int values;
00320
00321 typname=0;
00322 namewritten=0;
00323 values=0;
00324 while(cn) {
00325 char numbuffer[32];
00326 char *binbuffer=NULL;
00327 unsigned int bbsize;
00328 const char *pvalue=NULL;
00329 GWEN_BUFFER *vbuf=NULL;
00330
00331 switch(cn->typ) {
00332 case GWEN_DB_NodeType_ValueChar:
00333 typname="char ";
00334 pvalue=cn->data.dataChar;
00335 if (dbflags & GWEN_DB_FLAGS_ESCAPE_CHARVALUES) {
00336 vbuf=GWEN_Buffer_new(0, strlen(pvalue)+32, 0, 1);
00337 if (GWEN_Text_EscapeToBufferTolerant(pvalue, vbuf)) {
00338 DBG_INFO(GWEN_LOGDOMAIN, "called from here");
00339 GWEN_Buffer_free(vbuf);
00340 return 1;
00341 }
00342 pvalue=GWEN_Buffer_GetStart(vbuf);
00343 }
00344 break;
00345
00346 case GWEN_DB_NodeType_ValueInt:
00347 typname="int ";
00348 if (GWEN_Text_NumToString(cn->data.dataInt,
00349 numbuffer,
00350 sizeof(numbuffer)-1,
00351 0)<1) {
00352 DBG_ERROR(GWEN_LOGDOMAIN, "Error writing numeric value");
00353 return GWEN_ERROR_GENERIC;
00354 }
00355 pvalue=numbuffer;
00356 break;
00357
00358 case GWEN_DB_NodeType_ValueBin:
00359 bbsize=cn->dataSize*2+1;
00360 binbuffer=(char*)GWEN_Memory_malloc(bbsize);
00361 assert(binbuffer);
00362 typname="bin ";
00363 if (!GWEN_Text_ToHex(cn->data.dataBin,
00364 cn->dataSize,
00365 binbuffer,
00366 bbsize)) {
00367 DBG_ERROR(GWEN_LOGDOMAIN, "Error writing binary value");
00368 return GWEN_ERROR_GENERIC;
00369 }
00370 pvalue=binbuffer;
00371 break;
00372
00373 case GWEN_DB_NodeType_ValuePtr:
00374 DBG_DEBUG(GWEN_LOGDOMAIN, "Not writing ptr type");
00375 break;
00376
00377 default:
00378 DBG_DEBUG(GWEN_LOGDOMAIN, "Unhandled type [%d]", cn->typ);
00379 break;
00380 }
00381
00382 if (pvalue) {
00383 if (!namewritten) {
00384
00385
00386 if (dbflags & GWEN_DB_FLAGS_INDEND) {
00387 for (i=0; i<insert; i++) {
00388 GWEN_FASTBUFFER_WRITEBYTE(fb, err, ' ');
00389 if (err<0) {
00390 DBG_INFO(GWEN_LOGDOMAIN, "called from here");
00391 GWEN_Memory_dealloc(binbuffer);
00392 GWEN_Buffer_free(vbuf);
00393 return 1;
00394 }
00395 }
00396 }
00397 if (!(dbflags & GWEN_DB_FLAGS_OMIT_TYPES)) {
00398 GWEN_FASTBUFFER_WRITEFORCED(fb, err, typname, -1);
00399 if (err<0) {
00400 DBG_INFO(GWEN_LOGDOMAIN, "called from here");
00401 GWEN_Memory_dealloc(binbuffer);
00402 GWEN_Buffer_free(vbuf);
00403 return 1;
00404 }
00405 }
00406 if (dbflags & GWEN_DB_FLAGS_QUOTE_VARNAMES) {
00407 GWEN_FASTBUFFER_WRITEBYTE(fb, err, '\"');
00408 if (err<0) {
00409 DBG_INFO(GWEN_LOGDOMAIN, "called from here");
00410 GWEN_Memory_dealloc(binbuffer);
00411 GWEN_Buffer_free(vbuf);
00412 return 1;
00413 }
00414 }
00415 GWEN_FASTBUFFER_WRITEFORCED(fb, err, n->data.dataName, -1);
00416 if (err<0) {
00417 DBG_INFO(GWEN_LOGDOMAIN, "called from here");
00418 GWEN_Memory_dealloc(binbuffer);
00419 GWEN_Buffer_free(vbuf);
00420 return 1;
00421 }
00422 if (dbflags & GWEN_DB_FLAGS_QUOTE_VARNAMES) {
00423 GWEN_FASTBUFFER_WRITEBYTE(fb, err, '\"');
00424 if (err<0) {
00425 DBG_INFO(GWEN_LOGDOMAIN, "called from here");
00426 GWEN_Memory_dealloc(binbuffer);
00427 GWEN_Buffer_free(vbuf);
00428 return 1;
00429 }
00430 }
00431 GWEN_FASTBUFFER_WRITEFORCED(fb, err, ((dbflags & GWEN_DB_FLAGS_USE_COLON)?": ":"="), -1);
00432 if (err<0) {
00433 DBG_INFO(GWEN_LOGDOMAIN, "called from here");
00434 GWEN_Memory_dealloc(binbuffer);
00435 GWEN_Buffer_free(vbuf);
00436 return 1;
00437 }
00438 namewritten=1;
00439 }
00440
00441 if (values) {
00442 GWEN_FASTBUFFER_WRITEFORCED(fb, err, ", ", -1);
00443 if (err<0) {
00444 DBG_INFO(GWEN_LOGDOMAIN, "called from here");
00445 GWEN_Memory_dealloc(binbuffer);
00446 GWEN_Buffer_free(vbuf);
00447 return 1;
00448 }
00449 }
00450 values++;
00451 if (dbflags & GWEN_DB_FLAGS_QUOTE_VALUES) {
00452 GWEN_FASTBUFFER_WRITEBYTE(fb, err, '\"');
00453 if (err<0) {
00454 DBG_INFO(GWEN_LOGDOMAIN, "called from here");
00455 GWEN_Memory_dealloc(binbuffer);
00456 GWEN_Buffer_free(vbuf);
00457 return 1;
00458 }
00459 }
00460
00461 GWEN_FASTBUFFER_WRITEFORCED(fb, err, pvalue, -1);
00462 if (err<0) {
00463 DBG_INFO(GWEN_LOGDOMAIN, "called from here");
00464 GWEN_Memory_dealloc(binbuffer);
00465 GWEN_Buffer_free(vbuf);
00466 return 1;
00467 }
00468
00469 if (dbflags & GWEN_DB_FLAGS_QUOTE_VALUES) {
00470 GWEN_FASTBUFFER_WRITEBYTE(fb, err, '\"');
00471 if (err<0) {
00472 DBG_INFO(GWEN_LOGDOMAIN, "called from here");
00473 GWEN_Memory_dealloc(binbuffer);
00474 GWEN_Buffer_free(vbuf);
00475 return 1;
00476 }
00477 }
00478 }
00479
00480 GWEN_Memory_dealloc(binbuffer);
00481 GWEN_Buffer_free(vbuf);
00482 cn=GWEN_DB_Node_List_Next(cn);
00483 }
00484
00485 if (namewritten) {
00486 GWEN_FASTBUFFER_WRITELINE(fb, err, "");
00487 if (err<0) {
00488 DBG_INFO(GWEN_LOGDOMAIN, "called from here");
00489 return GWEN_ERROR_GENERIC;
00490 }
00491 }
00492 }
00493 lastWasVar=1;
00494 break;
00495
00496 default:
00497 DBG_WARN(GWEN_LOGDOMAIN, "[unhandled node type %d]", n->typ);
00498 }
00499 }
00500 else {
00501 DBG_DEBUG(GWEN_LOGDOMAIN, "Node is volatile, not writing it");
00502 }
00503 n=GWEN_DB_Node_List_Next(n);
00504 }
00505
00506 return 0;
00507 }
00508
00509
00510
00511 int GWEN_DB_WriteToFastBuffer(GWEN_DB_NODE *node,
00512 GWEN_FAST_BUFFER *fb,
00513 uint32_t dbflags) {
00514 int rv;
00515
00516 rv=GWEN_DB_WriteGroupToIoLayer(node, fb, dbflags, 0);
00517 if (rv<0) {
00518 return rv;
00519 }
00520 GWEN_FASTBUFFER_FLUSH(fb, rv);
00521 return rv;
00522 }
00523
00524
00525
00526 int GWEN_DB_WriteToIo(GWEN_DB_NODE *node,
00527 GWEN_IO_LAYER *io,
00528 uint32_t dbflags,
00529 uint32_t guiid,
00530 int msecs) {
00531 int rv;
00532 GWEN_FAST_BUFFER *fb;
00533
00534 fb=GWEN_FastBuffer_new(512, io, guiid, msecs);
00535 if (dbflags & GWEN_DB_FLAGS_DOSMODE)
00536 GWEN_FastBuffer_AddFlags(fb, GWEN_FAST_BUFFER_FLAGS_DOSMODE);
00537 rv=GWEN_DB_WriteGroupToIoLayer(node, fb, dbflags, 0);
00538 if (rv<0) {
00539 GWEN_FastBuffer_free(fb);
00540 return rv;
00541 }
00542 GWEN_FASTBUFFER_FLUSH(fb, rv);
00543 GWEN_FastBuffer_free(fb);
00544 return rv;
00545 }
00546
00547
00548
00549 int GWEN_DB_WriteToFd(GWEN_DB_NODE *n, int fd, uint32_t dbflags, uint32_t guiid, int msecs){
00550 GWEN_IO_LAYER *io;
00551 int rv;
00552
00553
00554 io=GWEN_Io_LayerFile_new(-1, fd);
00555 assert(io);
00556 GWEN_Io_Layer_AddFlags(io, GWEN_IO_LAYER_FLAGS_DONTCLOSE);
00557
00558 rv=GWEN_Io_Manager_RegisterLayer(io);
00559 if (rv) {
00560 DBG_ERROR(GWEN_LOGDOMAIN, "Internal error: Could not register io layer (%d)", rv);
00561 GWEN_Io_Layer_DisconnectRecursively(io, NULL, GWEN_IO_REQUEST_FLAGS_FORCE, guiid, msecs);
00562 GWEN_Io_Layer_free(io);
00563 return rv;
00564 }
00565
00566
00567 rv=GWEN_DB_WriteToIo(n, io, dbflags, guiid, msecs);
00568 if (rv<0) {
00569 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
00570 GWEN_Io_Layer_Disconnect(io, GWEN_IO_REQUEST_FLAGS_FORCE, guiid, 1000);
00571 GWEN_Io_Layer_free(io);
00572 return rv;
00573 }
00574
00575
00576 rv=GWEN_Io_Layer_DisconnectRecursively(io, NULL, 0, guiid, 30000);
00577 if (rv<0) {
00578 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
00579 GWEN_Io_Layer_Disconnect(io, GWEN_IO_REQUEST_FLAGS_FORCE, guiid, 1000);
00580 GWEN_Io_Layer_free(io);
00581 return rv;
00582 }
00583
00584 GWEN_Io_Layer_free(io);
00585
00586 return 0;
00587 }
00588
00589
00590
00591 int GWEN_DB_WriteFile(GWEN_DB_NODE *n, const char *fname, uint32_t dbflags, uint32_t guiid, int msecs){
00592 int fd;
00593 int rv;
00594 GWEN_FSLOCK *lck=0;
00595
00596
00597 if (dbflags & GWEN_DB_FLAGS_LOCKFILE) {
00598 GWEN_FSLOCK_RESULT res;
00599
00600 lck=GWEN_FSLock_new(fname, GWEN_FSLock_TypeFile);
00601 assert(lck);
00602 res=GWEN_FSLock_Lock(lck, GWEN_DB_DEFAULT_LOCK_TIMEOUT, 0);
00603 if (res!=GWEN_FSLock_ResultOk) {
00604 DBG_ERROR(GWEN_LOGDOMAIN,
00605 "Could not apply lock to file \"%s\" (%d)",
00606 fname, res);
00607 GWEN_FSLock_free(lck);
00608 return -1;
00609 }
00610 }
00611
00612
00613 if (dbflags & GWEN_DB_FLAGS_APPEND_FILE)
00614 fd=open(fname, O_RDWR | O_CREAT | O_APPEND, S_IRUSR | S_IWUSR);
00615 else
00616 fd=open(fname, O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);
00617 if (fd==-1) {
00618 DBG_ERROR(GWEN_LOGDOMAIN, "Error opening file \"%s\": %s",
00619 fname,
00620 strerror(errno));
00621 if (lck) {
00622 GWEN_FSLock_Unlock(lck);
00623 GWEN_FSLock_free(lck);
00624 }
00625 return GWEN_ERROR_IO;
00626 }
00627
00628 rv=GWEN_DB_WriteToFd(n, fd, dbflags, guiid, msecs);
00629 if (rv<0) {
00630 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
00631 close(fd);
00632 if (lck) {
00633 GWEN_FSLock_Unlock(lck);
00634 GWEN_FSLock_free(lck);
00635 }
00636 return rv;
00637 }
00638
00639 if (close(fd)) {
00640 DBG_ERROR(GWEN_LOGDOMAIN, "Error closing file \"%s\": %s",
00641 fname,
00642 strerror(errno));
00643 if (lck) {
00644 GWEN_FSLock_Unlock(lck);
00645 GWEN_FSLock_free(lck);
00646 }
00647 return GWEN_ERROR_IO;
00648 }
00649
00650
00651 if (lck) {
00652 GWEN_FSLOCK_RESULT res;
00653
00654 res=GWEN_FSLock_Unlock(lck);
00655 if (res!=GWEN_FSLock_ResultOk) {
00656 DBG_WARN(GWEN_LOGDOMAIN,
00657 "Could not remove lock on file \"%s\" (%d)",
00658 fname, res);
00659 }
00660 GWEN_FSLock_free(lck);
00661 }
00662
00663 return 0;
00664 }
00665
00666
00667
00668 int GWEN_DB__ReadValues(GWEN_DB_NODE *n,
00669 uint32_t dbflags,
00670 const char *typeName,
00671 const char *varName,
00672 uint8_t *p) {
00673 GWEN_DB_NODE_TYPE nodeType=GWEN_DB_NodeType_ValueChar;
00674 GWEN_DB_NODE *dbVar;
00675 GWEN_BUFFER *wbuf;
00676 uint8_t *pDebug;
00677
00678 pDebug=p;
00679
00680 if (typeName==NULL)
00681 typeName="char";
00682 if (strcasecmp(typeName, "int")==0)
00683 nodeType=GWEN_DB_NodeType_ValueInt;
00684 else if (strcasecmp(typeName, "char")==0)
00685 nodeType=GWEN_DB_NodeType_ValueChar;
00686 else if (strcasecmp(typeName, "bin")==0)
00687 nodeType=GWEN_DB_NodeType_ValueBin;
00688 else {
00689 DBG_ERROR(GWEN_LOGDOMAIN, "Unknown type \"%s\"", typeName);
00690 return GWEN_ERROR_BAD_DATA;
00691 }
00692
00693 dbVar=GWEN_DB_GetNode(n, varName, dbflags | GWEN_PATH_FLAGS_VARIABLE);
00694 if (dbVar==NULL) {
00695 DBG_INFO(GWEN_LOGDOMAIN, "Variable [%s] is not available", varName);
00696 return GWEN_ERROR_GENERIC;
00697 }
00698
00699 wbuf=GWEN_Buffer_new(0, 32, 0, 1);
00700 for (;;) {
00701 int quotes=0;
00702 GWEN_DB_NODE *dbVal=NULL;
00703 const char *v;
00704
00705 while(*p && isspace(*p))
00706 p++;
00707 if (!*p) {
00708 DBG_INFO(GWEN_LOGDOMAIN, "Missing value");
00709 GWEN_Buffer_free(wbuf);
00710 return GWEN_ERROR_BAD_DATA;
00711 }
00712
00713 if (*p=='"') {
00714 quotes=1;
00715 p++;
00716 }
00717
00718 while(*p) {
00719 if (*p=='%') {
00720 uint8_t c;
00721 uint8_t cHex;
00722
00723
00724 p++;
00725 if (!*p) {
00726 DBG_INFO(GWEN_LOGDOMAIN, "Incomplete escape sequence");
00727 GWEN_Buffer_free(wbuf);
00728 return GWEN_ERROR_BAD_DATA;
00729 }
00730 c=toupper(*p)-'0';
00731 if (c>9) c-=7;
00732 cHex=c<<4;
00733
00734 p++;
00735 if (!*p) {
00736 DBG_INFO(GWEN_LOGDOMAIN, "Incomplete escape sequence");
00737 GWEN_Buffer_free(wbuf);
00738 return GWEN_ERROR_BAD_DATA;
00739 }
00740 c=toupper(*p)-'0';
00741 if (c>9) c-=7;
00742 cHex|=c;
00743 GWEN_Buffer_AppendByte(wbuf, cHex);
00744 }
00745 else
00746 if (quotes) {
00747 if (*p=='"') {
00748 p++;
00749 break;
00750 }
00751 else
00752 GWEN_Buffer_AppendByte(wbuf, *p);
00753 }
00754 else {
00755 if (*p==',' || *p==';' || *p=='#')
00756 break;
00757 else if (*p=='"') {
00758 DBG_INFO(GWEN_LOGDOMAIN, "Unexpected quotation mark (Line: [%s], parsed: [%s]",
00759 pDebug, GWEN_Buffer_GetStart(wbuf));
00760 GWEN_Buffer_free(wbuf);
00761 return GWEN_ERROR_BAD_DATA;
00762 }
00763 else
00764 GWEN_Buffer_AppendByte(wbuf, *p);
00765 }
00766 p++;
00767 }
00768
00769 v=GWEN_Buffer_GetStart(wbuf);
00770 if (nodeType==GWEN_DB_NodeType_ValueInt) {
00771 int i;
00772
00773 if (1!=sscanf(v, "%d", &i)) {
00774 DBG_INFO(GWEN_LOGDOMAIN, "Not an integer value [%s]", v);
00775 GWEN_Buffer_free(wbuf);
00776 return GWEN_ERROR_BAD_DATA;
00777 }
00778 dbVal=GWEN_DB_ValueInt_new(i);
00779 }
00780 else if (nodeType==GWEN_DB_NodeType_ValueChar)
00781 dbVal=GWEN_DB_ValueChar_new(v);
00782 else if (nodeType==GWEN_DB_NodeType_ValueBin) {
00783 GWEN_BUFFER *bbuf;
00784 int rv;
00785
00786 bbuf=GWEN_Buffer_new(0, (GWEN_Buffer_GetUsedBytes(wbuf)/2)+1, 0, 1);
00787 rv=GWEN_Text_FromHexBuffer(v, bbuf);
00788 if (rv) {
00789 DBG_INFO(GWEN_LOGDOMAIN, "Bad bin value [%s]", v);
00790 GWEN_Buffer_free(bbuf);
00791 GWEN_Buffer_free(wbuf);
00792 return GWEN_ERROR_BAD_DATA;
00793 }
00794 dbVal=GWEN_DB_ValueBin_new(GWEN_Buffer_GetStart(bbuf),
00795 GWEN_Buffer_GetUsedBytes(bbuf));
00796 GWEN_Buffer_free(bbuf);
00797 }
00798 else {
00799
00800 assert(0);
00801 }
00802 GWEN_DB_Node_Append(dbVar, dbVal);
00803
00804
00805 while(*p && isspace(*p))
00806 p++;
00807 if (!*p || *p==';' || *p=='#')
00808 break;
00809 else if (*p!=',') {
00810 DBG_INFO(GWEN_LOGDOMAIN, "Unexpected character [%s]", p);
00811 GWEN_Buffer_free(wbuf);
00812 return GWEN_ERROR_BAD_DATA;
00813 }
00814 p++;
00815 GWEN_Buffer_Reset(wbuf);
00816 }
00817
00818 GWEN_Buffer_free(wbuf);
00819 return 0;
00820 }
00821
00822
00823
00824 int GWEN_DB_ReadFromFastBuffer(GWEN_DB_NODE *n,
00825 GWEN_FAST_BUFFER *fb,
00826 uint32_t dbflags) {
00827 GWEN_BUFFER *lbuf;
00828 GWEN_BUFFER *tbuf;
00829 int level=0;
00830 int someLinesRead=0;
00831
00832 lbuf=GWEN_Buffer_new(0, 128, 0, 1);
00833 tbuf=GWEN_Buffer_new(0, 128, 0, 1);
00834
00835 for (;;) {
00836 int rv;
00837 uint8_t *p;
00838
00839 rv=GWEN_FastBuffer_ReadLineToBuffer(fb, lbuf);
00840 if (rv<0) {
00841 if (rv==GWEN_ERROR_EOF) {
00842 if (!someLinesRead && !(dbflags & GWEN_DB_FLAGS_ALLOW_EMPTY_STREAM)){
00843 DBG_INFO(GWEN_LOGDOMAIN, "Unexpected EOF (%d)", rv);
00844 GWEN_Buffer_free(tbuf);
00845 GWEN_Buffer_free(lbuf);
00846 return rv;
00847 }
00848 break;
00849 }
00850 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
00851 GWEN_Buffer_free(tbuf);
00852 GWEN_Buffer_free(lbuf);
00853 return rv;
00854 }
00855
00856 if (GWEN_Buffer_GetUsedBytes(lbuf)==0) {
00857 if (dbflags & GWEN_DB_FLAGS_UNTIL_EMPTY_LINE) {
00858 break;
00859 }
00860 }
00861 else {
00862 someLinesRead=1;
00863 p=(uint8_t*)GWEN_Buffer_GetStart(lbuf);
00864 while(*p && isspace(*p))
00865 p++;
00866 if (*p) {
00867 uint8_t *p1begin=NULL, *p1end=NULL;
00868 uint8_t *p2begin=NULL, *p2end=NULL;
00869
00870
00871 if (*p=='}') {
00872
00873 if (level<1) {
00874 DBG_INFO(GWEN_LOGDOMAIN, "Unbalanced number of curly bracket");
00875 GWEN_Buffer_free(tbuf);
00876 GWEN_Buffer_free(lbuf);
00877 return GWEN_ERROR_BAD_DATA;
00878 }
00879 n=n->parent;
00880 assert(n);
00881 assert(n->typ==GWEN_DB_NodeType_Group);
00882 level--;
00883 }
00884 else if (*p=='#') {
00885
00886 }
00887 else {
00888 p1begin=p;
00889
00890 while(*p && !isspace(*p) &&
00891 *p!='{' &&
00892 *p!=((dbflags & GWEN_DB_FLAGS_USE_COLON)?':':'=') &&
00893 *p!='}' &&
00894 *p!=',' &&
00895 *p!=';')
00896 p++;
00897 if (!*p) {
00898 DBG_INFO(GWEN_LOGDOMAIN, "Missing 2nd token");
00899 GWEN_Buffer_Dump(lbuf, stderr, 2);
00900 GWEN_Buffer_free(tbuf);
00901 GWEN_Buffer_free(lbuf);
00902 return GWEN_ERROR_BAD_DATA;
00903 }
00904 p1end=p;
00905
00906
00907 while(*p && isspace(*p))
00908 p++;
00909 if (!*p) {
00910 DBG_INFO(GWEN_LOGDOMAIN, "Missing 2nd token");
00911 GWEN_Buffer_free(tbuf);
00912 GWEN_Buffer_free(lbuf);
00913 return GWEN_ERROR_BAD_DATA;
00914 }
00915
00916 if (*p=='{') {
00917 GWEN_DB_NODE *newGr;
00918
00919
00920 *p1end=0;
00921 rv=GWEN_DB_UnescapeToBufferTolerant((const char*)p1begin, tbuf);
00922 if (rv<0) {
00923 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
00924 GWEN_Buffer_free(tbuf);
00925 GWEN_Buffer_free(lbuf);
00926 return rv;
00927 }
00928 newGr=GWEN_DB_GetGroup(n, dbflags, GWEN_Buffer_GetStart(tbuf));
00929 if (newGr==NULL) {
00930 DBG_INFO(GWEN_LOGDOMAIN, "Could not create group [%s]", GWEN_Buffer_GetStart(tbuf));
00931 GWEN_Buffer_free(tbuf);
00932 GWEN_Buffer_free(lbuf);
00933 return GWEN_ERROR_GENERIC;
00934 }
00935 GWEN_Buffer_Reset(tbuf);
00936 n=newGr;
00937 level++;
00938 }
00939 else if (*p=='=' || *p==':') {
00940
00941 *p1end=0;
00942 p++;
00943 rv=GWEN_DB__ReadValues(n, dbflags, NULL, (const char*)p1begin, p);
00944 if (rv) {
00945 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
00946 GWEN_Buffer_free(tbuf);
00947 GWEN_Buffer_free(lbuf);
00948 return rv;
00949 }
00950 }
00951 else if (*p==',' || *p==';') {
00952 DBG_INFO(GWEN_LOGDOMAIN, "Unexpected delimiter found");
00953 GWEN_Buffer_free(tbuf);
00954 GWEN_Buffer_free(lbuf);
00955 return GWEN_ERROR_BAD_DATA;
00956 }
00957 else {
00958
00959 p2begin=p;
00960 while(*p &&
00961 !isspace(*p) &&
00962 *p!='{' &&
00963 *p!=((dbflags & GWEN_DB_FLAGS_USE_COLON)?':':'=') &&
00964 *p!='}' &&
00965 *p!=',' &&
00966 *p!=';')
00967 p++;
00968 if (!*p) {
00969 DBG_INFO(GWEN_LOGDOMAIN, "Missing 2nd token [%s], [%s]", p1begin, p2begin);
00970 GWEN_Buffer_free(tbuf);
00971 GWEN_Buffer_free(lbuf);
00972 return GWEN_ERROR_BAD_DATA;
00973 }
00974 p2end=p;
00975 if (isspace(*p)) {
00976 while(*p && isspace(*p))
00977 p++;
00978 if (!*p) {
00979 DBG_INFO(GWEN_LOGDOMAIN, "Missing 2nd token");
00980 GWEN_Buffer_free(tbuf);
00981 GWEN_Buffer_free(lbuf);
00982 return GWEN_ERROR_BAD_DATA;
00983 }
00984 }
00985 if (*p!='=' && *p!=':') {
00986 DBG_INFO(GWEN_LOGDOMAIN, "Equation mark expected");
00987 GWEN_Buffer_free(tbuf);
00988 GWEN_Buffer_free(lbuf);
00989 return GWEN_ERROR_BAD_DATA;
00990 }
00991 p++;
00992
00993 *p1end=0;
00994 *p2end=0;
00995 rv=GWEN_DB__ReadValues(n, dbflags, (const char*)p1begin, (const char*)p2begin, p);
00996 if (rv) {
00997 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
00998 GWEN_Buffer_free(tbuf);
00999 GWEN_Buffer_free(lbuf);
01000 return rv;
01001 }
01002 }
01003 }
01004 }
01005 }
01006 GWEN_Buffer_Reset(lbuf);
01007 }
01008
01009 if (level) {
01010 DBG_INFO(GWEN_LOGDOMAIN, "Unbalanced number of curly bracket (too few)");
01011 GWEN_Buffer_free(tbuf);
01012 GWEN_Buffer_free(lbuf);
01013 return GWEN_ERROR_BAD_DATA;
01014 }
01015
01016 GWEN_Buffer_free(tbuf);
01017 GWEN_Buffer_free(lbuf);
01018
01019 return 0;
01020 }
01021
01022
01023
01024 int GWEN_DB_ReadFromIo(GWEN_DB_NODE *n,
01025 GWEN_IO_LAYER *io,
01026 uint32_t dbflags,
01027 uint32_t guiid,
01028 int msecs) {
01029 GWEN_FAST_BUFFER *fb;
01030 int rv;
01031
01032
01033 fb=GWEN_FastBuffer_new(1024, io, guiid, msecs);
01034 if (dbflags & GWEN_DB_FLAGS_DOSMODE)
01035 GWEN_FastBuffer_AddFlags(fb, GWEN_FAST_BUFFER_FLAGS_DOSMODE);
01036
01037
01038 rv=GWEN_DB_ReadFromFastBuffer(n, fb, dbflags);
01039 if (rv) {
01040 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
01041 GWEN_FastBuffer_free(fb);
01042 return rv;
01043 }
01044
01045 GWEN_FastBuffer_free(fb);
01046 return 0;
01047 }
01048
01049
01050
01051 int GWEN_DB_ReadFromFd(GWEN_DB_NODE *n,
01052 int fd,
01053 uint32_t dbflags,
01054 uint32_t guiid,
01055 int msecs) {
01056 GWEN_IO_LAYER *io;
01057 int rv;
01058
01059
01060 io=GWEN_Io_LayerFile_new(fd, -1);
01061 assert(io);
01062 GWEN_Io_Layer_AddFlags(io, GWEN_IO_LAYER_FLAGS_DONTCLOSE);
01063
01064 rv=GWEN_Io_Manager_RegisterLayer(io);
01065 if (rv) {
01066 DBG_ERROR(GWEN_LOGDOMAIN, "Internal error: Could not register io layer (%d)", rv);
01067 GWEN_Io_Layer_free(io);
01068 return rv;
01069 }
01070
01071 rv=GWEN_DB_ReadFromIo(n, io, dbflags, guiid, msecs);
01072 if (rv) {
01073 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
01074 }
01075 GWEN_Io_Layer_DisconnectRecursively(io, NULL, GWEN_IO_REQUEST_FLAGS_FORCE, guiid, msecs);
01076 GWEN_Io_Layer_free(io);
01077
01078 return rv;
01079 }
01080
01081
01082
01083 int GWEN_DB_ReadFile(GWEN_DB_NODE *n,
01084 const char *fname,
01085 uint32_t dbflags,
01086 uint32_t guiid,
01087 int msecs) {
01088 int fd;
01089 int rv;
01090
01091 fd=open(fname, O_RDONLY);
01092 if (fd==-1) {
01093 DBG_ERROR(GWEN_LOGDOMAIN, "open(%s, O_RDONLY): %s", fname, strerror(errno));
01094 return GWEN_ERROR_IO;
01095 }
01096
01097 rv=GWEN_DB_ReadFromFd(n, fd, dbflags, guiid, msecs);
01098 close(fd);
01099
01100 return rv;
01101 }
01102
01103
01104
01105 int GWEN_DB_ReadFromString(GWEN_DB_NODE *n,
01106 const char *str,
01107 int len,
01108 uint32_t dbflags,
01109 uint32_t guiid,
01110 int msecs) {
01111 GWEN_IO_LAYER *io;
01112 int rv;
01113
01114 if (len==0)
01115 len=strlen(str);
01116
01117
01118 io=GWEN_Io_LayerMemory_fromString((const uint8_t*)str, len);
01119 assert(io);
01120
01121 rv=GWEN_Io_Manager_RegisterLayer(io);
01122 if (rv) {
01123 DBG_ERROR(GWEN_LOGDOMAIN, "Internal error: Could not register io layer (%d)", rv);
01124 GWEN_Io_Layer_DisconnectRecursively(io, NULL, GWEN_IO_REQUEST_FLAGS_FORCE, guiid, msecs);
01125 GWEN_Io_Layer_free(io);
01126 return rv;
01127 }
01128
01129 rv=GWEN_DB_ReadFromIo(n, io, dbflags, guiid, msecs);
01130 if (rv) {
01131 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
01132 }
01133 GWEN_Io_Layer_DisconnectRecursively(io, NULL, GWEN_IO_REQUEST_FLAGS_FORCE, guiid, msecs);
01134 GWEN_Io_Layer_free(io);
01135
01136 return rv;
01137 }
01138
01139
01140
01141 int GWEN_DB_WriteToBuffer(GWEN_DB_NODE *n,
01142 GWEN_BUFFER *buf,
01143 uint32_t dbflags,
01144 uint32_t guiid,
01145 int msecs) {
01146 GWEN_IO_LAYER *io;
01147 int rv;
01148
01149
01150 io=GWEN_Io_LayerMemory_new(buf);
01151 assert(io);
01152
01153 rv=GWEN_Io_Manager_RegisterLayer(io);
01154 if (rv) {
01155 DBG_ERROR(GWEN_LOGDOMAIN, "Internal error: Could not register io layer (%d)", rv);
01156 GWEN_Io_Layer_DisconnectRecursively(io, NULL, GWEN_IO_REQUEST_FLAGS_FORCE, guiid, msecs);
01157 GWEN_Io_Layer_free(io);
01158 return rv;
01159 }
01160
01161 rv=GWEN_DB_WriteToIo(n, io, dbflags, guiid, msecs);
01162 if (rv<0) {
01163 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
01164 GWEN_Io_Layer_Disconnect(io, GWEN_IO_REQUEST_FLAGS_FORCE, 0, 1000);
01165 GWEN_Io_Layer_free(io);
01166 return rv;
01167 }
01168
01169
01170 rv=GWEN_Io_Layer_WriteString(io, "",
01171 GWEN_IO_REQUEST_FLAGS_FLUSH,
01172 guiid,
01173 30000);
01174 if (rv<0) {
01175 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
01176 GWEN_Io_Layer_Disconnect(io, GWEN_IO_REQUEST_FLAGS_FORCE, 0, 1000);
01177 GWEN_Io_Layer_free(io);
01178 return rv;
01179 }
01180
01181
01182 rv=GWEN_Io_Layer_DisconnectRecursively(io, NULL, 0, guiid, 30000);
01183 if (rv<0) {
01184 DBG_INFO(GWEN_LOGDOMAIN, "here (%d)", rv);
01185 GWEN_Io_Layer_Disconnect(io, GWEN_IO_REQUEST_FLAGS_FORCE, guiid, 1000);
01186 GWEN_Io_Layer_free(io);
01187 return rv;
01188 }
01189
01190 GWEN_Io_Layer_free(io);
01191
01192 return 0;
01193 }
01194
01195
01196
01197
01198
01199
01200
01201
01202
01203
01204
01205